diff --git a/.devcontainer/README.md b/.devcontainer/README.md deleted file mode 100644 index 4a34b21153..0000000000 --- a/.devcontainer/README.md +++ /dev/null @@ -1,28 +0,0 @@ -# Codespaces - -You can modifiy Uptime Kuma in your browser without setting up a local development. - -![image](https://github.com/louislam/uptime-kuma/assets/1336778/31d9f06d-dd0b-4405-8e0d-a96586ee4595) - -1. Click `Code` -> `Create codespace on master` -2. Wait a few minutes until you see there are two exposed ports -3. Go to the `3000` url, see if it is working - -![image](https://github.com/louislam/uptime-kuma/assets/1336778/909b2eb4-4c5e-44e4-ac26-6d20ed856e7f) - -## Frontend - -Since the frontend is using [Vite.js](https://vitejs.dev/), all changes in this area will be hot-reloaded. -You don't need to restart the frontend, unless you try to add a new frontend dependency. - -## Backend - -The backend does not automatically hot-reload. -You will need to restart the backend after changing something using these steps: - -1. Click `Terminal` -2. Click `Codespaces: server-dev` in the right panel -3. Press `Ctrl + C` to stop the server -4. Press `Up` to run `npm run start-server-dev` - -![image](https://github.com/louislam/uptime-kuma/assets/1336778/e0c0a350-fe46-4588-9f37-e053c85834d1) diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json deleted file mode 100644 index 5b3ceabc82..0000000000 --- a/.devcontainer/devcontainer.json +++ /dev/null @@ -1,22 +0,0 @@ -{ - "image": "mcr.microsoft.com/devcontainers/javascript-node:dev-18-bookworm", - "features": { - "ghcr.io/devcontainers/features/github-cli:1": {} - }, - "updateContentCommand": "npm ci", - "postCreateCommand": "", - "postAttachCommand": { - "frontend-dev": "npm run start-frontend-devcontainer", - "server-dev": "npm run start-server-dev", - "open-port": "gh codespace ports visibility 3001:public -c $CODESPACE_NAME" - }, - "customizations": { - "vscode": { - "extensions": [ - "streetsidesoftware.code-spell-checker", - "dbaeumer.vscode-eslint" - ] - } - }, - "forwardPorts": [3000, 3001] -} diff --git a/.dockerignore b/.dockerignore index 226f8e22fa..5db08b7bf6 100644 --- a/.dockerignore +++ b/.dockerignore @@ -1,7 +1,6 @@ /.idea /node_modules -/data -/cypress +/data* /out /test /kubernetes @@ -18,7 +17,6 @@ README.md .vscode .eslint* .stylelint* -/.devcontainer /.github yarn.lock app.json @@ -30,7 +28,6 @@ SECURITY.md tsconfig.json .env /tmp -/babel.config.js /ecosystem.config.js /extra/healthcheck.exe /extra/healthcheck diff --git a/.eslintrc.js b/.eslintrc.js index 9b30158d66..5da22e72d7 100644 --- a/.eslintrc.js +++ b/.eslintrc.js @@ -1,7 +1,7 @@ module.exports = { ignorePatterns: [ - "test/*", - "server/modules/apicache/*", + "test/*.js", + "server/modules/*", "src/util.js" ], root: true, @@ -14,13 +14,18 @@ module.exports = { extends: [ "eslint:recommended", "plugin:vue/vue3-recommended", + "plugin:jsdoc/recommended-error", ], parser: "vue-eslint-parser", parserOptions: { - parser: "@babel/eslint-parser", + parser: "@typescript-eslint/parser", sourceType: "module", requireConfigFile: false, }, + plugins: [ + "jsdoc", + "@typescript-eslint", + ], rules: { "yoda": "error", eqeqeq: [ "warn", "smart" ], @@ -71,7 +76,7 @@ module.exports = { "no-var": "error", "key-spacing": "warn", "keyword-spacing": "warn", - "space-infix-ops": "warn", + "space-infix-ops": "error", "arrow-spacing": "warn", "no-trailing-spaces": "error", "no-constant-condition": [ "error", { @@ -98,7 +103,43 @@ module.exports = { }], "no-control-regex": "off", "one-var": [ "error", "never" ], - "max-statements-per-line": [ "error", { "max": 1 }] + "max-statements-per-line": [ "error", { "max": 1 }], + "jsdoc/check-tag-names": [ + "error", + { + "definedTags": [ "link" ] + } + ], + "jsdoc/no-undefined-types": "off", + "jsdoc/no-defaults": [ + "error", + { "noOptionalParamNames": true } + ], + "jsdoc/require-throws": "warn", + "jsdoc/require-jsdoc": [ + "error", + { + "require": { + "FunctionDeclaration": true, + "MethodDefinition": true, + } + } + ], + "jsdoc/no-blank-block-descriptions": "error", + "jsdoc/require-returns-description": "warn", + "jsdoc/require-returns-check": [ + "error", + { "reportMissingReturnForUndefinedTypes": false } + ], + "jsdoc/require-returns": [ + "warn", + { + "forceRequireReturn": true, + "forceReturnsWithAsync": true + } + ], + "jsdoc/require-param-type": "warn", + "jsdoc/require-param-description": "warn" }, "overrides": [ { @@ -108,21 +149,20 @@ module.exports = { } }, - // Override for jest puppeteer + // Override for TypeScript { "files": [ - "**/*.spec.js", - "**/*.spec.jsx" + "**/*.ts", ], - env: { - jest: true, - }, - globals: { - page: true, - browser: true, - context: true, - jestPuppeteer: true, - }, + extends: [ + "plugin:@typescript-eslint/recommended", + ], + "rules": { + "jsdoc/require-returns-type": "off", + "jsdoc/require-param-type": "off", + "@typescript-eslint/no-explicit-any": "off", + "prefer-const": "off", + } } ] }; diff --git a/.github/ISSUE_TEMPLATE/ask-for-help.yaml b/.github/ISSUE_TEMPLATE/ask-for-help.yaml index c082b2e34b..a708dbf233 100644 --- a/.github/ISSUE_TEMPLATE/ask-for-help.yaml +++ b/.github/ISSUE_TEMPLATE/ask-for-help.yaml @@ -6,7 +6,7 @@ body: - type: checkboxes id: no-duplicate-issues attributes: - label: "⚠️ Please verify that this bug has NOT been raised before." + label: "⚠️ Please verify that this question has NOT been raised before." description: "Search in the issues sections by clicking [HERE](https://github.com/louislam/uptime-kuma/issues?q=)" options: - label: "I checked and didn't find similar issue" @@ -24,7 +24,7 @@ body: required: true attributes: label: "📝 Describe your problem" - description: "Please walk us through it step by step." + description: "Please walk us through it step by step. Include all important details and add screenshots where appropriate" placeholder: "Describe what are you asking for..." - type: textarea id: error-msg @@ -56,19 +56,20 @@ body: placeholder: "Ex. Google Chrome 95.0.4638.69" validations: required: true - - type: input - id: docker-version - attributes: - label: "🐋 Docker Version" - description: "If running with Docker, which version are you running?" - placeholder: "Ex. Docker 20.10.9 / K8S / Podman" - validations: - required: false - - type: input - id: nodejs-version + - type: textarea + id: deployment-info attributes: - label: "🟩 NodeJS Version" - description: "If running with Node.js? which version are you running?" - placeholder: "Ex. 14.18.0" + label: "🖥️ Deployment Environment" + description: | + examples: + - **Runtime**: Docker 20.10.9 / nodejs 14.18.0 / K8S via ... v1.3.3 / .. + - **Database**: sqlite/embedded mariadb/external mariadb + - **Filesystem used to store the database on**: Windows/ZFS/btrfs/NFSv3 on a SSD/HDD/eMMC + - **number of monitors**: 42 + value: | + - Runtime: + - Database: + - Filesystem used to store the database on: + - number of monitors: validations: - required: false + required: true diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml index 0724442054..9745a76a62 100644 --- a/.github/ISSUE_TEMPLATE/bug_report.yaml +++ b/.github/ISSUE_TEMPLATE/bug_report.yaml @@ -3,14 +3,14 @@ description: "Submit a bug report to help us improve" #title: "[Bug] " labels: [bug] body: - - type: checkboxes - id: no-duplicate-issues + - type: textarea + id: related-issues + validations: + required: true attributes: - label: "⚠️ Please verify that this bug has NOT been raised before." - description: "Search in the issues sections by clicking [HERE](https://github.com/louislam/uptime-kuma/issues?q=)" - options: - - label: "I checked and didn't find similar issue" - required: true + label: "📑 I have found these related issues/pull requests" + description: "Search related issues by clicking [HERE](https://github.com/louislam/uptime-kuma/issues?q=) and explain what the difference between them or explain that you are unable to find any related issues" + placeholder: "Related to #1 by also touching the ... system. They should not be merged because ..." - type: checkboxes attributes: label: "🛡️ Security Policy" @@ -31,7 +31,7 @@ body: required: true attributes: label: "👟 Reproduction steps" - description: "How do you trigger this bug? Please walk us through it step by step." + description: "How do you trigger this bug? Please walk us through it step by step. Include all important details and add screenshots where appropriate" placeholder: "..." - type: textarea id: expected-behavior @@ -73,22 +73,23 @@ body: placeholder: "Ex. Google Chrome 95.0.4638.69" validations: required: true - - type: input - id: docker-version - attributes: - label: "🐋 Docker Version" - description: "If running with Docker, which version are you running?" - placeholder: "Ex. Docker 20.10.9 / K8S / Podman" - validations: - required: false - - type: input - id: nodejs-version + - type: textarea + id: deployment-info attributes: - label: "🟩 NodeJS Version" - description: "If running with Node.js? which version are you running?" - placeholder: "Ex. 14.18.0" + label: "🖥️ Deployment Environment" + description: | + examples: + - **Runtime**: Docker 20.10.9 / nodejs 18.17.1 / K8S via ... v1.3.3 / .. + - **Database**: sqlite/embedded mariadb/external mariadb + - **Filesystem used to store the database on**: Windows/ZFS/btrfs/NFSv3 on a SSD/HDD/eMMC + - **number of monitors**: 42 + value: | + - Runtime: + - Database: + - Filesystem used to store the database on: + - number of monitors: validations: - required: false + required: true - type: textarea id: logs attributes: diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml index b26841c425..531a2c25ee 100644 --- a/.github/ISSUE_TEMPLATE/feature_request.yaml +++ b/.github/ISSUE_TEMPLATE/feature_request.yaml @@ -3,14 +3,14 @@ description: "Submit a proposal for a new feature" #title: "[Feature] " labels: [feature-request] body: - - type: checkboxes - id: no-duplicate-issues + - type: textarea + id: related-issues + validations: + required: true attributes: - label: "⚠️ Please verify that this feature request has NOT been suggested before." - description: "Search in the issues sections by clicking [HERE](https://github.com/louislam/uptime-kuma/issues?q=)" - options: - - label: "I checked and didn't find similar feature request" - required: true + label: "📑 I have found these related issues/pull requests" + description: "Search related issues by clicking [HERE](https://github.com/louislam/uptime-kuma/issues?q=) and explain what the difference between them or explain that you are unable to find any related issues" + placeholder: "Related to #1 by also touching the ... system. They should not be merged because ..." - type: dropdown id: feature-area attributes: @@ -18,10 +18,17 @@ body: description: "What kind of feature request is this?" multiple: true options: - - API - - New Notification - - New Monitor - - UI Feature + - API / automation options + - New notification-provider + - Change to existing notification-provider + - New monitor + - Change to existing monitor + - Dashboard + - Status-page + - Maintenance + - Deployment + - Certificate expiry + - Settings - Other validations: required: true diff --git a/.github/ISSUE_TEMPLATE/security.md b/.github/ISSUE_TEMPLATE/security.md index 26450ed3a2..708670e857 100644 --- a/.github/ISSUE_TEMPLATE/security.md +++ b/.github/ISSUE_TEMPLATE/security.md @@ -12,8 +12,6 @@ labels: DO NOT PROVIDE ANY DETAILS HERE. Please privately report to https://github.com/louislam/uptime-kuma/security/advisories/new. - Why need this issue? It is because GitHub Advisory do not send a notification to @louislam, it is a workaround to do so. Your GitHub Advisory URL: - diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 87e7f5ff7b..0dfb5faed5 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -1,7 +1,7 @@ ⚠️⚠️⚠️ Since we do not accept all types of pull requests and do not want to waste your time. Please be sure that you have read pull request rules: https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md#can-i-create-a-pull-request-for-uptime-kuma -Tick the checkbox if you understand [x]: +Tick the checkbox if you understand [x]: - [ ] I have read and understand the pull request rules. # Description @@ -15,7 +15,7 @@ Please delete any options that are not relevant. - Bug fix (non-breaking change which fixes an issue) - User interface (UI) - New feature (non-breaking change which adds functionality) -- Breaking change (fix or feature that would cause existing functionality to not work as expected) +- Breaking change (a fix or feature that would cause existing functionality to not work as expected) - Other - This change requires a documentation update @@ -24,9 +24,8 @@ Please delete any options that are not relevant. - [ ] My code follows the style guidelines of this project - [ ] I ran ESLint and other linters for modified files - [ ] I have performed a self-review of my own code and tested it -- [ ] I have commented my code, particularly in hard-to-understand areas - (including JSDoc for methods) -- [ ] My changes generate no new warnings +- [ ] I have commented my code, particularly in hard-to-understand areas (including JSDoc for methods) +- [ ] My changes generates no new warnings - [ ] My code needed automated testing. I have added them (this is optional task) ## Screenshots (if any) diff --git a/.github/workflows/auto-test.yml b/.github/workflows/auto-test.yml index 071cc7df80..bf76d9eb6c 100644 --- a/.github/workflows/auto-test.yml +++ b/.github/workflows/auto-test.yml @@ -22,7 +22,7 @@ jobs: strategy: matrix: os: [macos-latest, ubuntu-latest, windows-latest, ARM64] - node: [ 16, 20.5 ] + node: [ 18, 20 ] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: @@ -33,23 +33,23 @@ jobs: uses: actions/setup-node@v4 with: node-version: ${{ matrix.node }} - - run: npm ci + - run: npm install - run: npm run build - - run: npm test + - run: npm run test-backend env: HEADLESS_TEST: 1 JUST_FOR_TEST: ${{ secrets.JUST_FOR_TEST }} # As a lot of dev dependencies are not supported on ARMv7, we have to test it separately and just test if `npm ci --production` works armv7-simple-test: - needs: [ check-linters ] + needs: [ ] runs-on: ${{ matrix.os }} timeout-minutes: 15 - + if: ${{ github.repository == 'louislam/uptime-kuma' }} strategy: matrix: os: [ ARMv7 ] - node: [ 16, 20.5 ] + node: [ 18, 20 ] # See supported Node.js release schedule at https://nodejs.org/en/about/releases/ steps: @@ -72,36 +72,22 @@ jobs: - name: Use Node.js 20 uses: actions/setup-node@v4 with: - node-version: 20.5 - - run: npm ci + node-version: 20 + - run: npm install - run: npm run lint:prod - e2e-tests: - needs: [ check-linters ] - runs-on: ubuntu-latest + e2e-test: + needs: [ ] + runs-on: ARM64 steps: - run: git config --global core.autocrlf false # Mainly for Windows - uses: actions/checkout@v4 - - name: Use Node.js 16 - uses: actions/setup-node@v4 - with: - node-version: 16 - - run: npm ci - - run: npm run build - - run: npm run cy:test - - frontend-unit-tests: - needs: [ check-linters ] - runs-on: ubuntu-latest - steps: - - run: git config --global core.autocrlf false # Mainly for Windows - - uses: actions/checkout@v4 - - - name: Use Node.js 16 + - name: Use Node.js 20 uses: actions/setup-node@v4 with: - node-version: 16 - - run: npm ci + node-version: 20 + - run: npm install + - run: npx playwright install - run: npm run build - - run: npm run cy:run:unit + - run: npm run test-e2e diff --git a/.github/workflows/close-incorrect-issue.yml b/.github/workflows/close-incorrect-issue.yml index e26cf5e5ee..3ef5ba3788 100644 --- a/.github/workflows/close-incorrect-issue.yml +++ b/.github/workflows/close-incorrect-issue.yml @@ -11,7 +11,7 @@ jobs: strategy: matrix: os: [ubuntu-latest] - node-version: [16] + node-version: [18] steps: - uses: actions/checkout@v4 diff --git a/.github/workflows/codeql-analysis.yml b/.github/workflows/codeql-analysis.yml new file mode 100644 index 0000000000..0e3b72c4b7 --- /dev/null +++ b/.github/workflows/codeql-analysis.yml @@ -0,0 +1,43 @@ +name: "CodeQL" + +on: + push: + branches: [ "master", "1.23.X"] + pull_request: + branches: [ "master", "1.23.X"] + schedule: + - cron: '16 22 * * 0' + +jobs: + analyze: + name: Analyze + runs-on: ubuntu-latest + timeout-minutes: 360 + + permissions: + actions: read + contents: read + security-events: write + + strategy: + fail-fast: false + matrix: + language: [ 'go', 'javascript-typescript' ] + + steps: + - name: Checkout repository + uses: actions/checkout@v3 + + # Initializes the CodeQL tools for scanning. + - name: Initialize CodeQL + uses: github/codeql-action/init@v2 + with: + languages: ${{ matrix.language }} + + - name: Autobuild + uses: github/codeql-action/autobuild@v2 + + - name: Perform CodeQL Analysis + uses: github/codeql-action/analyze@v2 + with: + category: "/language:${{matrix.language}}" diff --git a/.github/workflows/conflict_labeler.yml b/.github/workflows/conflict_labeler.yml new file mode 100644 index 0000000000..fdcc9c5516 --- /dev/null +++ b/.github/workflows/conflict_labeler.yml @@ -0,0 +1,25 @@ +name: Merge Conflict Labeler + +on: + push: + branches: + - master + pull_request_target: + branches: + - master + types: [synchronize] + +jobs: + label: + name: Labeling + runs-on: ubuntu-latest + if: ${{ github.repository == 'louislam/uptime-kuma' }} + permissions: + contents: read + pull-requests: write + steps: + - name: Apply label + uses: eps1lon/actions-label-merge-conflict@v3 + with: + dirtyLabel: 'needs:resolve-merge-conflict' + repoToken: '${{ secrets.GITHUB_TOKEN }}' diff --git a/.github/workflows/prevent-file-change.yml b/.github/workflows/prevent-file-change.yml new file mode 100644 index 0000000000..0af3a6cbf4 --- /dev/null +++ b/.github/workflows/prevent-file-change.yml @@ -0,0 +1,17 @@ +name: prevent-file-change + +on: + pull_request: + +jobs: + check-file-changes: + runs-on: ubuntu-latest + steps: + - name: Prevent file change + uses: xalvarez/prevent-file-change-action@v1 + with: + githubToken: ${{ secrets.GITHUB_TOKEN }} + # Regex, /src/lang/*.json is not allowed to be changed, except for /src/lang/en.json + pattern: '^(?!src/lang/en\.json$)src/lang/.*\.json$' + trustedAuthors: UptimeKumaBot + diff --git a/.github/workflows/stale-bot.yml b/.github/workflows/stale-bot.yml index 8238be0acc..60eca64030 100644 --- a/.github/workflows/stale-bot.yml +++ b/.github/workflows/stale-bot.yml @@ -1,4 +1,4 @@ -name: 'Automatically close stale issues and PRs' +name: 'Automatically close stale issues' on: workflow_dispatch: schedule: @@ -9,14 +9,34 @@ jobs: stale: runs-on: ubuntu-latest steps: - - uses: actions/stale@v8 + - uses: actions/stale@v9 with: - stale-issue-message: 'We are clearing up our old issues and your ticket has been open for 3 months with no activity. Remove stale label or comment or this will be closed in 2 days.' - close-issue-message: 'This issue was closed because it has been stalled for 2 days with no activity.' - days-before-stale: 90 - days-before-close: 2 - days-before-pr-stale: 999999999 - days-before-pr-close: 1 + stale-issue-message: |- + We are clearing up our old `help`-issues and your issue has been open for 60 days with no activity. + If no comment is made and the stale label is not removed, this issue will be closed in 7 days. + days-before-stale: 60 + days-before-close: 7 + days-before-pr-stale: -1 + days-before-pr-close: -1 exempt-issue-labels: 'News,Medium,High,discussion,bug,doc,feature-request' exempt-issue-assignees: 'louislam' operations-per-run: 200 + - uses: actions/stale@v9 + with: + stale-issue-message: |- + This issue was marked as `cannot-reproduce` by a maintainer. + If an issue is non-reproducible, we cannot fix it, as we do not know what the underlying issue is. + If you have any ideas how we can reproduce this issue, we would love to hear them. + + We don't have a good way to deal with truely unreproducible issues and are going to close this issue in a month. + If think there might be other differences in our environment or in how we tried to reproduce this, we would appreciate any ideas. + close-issue-message: |- + This issue will be closed as no way to reproduce it has been found. + If you/somebody finds a way how to (semi-reliably) reproduce this, we can reopen this issue. ^^ + days-before-stale: 180 + days-before-close: 30 + days-before-pr-stale: -1 + days-before-pr-close: -1 + any-of-issue-labels: 'cannot-reproduce' + operations-per-run: 200 + diff --git a/.github/workflows/json-yaml-validate.yml b/.github/workflows/validate.yml similarity index 58% rename from .github/workflows/json-yaml-validate.yml rename to .github/workflows/validate.yml index b6437ec496..7e631ccd44 100644 --- a/.github/workflows/json-yaml-validate.yml +++ b/.github/workflows/validate.yml @@ -1,4 +1,4 @@ -name: json-yaml-validate +name: validate on: push: branches: @@ -25,3 +25,19 @@ jobs: with: comment: "true" # enable comment mode exclude_file: ".github/config/exclude.txt" # gitignore style file for exclusions + + # General validations + validate: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - name: Use Node.js 20 + uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Validate language JSON files + run: node ./extra/check-lang-json.js + + - name: Validate knex migrations filename + run: node ./extra/check-knex-filenames.mjs diff --git a/.gitignore b/.gitignore index 009b15f104..b11a793542 100644 --- a/.gitignore +++ b/.gitignore @@ -7,6 +7,7 @@ dist-ssr /data !/data/.gitkeep +/data* .vscode /private @@ -14,9 +15,6 @@ dist-ssr /tmp .env -cypress/videos -cypress/screenshots - /extra/healthcheck.exe /extra/healthcheck /extra/healthcheck-armv7 diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d94eb71db8..2e10be48ca 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,92 +1,216 @@ # Project Info -First of all, I want to thank everyone who made pull requests for Uptime Kuma. I never thought the GitHub Community would be so nice! Because of this, I also never thought that other people would actually read and edit my code. It is not very well structured or commented, sorry about that. +First of all, I want to thank everyone who has submitted issues or shared pull requests for Uptime Kuma. +I never thought the GitHub community would be so nice! +Because of this, I also never thought that other people would actually read and edit my code. +Parts of the code are not very well-structured or commented, sorry about that. -The project was created with vite.js (vue3). Then I created a subdirectory called "server" for the server part. Both frontend and backend share the same package.json. +The project was created with `vite.js` and is written in `vue3`. +Our backend lives in the `server`-directory and mostly communicates via websockets. +Both frontend and backend share the same `package.json`. -The frontend code builds into "dist" directory. The server (express.js) exposes the "dist" directory as the root of the endpoint. This is how production is working. - -## Key Technical Skills - -- Node.js (You should know about promise, async/await and arrow function etc.) -- Socket.io -- SCSS -- Vue.js -- Bootstrap -- SQLite +For production, the frontend is built into the `dist`-directory and the server (`express.js`) exposes the `dist` directory as the root of the endpoint. +For development, we run vite in development mode on another port. ## Directories -- config (dev config files) -- data (App data) -- db (Base database and migration scripts) -- dist (Frontend build) -- docker (Dockerfiles) -- extra (Extra useful scripts) -- public (Frontend resources for dev only) -- server (Server source code) -- src (Frontend source code) -- test (unit test) +- `config` (dev config files) +- `data` (App data) +- `db` (Base database and migration scripts) +- `dist` (Frontend build) +- `docker` (Dockerfiles) +- `extra` (Extra useful scripts) +- `public` (Frontend resources for dev only) +- `server` (Server source code) +- `src` (Frontend source code) +- `test` (unit test) ## Can I create a pull request for Uptime Kuma? -Yes or no, it depends on what you will try to do. Since I don't want to waste your time, be sure to **create an empty draft pull request or open an issue, so we can have a discussion first**. Especially for a large pull request or you don't know if it will be merged or not. - -Here are some references: - -### ✅ Usually accepted: -- Bug fix -- Security fix -- Adding notification providers -- Adding new language files (see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md)) -- Adding new language keys: `$t("...")` +Yes or no, it depends on what you will try to do. +Both yours and our maintainers' time is precious, and we don't want to waste either. + +If you have any questions about any process/.. is not clear, you are likely not alone => please ask them ^^ + +Different guidelines exist for different types of pull requests (PRs): +-
security fixes +

+ + Submitting security fixes is something that may put the community at risk. + Please read through our [security policy](SECURITY.md) and submit vulnerabilities via an [advisory](https://github.com/louislam/uptime-kuma/security/advisories/new) + [issue](https://github.com/louislam/uptime-kuma/issues/new?assignees=&labels=help&template=security.md) instead. + We encourage you to submit how to fix a vulnerability if you know how to, this is not required. + Following the security policy allows us to properly test, fix bugs. + This review allows us to notice, if there are any changes necessary to unrelated parts like the documentation. + [**PLEASE SEE OUR SECURITY POLICY.**](SECURITY.md) + +

+
+-
small, non-breaking bug fixes +

+ + If you come across a bug and think you can solve, we appreciate your work. + Please make sure that you follow these rules: + - keep the PR as small as possible, fix only one thing at a time => keeping it reviewable + - test that your code does what you claim it does. + + Because maintainer time is precious, junior maintainers may merge uncontroversial PRs in this area. +

+
+-
translations / internationalisation (i18n) +

+ + We use weblate to localise this project into many languages. + If you are unhappy with a translation this is the best start. + On how to translate using weblate, please see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md). + + There are two cases in which a change cannot be done in weblate and requires a PR: + - A text may not be currently localisable. In this case, **adding a new language key** via `$t("languageKey")` might be nessesary + - language keys need to be **added to `en.json`** to be visible in weblate. If this has not happened, a PR is appreciated. + - **Adding a new language** requires a new file see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md) + + Because maintainer time is precious, junior maintainers may merge uncontroversial PRs in this area. +

+
+-
new notification providers +

+ + To set up a new notification provider these files need to be modified/created: + - `server/notification-providers/PROVIDER_NAME.js` is where the heart of the notification provider lives. + - Both `monitorJSON` and `heartbeatJSON` can be `null` for some events. + If both are `null`, this is a general testing message, but if just `heartbeatJSON` is `null` this is a certificate expiry. + - Please wrap the axios call into a + ```js + try { + let result = await axios.post(...); + if (result.status === ...) ... + } catch (error) { + this.throwGeneralAxiosError(error); + } + ``` + - `server/notification.js` is where the backend of the notification provider needs to be registered. + *If you have an idea how we can skip this step, we would love to hear about it ^^* + - `src/components/NotificationDialog.vue` you need to decide if the provider is a regional or a global one and add it with a name to the respective list + - `src/components/notifications/PROVIDER_NAME.vue` is where the frontend of each provider lives. + Please make sure that you have: + - used `HiddenInput` for secret credentials + - included all the necessary helptexts/placeholder/.. to make sure the notification provider is simple to setup for new users. + - include all translations (`{{ $t("Translation key") }}`, [`i18n-t keypath="Translation key">`](https://vue-i18n.intlify.dev/guide/advanced/component.html)) in `src/lang/en.json` to enable our translators to translate this + - `src/components/notifications/index.js` is where the frontend of the provider needs to be registered. + *If you have an idea how we can skip this step, we would love to hear about it ^^* + + Offering notifications is close to the core of what we are as an uptime monitor. + Therefore, making sure that they work is also really important. + Because testing notification providers is quite time intensive, we mostly offload this onto the person contributing a notification provider. + + To make sure you have tested the notification provider, please include screenshots of the following events in the pull-request description: + - `UP`/`DOWN` + - Certificate Expiry via https://expired.badssl.com/ + - Testing (the test button on the notification provider setup page) + + Using the following way to format this is encouraged: + ```md + | Event | Before | After | + ------------------ + | `UP` | paste-image-here | paste-image-here | + | `DOWN` | paste-image-here | paste-image-here | + | Certificate-expiry | paste-image-here | paste-image-here | + | Testing | paste-image-here | paste-image-here | + ``` + + Because maintainer time is precious, junior maintainers may merge uncontroversial PRs in this area. +

+
+-
new monitoring types +

+ + To set up a new notification provider these files need to be modified/created: + - `server/monitor-types/MONITORING_TYPE.js` is the core of each monitor. + the `async check(...)`-function should: + - throw an error for each fault that is detected with an actionable error message + - in the happy-path, you should set `heartbeat.msg` to a successful message and set `heartbeat.status = UP` + - `server/uptime-kuma-server.js` is where the monitoring backend needs to be registered. + *If you have an idea how we can skip this step, we would love to hear about it ^^* + - `src/pages/EditMonitor.vue` is the shared frontend users interact with. + Please make sure that you have: + - used `HiddenInput` for secret credentials + - included all the necessary helptexts/placeholder/.. to make sure the notification provider is simple to setup for new users. + - include all translations (`{{ $t("Translation key") }}`, [`i18n-t keypath="Translation key">`](https://vue-i18n.intlify.dev/guide/advanced/component.html)) in `src/lang/en.json` to enable our translators to translate this + - + + + Because maintainer time is precious, junior maintainers may merge uncontroversial PRs in this area. +

+
+-
new features/ major changes / breaking bugfixes +

+ + be sure to **create an empty draft pull request or open an issue, so we can have a discussion first**. + This is especially important for a large pull request or when you don't know if it will be merged or not. + + Because of the large impact of this work, only senior maintainers may merge PRs in this area. +

+
+ +The following rules are essential for making your PR mergable: +- Merging multiple issues by a huge PR is more difficult to review and causes conflicts with other PRs. Please + - (if possible) **create one PR for one issue** or + - (if not possible) **explain which issues a PR addresses and why this PR should not be broken apart** +- Make sure your **PR passes our continuous integration**. + PRs will not be merged unless all CI-Checks are green. +- **Breaking changes** (unless for a good reason and discussed beforehand) will not get merged / not get merged quickly. + Such changes require a major version release. +- **Test your code** before submitting a PR. + Buggy PRs will not be merged. +- Make sure the **UI/UX is close to Uptime Kuma**. +- **Think about the maintainability**: + Don't add functionality that is completely **out of scope**. + Keep in mind that we need to be able to maintain the functionality. +- Don't modify or delete existing logic without a valid reason. +- Don't convert existing code into other programming languages for no reason. + +I ([@louislam](https://github.com/louislam)) have the final say. +If your pull request does not meet my expectations, I will reject it, no matter how much time you spent on it. +Therefore, it is essential to have a discussion beforehand. -### ⚠️ Discussion required: -- Large pull requests -- New features - -### ❌ Won't be merged: -- A dedicated PR for translating existing languages (see [these instructions](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md)) -- Do not pass the auto-test -- Any breaking changes -- Duplicated pull requests -- Buggy -- UI/UX is not close to Uptime Kuma -- Modifications or deletions of existing logic without a valid reason. -- Adding functions that is completely out of scope -- Converting existing code into other programming languages -- Unnecessarily large code changes that are hard to review and cause conflicts with other PRs. - -The above cases may not cover all possible situations. +I will assign your pull request to a [milestone](https://github.com/louislam/uptime-kuma/milestones), if I plan to review and merge it. -I (@louislam) have the final say. If your pull request does not meet my expectations, I will reject it, no matter how much time you spend on it. Therefore, it is essential to have a discussion beforehand. +Please don't rush or ask for an ETA. +We have to understand the pull request, make sure it has no breaking changes and stick to the vision of this project, especially for large pull requests. -I will assign your pull request to a [milestone](https://github.com/louislam/uptime-kuma/milestones), if I plan to review and merge it. -Also, please don't rush or ask for an ETA, because I have to understand the pull request, make sure it is no breaking changes and stick to my vision of this project, especially for large pull requests. +## I'd like to work on an issue. How do I do that? +We have found that assigning people to issues is management-overhead that we don't need. +A short comment that you want to try your hand at this issue is appreciated to save other devs time. +If you come across any problem during development, feel free to leave a comment with what you are stuck on. ### Recommended Pull Request Guideline -Before deep into coding, discussion first is preferred. Creating an empty pull request for discussion would be recommended. +Before diving deep into coding, having a discussion first by creating an empty pull request for discussion is preferred. +The rationale behind this is that we can align the direction and scope of the feature to eliminate any conflicts with existing and planned work, and can help by pointing out any potential pitfalls. 1. Fork the project -1. Clone your fork repo to local -1. Create a new branch -1. Create an empty commit - `git commit -m "[empty commit] pull request for " --allow-empty` -1. Push to your fork repo -1. Create a pull request: https://github.com/louislam/uptime-kuma/compare -1. Write a proper description -1. Click "Change to draft" -1. Discussion +2. Clone your fork repo to local +3. Create a new branch +4. Create an empty commit: `git commit -m "" --allow-empty` +5. Push to your fork repo +6. Prepare a pull request: https://github.com/louislam/uptime-kuma/compare +7. Write a proper description. You can mention @louislam in it, so @louislam will get the notification. +8. Create your pull request as a Draft +9. Wait for the discussion ## Project Styles -I personally do not like something that requires so many configurations before you can finally start the app. I hope Uptime Kuma installation will be as easy as like installing a mobile app. +I personally do not like something that requires a lot of configuration before you can finally start the app. +The goal is to make the Uptime Kuma installation as easy as installing a mobile app. -- Easy to install for non-Docker users, no native build dependency is needed (for x86_64/armv7/arm64), no extra config, and no extra effort required to get it running -- Single container for Docker users, no very complex docker-compose file. Just map the volume and expose the port, then good to go +- Easy to install for non-Docker users + - no native build dependency is needed (for `x86_64`/`armv7`/`arm64`) + - no extra configuration and + - no extra effort required to get it running +- Single container for Docker users + - no complex docker-compose file + - mapping the volume and exposing the port should be the only requirements - Settings should be configurable in the frontend. Environment variables are discouraged, unless it is related to startup such as `DATA_DIR` - Easy to use - The web UI styling should be consistent and nice @@ -106,12 +230,18 @@ I personally do not like something that requires so many configurations before y ## Tools -- [`Node.js`](https://nodejs.org/) >= 14 -- [`npm`](https://www.npmjs.com/) >= 8.5 +- [`Node.js`](https://nodejs.org/) >= 18 +- [`npm`](https://www.npmjs.com/) >= 9.3 - [`git`](https://git-scm.com/) - IDE that supports [`ESLint`](https://eslint.org/) and EditorConfig (I am using [`IntelliJ IDEA`](https://www.jetbrains.com/idea/)) - A SQLite GUI tool (f.ex. [`SQLite Expert Personal`](https://www.sqliteexpert.com/download.html) or [`DBeaver Community`](https://dbeaver.io/download/)) +## Git Branches + +- `master`: 2.X.X development. If you want to add a new feature, your pull request should base on this. +- `1.23.X`: 1.23.X development. If you want to fix a bug for v1 and v2, your pull request should base on this. +- All other branches are unused, outdated or for dev. + ## Install Dependencies for Development ```bash @@ -130,8 +260,9 @@ Port `3000` and port `3001` will be used. npm run dev ``` -But sometimes, you would like to restart the server, but not the frontend, you can run these commands in two terminals: -``` +But sometimes you may want to restart the server without restarting the frontend. In that case, you can run these commands in two terminals: + +```bash npm run start-frontend-dev npm run start-server-dev ``` @@ -140,32 +271,31 @@ npm run start-server-dev It binds to `0.0.0.0:3001` by default. +The backend is an `express.js` server with `socket.io` integrated. +It uses `socket.io` to communicate with clients, and most server logic is encapsulated in the `socket.io` handlers. +`express.js` is also used to serve: -It is mainly a socket.io app + express.js. - -express.js is used for: -- entry point such as redirecting to a status page or the dashboard -- serving the frontend built files (index.html, .js and .css etc.) -- serving internal APIs of the status page +- as an entry point for redirecting to a status page or the dashboard +- the frontend built files (`index.html`, `*.js`, `*.css`, etc.) +- internal APIs of the status page +### Structure in `/server/` -### Structure in /server/ - -- jobs/ (Jobs that are running in another process) -- model/ (Object model, auto-mapping to the database table name) -- modules/ (Modified 3rd-party modules) -- monitor_types (Monitor Types) -- notification-providers/ (individual notification logic) -- routers/ (Express Routers) -- socket-handler (Socket.io Handlers) -- server.js (Server entry point) -- uptime-kuma-server.js (UptimeKumaServer class, main logic should be here, but some still in `server.js`) +- `jobs/` (Jobs that are running in another process) +- `model/` (Object model, auto-mapping to the database table name) +- `modules/` (Modified 3rd-party modules) +- `monitor_types/` (Monitor Types) +- `notification-providers/` (individual notification logic) +- `routers/` (Express Routers) +- `socket-handler/` (Socket.io Handlers) +- `server.js` (Server entry point) +- `uptime-kuma-server.js` (UptimeKumaServer class, main logic should be here, but some still in `server.js`) ## Frontend Dev Server -It binds to `0.0.0.0:3000` by default. The frontend dev server is used for development only. +It binds to `0.0.0.0:3000` by default. The frontend dev server is used for development only. -For production, it is not used. It will be compiled to `dist` directory instead. +For production, it is not used. It will be compiled to `dist` directory instead. You can use Vue.js devtools Chrome extension for debugging. @@ -187,8 +317,7 @@ The data and socket logic are in `src/mixins/socket.js`. ## Database Migration -1. Create `patch-{name}.sql` in `./db/` -2. Add your patch filename in the `patchList` list in `./server/database.js` +See: https://github.com/louislam/uptime-kuma/tree/master/db/knex_migrations ## Unit Test @@ -199,14 +328,15 @@ npm test ## Dependencies -Both frontend and backend share the same package.json. However, the frontend dependencies are eventually not used in the production environment, because it is usually also baked into dist files. So: +Both frontend and backend share the same `package.json`. +However, the frontend dependencies are eventually not used in the production environment, because it is usually also baked into `dist` files. So: - Frontend dependencies = "devDependencies" - - Examples: vue, chart.js + - Examples: `vue`, `chart.js` - Backend dependencies = "dependencies" - - Examples: socket.io, sqlite3 + - Examples: `socket.io`, `sqlite3` - Development dependencies = "devDependencies" - - Examples: eslint, sass + - Examples: `eslint`, `sass` ### Update Dependencies @@ -218,9 +348,9 @@ If for security / bug / other reasons, a library must be updated, breaking chang ## Translations -Please add **all** the strings which are translatable to `src/lang/en.json` (If translation keys are omitted, they can not be translated). +Please add **all** the strings which are translatable to `src/lang/en.json` (if translation keys are omitted, they can not be translated.) -**Don't include any other languages in your initial Pull-Request** (even if this is your mother tongue), to avoid merge-conflicts between weblate and `master`. +**Don't include any other languages in your initial pull request** (even if this is your mother tongue), to avoid merge-conflicts between weblate and `master`. The translations can then (after merging a PR into `master`) be translated by awesome people donating their language skills. If you want to help by translating Uptime Kuma into your language, please visit the [instructions on how to translate using weblate](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md). @@ -232,55 +362,151 @@ My mother language is not English and my grammar is not that great. ## Wiki -Since there is no way to make a pull request to wiki's repo, I have set up another repo to do that. +Since there is no way to make a pull request to the wiki, I have set up another repo to do that. https://github.com/louislam/uptime-kuma-wiki -## Maintainer +## Docker -Check the latest issues and pull requests: -https://github.com/louislam/uptime-kuma/issues?q=sort%3Aupdated-desc +### Arch -### Release Procedures +- amd64 +- arm64 +- armv7 -1. Draft a release note -2. Make sure the repo is cleared -3. If the healthcheck is updated, remember to re-compile it: `npm run build-docker-builder-go` -3. `npm run release-final with env vars: `VERSION` and `GITHUB_TOKEN` -4. Wait until the `Press any key to continue` -5. `git push` -6. Publish the release note as 1.X.X -7. Press any key to continue -8. Deploy to the demo server: `npm run deploy-demo-server` +### Docker Tags -Checking: +#### v2 -- Check all tags is fine on https://hub.docker.com/r/louislam/uptime-kuma/tags -- Try the Docker image with tag 1.X.X (Clean install / amd64 / arm64 / armv7) -- Try clean installation with Node.js +- `2`, `latest-2`: v2 with full features such as Chromium and bundled MariaDB +- `2.x.x` +- `2-slim`: v2 with basic features +- `2.x.x-slim` +- `beta2`: Latest beta build +- `2.x.x-beta.x` +- `nightly2`: Dev build +- `base2`: Basic Debian setup without Uptime Kuma source code (Full features) +- `base2-slim`: Basic Debian setup without Uptime Kuma source code +- `pr-test2`: For testing pull request without setting up a local environment -### Release Beta Procedures +#### v1 -1. Draft a release note, check "This is a pre-release" -2. Make sure the repo is cleared -3. `npm run release-beta` with env vars: `VERSION` and `GITHUB_TOKEN` -4. Wait until the `Press any key to continue` -5. Publish the release note as 1.X.X-beta.X -6. Press any key to continue +- `1`, `latest`, `1-debian`, `debian`: Latest version of v1 +- `1.x.x`, `1.x.x-debian` +- `1.x.x-beta.x`: Beta build +- `beta`: Latest beta build +- `nightly`: Dev build +- `base-debian`: Basic Debian setup without Uptime Kuma source code +- `pr-test`: For testing pull request without setting up a local environment +- `base-alpine`: (Deprecated) Basic Alpine setup without Uptime Kuma source code +- `1-alpine`, `alpine`: (Deprecated) +- `1.x.x-alpine`: (Deprecated) -### Release Wiki - -#### Setup Repo - -```bash -git clone https://github.com/louislam/uptime-kuma-wiki.git -cd uptime-kuma-wiki -git remote add production https://github.com/louislam/uptime-kuma.wiki.git -``` +## Maintainer -#### Push to Production Wiki +Check the latest issues and pull requests: +https://github.com/louislam/uptime-kuma/issues?q=sort%3Aupdated-desc -```bash -git pull -git push production master -``` +### What is a maintainer and what are their roles? + +This project has multiple maintainers who specialise in different areas. +Currently, there are 3 maintainers: + +| Person | Role | Main Area | +|-------------------|-------------------|------------------| +| `@louislam` | senior maintainer | major features | +| `@chakflying` | junior maintainer | fixing bugs | +| `@commanderstorm` | junior maintainer | issue-management | + +### Procedures + +We have a few procedures we follow. These are documented here: +-
Set up a Docker Builder +

+ + - amd64, armv7 using local. + - arm64 using remote arm64 cpu, as the emulator is too slow and can no longer pass the `npm ci` command. + 1. Add the public key to the remote server. + 2. Add the remote context. The remote machine must be arm64 and installed Docker CE. + ``` + docker context create oracle-arm64-jp --docker "host=ssh://root@100.107.174.88" + ``` + 3. Create a new builder. + ``` + docker buildx create --name kuma-builder --platform linux/amd64,linux/arm/v7 + docker buildx use kuma-builder + docker buildx inspect --bootstrap + ``` + 4. Append the remote context to the builder. + ``` + docker buildx create --append --name kuma-builder --platform linux/arm64 oracle-arm64-jp + ``` + 5. Verify the builder and check if the builder is using `kuma-builder`. + ``` + docker buildx inspect kuma-builder + docker buildx ls + ``` +

+
+-
Release +

+ + 1. Draft a release note + 2. Make sure the repo is cleared + 3. If the healthcheck is updated, remember to re-compile it: `npm run build-docker-builder-go` + 4. `npm run release-final` with env vars: `VERSION` and `GITHUB_TOKEN` + 5. Wait until the `Press any key to continue` + 6. `git push` + 7. Publish the release note as `1.X.X` + 8. Press any key to continue + 9. Deploy to the demo server: `npm run deploy-demo-server` + + These Items need to be checked: + + - [ ] Check all tags is fine on https://hub.docker.com/r/louislam/uptime-kuma/tags + - [ ] Try the Docker image with tag 1.X.X (Clean install / amd64 / arm64 / armv7) + - [ ] Try clean installation with Node.js + +

+
+-
Release Beta +

+ + 1. Draft a release note, check `This is a pre-release` + 2. Make sure the repo is cleared + 3. `npm run release-beta` with env vars: `VERSION` and `GITHUB_TOKEN` + 4. Wait until the `Press any key to continue` + 5. Publish the release note as `1.X.X-beta.X` + 6. Press any key to continue + +

+
+-
Release Wiki +

+ + **Setup Repo** + + ```bash + git clone https://github.com/louislam/uptime-kuma-wiki.git + cd uptime-kuma-wiki + git remote add production https://github.com/louislam/uptime-kuma.wiki.git + ``` + + **Push to Production Wiki** + + ```bash + git pull + git push production master + ``` + +

+
+-
Change the base of a pull request such as master to 1.23.X +

+ + ```bash + git rebase --onto + ``` + +

+
diff --git a/README.md b/README.md index 54b6892af2..1b4c885d0c 100644 --- a/README.md +++ b/README.md @@ -6,7 +6,7 @@ Uptime Kuma is an easy-to-use self-hosted monitoring tool. - + [![GitHub Sponsors](https://img.shields.io/github/sponsors/louislam?label=GitHub%20Sponsors)](https://github.com/sponsors/louislam) Translation status @@ -17,23 +17,23 @@ Uptime Kuma is an easy-to-use self-hosted monitoring tool. Try it! -- Tokyo Demo Server: https://demo.uptime.kuma.pet (Sponsored by [Uptime Kuma Sponsors](https://github.com/louislam/uptime-kuma#%EF%B8%8F-sponsors)) +Demo Server (Location: Frankfurt - Germany): https://demo.kuma.pet/start-demo -It is a temporary live demo, all data will be deleted after 10 minutes. Use the one that is closer to you, but I suggest that you should install and try it out for the best demo experience. +It is a temporary live demo, all data will be deleted after 10 minutes. Sponsored by [Uptime Kuma Sponsors](https://github.com/louislam/uptime-kuma#%EF%B8%8F-sponsors). ## ⭐ Features -* Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers -* Fancy, Reactive, Fast UI/UX -* Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications) -* 20-second intervals -* [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/lang) -* Multiple status pages -* Map status pages to specific domains -* Ping chart -* Certificate info -* Proxy support -* 2FA support +- Monitoring uptime for HTTP(s) / TCP / HTTP(s) Keyword / HTTP(s) Json Query / Ping / DNS Record / Push / Steam Game Server / Docker Containers +- Fancy, Reactive, Fast UI/UX +- Notifications via Telegram, Discord, Gotify, Slack, Pushover, Email (SMTP), and [90+ notification services, click here for the full list](https://github.com/louislam/uptime-kuma/tree/master/src/components/notifications) +- 20-second intervals +- [Multi Languages](https://github.com/louislam/uptime-kuma/tree/master/src/lang) +- Multiple status pages +- Map status pages to specific domains +- Ping chart +- Certificate info +- Proxy support +- 2FA support ## 🔧 How to Install @@ -43,26 +43,32 @@ It is a temporary live demo, all data will be deleted after 10 minutes. Use the docker run -d --restart=always -p 3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1 ``` -⚠️ Please use a **local volume** only. Other types such as NFS are not supported. +Uptime Kuma is now running on . -Uptime Kuma is now running on http://localhost:3001 +> [!WARNING] +> File Systems like **NFS** (Network File System) are **NOT** supported. Please map to a local directory or volume. + +> [!NOTE] +> If you want to limit exposure to localhost (without exposing port for other users or to use a [reverse proxy](https://github.com/louislam/uptime-kuma/wiki/Reverse-Proxy)), you can expose the port like this: +> +> ```bash +> docker run -d --restart=always -p 127.0.0.1:3001:3001 -v uptime-kuma:/app/data --name uptime-kuma louislam/uptime-kuma:1 +> ``` ### 💪🏻 Non-Docker Requirements: + - Platform - ✅ Major Linux distros such as Debian, Ubuntu, CentOS, Fedora and ArchLinux etc. - ✅ Windows 10 (x64), Windows Server 2012 R2 (x64) or higher - ❌ Replit / Heroku -- [Node.js](https://nodejs.org/en/download/) 14 / 16 / 18 / 20.4 -- [npm](https://docs.npmjs.com/cli/) >= 7 +- [Node.js](https://nodejs.org/en/download/) 18 / 20.4 +- [npm](https://docs.npmjs.com/cli/) 9 - [Git](https://git-scm.com/downloads) - [pm2](https://pm2.keymetrics.io/) - For running Uptime Kuma in the background ```bash -# Update your npm to the latest version -npm install npm -g - git clone https://github.com/louislam/uptime-kuma.git cd uptime-kuma npm run setup @@ -76,9 +82,8 @@ npm install pm2 -g && pm2 install pm2-logrotate # Start Server pm2 start server/server.js --name uptime-kuma - - ``` + Uptime Kuma is now running on http://localhost:3001 More useful PM2 Commands @@ -91,10 +96,6 @@ pm2 monit pm2 save && pm2 startup ``` -### Windows Portable (x64) - -https://github.com/louislam/uptime-kuma/releases/download/1.23.1/uptime-kuma-windows-x64-portable-1.23.1.zip - ### Advanced Installation If you need more options or need to browse via a reverse proxy, please read: @@ -113,10 +114,6 @@ I will assign requests/issues to the next milestone. https://github.com/louislam/uptime-kuma/milestones -Project Plan: - -https://github.com/users/louislam/projects/4/views/1 - ## ❤️ Sponsors Thank you so much! (GitHub Sponsors will be updated manually. OpenCollective sponsors will be updated automatically, the list will be cached by GitHub though. It may need some time to be updated) @@ -143,29 +140,33 @@ Telegram Notification Sample: ## Motivation -* I was looking for a self-hosted monitoring tool like "Uptime Robot", but it is hard to find a suitable one. One of the close ones is statping. Unfortunately, it is not stable and no longer maintained. -* Want to build a fancy UI. -* Learn Vue 3 and vite.js. -* Show the power of Bootstrap 5. -* Try to use WebSocket with SPA instead of REST API. -* Deploy my first Docker image to Docker Hub. +- I was looking for a self-hosted monitoring tool like "Uptime Robot", but it is hard to find a suitable one. One of the closest ones is statping. Unfortunately, it is not stable and no longer maintained. +- Wanted to build a fancy UI. +- Learn Vue 3 and vite.js. +- Show the power of Bootstrap 5. +- Try to use WebSocket with SPA instead of a REST API. +- Deploy my first Docker image to Docker Hub. -If you love this project, please consider giving me a ⭐. +If you love this project, please consider giving it a ⭐. ## 🗣️ Discussion / Ask for Help -⚠️ For any general or technical questions, please don't send me an email, as I am unable to provide support in that manner. I will not response if you asked such questions. +⚠️ For any general or technical questions, please don't send me an email, as I am unable to provide support in that manner. I will not respond if you ask questions there. -I recommend using Google, GitHub Issues, or Uptime Kuma's Subreddit for finding answers to your question. If you cannot find the information you need, feel free to ask: +I recommend using Google, GitHub Issues, or Uptime Kuma's subreddit for finding answers to your question. If you cannot find the information you need, feel free to ask: - [GitHub Issues](https://github.com/louislam/uptime-kuma/issues) -- [Subreddit r/Uptime kuma](https://www.reddit.com/r/UptimeKuma/) +- [Subreddit (r/UptimeKuma)](https://www.reddit.com/r/UptimeKuma/) -My Reddit account: [u/louislamlam](https://reddit.com/u/louislamlam). -You can mention me if you ask a question on Reddit. +My Reddit account: [u/louislamlam](https://reddit.com/u/louislamlam) +You can mention me if you ask a question on the subreddit. +## Contributions + +### Create Pull Requests -## Contribute +We DO NOT accept all types of pull requests and do not want to waste your time. Please be sure that you have read and follow pull request rules: +[CONTRIBUTING.md#can-i-create-a-pull-request-for-uptime-kuma](https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md#can-i-create-a-pull-request-for-uptime-kuma) ### Test Pull Requests @@ -179,15 +180,16 @@ https://github.com/louislam/uptime-kuma/wiki/Test-Pull-Requests Check out the latest beta release here: https://github.com/louislam/uptime-kuma/releases ### Bug Reports / Feature Requests + If you want to report a bug or request a new feature, feel free to open a [new issue](https://github.com/louislam/uptime-kuma/issues). ### Translations + If you want to translate Uptime Kuma into your language, please visit [Weblate Readme](https://github.com/louislam/uptime-kuma/blob/master/src/lang/README.md). -## Spelling & Grammar +### Spelling & Grammar Feel free to correct the grammar in the documentation or code. -My mother language is not english and my grammar is not that great. +My mother language is not English and my grammar is not that great. + -### Create Pull Requests -If you want to modify Uptime Kuma, please read this guide and follow the rules here: https://github.com/louislam/uptime-kuma/blob/master/CONTRIBUTING.md diff --git a/SECURITY.md b/SECURITY.md index db4bc138f0..72b4fc0f19 100644 --- a/SECURITY.md +++ b/SECURITY.md @@ -3,7 +3,7 @@ ## Reporting a Vulnerability 1. Please report security issues to https://github.com/louislam/uptime-kuma/security/advisories/new. -1. Please also create an empty security issue to alert me, as GitHub Advisories do not send a notification, I probably will miss it without this. https://github.com/louislam/uptime-kuma/issues/new?assignees=&labels=help&template=security.md +2. Please also create an empty security issue to alert me, as GitHub Advisories do not send a notification, I probably will miss it without this. https://github.com/louislam/uptime-kuma/issues/new?assignees=&labels=help&template=security.md Do not use the public issue tracker or discuss it in public as it will cause more damage. @@ -19,12 +19,12 @@ You should use or upgrade to the latest version of Uptime Kuma. All `1.X.X` vers ### Upgradable Docker Tags -| Tag | Supported | -| ------- | ------------------ | +| Tag | Supported | +|-|-| | 1 | :white_check_mark: | | 1-debian | :white_check_mark: | | latest | :white_check_mark: | | debian | :white_check_mark: | | 1-alpine | ⚠️ Deprecated | | alpine | ⚠️ Deprecated | -| All other tags | ❌ | +| All other tags | ❌ | diff --git a/babel.config.js b/babel.config.js deleted file mode 100644 index d4c895475c..0000000000 --- a/babel.config.js +++ /dev/null @@ -1,7 +0,0 @@ -const config = {}; - -if (process.env.TEST_FRONTEND) { - config.presets = [ "@babel/preset-env" ]; -} - -module.exports = config; diff --git a/compose.yaml b/compose.yaml new file mode 100644 index 0000000000..004705a636 --- /dev/null +++ b/compose.yaml @@ -0,0 +1,9 @@ +services: + uptime-kuma: + image: louislam/uptime-kuma:1 + volumes: + - ./data:/app/data + ports: + # : + - 3001:3001 + restart: unless-stopped diff --git a/config/cypress.config.js b/config/cypress.config.js deleted file mode 100644 index 26784e8823..0000000000 --- a/config/cypress.config.js +++ /dev/null @@ -1,28 +0,0 @@ -const { defineConfig } = require("cypress"); - -module.exports = defineConfig({ - projectId: "vyjuem", - e2e: { - experimentalStudio: true, - setupNodeEvents(on, config) { - - }, - fixturesFolder: "test/cypress/fixtures", - screenshotsFolder: "test/cypress/screenshots", - videosFolder: "test/cypress/videos", - downloadsFolder: "test/cypress/downloads", - supportFile: "test/cypress/support/e2e.js", - baseUrl: "http://localhost:3002", - defaultCommandTimeout: 10000, - pageLoadTimeout: 60000, - viewportWidth: 1920, - viewportHeight: 1080, - specPattern: [ - "test/cypress/e2e/setup.cy.js", - "test/cypress/e2e/**/*.js" - ], - }, - env: { - baseUrl: "http://localhost:3002", - }, -}); diff --git a/config/cypress.frontend.config.js b/config/cypress.frontend.config.js deleted file mode 100644 index eecdcb8dd9..0000000000 --- a/config/cypress.frontend.config.js +++ /dev/null @@ -1,10 +0,0 @@ -const { defineConfig } = require("cypress"); - -module.exports = defineConfig({ - e2e: { - supportFile: false, - specPattern: [ - "test/cypress/unit/**/*.js" - ], - } -}); diff --git a/config/playwright.config.js b/config/playwright.config.js new file mode 100644 index 0000000000..5c574eecc7 --- /dev/null +++ b/config/playwright.config.js @@ -0,0 +1,66 @@ +import { defineConfig, devices } from "@playwright/test"; + +const port = 30001; +export const url = `http://localhost:${port}`; + +export default defineConfig({ + // Look for test files in the "tests" directory, relative to this configuration file. + testDir: "../test/e2e/specs", + outputDir: "../private/playwright-test-results", + fullyParallel: false, + locale: "en-US", + + // Fail the build on CI if you accidentally left test.only in the source code. + forbidOnly: !!process.env.CI, + + // Retry on CI only. + retries: process.env.CI ? 2 : 0, + + // Opt out of parallel tests on CI. + workers: 1, + + // Reporter to use + reporter: [ + [ + "html", { + outputFolder: "../private/playwright-report", + open: "never", + } + ], + ], + + use: { + // Base URL to use in actions like `await page.goto('/')`. + baseURL: url, + + // Collect trace when retrying the failed test. + trace: "on-first-retry", + }, + + // Configure projects for major browsers. + projects: [ + { + name: "run-once setup", + testMatch: /setup-process\.once\.js/, + use: { ...devices["Desktop Chrome"] }, + }, + { + name: "specs", + use: { ...devices["Desktop Chrome"] }, + dependencies: [ "run-once setup" ], + }, + /* + { + name: "firefox", + use: { browserName: "firefox" } + },*/ + ], + + // Run your local dev server before starting the tests. + webServer: { + command: `node extra/remove-playwright-test-data.js && cross-env NODE_ENV=development node server/server.js --port=${port} --data-dir=./data/playwright-test`, + url, + reuseExistingServer: false, + cwd: "../", + }, +}); diff --git a/config/vite.config.js b/config/vite.config.js index 8aaa7d02c1..7f2dfb6ff1 100644 --- a/config/vite.config.js +++ b/config/vite.config.js @@ -1,8 +1,8 @@ -import legacy from "@vitejs/plugin-legacy"; import vue from "@vitejs/plugin-vue"; import { defineConfig } from "vite"; import visualizer from "rollup-plugin-visualizer"; import viteCompression from "vite-plugin-compression"; +import VueDevTools from "vite-plugin-vue-devtools"; const postCssScss = require("postcss-scss"); const postcssRTLCSS = require("postcss-rtlcss"); @@ -16,15 +16,10 @@ export default defineConfig({ }, define: { "FRONTEND_VERSION": JSON.stringify(process.env.npm_package_version), - "DEVCONTAINER": JSON.stringify(process.env.DEVCONTAINER), - "GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN": JSON.stringify(process.env.GITHUB_CODESPACES_PORT_FORWARDING_DOMAIN), - "CODESPACE_NAME": JSON.stringify(process.env.CODESPACE_NAME), + "process.env": {}, }, plugins: [ vue(), - legacy({ - targets: [ "since 2015" ], - }), visualizer({ filename: "tmp/dist-stats.html" }), @@ -36,6 +31,7 @@ export default defineConfig({ algorithm: "brotliCompress", filter: viteCompressionFilter, }), + VueDevTools(), ], css: { postcss: { diff --git a/db/knex_init_db.js b/db/knex_init_db.js new file mode 100644 index 0000000000..46bff4bfa6 --- /dev/null +++ b/db/knex_init_db.js @@ -0,0 +1,565 @@ +const { R } = require("redbean-node"); +const { log } = require("../src/util"); + +/** + * ⚠️⚠️⚠️⚠️⚠️⚠️ DO NOT ADD ANYTHING HERE! + * IF YOU NEED TO ADD FIELDS, ADD IT TO ./db/knex_migrations + * See ./db/knex_migrations/README.md for more information + * @returns {Promise} + */ +async function createTables() { + log.info("mariadb", "Creating basic tables for MariaDB"); + const knex = R.knex; + + // TODO: Should check later if it is really the final patch sql file. + + // docker_host + await knex.schema.createTable("docker_host", (table) => { + table.increments("id"); + table.integer("user_id").unsigned().notNullable(); + table.string("docker_daemon", 255); + table.string("docker_type", 255); + table.string("name", 255); + }); + + // group + await knex.schema.createTable("group", (table) => { + table.increments("id"); + table.string("name", 255).notNullable(); + table.datetime("created_date").notNullable().defaultTo(knex.fn.now()); + table.boolean("public").notNullable().defaultTo(false); + table.boolean("active").notNullable().defaultTo(true); + table.integer("weight").notNullable().defaultTo(1000); + table.integer("status_page_id").unsigned(); + }); + + // proxy + await knex.schema.createTable("proxy", (table) => { + table.increments("id"); + table.integer("user_id").unsigned().notNullable(); + table.string("protocol", 10).notNullable(); + table.string("host", 255).notNullable(); + table.smallint("port").notNullable(); // TODO: Maybe a issue with MariaDB, need migration to int + table.boolean("auth").notNullable(); + table.string("username", 255).nullable(); + table.string("password", 255).nullable(); + table.boolean("active").notNullable().defaultTo(true); + table.boolean("default").notNullable().defaultTo(false); + table.datetime("created_date").notNullable().defaultTo(knex.fn.now()); + + table.index("user_id", "proxy_user_id"); + }); + + // user + await knex.schema.createTable("user", (table) => { + table.increments("id"); + table.string("username", 255).notNullable().unique().collate("utf8_general_ci"); + table.string("password", 255); + table.boolean("active").notNullable().defaultTo(true); + table.string("timezone", 150); + table.string("twofa_secret", 64); + table.boolean("twofa_status").notNullable().defaultTo(false); + table.string("twofa_last_token", 6); + }); + + // monitor + await knex.schema.createTable("monitor", (table) => { + table.increments("id"); + table.string("name", 150); + table.boolean("active").notNullable().defaultTo(true); + table.integer("user_id").unsigned() + .references("id").inTable("user") + .onDelete("SET NULL") + .onUpdate("CASCADE"); + table.integer("interval").notNullable().defaultTo(20); + table.text("url"); + table.string("type", 20); + table.integer("weight").defaultTo(2000); + table.string("hostname", 255); + table.integer("port"); + table.datetime("created_date").notNullable().defaultTo(knex.fn.now()); + table.string("keyword", 255); + table.integer("maxretries").notNullable().defaultTo(0); + table.boolean("ignore_tls").notNullable().defaultTo(false); + table.boolean("upside_down").notNullable().defaultTo(false); + table.integer("maxredirects").notNullable().defaultTo(10); + table.text("accepted_statuscodes_json").notNullable().defaultTo("[\"200-299\"]"); + table.string("dns_resolve_type", 5); + table.string("dns_resolve_server", 255); + table.string("dns_last_result", 255); + table.integer("retry_interval").notNullable().defaultTo(0); + table.string("push_token", 20).defaultTo(null); + table.text("method").notNullable().defaultTo("GET"); + table.text("body").defaultTo(null); + table.text("headers").defaultTo(null); + table.text("basic_auth_user").defaultTo(null); + table.text("basic_auth_pass").defaultTo(null); + table.integer("docker_host").unsigned() + .references("id").inTable("docker_host"); + table.string("docker_container", 255); + table.integer("proxy_id").unsigned() + .references("id").inTable("proxy"); + table.boolean("expiry_notification").defaultTo(true); + table.text("mqtt_topic"); + table.string("mqtt_success_message", 255); + table.string("mqtt_username", 255); + table.string("mqtt_password", 255); + table.string("database_connection_string", 2000); + table.text("database_query"); + table.string("auth_method", 250); + table.text("auth_domain"); + table.text("auth_workstation"); + table.string("grpc_url", 255).defaultTo(null); + table.text("grpc_protobuf").defaultTo(null); + table.text("grpc_body").defaultTo(null); + table.text("grpc_metadata").defaultTo(null); + table.text("grpc_method").defaultTo(null); + table.text("grpc_service_name").defaultTo(null); + table.boolean("grpc_enable_tls").notNullable().defaultTo(false); + table.string("radius_username", 255); + table.string("radius_password", 255); + table.string("radius_calling_station_id", 50); + table.string("radius_called_station_id", 50); + table.string("radius_secret", 255); + table.integer("resend_interval").notNullable().defaultTo(0); + table.integer("packet_size").notNullable().defaultTo(56); + table.string("game", 255); + }); + + // heartbeat + await knex.schema.createTable("heartbeat", (table) => { + table.increments("id"); + table.boolean("important").notNullable().defaultTo(false); + table.integer("monitor_id").unsigned().notNullable() + .references("id").inTable("monitor") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.smallint("status").notNullable(); + + table.text("msg"); + table.datetime("time").notNullable(); + table.integer("ping"); + table.integer("duration").notNullable().defaultTo(0); + table.integer("down_count").notNullable().defaultTo(0); + + table.index("important"); + table.index([ "monitor_id", "time" ], "monitor_time_index"); + table.index("monitor_id"); + table.index([ "monitor_id", "important", "time" ], "monitor_important_time_index"); + }); + + // incident + await knex.schema.createTable("incident", (table) => { + table.increments("id"); + table.string("title", 255).notNullable(); + table.text("content", 255).notNullable(); + table.string("style", 30).notNullable().defaultTo("warning"); + table.datetime("created_date").notNullable().defaultTo(knex.fn.now()); + table.datetime("last_updated_date"); + table.boolean("pin").notNullable().defaultTo(true); + table.boolean("active").notNullable().defaultTo(true); + table.integer("status_page_id").unsigned(); + }); + + // maintenance + await knex.schema.createTable("maintenance", (table) => { + table.increments("id"); + table.string("title", 150).notNullable(); + table.text("description").notNullable(); + table.integer("user_id").unsigned() + .references("id").inTable("user") + .onDelete("SET NULL") + .onUpdate("CASCADE"); + table.boolean("active").notNullable().defaultTo(true); + table.string("strategy", 50).notNullable().defaultTo("single"); + table.datetime("start_date"); + table.datetime("end_date"); + table.time("start_time"); + table.time("end_time"); + table.string("weekdays", 250).defaultTo("[]"); + table.text("days_of_month").defaultTo("[]"); + table.integer("interval_day"); + + table.index("active"); + table.index([ "strategy", "active" ], "manual_active"); + table.index("user_id", "maintenance_user_id"); + }); + + // status_page + await knex.schema.createTable("status_page", (table) => { + table.increments("id"); + table.string("slug", 255).notNullable().unique().collate("utf8_general_ci"); + table.string("title", 255).notNullable(); + table.text("description"); + table.string("icon", 255).notNullable(); + table.string("theme", 30).notNullable(); + table.boolean("published").notNullable().defaultTo(true); + table.boolean("search_engine_index").notNullable().defaultTo(true); + table.boolean("show_tags").notNullable().defaultTo(false); + table.string("password"); + table.datetime("created_date").notNullable().defaultTo(knex.fn.now()); + table.datetime("modified_date").notNullable().defaultTo(knex.fn.now()); + table.text("footer_text"); + table.text("custom_css"); + table.boolean("show_powered_by").notNullable().defaultTo(true); + table.string("google_analytics_tag_id"); + }); + + // maintenance_status_page + await knex.schema.createTable("maintenance_status_page", (table) => { + table.increments("id"); + + table.integer("status_page_id").unsigned().notNullable() + .references("id").inTable("status_page") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + + table.integer("maintenance_id").unsigned().notNullable() + .references("id").inTable("maintenance") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + }); + + // maintenance_timeslot + await knex.schema.createTable("maintenance_timeslot", (table) => { + table.increments("id"); + table.integer("maintenance_id").unsigned().notNullable() + .references("id").inTable("maintenance") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.datetime("start_date").notNullable(); + table.datetime("end_date"); + table.boolean("generated_next").defaultTo(false); + + table.index("maintenance_id"); + table.index([ "maintenance_id", "start_date", "end_date" ], "active_timeslot_index"); + table.index("generated_next", "generated_next_index"); + }); + + // monitor_group + await knex.schema.createTable("monitor_group", (table) => { + table.increments("id"); + table.integer("monitor_id").unsigned().notNullable() + .references("id").inTable("monitor") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.integer("group_id").unsigned().notNullable() + .references("id").inTable("group") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.integer("weight").notNullable().defaultTo(1000); + table.boolean("send_url").notNullable().defaultTo(false); + + table.index([ "monitor_id", "group_id" ], "fk"); + }); + // monitor_maintenance + await knex.schema.createTable("monitor_maintenance", (table) => { + table.increments("id"); + table.integer("monitor_id").unsigned().notNullable() + .references("id").inTable("monitor") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.integer("maintenance_id").unsigned().notNullable() + .references("id").inTable("maintenance") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + + table.index("maintenance_id", "maintenance_id_index2"); + table.index("monitor_id", "monitor_id_index"); + }); + + // notification + await knex.schema.createTable("notification", (table) => { + table.increments("id"); + table.string("name", 255); + table.boolean("active").notNullable().defaultTo(true); + table.integer("user_id").unsigned(); + table.boolean("is_default").notNullable().defaultTo(false); + table.text("config", "longtext"); + }); + + // monitor_notification + await knex.schema.createTable("monitor_notification", (table) => { + table.increments("id").unsigned(); // TODO: no auto increment???? + table.integer("monitor_id").unsigned().notNullable() + .references("id").inTable("monitor") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.integer("notification_id").unsigned().notNullable() + .references("id").inTable("notification") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + + table.index([ "monitor_id", "notification_id" ], "monitor_notification_index"); + }); + + // tag + await knex.schema.createTable("tag", (table) => { + table.increments("id"); + table.string("name", 255).notNullable(); + table.string("color", 255).notNullable(); + table.datetime("created_date").notNullable().defaultTo(knex.fn.now()); + }); + + // monitor_tag + await knex.schema.createTable("monitor_tag", (table) => { + table.increments("id"); + table.integer("monitor_id").unsigned().notNullable() + .references("id").inTable("monitor") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.integer("tag_id").unsigned().notNullable() + .references("id").inTable("tag") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.text("value"); + }); + + // monitor_tls_info + await knex.schema.createTable("monitor_tls_info", (table) => { + table.increments("id"); + table.integer("monitor_id").unsigned().notNullable() + .references("id").inTable("monitor") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.text("info_json"); + }); + + // notification_sent_history + await knex.schema.createTable("notification_sent_history", (table) => { + table.increments("id"); + table.string("type", 50).notNullable(); + table.integer("monitor_id").unsigned().notNullable(); + table.integer("days").notNullable(); + table.unique([ "type", "monitor_id", "days" ]); + table.index([ "type", "monitor_id", "days" ], "good_index"); + }); + + // setting + await knex.schema.createTable("setting", (table) => { + table.increments("id"); + table.string("key", 200).notNullable().unique().collate("utf8_general_ci"); + table.text("value"); + table.string("type", 20); + }); + + // status_page_cname + await knex.schema.createTable("status_page_cname", (table) => { + table.increments("id"); + table.integer("status_page_id").unsigned() + .references("id").inTable("status_page") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.string("domain").notNullable().unique().collate("utf8_general_ci"); + }); + + /********************* + * Converted Patch here + *********************/ + + // 2023-06-30-1348-http-body-encoding.js + // ALTER TABLE monitor ADD http_body_encoding VARCHAR(25); + // UPDATE monitor SET http_body_encoding = 'json' WHERE (type = 'http' or type = 'keyword') AND http_body_encoding IS NULL; + await knex.schema.table("monitor", function (table) { + table.string("http_body_encoding", 25); + }); + + await knex("monitor") + .where(function () { + this.where("type", "http").orWhere("type", "keyword"); + }) + .whereNull("http_body_encoding") + .update({ + http_body_encoding: "json", + }); + + // 2023-06-30-1354-add-description-monitor.js + // ALTER TABLE monitor ADD description TEXT default null; + await knex.schema.table("monitor", function (table) { + table.text("description").defaultTo(null); + }); + + // 2023-06-30-1357-api-key-table.js + /* + CREATE TABLE [api_key] ( + [id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, + [key] VARCHAR(255) NOT NULL, + [name] VARCHAR(255) NOT NULL, + [user_id] INTEGER NOT NULL, + [created_date] DATETIME DEFAULT (DATETIME('now')) NOT NULL, + [active] BOOLEAN DEFAULT 1 NOT NULL, + [expires] DATETIME DEFAULT NULL, + CONSTRAINT FK_user FOREIGN KEY ([user_id]) REFERENCES [user]([id]) ON DELETE CASCADE ON UPDATE CASCADE + ); + */ + await knex.schema.createTable("api_key", function (table) { + table.increments("id").primary(); + table.string("key", 255).notNullable(); + table.string("name", 255).notNullable(); + table.integer("user_id").unsigned().notNullable() + .references("id").inTable("user") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.dateTime("created_date").defaultTo(knex.fn.now()).notNullable(); + table.boolean("active").defaultTo(1).notNullable(); + table.dateTime("expires").defaultTo(null); + }); + + // 2023-06-30-1400-monitor-tls.js + /* + ALTER TABLE monitor + ADD tls_ca TEXT default null; + + ALTER TABLE monitor + ADD tls_cert TEXT default null; + + ALTER TABLE monitor + ADD tls_key TEXT default null; + */ + await knex.schema.table("monitor", function (table) { + table.text("tls_ca").defaultTo(null); + table.text("tls_cert").defaultTo(null); + table.text("tls_key").defaultTo(null); + }); + + // 2023-06-30-1401-maintenance-cron.js + /* + -- 999 characters. https://stackoverflow.com/questions/46134830/maximum-length-for-cron-job + DROP TABLE maintenance_timeslot; + ALTER TABLE maintenance ADD cron TEXT; + ALTER TABLE maintenance ADD timezone VARCHAR(255); + ALTER TABLE maintenance ADD duration INTEGER; + */ + await knex.schema + .dropTableIfExists("maintenance_timeslot") + .table("maintenance", function (table) { + table.text("cron"); + table.string("timezone", 255); + table.integer("duration"); + }); + + // 2023-06-30-1413-add-parent-monitor.js. + /* + ALTER TABLE monitor + ADD parent INTEGER REFERENCES [monitor] ([id]) ON DELETE SET NULL ON UPDATE CASCADE; + */ + await knex.schema.table("monitor", function (table) { + table.integer("parent").unsigned() + .references("id").inTable("monitor") + .onDelete("SET NULL") + .onUpdate("CASCADE"); + }); + + /* + patch-add-invert-keyword.sql + ALTER TABLE monitor + ADD invert_keyword BOOLEAN default 0 not null; + */ + await knex.schema.table("monitor", function (table) { + table.boolean("invert_keyword").defaultTo(0).notNullable(); + }); + + /* + patch-added-json-query.sql + ALTER TABLE monitor + ADD json_path TEXT; + + ALTER TABLE monitor + ADD expected_value VARCHAR(255); + */ + await knex.schema.table("monitor", function (table) { + table.text("json_path"); + table.string("expected_value", 255); + }); + + /* + patch-added-kafka-producer.sql + + ALTER TABLE monitor + ADD kafka_producer_topic VARCHAR(255); + +ALTER TABLE monitor + ADD kafka_producer_brokers TEXT; + +ALTER TABLE monitor + ADD kafka_producer_ssl INTEGER; + +ALTER TABLE monitor + ADD kafka_producer_allow_auto_topic_creation VARCHAR(255); + +ALTER TABLE monitor + ADD kafka_producer_sasl_options TEXT; + +ALTER TABLE monitor + ADD kafka_producer_message TEXT; + */ + await knex.schema.table("monitor", function (table) { + table.string("kafka_producer_topic", 255); + table.text("kafka_producer_brokers"); + + // patch-fix-kafka-producer-booleans.sql + table.boolean("kafka_producer_ssl").defaultTo(0).notNullable(); + table.boolean("kafka_producer_allow_auto_topic_creation").defaultTo(0).notNullable(); + + table.text("kafka_producer_sasl_options"); + table.text("kafka_producer_message"); + }); + + /* + patch-add-certificate-expiry-status-page.sql + ALTER TABLE status_page + ADD show_certificate_expiry BOOLEAN default 0 NOT NULL; + */ + await knex.schema.table("status_page", function (table) { + table.boolean("show_certificate_expiry").defaultTo(0).notNullable(); + }); + + /* + patch-monitor-oauth-cc.sql + ALTER TABLE monitor + ADD oauth_client_id TEXT default null; + +ALTER TABLE monitor + ADD oauth_client_secret TEXT default null; + +ALTER TABLE monitor + ADD oauth_token_url TEXT default null; + +ALTER TABLE monitor + ADD oauth_scopes TEXT default null; + +ALTER TABLE monitor + ADD oauth_auth_method TEXT default null; + */ + await knex.schema.table("monitor", function (table) { + table.text("oauth_client_id").defaultTo(null); + table.text("oauth_client_secret").defaultTo(null); + table.text("oauth_token_url").defaultTo(null); + table.text("oauth_scopes").defaultTo(null); + table.text("oauth_auth_method").defaultTo(null); + }); + + /* + patch-add-timeout-monitor.sql + ALTER TABLE monitor + ADD timeout DOUBLE default 0 not null; + */ + await knex.schema.table("monitor", function (table) { + table.double("timeout").defaultTo(0).notNullable(); + }); + + /* + patch-add-gamedig-given-port.sql + ALTER TABLE monitor + ADD gamedig_given_port_only BOOLEAN default 1 not null; + */ + await knex.schema.table("monitor", function (table) { + table.boolean("gamedig_given_port_only").defaultTo(1).notNullable(); + }); + + log.info("mariadb", "Created basic tables for MariaDB"); +} + +module.exports = { + createTables, +}; diff --git a/db/knex_migrations/2023-08-16-0000-create-uptime.js b/db/knex_migrations/2023-08-16-0000-create-uptime.js new file mode 100644 index 0000000000..ab899311c9 --- /dev/null +++ b/db/knex_migrations/2023-08-16-0000-create-uptime.js @@ -0,0 +1,41 @@ +exports.up = function (knex) { + return knex.schema + .createTable("stat_minutely", function (table) { + table.increments("id"); + table.comment("This table contains the minutely aggregate statistics for each monitor"); + table.integer("monitor_id").unsigned().notNullable() + .references("id").inTable("monitor") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.integer("timestamp") + .notNullable() + .comment("Unix timestamp rounded down to the nearest minute"); + table.float("ping").notNullable().comment("Average ping in milliseconds"); + table.smallint("up").notNullable(); + table.smallint("down").notNullable(); + + table.unique([ "monitor_id", "timestamp" ]); + }) + .createTable("stat_daily", function (table) { + table.increments("id"); + table.comment("This table contains the daily aggregate statistics for each monitor"); + table.integer("monitor_id").unsigned().notNullable() + .references("id").inTable("monitor") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.integer("timestamp") + .notNullable() + .comment("Unix timestamp rounded down to the nearest day"); + table.float("ping").notNullable().comment("Average ping in milliseconds"); + table.smallint("up").notNullable(); + table.smallint("down").notNullable(); + + table.unique([ "monitor_id", "timestamp" ]); + }); +}; + +exports.down = function (knex) { + return knex.schema + .dropTable("stat_minutely") + .dropTable("stat_daily"); +}; diff --git a/db/knex_migrations/2023-08-18-0301-heartbeat.js b/db/knex_migrations/2023-08-18-0301-heartbeat.js new file mode 100644 index 0000000000..fe4152b488 --- /dev/null +++ b/db/knex_migrations/2023-08-18-0301-heartbeat.js @@ -0,0 +1,16 @@ +exports.up = function (knex) { + // Add new column heartbeat.end_time + return knex.schema + .alterTable("heartbeat", function (table) { + table.datetime("end_time").nullable().defaultTo(null); + }); + +}; + +exports.down = function (knex) { + // Rename heartbeat.start_time to heartbeat.time + return knex.schema + .alterTable("heartbeat", function (table) { + table.dropColumn("end_time"); + }); +}; diff --git a/db/knex_migrations/2023-09-29-0000-heartbeat-retires.js b/db/knex_migrations/2023-09-29-0000-heartbeat-retires.js new file mode 100644 index 0000000000..a6b9c7bb9e --- /dev/null +++ b/db/knex_migrations/2023-09-29-0000-heartbeat-retires.js @@ -0,0 +1,15 @@ +exports.up = function (knex) { + // Add new column heartbeat.retries + return knex.schema + .alterTable("heartbeat", function (table) { + table.integer("retries").notNullable().defaultTo(0); + }); + +}; + +exports.down = function (knex) { + return knex.schema + .alterTable("heartbeat", function (table) { + table.dropColumn("retries"); + }); +}; diff --git a/db/knex_migrations/2023-10-08-0000-mqtt-query.js b/db/knex_migrations/2023-10-08-0000-mqtt-query.js new file mode 100644 index 0000000000..f37bab8327 --- /dev/null +++ b/db/knex_migrations/2023-10-08-0000-mqtt-query.js @@ -0,0 +1,16 @@ +exports.up = function (knex) { + // Add new column monitor.mqtt_check_type + return knex.schema + .alterTable("monitor", function (table) { + table.string("mqtt_check_type", 255).notNullable().defaultTo("keyword"); + }); + +}; + +exports.down = function (knex) { + // Drop column monitor.mqtt_check_type + return knex.schema + .alterTable("monitor", function (table) { + table.dropColumn("mqtt_check_type"); + }); +}; diff --git a/db/knex_migrations/2023-10-11-1915-push-token-to-32.js b/db/knex_migrations/2023-10-11-1915-push-token-to-32.js new file mode 100644 index 0000000000..47e5ac0bfc --- /dev/null +++ b/db/knex_migrations/2023-10-11-1915-push-token-to-32.js @@ -0,0 +1,14 @@ +exports.up = function (knex) { + // update monitor.push_token to 32 length + return knex.schema + .alterTable("monitor", function (table) { + table.string("push_token", 32).alter(); + }); +}; + +exports.down = function (knex) { + return knex.schema + .alterTable("monitor", function (table) { + table.string("push_token", 20).alter(); + }); +}; diff --git a/db/knex_migrations/2023-10-16-0000-create-remote-browsers.js b/db/knex_migrations/2023-10-16-0000-create-remote-browsers.js new file mode 100644 index 0000000000..c720d3f4af --- /dev/null +++ b/db/knex_migrations/2023-10-16-0000-create-remote-browsers.js @@ -0,0 +1,21 @@ +exports.up = function (knex) { + return knex.schema + .createTable("remote_browser", function (table) { + table.increments("id"); + table.string("name", 255).notNullable(); + table.string("url", 255).notNullable(); + table.integer("user_id").unsigned(); + }).alterTable("monitor", function (table) { + // Add new column monitor.remote_browser + table.integer("remote_browser").nullable().defaultTo(null).unsigned() + .index() + .references("id") + .inTable("remote_browser"); + }); +}; + +exports.down = function (knex) { + return knex.schema.dropTable("remote_browser").alterTable("monitor", function (table) { + table.dropColumn("remote_browser"); + }); +}; diff --git a/db/knex_migrations/2023-12-20-0000-alter-status-page.js b/db/knex_migrations/2023-12-20-0000-alter-status-page.js new file mode 100644 index 0000000000..61ef5d607c --- /dev/null +++ b/db/knex_migrations/2023-12-20-0000-alter-status-page.js @@ -0,0 +1,12 @@ +exports.up = function (knex) { + return knex.schema + .alterTable("status_page", function (table) { + table.integer("auto_refresh_interval").defaultTo(300).unsigned(); + }); +}; + +exports.down = function (knex) { + return knex.schema.alterTable("status_page", function (table) { + table.dropColumn("auto_refresh_interval"); + }); +}; diff --git a/db/knex_migrations/2023-12-21-0000-stat-ping-min-max.js b/db/knex_migrations/2023-12-21-0000-stat-ping-min-max.js new file mode 100644 index 0000000000..d936ce56c8 --- /dev/null +++ b/db/knex_migrations/2023-12-21-0000-stat-ping-min-max.js @@ -0,0 +1,24 @@ +exports.up = function (knex) { + return knex.schema + .alterTable("stat_daily", function (table) { + table.float("ping_min").notNullable().defaultTo(0).comment("Minimum ping during this period in milliseconds"); + table.float("ping_max").notNullable().defaultTo(0).comment("Maximum ping during this period in milliseconds"); + }) + .alterTable("stat_minutely", function (table) { + table.float("ping_min").notNullable().defaultTo(0).comment("Minimum ping during this period in milliseconds"); + table.float("ping_max").notNullable().defaultTo(0).comment("Maximum ping during this period in milliseconds"); + }); + +}; + +exports.down = function (knex) { + return knex.schema + .alterTable("stat_daily", function (table) { + table.dropColumn("ping_min"); + table.dropColumn("ping_max"); + }) + .alterTable("stat_minutely", function (table) { + table.dropColumn("ping_min"); + table.dropColumn("ping_max"); + }); +}; diff --git a/db/knex_migrations/2023-12-22-0000-hourly-uptime.js b/db/knex_migrations/2023-12-22-0000-hourly-uptime.js new file mode 100644 index 0000000000..4305900a11 --- /dev/null +++ b/db/knex_migrations/2023-12-22-0000-hourly-uptime.js @@ -0,0 +1,26 @@ +exports.up = function (knex) { + return knex.schema + .createTable("stat_hourly", function (table) { + table.increments("id"); + table.comment("This table contains the hourly aggregate statistics for each monitor"); + table.integer("monitor_id").unsigned().notNullable() + .references("id").inTable("monitor") + .onDelete("CASCADE") + .onUpdate("CASCADE"); + table.integer("timestamp") + .notNullable() + .comment("Unix timestamp rounded down to the nearest hour"); + table.float("ping").notNullable().comment("Average ping in milliseconds"); + table.float("ping_min").notNullable().defaultTo(0).comment("Minimum ping during this period in milliseconds"); + table.float("ping_max").notNullable().defaultTo(0).comment("Maximum ping during this period in milliseconds"); + table.smallint("up").notNullable(); + table.smallint("down").notNullable(); + + table.unique([ "monitor_id", "timestamp" ]); + }); +}; + +exports.down = function (knex) { + return knex.schema + .dropTable("stat_hourly"); +}; diff --git a/db/knex_migrations/2024-01-22-0000-stats-extras.js b/db/knex_migrations/2024-01-22-0000-stats-extras.js new file mode 100644 index 0000000000..b92e8892a9 --- /dev/null +++ b/db/knex_migrations/2024-01-22-0000-stats-extras.js @@ -0,0 +1,26 @@ +exports.up = function (knex) { + return knex.schema + .alterTable("stat_daily", function (table) { + table.text("extras").defaultTo(null).comment("Extra statistics during this time period"); + }) + .alterTable("stat_minutely", function (table) { + table.text("extras").defaultTo(null).comment("Extra statistics during this time period"); + }) + .alterTable("stat_hourly", function (table) { + table.text("extras").defaultTo(null).comment("Extra statistics during this time period"); + }); + +}; + +exports.down = function (knex) { + return knex.schema + .alterTable("stat_daily", function (table) { + table.dropColumn("extras"); + }) + .alterTable("stat_minutely", function (table) { + table.dropColumn("extras"); + }) + .alterTable("stat_hourly", function (table) { + table.dropColumn("extras"); + }); +}; diff --git a/db/knex_migrations/2024-04-26-0000-snmp-monitor.js b/db/knex_migrations/2024-04-26-0000-snmp-monitor.js new file mode 100644 index 0000000000..24752f2dd4 --- /dev/null +++ b/db/knex_migrations/2024-04-26-0000-snmp-monitor.js @@ -0,0 +1,16 @@ +exports.up = function (knex) { + return knex.schema + .alterTable("monitor", function (table) { + table.string("snmp_oid").defaultTo(null); + table.enum("snmp_version", [ "1", "2c", "3" ]).defaultTo("2c"); + table.string("json_path_operator").defaultTo(null); + }); +}; + +exports.down = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.dropColumn("snmp_oid"); + table.dropColumn("snmp_version"); + table.dropColumn("json_path_operator"); + }); +}; diff --git a/db/knex_migrations/2024-08-24-000-add-cache-bust.js b/db/knex_migrations/2024-08-24-000-add-cache-bust.js new file mode 100644 index 0000000000..3644377c42 --- /dev/null +++ b/db/knex_migrations/2024-08-24-000-add-cache-bust.js @@ -0,0 +1,13 @@ +exports.up = function (knex) { + return knex.schema + .alterTable("monitor", function (table) { + table.boolean("cache_bust").notNullable().defaultTo(false); + }); +}; + +exports.down = function (knex) { + return knex.schema + .alterTable("monitor", function (table) { + table.dropColumn("cache_bust"); + }); +}; diff --git a/db/knex_migrations/2024-08-24-0000-conditions.js b/db/knex_migrations/2024-08-24-0000-conditions.js new file mode 100644 index 0000000000..96352fdc43 --- /dev/null +++ b/db/knex_migrations/2024-08-24-0000-conditions.js @@ -0,0 +1,12 @@ +exports.up = function (knex) { + return knex.schema + .alterTable("monitor", function (table) { + table.text("conditions").notNullable().defaultTo("[]"); + }); +}; + +exports.down = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.dropColumn("conditions"); + }); +}; diff --git a/db/knex_migrations/2024-10-1315-rabbitmq-monitor.js b/db/knex_migrations/2024-10-1315-rabbitmq-monitor.js new file mode 100644 index 0000000000..6a17f3366a --- /dev/null +++ b/db/knex_migrations/2024-10-1315-rabbitmq-monitor.js @@ -0,0 +1,17 @@ +exports.up = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.text("rabbitmq_nodes"); + table.string("rabbitmq_username"); + table.string("rabbitmq_password"); + }); + +}; + +exports.down = function (knex) { + return knex.schema.alterTable("monitor", function (table) { + table.dropColumn("rabbitmq_nodes"); + table.dropColumn("rabbitmq_username"); + table.dropColumn("rabbitmq_password"); + }); + +}; diff --git a/db/knex_migrations/2024-10-31-0000-fix-snmp-monitor.js b/db/knex_migrations/2024-10-31-0000-fix-snmp-monitor.js new file mode 100644 index 0000000000..0a605d38f2 --- /dev/null +++ b/db/knex_migrations/2024-10-31-0000-fix-snmp-monitor.js @@ -0,0 +1,7 @@ +exports.up = function (knex) { + return knex("monitor").whereNull("json_path_operator").update("json_path_operator", "=="); +}; +exports.down = function (knex) { + // changing the json_path_operator back to null for all "==" is not possible anymore + // we have lost the context which fields have been set explicitely in >= v2.0 and which would need to be reverted +}; diff --git a/db/knex_migrations/2024-11-27-1927-fix-info-json-data-type.js b/db/knex_migrations/2024-11-27-1927-fix-info-json-data-type.js new file mode 100644 index 0000000000..0f3f75e5be --- /dev/null +++ b/db/knex_migrations/2024-11-27-1927-fix-info-json-data-type.js @@ -0,0 +1,13 @@ +// Update info_json column to LONGTEXT mainly for MariaDB +exports.up = function (knex) { + return knex.schema + .alterTable("monitor_tls_info", function (table) { + table.text("info_json", "longtext").alter(); + }); +}; + +exports.down = function (knex) { + return knex.schema.alterTable("monitor_tls_info", function (table) { + table.text("info_json", "text").alter(); + }); +}; diff --git a/db/knex_migrations/README.md b/db/knex_migrations/README.md new file mode 100644 index 0000000000..d2b8470b1e --- /dev/null +++ b/db/knex_migrations/README.md @@ -0,0 +1,56 @@ +# Info + +https://knexjs.org/guide/migrations.html#knexfile-in-other-languages + +## Basic rules + +- All tables must have a primary key named `id` +- Filename format: `YYYY-MM-DD-HHMM-patch-name.js` +- Avoid native SQL syntax, use knex methods, because Uptime Kuma supports SQLite and MariaDB. + +## Template + +```js +exports.up = function(knex) { + +}; + +exports.down = function(knex) { + +}; + +// exports.config = { transaction: false }; +``` + +## Example + +Filename: 2023-06-30-1348-create-user-and-product.js + +```js +exports.up = function(knex) { + return knex.schema + .createTable('user', function (table) { + table.increments('id'); + table.string('first_name', 255).notNullable(); + table.string('last_name', 255).notNullable(); + }) + .createTable('product', function (table) { + table.increments('id'); + table.decimal('price').notNullable(); + table.string('name', 1000).notNullable(); + }).then(() => { + knex("products").insert([ + { price: 10, name: "Apple" }, + { price: 20, name: "Orange" }, + ]); + }); +}; + +exports.down = function(knex) { + return knex.schema + .dropTable("product") + .dropTable("user"); +}; +``` + +https://knexjs.org/guide/migrations.html#transactions-in-migrations diff --git a/db/old_migrations/README.md b/db/old_migrations/README.md new file mode 100644 index 0000000000..3b2bd9640d --- /dev/null +++ b/db/old_migrations/README.md @@ -0,0 +1,3 @@ +# Don't create a new migration file here + +Please go to ./db/knex_migrations/README.md diff --git a/db/patch-2fa-invalidate-used-token.sql b/db/old_migrations/patch-2fa-invalidate-used-token.sql similarity index 100% rename from db/patch-2fa-invalidate-used-token.sql rename to db/old_migrations/patch-2fa-invalidate-used-token.sql diff --git a/db/patch-2fa.sql b/db/old_migrations/patch-2fa.sql similarity index 100% rename from db/patch-2fa.sql rename to db/old_migrations/patch-2fa.sql diff --git a/db/patch-add-certificate-expiry-status-page.sql b/db/old_migrations/patch-add-certificate-expiry-status-page.sql similarity index 100% rename from db/patch-add-certificate-expiry-status-page.sql rename to db/old_migrations/patch-add-certificate-expiry-status-page.sql diff --git a/db/patch-add-clickable-status-page-link.sql b/db/old_migrations/patch-add-clickable-status-page-link.sql similarity index 98% rename from db/patch-add-clickable-status-page-link.sql rename to db/old_migrations/patch-add-clickable-status-page-link.sql index bacd669bdb..cd11cdd294 100644 --- a/db/patch-add-clickable-status-page-link.sql +++ b/db/old_migrations/patch-add-clickable-status-page-link.sql @@ -1,5 +1,7 @@ -- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; + ALTER TABLE monitor_group ADD send_url BOOLEAN DEFAULT 0 NOT NULL; + COMMIT; diff --git a/db/patch-add-description-monitor.sql b/db/old_migrations/patch-add-description-monitor.sql similarity index 100% rename from db/patch-add-description-monitor.sql rename to db/old_migrations/patch-add-description-monitor.sql diff --git a/db/patch-add-docker-columns.sql b/db/old_migrations/patch-add-docker-columns.sql similarity index 100% rename from db/patch-add-docker-columns.sql rename to db/old_migrations/patch-add-docker-columns.sql diff --git a/db/patch-add-gamedig-given-port.sql b/db/old_migrations/patch-add-gamedig-given-port.sql similarity index 100% rename from db/patch-add-gamedig-given-port.sql rename to db/old_migrations/patch-add-gamedig-given-port.sql diff --git a/db/patch-add-google-analytics-status-page-tag.sql b/db/old_migrations/patch-add-gamedig-monitor.sql similarity index 67% rename from db/patch-add-google-analytics-status-page-tag.sql rename to db/old_migrations/patch-add-gamedig-monitor.sql index 5de6ff37b7..e20a0cdfa1 100644 --- a/db/patch-add-google-analytics-status-page-tag.sql +++ b/db/old_migrations/patch-add-gamedig-monitor.sql @@ -1,4 +1,7 @@ -- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; -ALTER TABLE status_page ADD google_analytics_tag_id VARCHAR; + + ALTER TABLE monitor + ADD game VARCHAR(255); + COMMIT; diff --git a/db/old_migrations/patch-add-google-analytics-status-page-tag.sql b/db/old_migrations/patch-add-google-analytics-status-page-tag.sql new file mode 100644 index 0000000000..fe6fa34526 --- /dev/null +++ b/db/old_migrations/patch-add-google-analytics-status-page-tag.sql @@ -0,0 +1,7 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. +BEGIN TRANSACTION; + +ALTER TABLE status_page + ADD google_analytics_tag_id VARCHAR; + +COMMIT; diff --git a/db/patch-add-invert-keyword.sql b/db/old_migrations/patch-add-invert-keyword.sql similarity index 100% rename from db/patch-add-invert-keyword.sql rename to db/old_migrations/patch-add-invert-keyword.sql diff --git a/db/patch-add-other-auth.sql b/db/old_migrations/patch-add-other-auth.sql similarity index 100% rename from db/patch-add-other-auth.sql rename to db/old_migrations/patch-add-other-auth.sql diff --git a/db/patch-add-parent-monitor.sql b/db/old_migrations/patch-add-parent-monitor.sql similarity index 55% rename from db/patch-add-parent-monitor.sql rename to db/old_migrations/patch-add-parent-monitor.sql index 756ac5be21..ac2697ff38 100644 --- a/db/patch-add-parent-monitor.sql +++ b/db/old_migrations/patch-add-parent-monitor.sql @@ -1,6 +1,7 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; ALTER TABLE monitor ADD parent INTEGER REFERENCES [monitor] ([id]) ON DELETE SET NULL ON UPDATE CASCADE; -COMMIT +COMMIT; diff --git a/db/patch-add-radius-monitor.sql b/db/old_migrations/patch-add-radius-monitor.sql similarity index 75% rename from db/patch-add-radius-monitor.sql rename to db/old_migrations/patch-add-radius-monitor.sql index 1fd5b44f45..4625f21068 100644 --- a/db/patch-add-radius-monitor.sql +++ b/db/old_migrations/patch-add-radius-monitor.sql @@ -1,3 +1,4 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; ALTER TABLE monitor @@ -15,4 +16,4 @@ ALTER TABLE monitor ALTER TABLE monitor ADD radius_secret VARCHAR(255); -COMMIT +COMMIT; diff --git a/db/patch-add-retry-interval-monitor.sql b/db/old_migrations/patch-add-retry-interval-monitor.sql similarity index 100% rename from db/patch-add-retry-interval-monitor.sql rename to db/old_migrations/patch-add-retry-interval-monitor.sql diff --git a/db/patch-add-sqlserver-monitor.sql b/db/old_migrations/patch-add-sqlserver-monitor.sql similarity index 100% rename from db/patch-add-sqlserver-monitor.sql rename to db/old_migrations/patch-add-sqlserver-monitor.sql diff --git a/db/patch-add-timeout-monitor.sql b/db/old_migrations/patch-add-timeout-monitor.sql similarity index 95% rename from db/patch-add-timeout-monitor.sql rename to db/old_migrations/patch-add-timeout-monitor.sql index 32d49d1e26..b62eb14301 100644 --- a/db/patch-add-timeout-monitor.sql +++ b/db/old_migrations/patch-add-timeout-monitor.sql @@ -3,4 +3,5 @@ BEGIN TRANSACTION; ALTER TABLE monitor ADD timeout DOUBLE default 0 not null; -COMMIT; \ No newline at end of file + +COMMIT; diff --git a/db/patch-added-json-query.sql b/db/old_migrations/patch-added-json-query.sql similarity index 100% rename from db/patch-added-json-query.sql rename to db/old_migrations/patch-added-json-query.sql diff --git a/db/patch-added-kafka-producer.sql b/db/old_migrations/patch-added-kafka-producer.sql similarity index 100% rename from db/patch-added-kafka-producer.sql rename to db/old_migrations/patch-added-kafka-producer.sql diff --git a/db/patch-added-mqtt-monitor.sql b/db/old_migrations/patch-added-mqtt-monitor.sql similarity index 100% rename from db/patch-added-mqtt-monitor.sql rename to db/old_migrations/patch-added-mqtt-monitor.sql diff --git a/db/patch-api-key-table.sql b/db/old_migrations/patch-api-key-table.sql similarity index 99% rename from db/patch-api-key-table.sql rename to db/old_migrations/patch-api-key-table.sql index fc3a405bf9..4116db38e9 100644 --- a/db/patch-api-key-table.sql +++ b/db/old_migrations/patch-api-key-table.sql @@ -1,5 +1,6 @@ -- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; + CREATE TABLE [api_key] ( [id] INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, [key] VARCHAR(255) NOT NULL, @@ -10,4 +11,5 @@ CREATE TABLE [api_key] ( [expires] DATETIME DEFAULT NULL, CONSTRAINT FK_user FOREIGN KEY ([user_id]) REFERENCES [user]([id]) ON DELETE CASCADE ON UPDATE CASCADE ); + COMMIT; diff --git a/db/patch-fix-kafka-producer-booleans.sql b/db/old_migrations/patch-fix-kafka-producer-booleans.sql similarity index 100% rename from db/patch-fix-kafka-producer-booleans.sql rename to db/old_migrations/patch-fix-kafka-producer-booleans.sql diff --git a/db/patch-group-table.sql b/db/old_migrations/patch-group-table.sql similarity index 100% rename from db/patch-group-table.sql rename to db/old_migrations/patch-group-table.sql diff --git a/db/patch-grpc-monitor.sql b/db/old_migrations/patch-grpc-monitor.sql similarity index 100% rename from db/patch-grpc-monitor.sql rename to db/old_migrations/patch-grpc-monitor.sql diff --git a/db/patch-http-body-encoding.sql b/db/old_migrations/patch-http-body-encoding.sql similarity index 100% rename from db/patch-http-body-encoding.sql rename to db/old_migrations/patch-http-body-encoding.sql diff --git a/db/patch-http-monitor-method-body-and-headers.sql b/db/old_migrations/patch-http-monitor-method-body-and-headers.sql similarity index 100% rename from db/patch-http-monitor-method-body-and-headers.sql rename to db/old_migrations/patch-http-monitor-method-body-and-headers.sql diff --git a/db/patch-improve-performance.sql b/db/old_migrations/patch-improve-performance.sql similarity index 100% rename from db/patch-improve-performance.sql rename to db/old_migrations/patch-improve-performance.sql diff --git a/db/patch-incident-table.sql b/db/old_migrations/patch-incident-table.sql similarity index 100% rename from db/patch-incident-table.sql rename to db/old_migrations/patch-incident-table.sql diff --git a/db/patch-maintenance-cron.sql b/db/old_migrations/patch-maintenance-cron.sql similarity index 100% rename from db/patch-maintenance-cron.sql rename to db/old_migrations/patch-maintenance-cron.sql diff --git a/db/patch-maintenance-table2.sql b/db/old_migrations/patch-maintenance-table2.sql similarity index 100% rename from db/patch-maintenance-table2.sql rename to db/old_migrations/patch-maintenance-table2.sql diff --git a/db/patch-monitor-add-resend-interval.sql b/db/old_migrations/patch-monitor-add-resend-interval.sql similarity index 100% rename from db/patch-monitor-add-resend-interval.sql rename to db/old_migrations/patch-monitor-add-resend-interval.sql diff --git a/db/patch-monitor-basic-auth.sql b/db/old_migrations/patch-monitor-basic-auth.sql similarity index 100% rename from db/patch-monitor-basic-auth.sql rename to db/old_migrations/patch-monitor-basic-auth.sql diff --git a/db/patch-monitor-expiry-notification.sql b/db/old_migrations/patch-monitor-expiry-notification.sql similarity index 100% rename from db/patch-monitor-expiry-notification.sql rename to db/old_migrations/patch-monitor-expiry-notification.sql diff --git a/db/patch-monitor-oauth-cc.sql b/db/old_migrations/patch-monitor-oauth-cc.sql similarity index 100% rename from db/patch-monitor-oauth-cc.sql rename to db/old_migrations/patch-monitor-oauth-cc.sql diff --git a/db/patch-monitor-push_token.sql b/db/old_migrations/patch-monitor-push_token.sql similarity index 100% rename from db/patch-monitor-push_token.sql rename to db/old_migrations/patch-monitor-push_token.sql diff --git a/db/old_migrations/patch-monitor-tls-info-add-fk.sql b/db/old_migrations/patch-monitor-tls-info-add-fk.sql new file mode 100644 index 0000000000..9b9c2d2cbd --- /dev/null +++ b/db/old_migrations/patch-monitor-tls-info-add-fk.sql @@ -0,0 +1,18 @@ +BEGIN TRANSACTION; + +PRAGMA writable_schema = TRUE; + +UPDATE + SQLITE_MASTER +SET + sql = replace(sql, + 'monitor_id INTEGER NOT NULL', + 'monitor_id INTEGER NOT NULL REFERENCES [monitor] ([id]) ON DELETE CASCADE ON UPDATE CASCADE' +) +WHERE + name = 'monitor_tls_info' + AND type = 'table'; + +PRAGMA writable_schema = RESET; + +COMMIT; diff --git a/db/patch-monitor-tls.sql b/db/old_migrations/patch-monitor-tls.sql similarity index 100% rename from db/patch-monitor-tls.sql rename to db/old_migrations/patch-monitor-tls.sql diff --git a/db/patch-notification-config.sql b/db/old_migrations/patch-notification-config.sql similarity index 100% rename from db/patch-notification-config.sql rename to db/old_migrations/patch-notification-config.sql diff --git a/db/patch-notification_sent_history.sql b/db/old_migrations/patch-notification_sent_history.sql similarity index 100% rename from db/patch-notification_sent_history.sql rename to db/old_migrations/patch-notification_sent_history.sql diff --git a/db/patch-ping-packet-size.sql b/db/old_migrations/patch-ping-packet-size.sql similarity index 98% rename from db/patch-ping-packet-size.sql rename to db/old_migrations/patch-ping-packet-size.sql index d65ec8ed84..f127fc2518 100644 --- a/db/patch-ping-packet-size.sql +++ b/db/old_migrations/patch-ping-packet-size.sql @@ -1,5 +1,7 @@ -- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; + ALTER TABLE monitor ADD packet_size INTEGER DEFAULT 56 NOT NULL; + COMMIT; diff --git a/db/patch-proxy.sql b/db/old_migrations/patch-proxy.sql similarity index 100% rename from db/patch-proxy.sql rename to db/old_migrations/patch-proxy.sql diff --git a/db/patch-setting-value-type.sql b/db/old_migrations/patch-setting-value-type.sql similarity index 99% rename from db/patch-setting-value-type.sql rename to db/old_migrations/patch-setting-value-type.sql index 18d6390c3d..4816bc60f2 100644 --- a/db/patch-setting-value-type.sql +++ b/db/old_migrations/patch-setting-value-type.sql @@ -18,5 +18,4 @@ drop table setting; alter table setting_dg_tmp rename to setting; - COMMIT; diff --git a/db/old_migrations/patch-status-page-footer-css.sql b/db/old_migrations/patch-status-page-footer-css.sql new file mode 100644 index 0000000000..beef922216 --- /dev/null +++ b/db/old_migrations/patch-status-page-footer-css.sql @@ -0,0 +1,11 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. +BEGIN TRANSACTION; + +ALTER TABLE status_page + ADD footer_text TEXT; +ALTER TABLE status_page + ADD custom_css TEXT; +ALTER TABLE status_page + ADD show_powered_by BOOLEAN NOT NULL DEFAULT 1; + +COMMIT; diff --git a/db/patch-status-page.sql b/db/old_migrations/patch-status-page.sql similarity index 100% rename from db/patch-status-page.sql rename to db/old_migrations/patch-status-page.sql diff --git a/db/patch-timeout.sql b/db/old_migrations/patch-timeout.sql similarity index 100% rename from db/patch-timeout.sql rename to db/old_migrations/patch-timeout.sql diff --git a/db/patch1.sql b/db/old_migrations/patch1.sql similarity index 100% rename from db/patch1.sql rename to db/old_migrations/patch1.sql diff --git a/db/patch10.sql b/db/old_migrations/patch10.sql similarity index 100% rename from db/patch10.sql rename to db/old_migrations/patch10.sql diff --git a/db/patch2.sql b/db/old_migrations/patch2.sql similarity index 61% rename from db/patch2.sql rename to db/old_migrations/patch2.sql index 012d015020..2f34e292ca 100644 --- a/db/patch2.sql +++ b/db/old_migrations/patch2.sql @@ -1,3 +1,4 @@ +-- You should not modify if this have pushed to Github, unless it does serious wrong with the db. BEGIN TRANSACTION; CREATE TABLE monitor_tls_info ( diff --git a/db/patch3.sql b/db/old_migrations/patch3.sql similarity index 100% rename from db/patch3.sql rename to db/old_migrations/patch3.sql diff --git a/db/patch4.sql b/db/old_migrations/patch4.sql similarity index 100% rename from db/patch4.sql rename to db/old_migrations/patch4.sql diff --git a/db/patch5.sql b/db/old_migrations/patch5.sql similarity index 100% rename from db/patch5.sql rename to db/old_migrations/patch5.sql diff --git a/db/patch6.sql b/db/old_migrations/patch6.sql similarity index 100% rename from db/patch6.sql rename to db/old_migrations/patch6.sql diff --git a/db/patch7.sql b/db/old_migrations/patch7.sql similarity index 100% rename from db/patch7.sql rename to db/old_migrations/patch7.sql diff --git a/db/patch8.sql b/db/old_migrations/patch8.sql similarity index 100% rename from db/patch8.sql rename to db/old_migrations/patch8.sql diff --git a/db/patch9.sql b/db/old_migrations/patch9.sql similarity index 100% rename from db/patch9.sql rename to db/old_migrations/patch9.sql diff --git a/db/patch-add-gamedig-monitor.sql b/db/patch-add-gamedig-monitor.sql deleted file mode 100644 index 061bed3025..0000000000 --- a/db/patch-add-gamedig-monitor.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN TRANSACTION; - - ALTER TABLE monitor - ADD game VARCHAR(255); - COMMIT diff --git a/db/patch-status-page-footer-css.sql b/db/patch-status-page-footer-css.sql deleted file mode 100644 index 413918f11a..0000000000 --- a/db/patch-status-page-footer-css.sql +++ /dev/null @@ -1,6 +0,0 @@ --- You should not modify if this have pushed to Github, unless it does serious wrong with the db. -BEGIN TRANSACTION; -ALTER TABLE status_page ADD footer_text TEXT; -ALTER TABLE status_page ADD custom_css TEXT; -ALTER TABLE status_page ADD show_powered_by BOOLEAN NOT NULL DEFAULT 1; -COMMIT; diff --git a/docker/alpine-base.dockerfile b/docker/alpine-base.dockerfile deleted file mode 100644 index ee2090257f..0000000000 --- a/docker/alpine-base.dockerfile +++ /dev/null @@ -1,8 +0,0 @@ -# DON'T UPDATE TO alpine3.13, 1.14, see #41. -FROM node:16-alpine3.12 -WORKDIR /app - -# Install apprise, iputils for non-root ping, setpriv -RUN apk add --no-cache iputils setpriv dumb-init python3 py3-cryptography py3-pip py3-six py3-yaml py3-click py3-markdown py3-requests py3-requests-oauthlib git && \ - pip3 --no-cache-dir install apprise==1.4.0 && \ - rm -rf /root/.cache diff --git a/docker/debian-base.dockerfile b/docker/debian-base.dockerfile index 2be159d034..a171743713 100644 --- a/docker/debian-base.dockerfile +++ b/docker/debian-base.dockerfile @@ -1,12 +1,18 @@ -# DON'T UPDATE TO bullseye-slim, see #372. -# There is no 20-buster-slim for armv7 unfortunately, 18-buster-slim is the last one for Uptime Kuma v1. -FROM node:18-buster-slim -ARG TARGETPLATFORM - +# Download Apprise deb package +FROM node:20-bookworm-slim AS download-apprise WORKDIR /app +COPY ./extra/download-apprise.mjs ./download-apprise.mjs +RUN apt update && \ + apt --yes --no-install-recommends install curl && \ + npm install cheerio semver && \ + node ./download-apprise.mjs + +# Base Image (Slim) +# If the image changed, the second stage image should be changed too +FROM node:20-bookworm-slim AS base2-slim +ARG TARGETPLATFORM # Specify --no-install-recommends to skip unused dependencies, make the base much smaller! -# python3* = apprise's dependencies # sqlite3 = for debugging # iputils-ping = for ping # util-linux = for setpriv (Should be dropped in 2.0.0?) @@ -15,29 +21,35 @@ WORKDIR /app # ca-certificates = keep the cert up-to-date # sudo = for start service nscd with non-root user # nscd = for better DNS caching -# (pip) apprise = for notifications -RUN apt-get update && \ - apt-get --yes --no-install-recommends install \ - python3 python3-pip python3-cryptography python3-six python3-yaml python3-click python3-markdown python3-requests python3-requests-oauthlib \ +RUN apt update && \ + apt --yes --no-install-recommends install \ sqlite3 \ + ca-certificates \ iputils-ping \ util-linux \ dumb-init \ curl \ - ca-certificates \ sudo \ nscd && \ - pip3 --no-cache-dir install apprise==1.6.0 && \ rm -rf /var/lib/apt/lists/* && \ apt --yes autoremove +# apprise = for notifications (Install from the deb package, as the stable one is too old) (workaround for #4867) +# Switching to testing repo is no longer working, as the testing repo is not bookworm anymore. +# python3-paho-mqtt (#4859) +# TODO: no idea how to delete the deb file after installation as it becomes a layer already +COPY --from=download-apprise /app/apprise.deb ./apprise.deb +RUN apt update && \ + apt --yes --no-install-recommends install ./apprise.deb python3-paho-mqtt && \ + rm -rf /var/lib/apt/lists/* && \ + rm -f apprise.deb && \ + apt --yes autoremove + # Install cloudflared -RUN set -eux && \ - mkdir -p --mode=0755 /usr/share/keyrings && \ - curl --fail --show-error --silent --location --insecure https://pkg.cloudflare.com/cloudflare-main.gpg --output /usr/share/keyrings/cloudflare-main.gpg && \ - echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared buster main' | tee /etc/apt/sources.list.d/cloudflared.list && \ - apt-get update && \ - apt-get install --yes --no-install-recommends cloudflared && \ +RUN curl https://pkg.cloudflare.com/cloudflare-main.gpg --output /usr/share/keyrings/cloudflare-main.gpg && \ + echo 'deb [signed-by=/usr/share/keyrings/cloudflare-main.gpg] https://pkg.cloudflare.com/cloudflared bullseye main' | tee /etc/apt/sources.list.d/cloudflared.list && \ + apt update && \ + apt install --yes --no-install-recommends -t stable cloudflared && \ cloudflared version && \ rm -rf /var/lib/apt/lists/* && \ apt --yes autoremove @@ -46,3 +58,15 @@ RUN set -eux && \ COPY ./docker/etc/nscd.conf /etc/nscd.conf COPY ./docker/etc/sudoers /etc/sudoers + +# Full Base Image +# MariaDB, Chromium and fonts +# Make sure to reuse the slim image here. Uncomment the above line if you want to build it from scratch. +# FROM base2-slim AS base2 +FROM louislam/uptime-kuma:base2-slim AS base2 +ENV UPTIME_KUMA_ENABLE_EMBEDDED_MARIADB=1 +RUN apt update && \ + apt --yes --no-install-recommends install chromium fonts-indic fonts-noto fonts-noto-cjk mariadb-server && \ + rm -rf /var/lib/apt/lists/* && \ + apt --yes autoremove && \ + chown -R node:node /var/lib/mysql diff --git a/docker/docker-compose-dev.yml b/docker/docker-compose-dev.yml new file mode 100644 index 0000000000..c66b24b585 --- /dev/null +++ b/docker/docker-compose-dev.yml @@ -0,0 +1,14 @@ +version: '3.8' + +services: + uptime-kuma: + container_name: uptime-kuma-dev + image: louislam/uptime-kuma:nightly2 + volumes: + #- ./data:/app/data + - ../server:/app/server + - ../db:/app/db + ports: + - "3001:3001" # : + - "3307:3306" + diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml deleted file mode 100644 index f5c8f36615..0000000000 --- a/docker/docker-compose.yml +++ /dev/null @@ -1,14 +0,0 @@ -# Simple docker-compose.yml -# You can change your port or volume location - -version: '3.3' - -services: - uptime-kuma: - image: louislam/uptime-kuma:1 - container_name: uptime-kuma - volumes: - - ./uptime-kuma-data:/app/data - ports: - - 3001:3001 # : - restart: always diff --git a/docker/dockerfile b/docker/dockerfile index 1bc90f9290..d55f94f617 100644 --- a/docker/dockerfile +++ b/docker/dockerfile @@ -1,6 +1,8 @@ +ARG BASE_IMAGE=louislam/uptime-kuma:base2 + ############################################ # Build in Golang -# Run npm run build-healthcheck-armv7 in the host first, another it will be super slow where it is building the armv7 healthcheck +# Run npm run build-healthcheck-armv7 in the host first, otherwise it will be super slow where it is building the armv7 healthcheck # Check file: builder-go.dockerfile ############################################ FROM louislam/uptime-kuma:builder-go AS build_healthcheck @@ -8,49 +10,57 @@ FROM louislam/uptime-kuma:builder-go AS build_healthcheck ############################################ # Build in Node.js ############################################ -FROM louislam/uptime-kuma:base-debian AS build +FROM louislam/uptime-kuma:base2 AS build +USER node WORKDIR /app ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 -COPY .npmrc .npmrc -COPY package.json package.json -COPY package-lock.json package-lock.json +COPY --chown=node:node .npmrc .npmrc +COPY --chown=node:node package.json package.json +COPY --chown=node:node package-lock.json package-lock.json RUN npm ci --omit=dev COPY . . -COPY --from=build_healthcheck /app/extra/healthcheck /app/extra/healthcheck -RUN chmod +x /app/extra/entrypoint.sh +COPY --chown=node:node --from=build_healthcheck /app/extra/healthcheck /app/extra/healthcheck +RUN mkdir ./data ############################################ # ⭐ Main Image ############################################ -FROM louislam/uptime-kuma:base-debian AS release +FROM $BASE_IMAGE AS release WORKDIR /app +LABEL org.opencontainers.image.source="https://github.com/louislam/uptime-kuma" + ENV UPTIME_KUMA_IS_CONTAINER=1 # Copy app files from build layer -COPY --from=build /app /app - +COPY --chown=node:node --from=build /app /app EXPOSE 3001 -VOLUME ["/app/data"] HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD extra/healthcheck -ENTRYPOINT ["/usr/bin/dumb-init", "--", "extra/entrypoint.sh"] +ENTRYPOINT ["/usr/bin/dumb-init", "--"] CMD ["node", "server/server.js"] +############################################ +# Rootless Image +############################################ +FROM release AS rootless +USER node + ############################################ # Mark as Nightly ############################################ FROM release AS nightly RUN npm run mark-as-nightly +FROM nightly AS nightly-rootless +USER node + ############################################ # Build an image for testing pr ############################################ -FROM louislam/uptime-kuma:base-debian AS pr-test - +FROM louislam/uptime-kuma:base2 AS pr-test2 WORKDIR /app - ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 ## Install Git @@ -78,7 +88,7 @@ CMD ["npm", "run", "start-pr-test"] ############################################ # Upload the artifact to Github ############################################ -FROM louislam/uptime-kuma:base-debian AS upload-artifact +FROM louislam/uptime-kuma:base2 AS upload-artifact WORKDIR / RUN apt update && \ apt --yes install curl file diff --git a/docker/dockerfile-alpine b/docker/dockerfile-alpine deleted file mode 100644 index 43f26b8bbb..0000000000 --- a/docker/dockerfile-alpine +++ /dev/null @@ -1,27 +0,0 @@ -FROM louislam/uptime-kuma:base-alpine AS build -WORKDIR /app - -ENV PUPPETEER_SKIP_CHROMIUM_DOWNLOAD=1 - -COPY .npmrc .npmrc -COPY package.json package.json -COPY package-lock.json package-lock.json -RUN npm ci --omit=dev -COPY . . -RUN chmod +x /app/extra/entrypoint.sh - -FROM louislam/uptime-kuma:base-alpine AS release -WORKDIR /app - -# Copy app files from build layer -COPY --from=build /app /app - -EXPOSE 3001 -VOLUME ["/app/data"] -HEALTHCHECK --interval=60s --timeout=30s --start-period=180s --retries=5 CMD node extra/healthcheck.js -ENTRYPOINT ["/usr/bin/dumb-init", "--", "extra/entrypoint.sh"] -CMD ["node", "server/server.js"] - - -FROM release AS nightly -RUN npm run mark-as-nightly diff --git a/extra/beta/update-version.js b/extra/beta/update-version.js index 3dafbe8d47..9ab00155b8 100644 --- a/extra/beta/update-version.js +++ b/extra/beta/update-version.js @@ -5,7 +5,7 @@ const util = require("../../src/util"); util.polyfill(); -const version = process.env.VERSION; +const version = process.env.RELEASE_BETA_VERSION; console.log("Beta Version: " + version); @@ -36,6 +36,8 @@ if (! exists) { /** * Commit updated files * @param {string} version Version to update to + * @returns {void} + * @throws Error committing files */ function commit(version) { let msg = "Update to " + version; @@ -55,6 +57,7 @@ function commit(version) { /** * Create a tag with the specified version * @param {string} version Tag to create + * @returns {void} */ function tag(version) { let res = childProcess.spawnSync("git", [ "tag", version ]); @@ -68,6 +71,7 @@ function tag(version) { * Check if a tag exists for the specified version * @param {string} version Version to check * @returns {boolean} Does the tag already exist + * @throws Version is not valid */ function tagExists(version) { if (! version) { diff --git a/extra/check-knex-filenames.mjs b/extra/check-knex-filenames.mjs new file mode 100644 index 0000000000..4911fc5622 --- /dev/null +++ b/extra/check-knex-filenames.mjs @@ -0,0 +1,72 @@ +import fs from "fs"; +const dir = "./db/knex_migrations"; + +// Get the file list (ending with .js) from the directory +const files = fs.readdirSync(dir).filter((file) => file !== "README.md"); + +// They are wrong, but they had been merged, so allowed. +const exceptionList = [ + "2024-08-24-000-add-cache-bust.js", + "2024-10-1315-rabbitmq-monitor.js", +]; + +// Correct format: YYYY-MM-DD-HHmm-description.js + +for (const file of files) { + if (exceptionList.includes(file)) { + continue; + } + + // Check ending with .js + if (!file.endsWith(".js")) { + console.error(`It should end with .js: ${file}`); + process.exit(1); + } + + const parts = file.split("-"); + + // Should be at least 5 parts + if (parts.length < 5) { + console.error(`Invalid format: ${file}`); + process.exit(1); + } + + // First part should be a year >= 2024 + const year = parseInt(parts[0], 10); + if (isNaN(year) || year < 2023) { + console.error(`Invalid year: ${file}`); + process.exit(1); + } + + // Second part should be a month + const month = parseInt(parts[1], 10); + if (isNaN(month) || month < 1 || month > 12) { + console.error(`Invalid month: ${file}`); + process.exit(1); + } + + // Third part should be a day + const day = parseInt(parts[2], 10); + if (isNaN(day) || day < 1 || day > 31) { + console.error(`Invalid day: ${file}`); + process.exit(1); + } + + // Fourth part should be HHmm + const time = parts[3]; + + // Check length is 4 + if (time.length !== 4) { + console.error(`Invalid time: ${file}`); + process.exit(1); + } + + const hour = parseInt(time.substring(0, 2), 10); + const minute = parseInt(time.substring(2), 10); + if (isNaN(hour) || hour < 0 || hour > 23 || isNaN(minute) || minute < 0 || minute > 59) { + console.error(`Invalid time: ${file}`); + process.exit(1); + } +} + +console.log("All knex filenames are correct."); diff --git a/extra/check-lang-json.js b/extra/check-lang-json.js new file mode 100644 index 0000000000..dfda34892a --- /dev/null +++ b/extra/check-lang-json.js @@ -0,0 +1,27 @@ +// For #5231 + +const fs = require("fs"); + +let path = "./src/lang"; + +// list directories in the lang directory +let jsonFileList = fs.readdirSync(path); + +for (let jsonFile of jsonFileList) { + if (!jsonFile.endsWith(".json")) { + continue; + } + + let jsonPath = path + "/" + jsonFile; + let originalContent = fs.readFileSync(jsonPath, "utf8"); + let langData = JSON.parse(originalContent); + + let formattedContent = JSON.stringify(langData, null, 4) + "\n"; + + if (originalContent !== formattedContent) { + console.error(`File ${jsonFile} is not formatted correctly.`); + process.exit(1); + } +} + +console.log("All lang json files are formatted correctly."); diff --git a/extra/close-incorrect-issue.js b/extra/close-incorrect-issue.js index ae38bccc2c..9bb01b19d8 100644 --- a/extra/close-incorrect-issue.js +++ b/extra/close-incorrect-issue.js @@ -37,7 +37,7 @@ const github = require("@actions/github"); owner: issue.owner, repo: issue.repo, issue_number: issue.number, - body: `@${username}: Hello! :wave:\n\nThis issue is being automatically closed because it does not follow the issue template. Please DO NOT open a blank issue.` + body: `@${username}: Hello! :wave:\n\nThis issue is being automatically closed because it does not follow the issue template. Please **DO NOT open blank issues and use our [issue-templates](https://github.com/louislam/uptime-kuma/issues/new/choose) instead**.\nBlank Issues do not contain the context nessesary for a good discussions.` }); // Close the issue diff --git a/extra/download-apprise.mjs b/extra/download-apprise.mjs new file mode 100644 index 0000000000..3d31f7cf4d --- /dev/null +++ b/extra/download-apprise.mjs @@ -0,0 +1,57 @@ +// Go to http://ftp.debian.org/debian/pool/main/a/apprise/ using fetch api, where it is a apache directory listing page +// Use cheerio to parse the html and get the latest version of Apprise +// call curl to download the latest version of Apprise +// Target file: the latest version of Apprise, which the format is apprise_{VERSION}_all.deb + +import * as cheerio from "cheerio"; +import semver from "semver"; +import * as childProcess from "child_process"; + +const baseURL = "http://ftp.debian.org/debian/pool/main/a/apprise/"; +const response = await fetch(baseURL); + +if (!response.ok) { + throw new Error("Failed to fetch page of Apprise Debian repository."); +} + +const html = await response.text(); + +const $ = cheerio.load(html); + +// Get all the links in the page +const linkElements = $("a"); + +// Filter the links which match apprise_{VERSION}_all.deb +const links = []; +const pattern = /apprise_(.*?)_all.deb/; + +for (let i = 0; i < linkElements.length; i++) { + const link = linkElements[i]; + if (link.attribs.href.match(pattern) && !link.attribs.href.includes("~")) { + links.push({ + filename: link.attribs.href, + version: link.attribs.href.match(pattern)[1], + }); + } +} + +console.log(links); + +// semver compare and download +let latestLink = { + filename: "", + version: "0.0.0", +}; + +for (const link of links) { + if (semver.gt(link.version, latestLink.version)) { + latestLink = link; + } +} + +const downloadURL = baseURL + latestLink.filename; +console.log(`Downloading ${downloadURL}...`); +let result = childProcess.spawnSync("curl", [ downloadURL, "--output", "apprise.deb" ]); +console.log(result.stdout?.toString()); +console.error(result.stderr?.toString()); +process.exit(result.status !== null ? result.status : 1); diff --git a/extra/download-dist.js b/extra/download-dist.js index a854ca8b24..b339ac9300 100644 --- a/extra/download-dist.js +++ b/extra/download-dist.js @@ -4,7 +4,6 @@ const tar = require("tar"); const packageJSON = require("../package.json"); const fs = require("fs"); -const rmSync = require("./fs-rmSync.js"); const version = packageJSON.version; const filename = "dist.tar.gz"; @@ -15,6 +14,7 @@ download(url); /** * Downloads the latest version of the dist from a GitHub release. * @param {string} url The URL to download from. + * @returns {void} * * Generated by Trelent */ @@ -28,8 +28,9 @@ function download(url) { if (fs.existsSync("./dist")) { if (fs.existsSync("./dist-backup")) { - rmSync("./dist-backup", { - recursive: true + fs.rmSync("./dist-backup", { + recursive: true, + force: true, }); } @@ -42,8 +43,9 @@ function download(url) { tarStream.on("close", () => { if (fs.existsSync("./dist-backup")) { - rmSync("./dist-backup", { - recursive: true + fs.rmSync("./dist-backup", { + recursive: true, + force: true, }); } console.log("Done"); diff --git a/extra/entrypoint.sh b/extra/entrypoint.sh deleted file mode 100644 index 23c4f01774..0000000000 --- a/extra/entrypoint.sh +++ /dev/null @@ -1,21 +0,0 @@ -#!/usr/bin/env sh - -# set -e Exit the script if an error happens -set -e -PUID=${PUID=0} -PGID=${PGID=0} - -files_ownership () { - # -h Changes the ownership of an encountered symbolic link and not that of the file or directory pointed to by the symbolic link. - # -R Recursively descends the specified directories - # -c Like verbose but report only when a change is made - chown -hRc "$PUID":"$PGID" /app/data -} - -echo "==> Performing startup jobs and maintenance tasks" -files_ownership - -echo "==> Starting application with user $PUID group $PGID" - -# --clear-groups Clear supplementary groups. -exec setpriv --reuid "$PUID" --regid "$PGID" --clear-groups "$@" diff --git a/extra/env2arg.js b/extra/env2arg.js deleted file mode 100644 index f89a91e438..0000000000 --- a/extra/env2arg.js +++ /dev/null @@ -1,19 +0,0 @@ -#!/usr/bin/env node - -const childProcess = require("child_process"); -let env = process.env; - -let cmd = process.argv[2]; -let args = process.argv.slice(3); -let replacedArgs = []; - -for (let arg of args) { - for (let key in env) { - arg = arg.replaceAll(`$${key}`, env[key]); - } - replacedArgs.push(arg); -} - -let child = childProcess.spawn(cmd, replacedArgs); -child.stdout.pipe(process.stdout); -child.stderr.pipe(process.stderr); diff --git a/extra/exe-builder/.gitignore b/extra/exe-builder/.gitignore deleted file mode 100644 index d52874b6cc..0000000000 --- a/extra/exe-builder/.gitignore +++ /dev/null @@ -1 +0,0 @@ -packages/ diff --git a/extra/exe-builder/App.config b/extra/exe-builder/App.config deleted file mode 100644 index 97eb34aff2..0000000000 --- a/extra/exe-builder/App.config +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/extra/exe-builder/DownloadForm.Designer.cs b/extra/exe-builder/DownloadForm.Designer.cs deleted file mode 100644 index 26a474e9c6..0000000000 --- a/extra/exe-builder/DownloadForm.Designer.cs +++ /dev/null @@ -1,84 +0,0 @@ -using System.ComponentModel; - -namespace UptimeKuma { - partial class DownloadForm { - /// - /// Required designer variable. - /// - private IContainer components = null; - - /// - /// Clean up any resources being used. - /// - /// true if managed resources should be disposed; otherwise, false. - protected override void Dispose(bool disposing) { - if (disposing && (components != null)) { - components.Dispose(); - } - - base.Dispose(disposing); - } - - #region Windows Form Designer generated code - - /// - /// Required method for Designer support - do not modify - /// the contents of this method with the code editor. - /// - private void InitializeComponent() { - System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(DownloadForm)); - this.progressBar = new System.Windows.Forms.ProgressBar(); - this.label = new System.Windows.Forms.Label(); - this.labelData = new System.Windows.Forms.Label(); - this.SuspendLayout(); - // - // progressBar - // - this.progressBar.Location = new System.Drawing.Point(12, 12); - this.progressBar.Name = "progressBar"; - this.progressBar.Size = new System.Drawing.Size(472, 41); - this.progressBar.TabIndex = 0; - // - // label - // - this.label.Location = new System.Drawing.Point(12, 59); - this.label.Name = "label"; - this.label.Size = new System.Drawing.Size(472, 23); - this.label.TabIndex = 1; - this.label.Text = "Preparing..."; - // - // labelData - // - this.labelData.Location = new System.Drawing.Point(12, 82); - this.labelData.Name = "labelData"; - this.labelData.Size = new System.Drawing.Size(472, 23); - this.labelData.TabIndex = 2; - // - // DownloadForm - // - this.AutoScaleDimensions = new System.Drawing.SizeF(8F, 16F); - this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; - this.ClientSize = new System.Drawing.Size(496, 117); - this.Controls.Add(this.labelData); - this.Controls.Add(this.label); - this.Controls.Add(this.progressBar); - this.FormBorderStyle = System.Windows.Forms.FormBorderStyle.FixedDialog; - this.Icon = ((System.Drawing.Icon)(resources.GetObject("$this.Icon"))); - this.MaximizeBox = false; - this.Name = "DownloadForm"; - this.StartPosition = System.Windows.Forms.FormStartPosition.CenterScreen; - this.Text = "Uptime Kuma"; - this.Load += new System.EventHandler(this.DownloadForm_Load); - this.ResumeLayout(false); - } - - private System.Windows.Forms.Label labelData; - - private System.Windows.Forms.Label label; - - private System.Windows.Forms.ProgressBar progressBar; - - #endregion - } -} - diff --git a/extra/exe-builder/DownloadForm.cs b/extra/exe-builder/DownloadForm.cs deleted file mode 100644 index 28a57c5278..0000000000 --- a/extra/exe-builder/DownloadForm.cs +++ /dev/null @@ -1,204 +0,0 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; -using System.Diagnostics; -using System.IO; -using System.IO.Compression; -using System.Net; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; -using Newtonsoft.Json; - -namespace UptimeKuma { - public partial class DownloadForm : Form { - private readonly Queue downloadQueue = new(); - private readonly WebClient webClient = new(); - private DownloadItem currentDownloadItem; - - public DownloadForm() { - InitializeComponent(); - } - - private void DownloadForm_Load(object sender, EventArgs e) { - webClient.DownloadProgressChanged += DownloadProgressChanged; - webClient.DownloadFileCompleted += DownloadFileCompleted; - - label.Text = "Reading latest version..."; - - // Read json from https://uptime.kuma.pet/version - var versionJson = new WebClient().DownloadString("https://uptime.kuma.pet/version"); - var versionObj = JsonConvert.DeserializeObject(versionJson); - - var nodeVersion = versionObj.nodejs; - var uptimeKumaVersion = versionObj.latest; - var hasUpdateFile = File.Exists("update"); - - if (!Directory.Exists("node")) { - downloadQueue.Enqueue(new DownloadItem { - URL = $"https://nodejs.org/dist/v{nodeVersion}/node-v{nodeVersion}-win-x64.zip", - Filename = "node.zip", - TargetFolder = "node" - }); - } - - if (!Directory.Exists("core") || hasUpdateFile) { - - // It is update, rename the core folder to core.old - if (Directory.Exists("core")) { - // Remove the old core.old folder - if (Directory.Exists("core.old")) { - Directory.Delete("core.old", true); - } - - Directory.Move("core", "core.old"); - } - - downloadQueue.Enqueue(new DownloadItem { - URL = $"https://github.com/louislam/uptime-kuma/archive/refs/tags/{uptimeKumaVersion}.zip", - Filename = "core.zip", - TargetFolder = "core" - }); - - File.WriteAllText("version.json", versionJson); - - // Delete the update file - if (hasUpdateFile) { - File.Delete("update"); - } - } - - DownloadNextFile(); - } - - void DownloadNextFile() { - if (downloadQueue.Count > 0) { - var item = downloadQueue.Dequeue(); - - currentDownloadItem = item; - - // Download if the zip file is not existing - if (!File.Exists(item.Filename)) { - label.Text = item.URL; - webClient.DownloadFileAsync(new Uri(item.URL), item.Filename); - } else { - progressBar.Value = 100; - label.Text = "Use local " + item.Filename; - DownloadFileCompleted(null, null); - } - } else { - npmSetup(); - } - } - - void npmSetup() { - labelData.Text = ""; - - var npm = "..\\node\\npm.cmd"; - var cmd = $"{npm} ci --production & {npm} run download-dist & exit"; - - var startInfo = new ProcessStartInfo { - FileName = "cmd.exe", - Arguments = $"/k \"{cmd}\"", - RedirectStandardOutput = false, - RedirectStandardError = false, - RedirectStandardInput = true, - UseShellExecute = false, - CreateNoWindow = false, - WorkingDirectory = "core" - }; - - var process = new Process(); - process.StartInfo = startInfo; - process.EnableRaisingEvents = true; - process.Exited += (_, e) => { - progressBar.Value = 100; - - if (process.ExitCode == 0) { - Task.Delay(2000).ContinueWith(_ => { - Application.Restart(); - }); - label.Text = "Done"; - } else { - label.Text = "Failed, exit code: " + process.ExitCode; - } - - }; - process.Start(); - label.Text = "Installing dependencies and download dist files"; - progressBar.Value = 50; - process.WaitForExit(); - } - - void DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e) { - progressBar.Value = e.ProgressPercentage; - var total = e.TotalBytesToReceive / 1024; - var current = e.BytesReceived / 1024; - - if (total > 0) { - labelData.Text = $"{current}KB/{total}KB"; - } - } - - void DownloadFileCompleted(object sender, AsyncCompletedEventArgs e) { - Extract(currentDownloadItem); - DownloadNextFile(); - } - - void Extract(DownloadItem item) { - if (Directory.Exists(item.TargetFolder)) { - var dir = new DirectoryInfo(item.TargetFolder); - dir.Delete(true); - } - - if (Directory.Exists("temp")) { - var dir = new DirectoryInfo("temp"); - dir.Delete(true); - } - - labelData.Text = $"Extracting {item.Filename}..."; - - ZipFile.ExtractToDirectory(item.Filename, "temp"); - - string[] dirList; - - // Move to the correct level - dirList = Directory.GetDirectories("temp"); - - - - if (dirList.Length > 0) { - var dir = dirList[0]; - - // As sometime ExtractToDirectory is still locking the directory, loop until ok - while (true) { - try { - Directory.Move(dir, item.TargetFolder); - break; - } catch (Exception exception) { - Thread.Sleep(1000); - } - } - - } else { - MessageBox.Show("Unexcepted Error: Cannot move extracted files, folder not found."); - } - - labelData.Text = $"Extracted"; - - if (Directory.Exists("temp")) { - var dir = new DirectoryInfo("temp"); - dir.Delete(true); - } - - File.Delete(item.Filename); - } - } - - public class DownloadItem { - public string URL { get; set; } - public string Filename { get; set; } - public string TargetFolder { get; set; } - } -} - diff --git a/extra/exe-builder/DownloadForm.resx b/extra/exe-builder/DownloadForm.resx deleted file mode 100644 index e87e0c0d40..0000000000 --- a/extra/exe-builder/DownloadForm.resx +++ /dev/null @@ -1,377 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - - - AAABAAMAMDAAAAEAIACoJQAANgAAACAgAAABACAAqBAAAN4lAAAQEAAAAQAgAGgEAACGNgAAKAAAADAA - AABgAAAAAQAgAAAAAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA////BPT09Bfu7u4e8fHxJPPz8yv19fUy9fX1M/Pz8yvx8fEk9vb2HPPz8xXMzMwFAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP// - /wHv7+8f7u7uPPPz81Tx8fFs8fHxgPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGB8fHxcfHx8V3x8fFI9PT0MOvr6w0AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AADy8vIU8fHxS/Dw8Hbx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fFr9PT0R/Dw8CIAAAABAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA8vLyFPHx8Vnx8fGB8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fFs9fX1Mb+/vwQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAICAgALy8vI88fHxfvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvLy8nby8vI8gICAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAzMzMBfHx8Vrx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8vLyYf///wwAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMwF8vLyYPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8W/z8/MWAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7+9R8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLw8PB26urqDAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAPLy8ijx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgu7w7Ifj79ud2u7PtNLrw83P677dzeu85c3r - u+rM67rwzOu68c7rverQ68Dj0uvD3NbuyM3b7c+64u7apujv5ZPx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxXgAAAAEAAAAAAAAAAAAAAAAAAAAA4+PjCfDw - 8Hfx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLd7tSmzeu92MbqsvvG6bH/xumy/8fq - s//H6rP/yOq0/8jqtf/J6rb/yeq2/8rrt//K67j/y+u4/8vruf/M67r/zOu7/83ru//Q7MDx1u7Kz9/t - 163s8OuJ8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgu/v7y8AAAAAAAAAAAAA - AAAAAAAA7u7uPfHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC5PDdl8jqtuTE6a7/xOmv/8Xp - sP/G6bH/xumx/8bpsv/H6rP/x+qz/8jqtP/I6rX/yeq2/8nqtv/K67f/yuu4/8vruP/L67n/zOu6/8zr - u//N67v/zey8/87svf/P67742e3Mx+jv5ZLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvDw - 8HWAgIACAAAAAAAAAACqqqoD8vLyc/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLf7degxOiu+cPo - rf/D6a7/xOmu/8Xpr//F6bD/xumx/8bpsf/G6bL/x+qz/8fqs//I6rT/yOq1/8nqtv/J6rb/yuu3/8rr - uP/L67j/y+u5/8zruv/M67v/zeu7/83svP/O7L3/zuy9/87svfzc7tK28fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fEkAAAAAAAAAADz8/Mq8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgunv - 5o3D6a/0wuis/8Lorf/D6K3/xOmu/8Tprv/F6a//xemw/8bpsf/G6bH/xumy/8fqs//H6rP/yOq0/8jq - tf/J6rb/yeq2/8rrt//K67j/y+u4/8vruf/M67r/zOu7/83ru//N7Lz/zuy9/87svf/O7L3/3e/TtPHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLy8vJNAAAAAAAAAADy8vJM8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgszqutDB6Kv/weir/8LorP/D6K3/w+it/8Tprv/E6a7/xemv/8XpsP/G6bH/xumx/8bp - sv/H6rP/x+qz/8jqtP/I6rX/yeq2/8nqtv/K67f/yuu4/8vruP/L67n/zOu6/8zru//N67v/zey8/87s - vf/O7L3/zuy++u3w6Yzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLy8vJ1AAAAAAAAAADx8fFr8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC6O/kjsDoqvzA6Kr/weir/8Loq//C6Kz/w+it/8Porf/E6a7/xOmu/8Xp - r//F6bD/xumx/8bpsf/G6bL/x+qz/8fqtP/I6rT/yOq1/8nqtv/J6rb/yuu3/8rruP/L67n/y+u5/8zr - uv/M67v/zeu7/83svP/O7L3/zuy9/93u07Xx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC////Bv// - /wfx8fGB8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC1ezJsr/nqf/A56n/weiq/8Hoq//C6Kv/wuis/8Po - rf/D6K3/xOmu/8Pprv+856T/uOed/7bmmv+05Zf/teWZ/7jnnf+86KP/wOio/8fqs//J6rb/yeq2/8rr - t//K67j/y+u5/8vruf/M67r/zOu7/83ru//N7Lz/zuy9/9buyNLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8vLyE/Ly8hPx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCy+q6zr/nqP/A56n/wOep/8Ho - qv/B6Kv/wuir/8LorP+u5Y//neF2/5bgav+V4Gr/luBr/5fhbP+Y4W7/meFv/5rhcf+b4nL/nOJ0/53i - dv+j5H//reaM/7nnnf/E6q//y+y4/8vruf/L67n/zOu6/8zru//N67v/zey8/9Lsxd/x8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC7+/vIPb29hzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCx+m03L/n - qP+/56j/wOep/8Dnqf/B6Kr/weir/7nmn/+R32T/kt9l/5PfZ/+U4Gj/leBq/5bga/+X4W3/mOFu/5nh - b/+a4XH/m+Jy/5zidP+d4nX/nuN3/5/jeP+f4nn/weqq/8rruP/L67n/y+u5/8zruv/M67v/zeu7/9Ls - w+Lx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8PDwI/Hx8SXx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGCxeix5L/nqP+/56j/v+eo/8Dnqf/A56n/weiq/7Pllv+Q3mP/kd9k/5LfZf+T32f/lOBo/5Xg - av+W4Gv/l+Ft/5jhbv+Z4W//muFx/5vicv+c4nT/neJ1/57jd/+f43j/xOmu/8rrt//K67j/y+u5/8vr - uf/M67r/zOu7/9Tsxtfx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC9PT0GO/v7yDx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGCx+m037/nqP+/56j/v+eo/7/nqP/A56n/wOip/7TmmP+P3mH/kN5j/5Hf - ZP+S32b/k99n/5TgaP+V4Gr/luBr/5fhbf+Y4W7/meFw/5rhcf+b4nL/nOJ0/53idf+h5Hz/yuu2/8nq - t//K67f/yuu4/8vruf/L67n/zOu6/9ftysrx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC7e3tDvT0 - 9Bfx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCyOq117/nqP+/56j/v+eo/7/nqP+/56j/wOep/7vn - of+O3mD/j95h/5DeY/+R32T/kt9m/5PfZ/+U4Gj/leBq/5bga/+X4W3/mOFu/5nhcP+a4nH/m+Jy/5zi - dP+r5Yr/yOq1/8nqtv/J6rf/yuu3/8rruP/L67n/y+u5/9zu1LHx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLz8/OA////A+7u7g/x8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCz+q+xb/nqP+/56j/v+eo/7/n - qP+/56j/v+eo/8Dnqf+S4Gb/jt5g/4/eYf+Q3mP/kd9k/5LfZv+T32f/lOBo/5Xgav+W4Gv/l+Ft/5jh - bv+Z4XD/muJx/5vic/+4553/yOq0/8jqtf/J6rb/yeq3/8rrt//K67j/y+u5/+bw4Zfx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fFrAAAAAP///wHz8/N88fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC1+zMrr/n - qP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+f4Xn/jd5f/47eYP+P3mH/kN5j/5HfZP+S32b/k99n/5Tg - af+V4Gr/luBr/5fhbf+Y4W7/meFw/5vic//F6rD/x+q0/8jqtP/I6rX/yeq2/8nqt//K67f/zOu88u/x - 74Px8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLv7+9QAAAAAAAAAADw8PBm8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC5e7gk7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+u5I//jN1d/43eX/+O3mD/j95h/5De - Y/+R32T/kt9m/5PfZ/+U4Gn/leBq/5bga/+X4W3/mOFu/6rliP/G6rL/x+qz/8fqtP/I6rT/yOq1/8nq - tv/J6rf/1OzGy/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YL19fUzAAAAAAAAAADy8vJO8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgsPoru2/56j/v+eo/7/nqP+/56j/v+eo/7/nqP++6Kf/j95i/4zd - Xf+N3l//jt5g/4/eYv+Q3mP/kd9k/5LfZv+T32f/lOBp/5Xgav+W4Gz/l+Ft/7voov/G6bL/xuqy/8fq - s//H6rT/yOq1/8jqtf/J6rb/4e/Zo/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLw8PARAAAAAAAA - AADu7u4u8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgszpvMm/56j/v+eo/7/nqP+/56j/v+eo/7/n - qP+/56j/q+SL/4vdXP+M3V3/jd5f/47eYP+P3mL/kN9j/5HfZP+S32b/k99n/5Tgaf+V4Gr/qOOH/8Xp - sP/G6bH/xumy/8bqsv/H6rP/x+q0/8jqtf/K67jy8PHwhPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8WoAAAAAAAAAAAAAAADo6OgL8fHxgfHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxguDv2J2/56j/v+eo/7/n - qP+/56j/v+eo/7/nqP+/56j/v+eo/6Xjgv+L3Vz/jN1d/43eX/+O3mD/j95i/5DfY/+R32T/kt9m/5Pf - Z/+k44D/xOmu/8XpsP/F6bD/xumx/8bpsv/G6rL/x+qz/8fqtP/W7cnB8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvPz80AAAAAAAAAAAAAAAAAAAAAA8PDwZ/Hx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLD6K/rv+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+u5I//kt5n/4zdXf+N3l//jt5g/4/e - Yv+Q32P/luFs/67kj//D6K3/xOmu/8Tpr//F6bD/xemw/8bpsf/G6bL/xuqy/8fqtP7o7+WR8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz8xYAAAAAAAAAAAAAAAAAAAAA8vLyPPHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLV7ci0v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/wOio/7Xl - mv+u5I7/rOSM/67kj/+35pz/wumr/8Lorf/D6K3/w+it/8Tprv/E6a//xemw/8XpsP/G6bH/xumy/9Ds - wNPx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8vLyZQAAAAAAAAAAAAAAAAAAAAAAAAAA////DPHx - 8YDx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGCx+m03L/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/n - qP+/56j/v+eo/7/nqP+/56j/wOep/8Doqv/B6Kr/weir/8LorP/C6K3/w+it/8Porv/E6a7/xOmv/8Xp - sP/F6bD/yOq18uvw6Yvx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC7+/vMQAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAPHx8Vzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC6O/ij8LorPG/56j/v+eo/7/n - qP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/8Dnqf/A6Kr/weiq/8Hoq//C6Kz/wuit/8Po - rf/D6K7/xOmu/8Tpr//F6bH74u/anvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLw8PB6////BQAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPPz8yrx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxguHu - 2pnB56v2v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP/A56n/wOiq/8Ho - q//B6Kv/wuis/8Lorf/D6K3/w+mu/8Tprv3b7dKq8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fFJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHy8vJf8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLi7tyXwumt8L/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/n - qP+/56j/wOep/8Doqv/B6Kv/weir/8LorP/C6K3/xOiv+d7u1aTx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvLy8nb///8KAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADv7+8Q8/Pze/Hx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC6/Dpiszqu82/56j/v+eo/7/nqP+/56j/v+eo/7/n - qP+/56j/v+eo/7/nqP+/56j/v+eo/8Dnqf/A6Kr/weir/8Hoq//H6bTj5e7elfHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz8yoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA9fX1MvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLe7tShx+mz3r/n - qP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/v+eo/7/nqP/A56n/xumy5drtz6rv8e+D8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8vLyTgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAPHx8Unx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgubv45DU68e2y+q6z8XoseTD6a7uweir9MPpru7F6bHly+q50tLsxLrl796U8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLy8vJh////AwAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wHx8fFZ8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8Wzf398IAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8D8/PzVfHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8PDwZujo - 6AsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA////AfHx8Ujx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fFa////BQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADz8/Mp8vLydvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8/PzfPHx8TcAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CvLy8lDz8/N/8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvPz84Hx8fFa8PDwEQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AADw8PAR8vLyTvHx8X3x8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fF/8/PzVvT09BgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///wXz8/Mq8/PzU/Hx8XDx8fGB8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLy8vJz8fHxWO/v7y////8IAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8G7e3tHfLy - 8ifu7u4u8PDwNPT09C/y8vIo7+/vH+Pj4wkAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAP///////wAA////////AAD///////8AAP//gAf//wAA//gAAD//AAD/wAAAB/8AAP+A - AAAB/wAA/gAAAAB/AAD8AAAAAD8AAPgAAAAAHwAA8AAAAAAPAADwAAAAAAcAAOAAAAAABwAA4AAAAAAD - AADAAAAAAAMAAMAAAAAAAwAAwAAAAAABAACAAAAAAAEAAIAAAAAAAQAAgAAAAAABAACAAAAAAAEAAIAA - AAAAAQAAgAAAAAABAACAAAAAAAMAAMAAAAAAAwAAwAAAAAADAADAAAAAAAMAAMAAAAAABwAAwAAAAAAH - AADgAAAAAAcAAOAAAAAADwAA4AAAAAAPAADwAAAAAB8AAPAAAAAAHwAA+AAAAAA/AAD8AAAAAD8AAPwA - AAAAfwAA/gAAAAD/AAD/AAAAAf8AAP+AAAAD/wAA/8AAAAf/AAD/8AAAH/8AAP/8AAA//wAA//8AAf// - AAD//+AP//8AAP///////wAA////////AAD///////8AACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAgICAAu/v7xD09PQX7u7uHvDw8CP29vYb8vLyFOrq6gwAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAICA - gALy8vIm7+/vT/Pz82fz8/N98fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvDw8Hrw8PBm7+/vUPT0 - 9C3o6OgLAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAOPj - 4wnz8/NC8vLydPHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YHy8vJj8/PzKoCAgAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AADx8fEl8vLydfHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxcfHx8SUAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA9PT0LfHx8YDx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8/PzgPLy8j0AAAABAAAAAAAA - AAAAAAAAAAAAAO3t7Rzx8fGA8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLr8OmM5O7emeTv - 3Z7h79mj5fDem+nv45Tu8u6H8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvLy - 8joAAAAAAAAAAAAAAAD///8E8fHxbvHx8YLx8fGC8fHxgvHx8YLx8fGC7vDshtns0K7N67zayeq288fq - s//I6rT/yOq1/8nqtv/K67f/y+u4/8vruf/P7L7w0+zF29vv0Lrn8OKX8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8/PzfvPz8xUAAAAAAAAAAPX19TLx8fGC8fHxgvHx8YLx8fGC8fHxgt3u1KXF6rHzxOmv/8Xp - sP/G6bH/xumy/8fqs//I6rT/yOq1/8nqtv/K67f/y+u4/8vruf/M67v/zey8/87svf/S7MPj4u7Zp/Hx - 8YLx8fGC8fHxgvHx8YLx8fGC8/PzVQAAAAAAAAAA8fHxavHx8YLx8fGC8fHxgvHx8YLf7defwuis/cPo - rf/E6a7/xOmv/8XpsP/G6bH/xumy/8fqs//I6rT/yOq1/8nqtv/K67f/y+u4/8vruv/M67v/zey8/87s - vf/N67z/3e7SufHx8YLx8fGC8fHxgvHx8YLz8/N8////Bf///w3x8fGC8fHxgvHx8YLx8fGC8fHxgsXp - sOnB6Kv/wuis/8Porf/E6a7/xOmv/8XpsP/G6bH/xumy/8fqs//I6rT/yOq1/8nqtv/K67f/y+u4/8vr - uv/M67v/zey8/87svf/O67z96/Hoj/Hx8YLx8fGC8fHxgvHx8YLy8vIm8/PzK/Hx8YLx8fGC8fHxgvHx - 8YLg79icwOep/8Hoqv/B6Kv/wuis/8Porf/E6a7/wuit/73opP+76KL/u+eh/77opv/D6a3/yeu1/8nq - tv/K67f/y+u5/8zruv/M67v/zey8/87svf/d7tSz8fHxgvHx8YLx8fGC8fHxgvHx8Tby8vI68fHxgvHx - 8YLx8fGC8fHxgtTrxre/56j/wOep/8Hoqv/B6Kv/uOad/53idv+V4Gn/leBq/5fhbP+Y4W//muFx/5vi - c/+e4Xb/puWD/7PmlP/D6a3/y+u5/8zruv/M67v/zey8/9rtzsHx8fGC8fHxgvHx8YLx8fGC8/PzQfPz - 80Lx8fGC8fHxgvHx8YLx8fGC0OvAwr/nqP+/56j/wOep/8Hoqv+o44b/kd9k/5LfZv+U4Gj/leBq/5fh - bf+Y4W//muFx/5vic/+d4nX/n+N3/7fnm//K67j/y+u5/8zruv/M67v/2u3QvPHx8YLx8fGC8fHxgvHx - 8YLy8vI98/PzP/Hx8YLx8fGC8fHxgvHx8YLQ6sK/v+eo/7/nqP+/56j/wOep/6jjhv+P3mL/kd9k/5Lf - Zv+U4Gj/leBr/5fhbf+Y4W//muFx/5zic/+d4nX/v+mm/8nqt//K67j/y+u5/8zruv/f79au8fHxgvHx - 8YLx8fGC8fHxgvX19TLx8fE38fHxgvHx8YLx8fGC8fHxgtTrybO/56j/v+eo/7/nqP+/56j/sOSS/47e - YP+P3mL/kd9k/5LfZv+U4Gj/leBr/5fhbf+Z4W//muJx/5/jd//H6bP/yeq2/8nqt//K67j/y+u5/+nv - 45Tx8fGC8fHxgvHx8YLx8fGC7+/vIPHx8SXx8fGC8fHxgvHx8YLx8fGC4e/Zm7/nqP+/56j/v+eo/7/n - qP+956X/jt5h/47eYP+P3mL/kd9k/5LfZv+U4Gn/luBr/5fhbf+Z4W//q+aK/8fqs//I6rT/yeq2/8nq - t//N7Lvw8fHxgvHx8YLx8fGC8fHxgvPz84D///8G6+vrDfHx8YLx8fGC8fHxgvHx8YLv8e+Dweis87/n - qP+/56j/v+eo/7/nqP+d4XX/jN1e/47eYP+P3mL/kd9k/5PfZ/+U4Gn/luBr/5fhbf+86KP/xuqy/8fq - s//I6rX/yeq2/9Tsx8nx8fGC8fHxgvHx8YLx8fGC8PDwaAAAAAAAAAAA8fHxbPHx8YLx8fGC8fHxgvHx - 8YLM6rrMv+eo/7/nqP+/56j/v+eo/7blmv+N3V//jN1e/47eYP+Q3mL/kd9k/5PfZ/+U4Gn/qeSH/8Xp - sP/G6bH/xuqy/8fqs//I6rX/5fDem/Hx8YLx8fGC8fHxgvHx8YLz8/M/AAAAAAAAAADz8/NB8fHxgvHx - 8YLx8fGC8fHxgt3s06O/56j/v+eo/7/nqP+/56j/v+eo/7Xmmf+U32n/jN1e/47eYP+Q3mL/k99o/6zk - i//D6a7/xemv/8XpsP/G6bH/xuqy/8vqu+jx8fGC8fHxgvHx8YLx8fGC8fHxgvPz8xUAAAAAAAAAAPT0 - 9Bfx8fGC8fHxgvHx8YLx8fGC8fHvg8Tpsee/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+35pz/suWV/7Xm - mf/A6Kj/wuit/8Porf/E6a7/xemv/8XpsP/G6bH/3e3UqvHx8YLx8fGC8fHxgvHx8YLw8PBmAAAAAAAA - AAAAAAAAAAAAAPHx8W7x8fGC8fHxgvHx8YLx8fGC4u7cmMHnqvm/56j/v+eo/7/nqP+/56j/v+eo/7/n - qP+/56j/wOep/8Hoqv/C6Kz/wuit/8Porf/E6a7/xemv/9Hrwszx8fGC8fHxgvHx8YLx8fGC8fHxgvX1 - 9TEAAAAAAAAAAAAAAAAAAAAA7u7uO/Hx8YLx8fGC8fHxgvHx8YLx8fGC3e7SpMHoqfq/56j/v+eo/7/n - qP+/56j/v+eo/7/nqP+/56j/wOip/8Hoq//C6Kz/wuit/8Porf/O67zV8PHwhPHx8YLx8fGC8fHxgvHx - 8YLy8vJ2////BQAAAAAAAAAAAAAAAAAAAACqqqoD8PDwafHx8YLx8fGC8fHxgvHx8YLx8fGC4O/YnMTo - ruy/56j/v+eo/7/nqP+/56j/v+eo/7/nqP+/56j/wOip/8Hoq//C6Kz90uvEwe/x74Px8fGC8fHxgvHx - 8YLx8fGC8fHxgvPz8ykAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADz8/MW8fHxfPHx8YLx8fGC8fHxgvHx - 8YLx8fGC8PLuhdXtyLXF6bHlv+eo/7/nqP+/56j/v+eo/7/nqP/B6Kv0zeq8zOXv4JTx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLy8vJNAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADy8vIm8fHxgPHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLs8OmJ4e/Zm93u06Pf7def5+/hkvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxXf///wIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AADy8vIo8/PzffHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8VnMzMwFAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAD29vYb8fHxbvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz83/v7+9BgICAAgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADMzMwF8/PzQPLy8nnx8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgvPz84Hx8fFc9PT0GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////B/X19TLx8fFc8PDwevHx - 8YLx8fGC8fHxgvHx8YLx8fGC8fHxgPHx8Wv09PRE9PT0FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAA7+/vEPb29hvw8PAj7+/vH/T09Be/v78EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////////////8B///wAA//wAAD/wAAAP4AAAB+AA - AAfAAAADwAAAA4AAAAGAAAABgAAAAYAAAAGAAAABgAAAAYAAAAGAAAADwAAAA8AAAAPAAAAH4AAAB+AA - AA/wAAAP+AAAH/gAAD/+AAB//wAB///AA///+B////////////8oAAAAEAAAACAAAAABACAAAAAAAAAE - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////CfDw8BH///8GAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgICAAu7u7i7x8fFe8PDwevHx8YLx8fGC8fHxgvDw - 8Hvx8fFs7+/vT/Dw8CMAAAABAAAAAAAAAAAAAAAA5ubmCvLy8l/x8fGC8fHxgvHx8YLx8fGC8fHxgvHx - 8YLx8fGC8fHxgvHx8YLx8fGC8/PzZu7u7g8AAAAAAAAAAPHx8V3x8fGC8fHxgunv5o7Z7c200+vFytTs - xc7W7cnH2+7QueLu2qbu8OyH8fHxgvHx8YLx8fFu////BfHx8STx8fGC8fHxgtrtzq3D6a/8xemw/8bp - sv/I6rT/yeq2/8vruP/M67v/z+u++Nzu0bjx8fGC8fHxgu/v7zDx8fFI8fHxguzw6ojC56z3wuis/8Tp - rv/E6q3/weiq/8fqsv/J6rb/y+u5/8zru//N67z/6/HpjfHx8YLy8vJN8fHxXPHx8YLg79icv+eo/8Ho - qv+k4n//lOBo/5fhbf+a4XH/n+J5/7Pmlv/L67n/zOu7/+Xw353x8fGC8fHxXvHx8Vrx8fGC4O3Zm7/n - qP+/56j/nuF3/5HfZP+U4Gj/l+Ft/5ricf+x5pL/yeq3/8vruf/r8emN8fHxgu/v70/x8fFK8fHxguzw - 6ojA6Kn8v+eo/6njiP+O3mD/kd9k/5Tgaf+X4W3/vuim/8jqtP/N67zr8fHxgvHx8YLy8vI68/PzK/Hx - 8YLx8fGCx+m03L/nqP++6Kb/meBw/47eYP+S32X/q+SL/8XpsP/G6rL/1+zLvvHx8YLz8/OB8PDwEdXV - 1Qbx8fF98fHxgt/t1Z/A56j9v+eo/7/nqP+656H/vuim/8Lorf/E6a7/yOq18Ovw6Yvx8fGC8vLyYwAA - AAAAAAAA8fHxR/Hx8YLx8fGC2O3NrMDnqfq/56j/v+eo/7/nqP/B6Kv/xumy7OTu3Zfx8fGC8/PzgfLy - 8icAAAAAAAAAAP///wPz8/Nm8fHxgvHx8YLo7+SO0+zFuczquszM6bzJ1+zMru7w7Ibx8fGC8fHxgvHx - 8UcAAAAAAAAAAAAAAAAAAAAA4+PjCfHx8Vzx8fGC8fHxgvHx8YLx8fGC8fHxgvHx8YLx8fGC8fHxgfPz - 80D///8BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAB8/PzK/Ly8mDz8/N+8fHxgvHx8YLy8vJ68vLyUezs - 7BsAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAevr6w3j4+MJAAAAAAAA - AAAAAAAAAAAAAAAAAAAAAAAAAAAAAP//AAD8fwAA4AcAAMADAACAAQAAgAEAAIABAACAAQAAgAEAAIAB - AADAAwAAwAMAAOAHAADwDwAA/n8AAP//AAA= - - - \ No newline at end of file diff --git a/extra/exe-builder/FodyWeavers.xml b/extra/exe-builder/FodyWeavers.xml deleted file mode 100644 index 0b37e4ef43..0000000000 --- a/extra/exe-builder/FodyWeavers.xml +++ /dev/null @@ -1,3 +0,0 @@ - - - \ No newline at end of file diff --git a/extra/exe-builder/FodyWeavers.xsd b/extra/exe-builder/FodyWeavers.xsd deleted file mode 100644 index ff119f7131..0000000000 --- a/extra/exe-builder/FodyWeavers.xsd +++ /dev/null @@ -1,141 +0,0 @@ - - - - - - - - - - - - A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks - - - - - A list of assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. - - - - - A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with line breaks - - - - - A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with line breaks. - - - - - A list of unmanaged 32 bit assembly names to include, delimited with line breaks. - - - - - A list of unmanaged 64 bit assembly names to include, delimited with line breaks. - - - - - The order of preloaded assemblies, delimited with line breaks. - - - - - - This will copy embedded files to disk before loading them into memory. This is helpful for some scenarios that expected an assembly to be loaded from a physical file. - - - - - Controls if .pdbs for reference assemblies are also embedded. - - - - - Controls if runtime assemblies are also embedded. - - - - - Controls whether the runtime assemblies are embedded with their full path or only with their assembly name. - - - - - Embedded assemblies are compressed by default, and uncompressed when they are loaded. You can turn compression off with this option. - - - - - As part of Costura, embedded assemblies are no longer included as part of the build. This cleanup can be turned off. - - - - - Costura by default will load as part of the module initialization. This flag disables that behavior. Make sure you call CosturaUtility.Initialize() somewhere in your code. - - - - - Costura will by default use assemblies with a name like 'resources.dll' as a satellite resource and prepend the output path. This flag disables that behavior. - - - - - A list of assembly names to exclude from the default action of "embed all Copy Local references", delimited with | - - - - - A list of assembly names to include from the default action of "embed all Copy Local references", delimited with |. - - - - - A list of runtime assembly names to exclude from the default action of "embed all Copy Local references", delimited with | - - - - - A list of runtime assembly names to include from the default action of "embed all Copy Local references", delimited with |. - - - - - A list of unmanaged 32 bit assembly names to include, delimited with |. - - - - - A list of unmanaged 64 bit assembly names to include, delimited with |. - - - - - The order of preloaded assemblies, delimited with |. - - - - - - - - 'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed. - - - - - A comma-separated list of error codes that can be safely ignored in assembly verification. - - - - - 'false' to turn off automatic generation of the XML Schema file. - - - - - \ No newline at end of file diff --git a/extra/exe-builder/Program.cs b/extra/exe-builder/Program.cs deleted file mode 100644 index 6004f6d4b1..0000000000 --- a/extra/exe-builder/Program.cs +++ /dev/null @@ -1,243 +0,0 @@ -using System; -using System.Collections.Generic; -using System.Diagnostics; -using System.Drawing; -using System.IO; -using System.Linq; -using System.Net; -using System.Net.Sockets; -using System.Reflection; -using System.Runtime.InteropServices; -using System.Threading; -using System.Threading.Tasks; -using System.Windows.Forms; -using Microsoft.Win32; -using Newtonsoft.Json; -using UptimeKuma.Properties; - -namespace UptimeKuma { - static class Program { - /// - /// The main entry point for the application. - /// - [STAThread] - static void Main(string[] args) { - var cwd = Path.GetDirectoryName(Application.ExecutablePath); - - if (cwd != null) { - Environment.CurrentDirectory = cwd; - } - - Application.EnableVisualStyles(); - Application.SetCompatibleTextRenderingDefault(false); - Application.Run(new UptimeKumaApplicationContext()); - } - } - - public class UptimeKumaApplicationContext : ApplicationContext - { - private static Mutex mutex = null; - - const string appName = "Uptime Kuma"; - - private NotifyIcon trayIcon; - private Process process; - - private MenuItem statusMenuItem; - private MenuItem runWhenStarts; - private MenuItem openMenuItem; - - private RegistryKey registryKey = Registry.CurrentUser.OpenSubKey("SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Run", true); - - - public UptimeKumaApplicationContext() { - - // Single instance only - bool createdNew; - mutex = new Mutex(true, appName, out createdNew); - if (!createdNew) { - return; - } - - var startingText = "Starting server..."; - trayIcon = new NotifyIcon(); - trayIcon.Text = startingText; - - runWhenStarts = new MenuItem("Run when system starts", RunWhenStarts); - runWhenStarts.Checked = registryKey.GetValue(appName) != null; - - statusMenuItem = new MenuItem(startingText); - statusMenuItem.Enabled = false; - - openMenuItem = new MenuItem("Open", Open); - openMenuItem.Enabled = false; - - trayIcon.Icon = Icon.ExtractAssociatedIcon(Assembly.GetExecutingAssembly().Location); - trayIcon.ContextMenu = new ContextMenu(new MenuItem[] { - statusMenuItem, - openMenuItem, - //new("Debug Console", DebugConsole), - runWhenStarts, - new("Check for Update...", CheckForUpdate), - new("Visit GitHub...", VisitGitHub), - new("About", About), - new("Exit", Exit), - }); - - trayIcon.MouseDoubleClick += new MouseEventHandler(Open); - trayIcon.Visible = true; - - var hasUpdateFile = File.Exists("update"); - - if (!hasUpdateFile && Directory.Exists("core") && Directory.Exists("node") && Directory.Exists("core/node_modules") && Directory.Exists("core/dist")) { - // Go go go - StartProcess(); - } else { - DownloadFiles(); - } - } - - void DownloadFiles() { - var form = new DownloadForm(); - form.Closed += Exit; - form.Show(); - } - - private void RunWhenStarts(object sender, EventArgs e) { - if (registryKey == null) { - MessageBox.Show("Error: Unable to set startup registry key."); - return; - } - - if (runWhenStarts.Checked) { - registryKey.DeleteValue(appName, false); - runWhenStarts.Checked = false; - } else { - registryKey.SetValue(appName, Application.ExecutablePath); - runWhenStarts.Checked = true; - } - } - - void StartProcess() { - var startInfo = new ProcessStartInfo { - FileName = "node/node.exe", - Arguments = "server/server.js --data-dir=\"../data/\"", - RedirectStandardOutput = false, - RedirectStandardError = false, - UseShellExecute = false, - CreateNoWindow = true, - WorkingDirectory = "core" - }; - - process = new Process(); - process.StartInfo = startInfo; - process.EnableRaisingEvents = true; - process.Exited += ProcessExited; - - try { - process.Start(); - //Open(null, null); - - // Async task to check if the server is ready - Task.Run(() => { - var runningText = "Server is running"; - using TcpClient tcpClient = new TcpClient(); - while (true) { - try { - tcpClient.Connect("127.0.0.1", 3001); - statusMenuItem.Text = runningText; - openMenuItem.Enabled = true; - trayIcon.Text = runningText; - break; - } catch (Exception) { - System.Threading.Thread.Sleep(2000); - } - } - }); - - } catch (Exception e) { - MessageBox.Show("Startup failed: " + e.Message, "Uptime Kuma Error"); - } - } - - void StopProcess() { - process?.Kill(); - } - - void Open(object sender, EventArgs e) { - Process.Start("http://localhost:3001"); - } - - void DebugConsole(object sender, EventArgs e) { - - } - - void CheckForUpdate(object sender, EventArgs e) { - var needUpdate = false; - - // Check version.json exists - if (File.Exists("version.json")) { - // Load version.json and compare with the latest version from GitHub - var currentVersionObj = JsonConvert.DeserializeObject(File.ReadAllText("version.json")); - - var versionJson = new WebClient().DownloadString("https://uptime.kuma.pet/version"); - var latestVersionObj = JsonConvert.DeserializeObject(versionJson); - - // Compare version, if the latest version is newer, then update - if (new System.Version(latestVersionObj.latest).CompareTo(new System.Version(currentVersionObj.latest)) > 0) { - var result = MessageBox.Show("A new version is available. Do you want to update?", "Update", MessageBoxButtons.YesNo); - if (result == DialogResult.Yes) { - // Create a empty file `update`, so the app will download the core files again at startup - File.Create("update").Close(); - - trayIcon.Visible = false; - process?.Kill(); - - // Restart the app, it will download the core files again at startup - Application.Restart(); - } - } else { - MessageBox.Show("You are using the latest version."); - } - } - - - } - - void VisitGitHub(object sender, EventArgs e) - { - Process.Start("https://github.com/louislam/uptime-kuma"); - } - - void About(object sender, EventArgs e) - { - MessageBox.Show("Uptime Kuma Windows Runtime v1.0.0" + Environment.NewLine + "© 2023 Louis Lam", "Info"); - } - - void Exit(object sender, EventArgs e) - { - // Hide tray icon, otherwise it will remain shown until user mouses over it - trayIcon.Visible = false; - process?.Kill(); - Application.Exit(); - } - - void ProcessExited(object sender, EventArgs e) { - - if (process.ExitCode != 0) { - var line = ""; - while (!process.StandardOutput.EndOfStream) - { - line += process.StandardOutput.ReadLine(); - } - - MessageBox.Show("Uptime Kuma exited unexpectedly. Exit code: " + process.ExitCode + " " + line); - } - - trayIcon.Visible = false; - Application.Exit(); - } - - } -} - diff --git a/extra/exe-builder/Properties/AssemblyInfo.cs b/extra/exe-builder/Properties/AssemblyInfo.cs deleted file mode 100644 index 7b20d94c19..0000000000 --- a/extra/exe-builder/Properties/AssemblyInfo.cs +++ /dev/null @@ -1,36 +0,0 @@ -using System.Reflection; -using System.Runtime.CompilerServices; -using System.Runtime.InteropServices; - -// General Information about an assembly is controlled through the following -// set of attributes. Change these attribute values to modify the information -// associated with an assembly. -[assembly: AssemblyTitle("Uptime Kuma")] -[assembly: AssemblyDescription("A portable executable for running Uptime Kuma")] -[assembly: AssemblyConfiguration("")] -[assembly: AssemblyCompany("Uptime Kuma")] -[assembly: AssemblyProduct("Uptime Kuma")] -[assembly: AssemblyCopyright("Copyright © 2023 Louis Lam")] -[assembly: AssemblyTrademark("")] -[assembly: AssemblyCulture("")] - -// Setting ComVisible to false makes the types in this assembly not visible -// to COM components. If you need to access a type in this assembly from -// COM, set the ComVisible attribute to true on that type. -[assembly: ComVisible(false)] - -// The following GUID is for the ID of the typelib if this project is exposed to COM -[assembly: Guid("86B40AFB-61FC-433D-8C31-650B0F32EA8F")] - -// Version information for an assembly consists of the following four values: -// -// Major Version -// Minor Version -// Build Number -// Revision -// -// You can specify all the values or you can default the Build and Revision Numbers -// by using the '*' as shown below: -// [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.0.1.0")] -[assembly: AssemblyFileVersion("1.0.1.0")] diff --git a/extra/exe-builder/Properties/Resources.Designer.cs b/extra/exe-builder/Properties/Resources.Designer.cs deleted file mode 100644 index 8c8e559c55..0000000000 --- a/extra/exe-builder/Properties/Resources.Designer.cs +++ /dev/null @@ -1,62 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace UptimeKuma.Properties { - /// - /// A strongly-typed resource class, for looking up localized strings, etc. - /// - // This class was auto-generated by the StronglyTypedResourceBuilder - // class via a tool like ResGen or Visual Studio. - // To add or remove a member, edit your .ResX file then rerun ResGen - // with the /str option, or rebuild your VS project. - [global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Resources.Tools.StronglyTypedResourceBuilder", - "4.0.0.0")] - [global::System.Diagnostics.DebuggerNonUserCodeAttribute()] - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - internal class Resources { - private static global::System.Resources.ResourceManager resourceMan; - - private static global::System.Globalization.CultureInfo resourceCulture; - - [global::System.Diagnostics.CodeAnalysis.SuppressMessageAttribute("Microsoft.Performance", - "CA1811:AvoidUncalledPrivateCode")] - internal Resources() { - } - - /// - /// Returns the cached ResourceManager instance used by this class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState - .Advanced)] - internal static global::System.Resources.ResourceManager ResourceManager { - get { - if ((resourceMan == null)) { - global::System.Resources.ResourceManager temp = - new global::System.Resources.ResourceManager("UptimeKuma.Properties.Resources", - typeof(Resources).Assembly); - resourceMan = temp; - } - - return resourceMan; - } - } - - /// - /// Overrides the current thread's CurrentUICulture property for all - /// resource lookups using this strongly typed resource class. - /// - [global::System.ComponentModel.EditorBrowsableAttribute(global::System.ComponentModel.EditorBrowsableState - .Advanced)] - internal static global::System.Globalization.CultureInfo Culture { - get { return resourceCulture; } - set { resourceCulture = value; } - } - } -} \ No newline at end of file diff --git a/extra/exe-builder/Properties/Resources.resx b/extra/exe-builder/Properties/Resources.resx deleted file mode 100644 index ffecec851a..0000000000 --- a/extra/exe-builder/Properties/Resources.resx +++ /dev/null @@ -1,117 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - text/microsoft-resx - - - 2.0 - - - System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - - System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 - - \ No newline at end of file diff --git a/extra/exe-builder/Properties/Settings.Designer.cs b/extra/exe-builder/Properties/Settings.Designer.cs deleted file mode 100644 index 6c63b395bb..0000000000 --- a/extra/exe-builder/Properties/Settings.Designer.cs +++ /dev/null @@ -1,23 +0,0 @@ -//------------------------------------------------------------------------------ -// -// This code was generated by a tool. -// Runtime Version:4.0.30319.42000 -// -// Changes to this file may cause incorrect behavior and will be lost if -// the code is regenerated. -// -//------------------------------------------------------------------------------ - -namespace UptimeKuma.Properties { - [global::System.Runtime.CompilerServices.CompilerGeneratedAttribute()] - [global::System.CodeDom.Compiler.GeneratedCodeAttribute( - "Microsoft.VisualStudio.Editors.SettingsDesigner.SettingsSingleFileGenerator", "11.0.0.0")] - internal sealed partial class Settings : global::System.Configuration.ApplicationSettingsBase { - private static Settings defaultInstance = - ((Settings)(global::System.Configuration.ApplicationSettingsBase.Synchronized(new Settings()))); - - public static Settings Default { - get { return defaultInstance; } - } - } -} \ No newline at end of file diff --git a/extra/exe-builder/Properties/Settings.settings b/extra/exe-builder/Properties/Settings.settings deleted file mode 100644 index abf36c5d3d..0000000000 --- a/extra/exe-builder/Properties/Settings.settings +++ /dev/null @@ -1,7 +0,0 @@ - - - - - - - diff --git a/extra/exe-builder/UptimeKuma.csproj b/extra/exe-builder/UptimeKuma.csproj deleted file mode 100644 index ecd6a46b63..0000000000 --- a/extra/exe-builder/UptimeKuma.csproj +++ /dev/null @@ -1,212 +0,0 @@ - - - - - - Debug - AnyCPU - {2DB53988-1D93-4AC0-90C4-96ADEAAC5C04} - WinExe - UptimeKuma - uptime-kuma - v4.7.2 - 512 - true - true - ..\..\public\favicon.ico - 9 - - - AnyCPU - true - full - false - bin\Debug\ - DEBUG;TRACE - prompt - 4 - - - AnyCPU - pdbonly - true - bin\Release\ - TRACE - prompt - 4 - - - app.manifest - - - COPY "$(SolutionDir)bin\Debug\uptime-kuma.exe" "%UserProfile%\Desktop\uptime-kuma-win64\" - - - - packages\Costura.Fody.5.7.0\lib\netstandard1.0\Costura.dll - - - packages\Microsoft.Win32.Primitives.4.3.0\lib\net46\Microsoft.Win32.Primitives.dll - - - - packages\Newtonsoft.Json.13.0.2\lib\net45\Newtonsoft.Json.dll - - - - packages\System.AppContext.4.3.0\lib\net463\System.AppContext.dll - - - packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll - - - - packages\System.Console.4.3.1\lib\net46\System.Console.dll - - - - packages\System.Diagnostics.DiagnosticSource.7.0.1\lib\net462\System.Diagnostics.DiagnosticSource.dll - - - packages\System.Diagnostics.Tracing.4.3.0\lib\net462\System.Diagnostics.Tracing.dll - - - packages\System.Globalization.Calendars.4.3.0\lib\net46\System.Globalization.Calendars.dll - - - packages\System.IO.4.3.0\lib\net462\System.IO.dll - - - packages\System.IO.Compression.4.3.0\lib\net46\System.IO.Compression.dll - - - - packages\System.IO.Compression.ZipFile.4.3.0\lib\net46\System.IO.Compression.ZipFile.dll - - - packages\System.IO.FileSystem.4.3.0\lib\net46\System.IO.FileSystem.dll - - - packages\System.IO.FileSystem.Primitives.4.3.0\lib\net46\System.IO.FileSystem.Primitives.dll - - - packages\System.Linq.4.3.0\lib\net463\System.Linq.dll - - - packages\System.Linq.Expressions.4.3.0\lib\net463\System.Linq.Expressions.dll - - - packages\System.Memory.4.5.5\lib\net461\System.Memory.dll - - - packages\System.Net.Http.4.3.4\lib\net46\System.Net.Http.dll - - - packages\System.Net.Sockets.4.3.0\lib\net46\System.Net.Sockets.dll - - - - packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll - - - packages\System.Reflection.4.3.0\lib\net462\System.Reflection.dll - - - packages\System.Runtime.4.3.1\lib\net462\System.Runtime.dll - - - packages\System.Runtime.CompilerServices.Unsafe.6.0.0\lib\net461\System.Runtime.CompilerServices.Unsafe.dll - - - packages\System.Runtime.Extensions.4.3.1\lib\net462\System.Runtime.Extensions.dll - - - packages\System.Runtime.InteropServices.4.3.0\lib\net463\System.Runtime.InteropServices.dll - - - packages\System.Runtime.InteropServices.RuntimeInformation.4.3.0\lib\net45\System.Runtime.InteropServices.RuntimeInformation.dll - - - packages\System.Security.Cryptography.Algorithms.4.3.1\lib\net463\System.Security.Cryptography.Algorithms.dll - - - packages\System.Security.Cryptography.Encoding.4.3.0\lib\net46\System.Security.Cryptography.Encoding.dll - - - packages\System.Security.Cryptography.Primitives.4.3.0\lib\net46\System.Security.Cryptography.Primitives.dll - - - packages\System.Security.Cryptography.X509Certificates.4.3.2\lib\net461\System.Security.Cryptography.X509Certificates.dll - - - packages\System.Text.RegularExpressions.4.3.1\lib\net463\System.Text.RegularExpressions.dll - - - - - - - - - - - packages\System.Xml.ReaderWriter.4.3.1\lib\net46\System.Xml.ReaderWriter.dll - - - - - Form - - - DownloadForm.cs - - - - - - DownloadForm.cs - - - ResXFileCodeGenerator - Resources.Designer.cs - Designer - - - True - Resources.resx - - - favicon.ico - - - - SettingsSingleFileGenerator - Settings.Designer.cs - - - True - Settings.settings - True - - - - - - - - - - - - - This project references NuGet package(s) that are missing on this computer. Enable NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105.The missing file is {0}. - - - - - - - - - - \ No newline at end of file diff --git a/extra/exe-builder/UptimeKuma.sln b/extra/exe-builder/UptimeKuma.sln deleted file mode 100644 index 201d7e2341..0000000000 --- a/extra/exe-builder/UptimeKuma.sln +++ /dev/null @@ -1,16 +0,0 @@ - -Microsoft Visual Studio Solution File, Format Version 12.00 -Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UptimeKuma", "UptimeKuma.csproj", "{2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}" -EndProject -Global - GlobalSection(SolutionConfigurationPlatforms) = preSolution - Debug|Any CPU = Debug|Any CPU - Release|Any CPU = Release|Any CPU - EndGlobalSection - GlobalSection(ProjectConfigurationPlatforms) = postSolution - {2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Debug|Any CPU.ActiveCfg = Debug|Any CPU - {2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Debug|Any CPU.Build.0 = Debug|Any CPU - {2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Release|Any CPU.ActiveCfg = Release|Any CPU - {2DB53988-1D93-4AC0-90C4-96ADEAAC5C04}.Release|Any CPU.Build.0 = Release|Any CPU - EndGlobalSection -EndGlobal diff --git a/extra/exe-builder/UptimeKuma.sln.DotSettings.user b/extra/exe-builder/UptimeKuma.sln.DotSettings.user deleted file mode 100644 index b4ca9dadfa..0000000000 --- a/extra/exe-builder/UptimeKuma.sln.DotSettings.user +++ /dev/null @@ -1,3 +0,0 @@ - - True - True \ No newline at end of file diff --git a/extra/exe-builder/Version.cs b/extra/exe-builder/Version.cs deleted file mode 100644 index 896c7a2449..0000000000 --- a/extra/exe-builder/Version.cs +++ /dev/null @@ -1,9 +0,0 @@ -namespace UptimeKuma { - public class Version { - public string latest { get; set; } - public string slow { get; set; } - public string beta { get; set; } - public string nodejs { get; set; } - public string exe { get; set; } - } -} diff --git a/extra/exe-builder/app.manifest b/extra/exe-builder/app.manifest deleted file mode 100644 index 4a48528fcc..0000000000 --- a/extra/exe-builder/app.manifest +++ /dev/null @@ -1,28 +0,0 @@ - - - - - true - PerMonitorV2 - - - - - - - - - - - diff --git a/extra/exe-builder/packages.config b/extra/exe-builder/packages.config deleted file mode 100644 index aca26d6708..0000000000 --- a/extra/exe-builder/packages.config +++ /dev/null @@ -1,56 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/extra/fs-rmSync.js b/extra/fs-rmSync.js deleted file mode 100644 index aa45b6dc3e..0000000000 --- a/extra/fs-rmSync.js +++ /dev/null @@ -1,23 +0,0 @@ -const fs = require("fs"); -/** - * Detect if `fs.rmSync` is available - * to avoid the runtime deprecation warning triggered for using `fs.rmdirSync` with `{ recursive: true }` in Node.js v16, - * or the `recursive` property removing completely in the future Node.js version. - * See the link below. - * - * @todo Once we drop the support for Node.js v14 (or at least versions before v14.14.0), we can safely replace this function with `fs.rmSync`, since `fs.rmSync` was add in Node.js v14.14.0 and currently we supports all the Node.js v14 versions that include the versions before the v14.14.0, and this function have almost the same signature with `fs.rmSync`. - * @link https://nodejs.org/docs/latest-v16.x/api/deprecations.html#dep0147-fsrmdirpath--recursive-true- the deprecation infomation of `fs.rmdirSync` - * @link https://nodejs.org/docs/latest-v16.x/api/fs.html#fsrmsyncpath-options the document of `fs.rmSync` - * @param {fs.PathLike} path Valid types for path values in "fs". - * @param {fs.RmDirOptions} [options] options for `fs.rmdirSync`, if `fs.rmSync` is available and property `recursive` is true, it will automatically have property `force` with value `true`. - */ -const rmSync = (path, options) => { - if (typeof fs.rmSync === "function") { - if (options.recursive) { - options.force = true; - } - return fs.rmSync(path, options); - } - return fs.rmdirSync(path, options); -}; -module.exports = rmSync; diff --git a/extra/install.batsh b/extra/install.batsh deleted file mode 100644 index e2f9a75116..0000000000 --- a/extra/install.batsh +++ /dev/null @@ -1,276 +0,0 @@ -// install.sh is generated by ./extra/install.batsh, do not modify it directly. -// "npm run compile-install-script" to compile install.sh -// The command is working on Windows PowerShell and Docker for Windows only. - - -// curl -o kuma_install.sh https://raw.githubusercontent.com/louislam/uptime-kuma/master/install.sh && sudo bash kuma_install.sh -println("====================="); -println("Uptime Kuma Install Script"); -println("====================="); -println("Supported OS: Ubuntu >= 16.04, Debian and CentOS/RHEL 7/8"); -println("---------------------------------------"); -println("This script is designed for Linux and basic usage."); -println("For advanced usage, please go to https://github.com/louislam/uptime-kuma/wiki/Installation"); -println("---------------------------------------"); -println(""); -println("Local - Install Uptime Kuma on your current machine with git, Node.js and pm2"); -println("Docker - Install Uptime Kuma Docker container"); -println(""); - -if ("$1" != "") { - type = "$1"; -} else { - call("read", "-p", "Which installation method do you prefer? [DOCKER/local]: ", "type"); -} - -defaultPort = "3001"; - -function checkNode() { - bash("nodeVersion=$(node -e 'console.log(process.versions.node.split(`.`)[0])')"); - println("Node Version: " ++ nodeVersion); - - if (nodeVersion <= "12") { - println("Error: Required Node.js 14"); - call("exit", "1"); - } -} - -function deb() { - bash("nodeCheck=$(node -v)"); - bash("apt --yes update"); - - if (nodeCheck != "") { - checkNode(); - } else { - - // Old nodejs binary name is "nodejs" - bash("check=$(nodejs --version)"); - if (check != "") { - println("Error: 'node' command is not found, but 'nodejs' command is found. Your NodeJS should be too old."); - bash("exit 1"); - } - - bash("curlCheck=$(curl --version)"); - if (curlCheck == "") { - println("Installing Curl"); - bash("apt --yes install curl"); - } - - println("Installing Node.js 16"); - bash("curl -sL https://deb.nodesource.com/setup_16.x | bash - > log.txt"); - bash("apt --yes install nodejs"); - bash("node -v"); - - bash("nodeCheckAgain=$(node -v)"); - - if (nodeCheckAgain == "") { - println("Error during Node.js installation"); - bash("exit 1"); - } - } - - bash("check=$(git --version)"); - if (check == "") { - println("Installing Git"); - bash("apt --yes install git"); - } -} - -if (type == "local") { - defaultInstallPath = "/opt/uptime-kuma"; - - if (exists("/etc/redhat-release")) { - os = call("cat", "/etc/redhat-release"); - distribution = "rhel"; - - } else if (exists("/etc/issue")) { - bash("os=$(head -n1 /etc/issue | cut -f 1 -d ' ')"); - if (os == "Ubuntu") { - distribution = "ubuntu"; - - // Get ubuntu version - bash(". /etc/lsb-release"); - version = DISTRIB_RELEASE; - } - if (os == "Debian") { - distribution = "debian"; - } - } - - bash("arch=$(uname -i)"); - - println("Your OS: " ++ os); - println("Distribution: " ++ distribution); - println("Version: " ++ version); - println("Arch: " ++ arch); - - if ("$3" != "") { - port = "$3"; - } else { - call("read", "-p", "Listening Port [$defaultPort]: ", "port"); - - if (port == "") { - port = defaultPort; - } - } - - if ("$2" != "") { - installPath = "$2"; - } else { - call("read", "-p", "Installation Path [$defaultInstallPath]: ", "installPath"); - - if (installPath == "") { - installPath = defaultInstallPath; - } - } - - // CentOS - if (distribution == "rhel") { - bash("nodeCheck=$(node -v)"); - - if (nodeCheck != "") { - checkNode(); - } else { - - bash("dnfCheck=$(dnf --version)"); - - // Use yum - if (dnfCheck == "") { - bash("curlCheck=$(curl --version)"); - if (curlCheck == "") { - println("Installing Curl"); - bash("yum -y -q install curl"); - } - - println("Installing Node.js 16"); - bash("curl -sL https://rpm.nodesource.com/setup_16.x | bash - > log.txt"); - bash("yum install -y -q nodejs"); - } else { - bash("curlCheck=$(curl --version)"); - if (curlCheck == "") { - println("Installing Curl"); - bash("dnf -y install curl"); - } - - println("Installing Node.js 16"); - bash("curl -sL https://rpm.nodesource.com/setup_16.x | bash - > log.txt"); - bash("dnf install -y nodejs"); - } - - - bash("node -v"); - - bash("nodeCheckAgain=$(node -v)"); - - if (nodeCheckAgain == "") { - println("Error during Node.js installation"); - bash("exit 1"); - } - } - - bash("check=$(git --version)"); - if (check == "") { - println("Installing Git"); - bash("yum -y -q install git"); - } - - // Ubuntu - } else if (distribution == "ubuntu") { - deb(); - - // Debian - } else if (distribution == "debian") { - deb(); - - } else { - // Unknown distribution - error = 0; - - bash("check=$(git --version)"); - if (check == "") { - error = 1; - println("Error: git is not found!"); - println("help: an installation guide is available at https://git-scm.com/book/en/v2/Getting-Started-Installing-Git"); - } - - bash("check=$(node -v)"); - if (check == "") { - error = 1; - println("Error: node is not found"); - println("help: an installation guide is available at https://nodejs.org/en/download"); - } - - if (error > 0) { - println("Please install above missing software"); - bash("exit 1"); - } - } - - bash("check=$(pm2 --version)"); - if (check == "") { - println("Installing PM2"); - bash("npm install pm2 -g && pm2 install pm2-logrotate"); - bash("pm2 startup"); - } - - - // Check again - bash("check=$(pm2 --version)"); - if (check == "") { - println("Error: pm2 is not found!"); - println("help: an installation guide is available at https://pm2.keymetrics.io/docs/usage/quick-start/"); - bash("exit 1"); - } - - bash("mkdir -p $installPath"); - bash("cd $installPath"); - bash("git clone https://github.com/louislam/uptime-kuma.git ."); - bash("npm run setup"); - - bash("pm2 start server/server.js --name uptime-kuma -- --port=$port"); - -} else { - defaultVolume = "uptime-kuma"; - - bash("check=$(docker -v)"); - if (check == "") { - println("Error: docker is not found!"); - println("help: an installation guide is available at https://docs.docker.com/desktop/"); - bash("exit 1"); - } - - bash("check=$(docker info)"); - - bash("if [[ \"$check\" == *\"Is the docker daemon running\"* ]]; then - \"echo\" \"Error: docker is not running\" - \"echo\" \"help: a troubleshooting guide is available at https://docs.docker.com/config/daemon/troubleshoot/\" - \"exit\" \"1\" - fi"); - - if ("$3" != "") { - port = "$3"; - } else { - call("read", "-p", "Expose Port [$defaultPort]: ", "port"); - - if (port == "") { - port = defaultPort; - } - } - - if ("$2" != "") { - volume = "$2"; - } else { - call("read", "-p", "Volume Name [$defaultVolume]: ", "volume"); - - if (volume == "") { - volume = defaultVolume; - } - } - - println("Port: $port"); - println("Volume: $volume"); - bash("docker volume create $volume"); - bash("docker run -d --restart=always -p $port:3001 -v $volume:/app/data --name uptime-kuma louislam/uptime-kuma:1"); -} - -println("http://localhost:$port"); diff --git a/extra/mark-as-nightly.js b/extra/mark-as-nightly.js index ada2aca81f..d2cb8cb4bf 100644 --- a/extra/mark-as-nightly.js +++ b/extra/mark-as-nightly.js @@ -15,7 +15,6 @@ if (newVersion) { // Process package.json pkg.version = newVersion; pkg.scripts.setup = pkg.scripts.setup.replaceAll(oldVersion, newVersion); - pkg.scripts["build-docker"] = pkg.scripts["build-docker"].replaceAll(oldVersion, newVersion); fs.writeFileSync("package.json", JSON.stringify(pkg, null, 4) + "\n"); // Process README.md diff --git a/extra/press-any-key.js b/extra/press-any-key.js deleted file mode 100644 index 42fc363cd9..0000000000 --- a/extra/press-any-key.js +++ /dev/null @@ -1,6 +0,0 @@ -console.log("Git Push and Publish the release note on github, then press any key to continue"); - -process.stdin.setRawMode(true); -process.stdin.resume(); -process.stdin.on("data", process.exit.bind(process, 0)); - diff --git a/extra/push-examples/.gitignore b/extra/push-examples/.gitignore new file mode 100644 index 0000000000..717394d0bd --- /dev/null +++ b/extra/push-examples/.gitignore @@ -0,0 +1,3 @@ +java/Index.class +csharp/index.exe +typescript-fetch/index.js diff --git a/extra/push-examples/bash-curl/index.sh b/extra/push-examples/bash-curl/index.sh new file mode 100644 index 0000000000..3031255f42 --- /dev/null +++ b/extra/push-examples/bash-curl/index.sh @@ -0,0 +1,10 @@ +#!/bin/bash +# Filename: index.sh +PUSH_URL="https://example.com/api/push/key?status=up&msg=OK&ping=" +INTERVAL=60 + +while true; do + curl -s -o /dev/null $PUSH_URL + echo "Pushed!" + sleep $INTERVAL +done diff --git a/extra/push-examples/csharp/index.cs b/extra/push-examples/csharp/index.cs new file mode 100644 index 0000000000..94eecfb848 --- /dev/null +++ b/extra/push-examples/csharp/index.cs @@ -0,0 +1,24 @@ +using System; +using System.Net; +using System.Threading; + +/** + * Compile: C:\Windows\Microsoft.NET\Framework\v4.0.30319\csc.exe index.cs + * Run: index.exe + */ +class Index +{ + const string PushURL = "https://example.com/api/push/key?status=up&msg=OK&ping="; + const int Interval = 60; + + static void Main(string[] args) + { + while (true) + { + WebClient client = new WebClient(); + client.DownloadString(PushURL); + Console.WriteLine("Pushed!"); + Thread.Sleep(Interval * 1000); + } + } +} diff --git a/extra/push-examples/docker/index.sh b/extra/push-examples/docker/index.sh new file mode 100644 index 0000000000..1eb43d650d --- /dev/null +++ b/extra/push-examples/docker/index.sh @@ -0,0 +1 @@ +docker run -d --restart=always --name uptime-kuma-push louislam/uptime-kuma:push "https://example.com/api/push/key?status=up&msg=OK&ping=" 60 diff --git a/extra/push-examples/go/index.go b/extra/push-examples/go/index.go new file mode 100644 index 0000000000..2e518e74ed --- /dev/null +++ b/extra/push-examples/go/index.go @@ -0,0 +1,20 @@ +package main + +import ( + "fmt" + "net/http" + "time" +) + +func main() { + const PushURL = "https://example.com/api/push/key?status=up&msg=OK&ping=" + const Interval = 60 + + for { + _, err := http.Get(PushURL) + if err == nil { + fmt.Println("Pushed!") + } + time.Sleep(Interval * time.Second) + } +} diff --git a/extra/push-examples/java/index.java b/extra/push-examples/java/index.java new file mode 100644 index 0000000000..5a773428ac --- /dev/null +++ b/extra/push-examples/java/index.java @@ -0,0 +1,32 @@ +import java.net.HttpURLConnection; +import java.net.URL; + +/** + * Compile: javac index.java + * Run: java Index + */ +class Index { + + public static final String PUSH_URL = "https://example.com/api/push/key?status=up&msg=OK&ping="; + public static final int INTERVAL = 60; + + public static void main(String[] args) { + while (true) { + try { + URL url = new URL(PUSH_URL); + HttpURLConnection con = (HttpURLConnection) url.openConnection(); + con.setRequestMethod("GET"); + con.getResponseCode(); + con.disconnect(); + System.out.println("Pushed!"); + } catch (Exception e) { + e.printStackTrace(); + } + try { + Thread.sleep(INTERVAL * 1000); + } catch (Exception e) { + e.printStackTrace(); + } + } + } +} diff --git a/extra/push-examples/javascript-fetch/index.js b/extra/push-examples/javascript-fetch/index.js new file mode 100644 index 0000000000..9d21d0db82 --- /dev/null +++ b/extra/push-examples/javascript-fetch/index.js @@ -0,0 +1,11 @@ +// Supports: Node.js >= 18, Deno, Bun +const pushURL = "https://example.com/api/push/key?status=up&msg=OK&ping="; +const interval = 60; + +const push = async () => { + await fetch(pushURL); + console.log("Pushed!"); +}; + +push(); +setInterval(push, interval * 1000); diff --git a/extra/push-examples/javascript-fetch/package.json b/extra/push-examples/javascript-fetch/package.json new file mode 100644 index 0000000000..78aefc2348 --- /dev/null +++ b/extra/push-examples/javascript-fetch/package.json @@ -0,0 +1,5 @@ +{ + "scripts": { + "start": "node index.js" + } +} diff --git a/extra/push-examples/php/index.php b/extra/push-examples/php/index.php new file mode 100644 index 0000000000..d08b451ab9 --- /dev/null +++ b/extra/push-examples/php/index.php @@ -0,0 +1,13 @@ += 18 (ts-node) +const pushURL : string = "https://example.com/api/push/key?status=up&msg=OK&ping="; +const interval : number = 60; + +const push = async () => { + await fetch(pushURL); + console.log("Pushed!"); +}; + +push(); +setInterval(push, interval * 1000); diff --git a/extra/push-examples/typescript-fetch/package.json b/extra/push-examples/typescript-fetch/package.json new file mode 100644 index 0000000000..9d7e974437 --- /dev/null +++ b/extra/push-examples/typescript-fetch/package.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "ts-node": "ts-node index.ts", + "deno": "deno run --allow-net index.ts", + "bun": "bun index.ts" + }, + "devDependencies": { + "@types/node": "^20.6.0", + "ts-node": "^10.9.1", + "tslib": "^2.6.2", + "typescript": "^5.2.2" + } +} diff --git a/extra/rebase-pr.js b/extra/rebase-pr.js new file mode 100644 index 0000000000..4921d2e7c8 --- /dev/null +++ b/extra/rebase-pr.js @@ -0,0 +1,40 @@ +const { execSync } = require("child_process"); + +/** + * Rebase a PR onto such as 1.23.X or master + * @returns {Promise} + */ +async function main() { + const branch = process.argv[2]; + + // Use gh to get current branch's pr id + let currentBranchPRID = execSync("gh pr view --json number --jq \".number\"").toString().trim(); + console.log("Pr ID: ", currentBranchPRID); + + // Use gh commend to get pr commits + const prCommits = JSON.parse(execSync(`gh pr view ${currentBranchPRID} --json commits`).toString().trim()).commits; + + console.log("Found commits: ", prCommits.length); + + // Sort the commits by authoredDate + prCommits.sort((a, b) => { + return new Date(a.authoredDate) - new Date(b.authoredDate); + }); + + // Get the oldest commit id + const oldestCommitID = prCommits[0].oid; + console.log("Oldest commit id of this pr:", oldestCommitID); + + // Get the latest commit id of the target branch + const latestCommitID = execSync(`git rev-parse origin/${branch}`).toString().trim(); + console.log("Latest commit id of " + branch + ":", latestCommitID); + + // Get the original parent commit id of the oldest commit + const originalParentCommitID = execSync(`git log --pretty=%P -n 1 "${oldestCommitID}"`).toString().trim(); + console.log("Original parent commit id of the oldest commit:", originalParentCommitID); + + // Rebase the pr onto the target branch + execSync(`git rebase --onto ${latestCommitID} ${originalParentCommitID}`); +} + +main(); diff --git a/extra/release/beta.mjs b/extra/release/beta.mjs new file mode 100644 index 0000000000..7ea13b9b4f --- /dev/null +++ b/extra/release/beta.mjs @@ -0,0 +1,64 @@ +import "dotenv/config"; +import { + ver, + buildDist, + buildImage, + checkDocker, + checkTagExists, + checkVersionFormat, + getRepoNames, + pressAnyKey, + execSync, uploadArtifacts, +} from "./lib.mjs"; +import semver from "semver"; + +const repoNames = getRepoNames(); +const version = process.env.RELEASE_BETA_VERSION; +const githubToken = process.env.RELEASE_GITHUB_TOKEN; + +console.log("RELEASE_BETA_VERSION:", version); + +if (!githubToken) { + console.error("GITHUB_TOKEN is required"); + process.exit(1); +} + +// Check if the version is a valid semver +checkVersionFormat(version); + +// Check if the semver identifier is "beta" +const semverIdentifier = semver.prerelease(version); +console.log("Semver identifier:", semverIdentifier); +if (semverIdentifier[0] !== "beta") { + console.error("VERSION should have a semver identifier of 'beta'"); + process.exit(1); +} + +// Check if docker is running +checkDocker(); + +// Check if the tag exists +await checkTagExists(repoNames, version); + +// node extra/beta/update-version.js +execSync("node ./extra/beta/update-version.js"); + +// Build frontend dist +buildDist(); + +// Build slim image (rootless) +buildImage(repoNames, [ "beta-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base2-slim"); + +// Build full image (rootless) +buildImage(repoNames, [ "beta-rootless", ver(version, "rootless") ], "rootless"); + +// Build slim image +buildImage(repoNames, [ "beta-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base2-slim"); + +// Build full image +buildImage(repoNames, [ "beta", version ], "release"); + +await pressAnyKey(); + +// npm run upload-artifacts +uploadArtifacts(version, githubToken); diff --git a/extra/release/final.mjs b/extra/release/final.mjs new file mode 100644 index 0000000000..bf0ec2b0cd --- /dev/null +++ b/extra/release/final.mjs @@ -0,0 +1,57 @@ +import "dotenv/config"; +import { + ver, + buildDist, + buildImage, + checkDocker, + checkTagExists, + checkVersionFormat, + getRepoNames, + pressAnyKey, execSync, uploadArtifacts +} from "./lib.mjs"; + +const repoNames = getRepoNames(); +const version = process.env.RELEASE_VERSION; +const githubToken = process.env.RELEASE_GITHUB_TOKEN; + +console.log("RELEASE_VERSION:", version); + +if (!githubToken) { + console.error("GITHUB_TOKEN is required"); + process.exit(1); +} + +// Check if the version is a valid semver +checkVersionFormat(version); + +// Check if docker is running +checkDocker(); + +// Check if the tag exists +await checkTagExists(repoNames, version); + +// node extra/beta/update-version.js +execSync("node extra/update-version.js"); + +// Build frontend dist +buildDist(); + +// Build slim image (rootless) +buildImage(repoNames, [ "2-slim-rootless", ver(version, "slim-rootless") ], "rootless", "BASE_IMAGE=louislam/uptime-kuma:base2-slim"); + +// Build full image (rootless) +buildImage(repoNames, [ "2-rootless", ver(version, "rootless") ], "rootless"); + +// Build slim image +buildImage(repoNames, [ "next-slim", "2-slim", ver(version, "slim") ], "release", "BASE_IMAGE=louislam/uptime-kuma:base2-slim"); + +// Build full image +buildImage(repoNames, [ "next", "2", version ], "release"); + +await pressAnyKey(); + +// npm run upload-artifacts +uploadArtifacts(version, githubToken); + +// node extra/update-wiki-version.js +execSync("node extra/update-wiki-version.js"); diff --git a/extra/release/lib.mjs b/extra/release/lib.mjs new file mode 100644 index 0000000000..cd06cd3705 --- /dev/null +++ b/extra/release/lib.mjs @@ -0,0 +1,233 @@ +import "dotenv/config"; +import * as childProcess from "child_process"; +import semver from "semver"; + +export const dryRun = process.env.RELEASE_DRY_RUN === "1"; + +if (dryRun) { + console.info("Dry run enabled."); +} + +/** + * Check if docker is running + * @returns {void} + */ +export function checkDocker() { + try { + childProcess.execSync("docker ps"); + } catch (error) { + console.error("Docker is not running. Please start docker and try again."); + process.exit(1); + } +} + +/** + * Get Docker Hub repository name + */ +export function getRepoNames() { + if (process.env.RELEASE_REPO_NAMES) { + // Split by comma + return process.env.RELEASE_REPO_NAMES.split(",").map((name) => name.trim()); + } + return [ + "louislam/uptime-kuma", + "ghcr.io/louislam/uptime-kuma", + ]; +} + +/** + * Build frontend dist + * @returns {void} + */ +export function buildDist() { + if (!dryRun) { + childProcess.execSync("npm run build", { stdio: "inherit" }); + } else { + console.info("[DRY RUN] npm run build"); + } +} + +/** + * Build docker image and push to Docker Hub + * @param {string[]} repoNames Docker Hub repository names + * @param {string[]} tags Docker image tags + * @param {string} target Dockerfile's target name + * @param {string} buildArgs Docker build args + * @param {string} dockerfile Path to Dockerfile + * @param {string} platform Build platform + * @returns {void} + */ +export function buildImage(repoNames, tags, target, buildArgs = "", dockerfile = "docker/dockerfile", platform = "linux/amd64,linux/arm64,linux/arm/v7") { + let args = [ + "buildx", + "build", + "-f", + dockerfile, + "--platform", + platform, + ]; + + for (let repoName of repoNames) { + // Add tags + for (let tag of tags) { + args.push("-t", `${repoName}:${tag}`); + } + } + + args = [ + ...args, + "--target", + target, + ]; + + // Add build args + if (buildArgs) { + args.push("--build-arg", buildArgs); + } + + args = [ + ...args, + ".", + "--push", + ]; + + if (!dryRun) { + childProcess.spawnSync("docker", args, { stdio: "inherit" }); + } else { + console.log(`[DRY RUN] docker ${args.join(" ")}`); + } +} + +/** + * Check if the version already exists on Docker Hub + * TODO: use semver to compare versions if it is greater than the previous? + * @param {string} repoName Docker Hub repository name + * @param {string} version Version to check + * @returns {void} + */ +export async function checkTagExists(repoName, version) { + console.log(`Checking if version ${version} exists on Docker Hub`); + + // Get a list of tags from the Docker Hub repository + let tags = []; + + // It is mainly to check my careless mistake that I forgot to update the release version in .env, so `page_size` is set to 100 is enough, I think. + const response = await fetch(`https://hub.docker.com/v2/repositories/${repoName}/tags/?page_size=100`); + if (response.ok) { + const data = await response.json(); + tags = data.results.map((tag) => tag.name); + } else { + console.error("Failed to get tags from Docker Hub"); + process.exit(1); + } + + // Check if the version already exists + if (tags.includes(version)) { + console.error(`Version ${version} already exists`); + process.exit(1); + } +} + +/** + * Check the version format + * @param {string} version Version to check + * @returns {void} + */ +export function checkVersionFormat(version) { + if (!version) { + console.error("VERSION is required"); + process.exit(1); + } + + // Check the version format, it should be a semver and must be like this: "2.0.0-beta.0" + if (!semver.valid(version)) { + console.error("VERSION is not a valid semver version"); + process.exit(1); + } +} + +/** + * Press any key to continue + * @returns {Promise} + */ +export function pressAnyKey() { + console.log("Git Push and Publish the release note on github, then press any key to continue"); + process.stdin.setRawMode(true); + process.stdin.resume(); + return new Promise(resolve => process.stdin.once("data", data => { + process.stdin.setRawMode(false); + process.stdin.pause(); + resolve(); + })); +} + +/** + * Append version identifier + * @param {string} version Version + * @param {string} identifier Identifier + * @returns {string} Version with identifier + */ +export function ver(version, identifier) { + const obj = semver.parse(version); + + if (obj.prerelease.length === 0) { + obj.prerelease = [ identifier ]; + } else { + obj.prerelease[0] = [ obj.prerelease[0], identifier ].join("-"); + } + return obj.format(); +} + +/** + * Upload artifacts to GitHub + * docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain + * @param {string} version Version + * @param {string} githubToken GitHub token + * @returns {void} + */ +export function uploadArtifacts(version, githubToken) { + let args = [ + "buildx", + "build", + "-f", + "docker/dockerfile", + "--platform", + "linux/amd64", + "-t", + "louislam/uptime-kuma:upload-artifact", + "--build-arg", + `VERSION=${version}`, + "--build-arg", + "GITHUB_TOKEN", + "--target", + "upload-artifact", + ".", + "--progress", + "plain", + ]; + + if (!dryRun) { + childProcess.spawnSync("docker", args, { + stdio: "inherit", + env: { + ...process.env, + GITHUB_TOKEN: githubToken, + }, + }); + } else { + console.log(`[DRY RUN] docker ${args.join(" ")}`); + } +} + +/** + * Execute a command + * @param {string} cmd Command to execute + * @returns {void} + */ +export function execSync(cmd) { + if (!dryRun) { + childProcess.execSync(cmd, { stdio: "inherit" }); + } else { + console.info(`[DRY RUN] ${cmd}`); + } +} diff --git a/extra/release/nightly.mjs b/extra/release/nightly.mjs new file mode 100644 index 0000000000..54951ac42a --- /dev/null +++ b/extra/release/nightly.mjs @@ -0,0 +1,16 @@ +import { buildDist, buildImage, checkDocker, getRepoNames } from "./lib.mjs"; + +// Docker Hub repository name +const repoNames = getRepoNames(); + +// Check if docker is running +checkDocker(); + +// Build frontend dist (it will build on the host machine, TODO: build on a container?) +buildDist(); + +// Build full image (rootless) +buildImage(repoNames, [ "nightly2-rootless" ], "nightly-rootless"); + +// Build full image +buildImage(repoNames, [ "nightly2" ], "nightly"); diff --git a/extra/release/upload-artifacts-beta.mjs b/extra/release/upload-artifacts-beta.mjs new file mode 100644 index 0000000000..2897097e66 --- /dev/null +++ b/extra/release/upload-artifacts-beta.mjs @@ -0,0 +1,6 @@ +import { uploadArtifacts } from "./lib.mjs"; + +const version = process.env.RELEASE_BETA_VERSION; +const githubToken = process.env.RELEASE_GITHUB_TOKEN; + +uploadArtifacts(version, githubToken); diff --git a/extra/release/upload-artifacts.mjs b/extra/release/upload-artifacts.mjs new file mode 100644 index 0000000000..cd34bd7d41 --- /dev/null +++ b/extra/release/upload-artifacts.mjs @@ -0,0 +1,6 @@ +import { uploadArtifacts } from "./lib.mjs"; + +const version = process.env.RELEASE_VERSION; +const githubToken = process.env.RELEASE_GITHUB_TOKEN; + +uploadArtifacts(version, githubToken); diff --git a/extra/remove-2fa.js b/extra/remove-2fa.js index f88c43fcac..e6a8b97c80 100644 --- a/extra/remove-2fa.js +++ b/extra/remove-2fa.js @@ -12,7 +12,7 @@ const rl = readline.createInterface({ }); const main = async () => { - Database.init(args); + Database.initDataDir(args); await Database.connect(); try { diff --git a/extra/remove-empty-lang-keys.js b/extra/remove-empty-lang-keys.js new file mode 100644 index 0000000000..6b34fa00c9 --- /dev/null +++ b/extra/remove-empty-lang-keys.js @@ -0,0 +1,25 @@ +// For #5231 + +const fs = require("fs"); + +let path = "../src/lang"; + +// list directories in the lang directory +let jsonFileList = fs.readdirSync(path); + +for (let jsonFile of jsonFileList) { + if (!jsonFile.endsWith(".json")) { + continue; + } + + let jsonPath = path + "/" + jsonFile; + let langData = JSON.parse(fs.readFileSync(jsonPath, "utf8")); + + for (let key in langData) { + if (langData[key] === "") { + delete langData[key]; + } + } + + fs.writeFileSync(jsonPath, JSON.stringify(langData, null, 4) + "\n"); +} diff --git a/extra/remove-playwright-test-data.js b/extra/remove-playwright-test-data.js new file mode 100644 index 0000000000..0628807e77 --- /dev/null +++ b/extra/remove-playwright-test-data.js @@ -0,0 +1,6 @@ +const fs = require("fs"); + +fs.rmSync("./data/playwright-test", { + recursive: true, + force: true, +}); diff --git a/extra/reset-migrate-aggregate-table-state.js b/extra/reset-migrate-aggregate-table-state.js new file mode 100644 index 0000000000..e6c51fbd0b --- /dev/null +++ b/extra/reset-migrate-aggregate-table-state.js @@ -0,0 +1,24 @@ +const { R } = require("redbean-node"); +const Database = require("../server/database"); +const args = require("args-parser")(process.argv); +const { Settings } = require("../server/settings"); + +const main = async () => { + console.log("Connecting the database"); + Database.initDataDir(args); + await Database.connect(false, false, true); + + console.log("Deleting all data from aggregate tables"); + await R.exec("DELETE FROM stat_minutely"); + await R.exec("DELETE FROM stat_hourly"); + await R.exec("DELETE FROM stat_daily"); + + console.log("Resetting the aggregate table state"); + await Settings.set("migrateAggregateTableState", ""); + + await Database.close(); + console.log("Done"); +}; + +main(); + diff --git a/extra/reset-password.js b/extra/reset-password.js index a7cf3e20b0..b87d90f16a 100644 --- a/extra/reset-password.js +++ b/extra/reset-password.js @@ -8,17 +8,22 @@ const User = require("../server/model/user"); const { io } = require("socket.io-client"); const { localWebSocketURL } = require("../server/config"); const args = require("args-parser")(process.argv); + const rl = readline.createInterface({ input: process.stdin, output: process.stdout }); const main = async () => { + if ("dry-run" in args) { + console.log("Dry run mode, no changes will be made."); + } + console.log("Connecting the database"); - Database.init(args); - await Database.connect(false, false, true); try { + Database.initDataDir(args); + await Database.connect(false, false, true); // No need to actually reset the password for testing, just make sure no connection problem. It is ok for now. if (!process.env.TEST_BACKEND) { const user = await R.findOne("user"); @@ -29,18 +34,29 @@ const main = async () => { console.log("Found user: " + user.username); while (true) { - let password = await question("New Password: "); - let confirmPassword = await question("Confirm New Password: "); + let password; + let confirmPassword; + + // When called with "--new-password" argument for unattended modification (e.g. npm run reset-password -- --new_password=secret) + if ("new-password" in args) { + console.log("Using password from argument"); + console.warn("\x1b[31m%s\x1b[0m", "Warning: the password might be stored, in plain text, in your shell's history"); + password = confirmPassword = args["new-password"] + ""; + } else { + password = await question("New Password: "); + confirmPassword = await question("Confirm New Password: "); + } if (password === confirmPassword) { - await User.resetPassword(user.id, password); - - // Reset all sessions by reset jwt secret - await initJWTSecret(); + if (!("dry-run" in args)) { + await User.resetPassword(user.id, password); - // Disconnect all other socket clients of the user - await disconnectAllSocketClients(user.username, password); + // Reset all sessions by reset jwt secret + await initJWTSecret(); + // Disconnect all other socket clients of the user + await disconnectAllSocketClients(user.username, password); + } break; } else { console.log("Passwords do not match, please try again."); @@ -72,6 +88,12 @@ function question(question) { }); } +/** + * Disconnect all socket clients of the user + * @param {string} username Username + * @param {string} password Password + * @returns {Promise} Promise + */ function disconnectAllSocketClients(username, password) { return new Promise((resolve) => { console.log("Connecting to " + localWebSocketURL + " to disconnect all other socket clients"); diff --git a/extra/simple-dns-server.js b/extra/simple-dns-server.js index a6946dcb30..38bf74f68a 100644 --- a/extra/simple-dns-server.js +++ b/extra/simple-dns-server.js @@ -138,7 +138,7 @@ server.listen({ /** * Get human readable request type from request code * @param {number} code Request code to translate - * @returns {string} Human readable request type + * @returns {string|void} Human readable request type */ function type(code) { for (let name in Packet.TYPE) { diff --git a/extra/simple-mqtt-server.js b/extra/simple-mqtt-server.js index b970a380ee..66ebfe4d95 100644 --- a/extra/simple-mqtt-server.js +++ b/extra/simple-mqtt-server.js @@ -7,11 +7,17 @@ class SimpleMqttServer { aedes = require("aedes")(); server = require("net").createServer(this.aedes.handle); + /** + * @param {number} port Port to listen on + */ constructor(port) { this.port = port; } - /** Start the MQTT server */ + /** + * Start the MQTT server + * @returns {void} + */ start() { this.server.listen(this.port, () => { console.log("server started and listening on port ", this.port); diff --git a/extra/test-docker.js b/extra/test-docker.js deleted file mode 100644 index d7926fcca6..0000000000 --- a/extra/test-docker.js +++ /dev/null @@ -1,9 +0,0 @@ -// Check if docker is running -const { exec } = require("child_process"); - -exec("docker ps", (err, stdout, stderr) => { - if (err) { - console.error("Docker is not running. Please start docker and try again."); - process.exit(1); - } -}); diff --git a/extra/update-language-files/index.js b/extra/update-language-files/index.js index 078c4e6f8e..acb6bd4673 100644 --- a/extra/update-language-files/index.js +++ b/extra/update-language-files/index.js @@ -2,7 +2,6 @@ import fs from "fs"; import util from "util"; -import rmSync from "../fs-rmSync.js"; /** * Copy across the required language files @@ -12,10 +11,14 @@ import rmSync from "../fs-rmSync.js"; * created with this code if one does not already exist * @param {string} baseLang The second base language file to copy. This * will be ignored if set to "en" as en.js is copied by default + * @returns {void} */ function copyFiles(langCode, baseLang) { if (fs.existsSync("./languages")) { - rmSync("./languages", { recursive: true }); + fs.rmSync("./languages", { + recursive: true, + force: true, + }); } fs.mkdirSync("./languages"); @@ -33,7 +36,8 @@ function copyFiles(langCode, baseLang) { /** * Update the specified language file * @param {string} langCode Language code to update - * @param {string} baseLang Second language to copy keys from + * @param {string} baseLangCode Second language to copy keys from + * @returns {void} */ async function updateLanguage(langCode, baseLangCode) { const en = (await import("./languages/en.js")).default; @@ -91,6 +95,9 @@ console.log("Updating: " + langCode); copyFiles(langCode, baseLangCode); await updateLanguage(langCode, baseLangCode); -rmSync("./languages", { recursive: true }); +fs.rmSync("./languages", { + recursive: true, + force: true, +}); console.log("Done. Fixing formatting by ESLint..."); diff --git a/extra/update-version.js b/extra/update-version.js index 8d78f17db7..f9aead09de 100644 --- a/extra/update-version.js +++ b/extra/update-version.js @@ -5,7 +5,7 @@ const util = require("../src/util"); util.polyfill(); -const newVersion = process.env.VERSION; +const newVersion = process.env.RELEASE_VERSION; console.log("New Version: " + newVersion); @@ -39,6 +39,8 @@ if (! exists) { /** * Commit updated files * @param {string} version Version to update to + * @returns {void} + * @throws Error when committing files */ function commit(version) { let msg = "Update to " + version; @@ -55,6 +57,7 @@ function commit(version) { /** * Create a tag with the specified version * @param {string} version Tag to create + * @returns {void} */ function tag(version) { let res = childProcess.spawnSync("git", [ "tag", version ]); @@ -65,6 +68,7 @@ function tag(version) { * Check if a tag exists for the specified version * @param {string} version Version to check * @returns {boolean} Does the tag already exist + * @throws Version is not valid */ function tagExists(version) { if (! version) { diff --git a/extra/update-wiki-version.js b/extra/update-wiki-version.js index f551db41b7..f6c961213f 100644 --- a/extra/update-wiki-version.js +++ b/extra/update-wiki-version.js @@ -1,7 +1,7 @@ const childProcess = require("child_process"); const fs = require("fs"); -const newVersion = process.env.VERSION; +const newVersion = process.env.RELEASE_VERSION; if (!newVersion) { console.log("Missing version"); @@ -13,6 +13,7 @@ updateWiki(newVersion); /** * Update the wiki with new version number * @param {string} newVersion Version to update to + * @returns {void} */ function updateWiki(newVersion) { const wikiDir = "./tmp/wiki"; @@ -46,6 +47,7 @@ function updateWiki(newVersion) { /** * Check if a directory exists and then delete it * @param {string} dir Directory to delete + * @returns {void} */ function safeDelete(dir) { if (fs.existsSync(dir)) { diff --git a/extra/uptime-kuma-push/.gitignore b/extra/uptime-kuma-push/.gitignore new file mode 100644 index 0000000000..a007feab07 --- /dev/null +++ b/extra/uptime-kuma-push/.gitignore @@ -0,0 +1 @@ +build/* diff --git a/extra/uptime-kuma-push/Dockerfile b/extra/uptime-kuma-push/Dockerfile new file mode 100644 index 0000000000..9d619d60de --- /dev/null +++ b/extra/uptime-kuma-push/Dockerfile @@ -0,0 +1,18 @@ +FROM node AS build +RUN useradd --create-home kuma +USER kuma +WORKDIR /home/kuma +ARG TARGETPLATFORM +COPY --chown=kuma:kuma ./build/ ./build/ +COPY --chown=kuma:kuma build.js build.js +RUN node build.js $TARGETPLATFORM + +FROM debian:bookworm-slim AS release +RUN useradd --create-home kuma +USER kuma +WORKDIR /home/kuma +COPY --from=build /home/kuma/uptime-kuma-push ./uptime-kuma-push + +ENTRYPOINT ["/home/kuma/uptime-kuma-push"] + + diff --git a/extra/uptime-kuma-push/build.js b/extra/uptime-kuma-push/build.js new file mode 100644 index 0000000000..3dc8bf43b6 --- /dev/null +++ b/extra/uptime-kuma-push/build.js @@ -0,0 +1,48 @@ +const fs = require("fs"); +const platform = process.argv[2]; + +if (!platform) { + console.error("No platform??"); + process.exit(1); +} + +const supportedPlatforms = [ + { + name: "linux/amd64", + bin: "./build/uptime-kuma-push-amd64" + }, + { + name: "linux/arm64", + bin: "./build/uptime-kuma-push-arm64" + }, + { + name: "linux/arm/v7", + bin: "./build/uptime-kuma-push-armv7" + } +]; + +let platformObj = null; + +// Check if the platform is supported +for (let i = 0; i < supportedPlatforms.length; i++) { + if (supportedPlatforms[i].name === platform) { + platformObj = supportedPlatforms[i]; + break; + } +} + +if (platformObj) { + let filename = platformObj.bin; + + if (!fs.existsSync(filename)) { + console.error(`prebuilt: ${filename} is not found, please build it first`); + process.exit(1); + } + + fs.renameSync(filename, "./uptime-kuma-push"); + process.exit(0); +} else { + console.error("Unsupported platform: " + platform); + process.exit(1); +} + diff --git a/extra/uptime-kuma-push/package.json b/extra/uptime-kuma-push/package.json new file mode 100644 index 0000000000..f215436c87 --- /dev/null +++ b/extra/uptime-kuma-push/package.json @@ -0,0 +1,13 @@ +{ + "scripts": { + "build-docker": "npm run build-all && docker buildx build --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:push . --push --target release", + "build-all": "npm run build-win && npm run build-linux-amd64 && npm run build-linux-arm64 && npm run build-linux-armv7 && npm run build-linux-armv6 && npm run build-linux-armv5 && npm run build-linux-riscv64", + "build-win": "cross-env GOOS=windows GOARCH=amd64 go build -x -o ./build/uptime-kuma-push.exe uptime-kuma-push.go", + "build-linux-amd64": "cross-env GOOS=linux GOARCH=amd64 go build -x -o ./build/uptime-kuma-push-amd64 uptime-kuma-push.go", + "build-linux-arm64": "cross-env GOOS=linux GOARCH=arm64 go build -x -o ./build/uptime-kuma-push-arm64 uptime-kuma-push.go", + "build-linux-armv7": "cross-env GOOS=linux GOARCH=arm GOARM=7 go build -x -o ./build/uptime-kuma-push-armv7 uptime-kuma-push.go", + "build-linux-armv6": "cross-env GOOS=linux GOARCH=arm GOARM=6 go build -x -o ./build/uptime-kuma-push-armv6 uptime-kuma-push.go", + "build-linux-armv5": "cross-env GOOS=linux GOARCH=arm GOARM=5 go build -x -o ./build/uptime-kuma-push-armv5 uptime-kuma-push.go", + "build-linux-riscv64": "cross-env GOOS=linux GOARCH=riscv64 go build -x -o ./build/uptime-kuma-push-riscv64 uptime-kuma-push.go" + } +} diff --git a/extra/uptime-kuma-push/uptime-kuma-push.go b/extra/uptime-kuma-push/uptime-kuma-push.go new file mode 100644 index 0000000000..69cd1f8c27 --- /dev/null +++ b/extra/uptime-kuma-push/uptime-kuma-push.go @@ -0,0 +1,44 @@ +package main + +import ( + "fmt" + "net/http" + os "os" + "time" +) + +func main() { + if len(os.Args) < 2 { + fmt.Fprintln(os.Stderr, "Usage: uptime-kuma-push []") + os.Exit(1) + } + + pushURL := os.Args[1] + + var interval time.Duration + + if len(os.Args) >= 3 { + intervalString, err := time.ParseDuration(os.Args[2] + "s") + interval = intervalString + + if err != nil { + fmt.Fprintln(os.Stderr, "Error: Invalid interval", err) + os.Exit(1) + } + + } else { + interval = 60 * time.Second + } + + for { + _, err := http.Get(pushURL) + if err == nil { + fmt.Print("Pushed!") + } else { + fmt.Print("Error: ", err) + } + + fmt.Println(" Sleeping for", interval) + time.Sleep(interval) + } +} diff --git a/install.sh b/install.sh deleted file mode 100644 index d965867cbc..0000000000 --- a/install.sh +++ /dev/null @@ -1,228 +0,0 @@ -# install.sh is generated by ./extra/install.batsh, do not modify it directly. -# "npm run compile-install-script" to compile install.sh -# The command is working on Windows PowerShell and Docker for Windows only. -# curl -o kuma_install.sh https://raw.githubusercontent.com/louislam/uptime-kuma/master/install.sh && sudo bash kuma_install.sh -"echo" "-e" "=====================" -"echo" "-e" "Uptime Kuma Install Script" -"echo" "-e" "=====================" -"echo" "-e" "Supported OS: Ubuntu >= 16.04, Debian and CentOS/RHEL 7/8" -"echo" "-e" "---------------------------------------" -"echo" "-e" "This script is designed for Linux and basic usage." -"echo" "-e" "For advanced usage, please go to https://github.com/louislam/uptime-kuma/wiki/Installation" -"echo" "-e" "---------------------------------------" -"echo" "-e" "" -"echo" "-e" "Local - Install Uptime Kuma on your current machine with git, Node.js and pm2" -"echo" "-e" "Docker - Install Uptime Kuma Docker container" -"echo" "-e" "" -if [ "$1" != "" ]; then - type="$1" -else - "read" "-p" "Which installation method do you prefer? [DOCKER/local]: " "type" -fi -defaultPort="3001" -function checkNode { - local _0 - nodeVersion=$(node -e 'console.log(process.versions.node.split(`.`)[0])') - "echo" "-e" "Node Version: ""$nodeVersion" - _0="12" - if [ $(($nodeVersion <= $_0)) == 1 ]; then - "echo" "-e" "Error: Required Node.js 14" - "exit" "1" -fi -} -function deb { - nodeCheck=$(node -v) - apt --yes update - if [ "$nodeCheck" != "" ]; then - "checkNode" - else - # Old nodejs binary name is "nodejs" - check=$(nodejs --version) - if [ "$check" != "" ]; then - "echo" "-e" "Error: 'node' command is not found, but 'nodejs' command is found. Your NodeJS should be too old." - exit 1 -fi - curlCheck=$(curl --version) - if [ "$curlCheck" == "" ]; then - "echo" "-e" "Installing Curl" - apt --yes install curl -fi - "echo" "-e" "Installing Node.js 16" - curl -sL https://deb.nodesource.com/setup_16.x | bash - > log.txt - apt --yes install nodejs - node -v - nodeCheckAgain=$(node -v) - if [ "$nodeCheckAgain" == "" ]; then - "echo" "-e" "Error during Node.js installation" - exit 1 -fi - fi - check=$(git --version) - if [ "$check" == "" ]; then - "echo" "-e" "Installing Git" - apt --yes install git -fi -} -if [ "$type" == "local" ]; then - defaultInstallPath="/opt/uptime-kuma" - if [ -e "/etc/redhat-release" ]; then - os=$("cat" "/etc/redhat-release") - distribution="rhel" - else - if [ -e "/etc/issue" ]; then - os=$(head -n1 /etc/issue | cut -f 1 -d ' ') - if [ "$os" == "Ubuntu" ]; then - distribution="ubuntu" - # Get ubuntu version - . /etc/lsb-release - version="$DISTRIB_RELEASE" -fi - if [ "$os" == "Debian" ]; then - distribution="debian" -fi -fi - fi - arch=$(uname -i) - "echo" "-e" "Your OS: ""$os" - "echo" "-e" "Distribution: ""$distribution" - "echo" "-e" "Version: ""$version" - "echo" "-e" "Arch: ""$arch" - if [ "$3" != "" ]; then - port="$3" - else - "read" "-p" "Listening Port [$defaultPort]: " "port" - if [ "$port" == "" ]; then - port="$defaultPort" -fi - fi - if [ "$2" != "" ]; then - installPath="$2" - else - "read" "-p" "Installation Path [$defaultInstallPath]: " "installPath" - if [ "$installPath" == "" ]; then - installPath="$defaultInstallPath" -fi - fi - # CentOS - if [ "$distribution" == "rhel" ]; then - nodeCheck=$(node -v) - if [ "$nodeCheck" != "" ]; then - "checkNode" - else - dnfCheck=$(dnf --version) - # Use yum - if [ "$dnfCheck" == "" ]; then - curlCheck=$(curl --version) - if [ "$curlCheck" == "" ]; then - "echo" "-e" "Installing Curl" - yum -y -q install curl -fi - "echo" "-e" "Installing Node.js 16" - curl -sL https://rpm.nodesource.com/setup_16.x | bash - > log.txt - yum install -y -q nodejs - else - curlCheck=$(curl --version) - if [ "$curlCheck" == "" ]; then - "echo" "-e" "Installing Curl" - dnf -y install curl -fi - "echo" "-e" "Installing Node.js 16" - curl -sL https://rpm.nodesource.com/setup_16.x | bash - > log.txt - dnf install -y nodejs - fi - node -v - nodeCheckAgain=$(node -v) - if [ "$nodeCheckAgain" == "" ]; then - "echo" "-e" "Error during Node.js installation" - exit 1 -fi - fi - check=$(git --version) - if [ "$check" == "" ]; then - "echo" "-e" "Installing Git" - yum -y -q install git -fi - # Ubuntu - else - if [ "$distribution" == "ubuntu" ]; then - "deb" - # Debian - else - if [ "$distribution" == "debian" ]; then - "deb" - else - # Unknown distribution - error=$((0)) - check=$(git --version) - if [ "$check" == "" ]; then - error=$((1)) - "echo" "-e" "Error: git is not found!" - "echo" "-e" "help: an installation guide is available at https://git-scm.com/book/en/v2/Getting-Started-Installing-Git" -fi - check=$(node -v) - if [ "$check" == "" ]; then - error=$((1)) - "echo" "-e" "Error: node is not found" - "echo" "-e" "help: an installation guide is available at https://nodejs.org/en/download" -fi - if [ $(($error > 0)) == 1 ]; then - "echo" "-e" "Please install above missing software" - exit 1 -fi - fi - fi - fi - check=$(pm2 --version) - if [ "$check" == "" ]; then - "echo" "-e" "Installing PM2" - npm install pm2 -g && pm2 install pm2-logrotate - pm2 startup -fi - # Check again - check=$(pm2 --version) - if [ "$check" == "" ]; then - "echo" "-e" "Error: pm2 is not found!" - "echo" "-e" "help: an installation guide is available at https://pm2.keymetrics.io/docs/usage/quick-start/" - exit 1 -fi - mkdir -p $installPath - cd $installPath - git clone https://github.com/louislam/uptime-kuma.git . - npm run setup - pm2 start server/server.js --name uptime-kuma -- --port=$port -else - defaultVolume="uptime-kuma" - check=$(docker -v) - if [ "$check" == "" ]; then - "echo" "-e" "Error: docker is not found!" - "echo" "-e" "help: an installation guide is available at https://docs.docker.com/desktop/" - exit 1 -fi - check=$(docker info) - if [[ "$check" == *"Is the docker daemon running"* ]]; then - "echo" "Error: docker is not running" - "echo" "help: a troubleshooting guide is available at https://docs.docker.com/config/daemon/troubleshoot/" - "exit" "1" - fi - if [ "$3" != "" ]; then - port="$3" - else - "read" "-p" "Expose Port [$defaultPort]: " "port" - if [ "$port" == "" ]; then - port="$defaultPort" -fi - fi - if [ "$2" != "" ]; then - volume="$2" - else - "read" "-p" "Volume Name [$defaultVolume]: " "volume" - if [ "$volume" == "" ]; then - volume="$defaultVolume" -fi - fi - "echo" "-e" "Port: $port" - "echo" "-e" "Volume: $volume" - docker volume create $volume - docker run -d --restart=always -p $port:3001 -v $volume:/app/data --name uptime-kuma louislam/uptime-kuma:1 -fi -"echo" "-e" "http://localhost:$port" diff --git a/package-lock.json b/package-lock.json index c04af38517..100cdcd882 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,39 +1,41 @@ { "name": "uptime-kuma", - "version": "1.23.15", + "version": "2.0.0-dev", "lockfileVersion": 3, "requires": true, "packages": { "": { "name": "uptime-kuma", - "version": "1.23.15", + "version": "2.0.0-dev", "license": "MIT", "dependencies": { "@grpc/grpc-js": "~1.8.22", "@louislam/ping": "~0.4.4-mod.1", "@louislam/sqlite3": "15.1.6", + "@vvo/tzdb": "^6.125.0", "args-parser": "~1.3.0", "axios": "~0.28.1", - "axios-ntlm": "1.3.0", "badge-maker": "~3.3.1", "bcryptjs": "~2.4.3", - "cacheable-lookup": "~6.0.4", "chardet": "~1.4.0", "check-password-strength": "^2.0.5", - "cheerio": "1.0.0-rc.12", + "cheerio": "~1.0.0-rc.12", "chroma-js": "~2.4.2", "command-exists": "~1.2.9", "compare-versions": "~3.6.0", "compression": "~1.7.4", - "croner": "~6.0.5", + "croner": "~8.1.0", "dayjs": "~1.11.5", + "dev-null": "^0.1.1", "dotenv": "~16.0.3", "express": "~4.21.0", "express-basic-auth": "~1.2.1", "express-static-gzip": "~2.1.7", + "feed": "^4.2.2", "form-data": "~4.0.0", "gamedig": "^4.2.0", "html-escaper": "^3.0.3", + "http-cookie-agent": "~5.0.4", "http-graceful-shutdown": "~3.1.7", "http-proxy-agent": "~5.0.0", "https-proxy-agent": "~5.0.1", @@ -44,13 +46,17 @@ "jsonwebtoken": "~9.0.0", "jwt-decode": "~3.1.2", "kafkajs": "^2.2.4", + "knex": "~3.1.0", "limiter": "~2.1.0", "liquidjs": "^10.7.0", + "marked": "^14.0.0", + "mitt": "~3.0.1", "mongodb": "~4.17.1", "mqtt": "~4.3.7", - "mssql": "~8.1.4", - "mysql2": "~3.9.6", + "mssql": "~11.0.0", + "mysql2": "~3.11.3", "nanoid": "~3.3.4", + "net-snmp": "^3.11.2", "node-cloudflared-tunnel": "~1.0.9", "node-radius-client": "~1.0.0", "nodemailer": "~6.9.13", @@ -60,7 +66,7 @@ "password-hash": "~1.2.2", "pg": "~8.11.3", "pg-connection-string": "~2.6.2", - "playwright-core": "~1.35.1", + "playwright-core": "~1.39.0", "prom-client": "~13.2.0", "prometheus-api-metrics": "~3.2.1", "promisify-child-process": "~4.1.2", @@ -75,21 +81,25 @@ "tar": "~6.2.1", "tcp-ping": "~0.1.1", "thirty-two": "~1.0.2", + "tough-cookie": "~4.1.3", "ws": "^8.13.0" }, "devDependencies": { "@actions/github": "~5.1.1", - "@babel/eslint-parser": "^7.22.7", - "@babel/preset-env": "^7.15.8", "@fortawesome/fontawesome-svg-core": "~1.2.36", "@fortawesome/free-regular-svg-icons": "~5.15.4", "@fortawesome/free-solid-svg-icons": "~5.15.4", "@fortawesome/vue-fontawesome": "~3.0.0-5", + "@playwright/test": "~1.39.0", "@popperjs/core": "~2.10.2", + "@testcontainers/hivemq": "^10.13.1", + "@testcontainers/rabbitmq": "^10.13.2", "@types/bootstrap": "~5.1.9", - "@vitejs/plugin-legacy": "~4.1.0", - "@vitejs/plugin-vue": "~4.2.3", - "@vue/compiler-sfc": "~3.3.4", + "@types/node": "^20.8.6", + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", + "@vitejs/plugin-vue": "~5.0.1", + "@vue/compiler-sfc": "~3.4.2", "@vuepic/vue-datepicker": "~3.4.8", "aedes": "^0.46.3", "bootstrap": "5.1.3", @@ -99,15 +109,14 @@ "core-js": "~3.26.1", "cronstrue": "~2.24.0", "cross-env": "~7.0.3", - "cypress": "^13.2.0", "delay": "^5.0.0", "dns2": "~2.0.1", "dompurify": "~3.1.7", "eslint": "~8.14.0", + "eslint-plugin-jsdoc": "~46.4.6", "eslint-plugin-vue": "~8.7.1", "favico.js": "~0.3.10", - "jest": "~29.6.1", - "marked": "~4.2.5", + "get-port-please": "^3.1.1", "node-ssh": "~13.1.0", "postcss-html": "~1.5.0", "postcss-rtlcss": "~3.7.2", @@ -119,12 +128,14 @@ "stylelint": "^15.10.1", "stylelint-config-standard": "~25.0.0", "terser": "~5.15.0", - "timezones-list": "~3.0.1", + "test": "~3.3.0", + "testcontainers": "^10.13.1", "typescript": "~4.4.4", "v-pagination-3": "~0.1.7", "vite": "~5.2.8", "vite-plugin-compression": "^0.5.1", - "vue": "~3.3.4", + "vite-plugin-vue-devtools": "^7.0.15", + "vue": "~3.4.2", "vue-chartjs": "~5.2.0", "vue-confirm-dialog": "~1.0.2", "vue-contenteditable": "~3.0.4", @@ -133,14 +144,14 @@ "vue-multiselect": "~3.0.0-alpha.2", "vue-prism-editor": "~2.0.0-alpha.2", "vue-qrcode": "~1.0.0", - "vue-router": "~4.0.14", + "vue-router": "~4.2.5", "vue-toastification": "~2.0.0-rc.5", "vuedraggable": "~4.1.0", "wait-on": "^7.2.0", "whatwg-url": "~12.0.1" }, "engines": { - "node": "14 || 16 || 18 || >= 20.4.0" + "node": "18 || >= 20.4.0" } }, "node_modules/@actions/github": { @@ -181,6 +192,16 @@ "node": ">=6.0.0" } }, + "node_modules/@antfu/utils": { + "version": "0.7.10", + "resolved": "https://registry.npmjs.org/@antfu/utils/-/utils-0.7.10.tgz", + "integrity": "sha512-+562v9k4aI80m1+VuMHehNJWLOFjBnXn3tdOitzD0il5b7smkSBal4+a3oKiQTbrwMmN/TBUMDvbdoWDehgOww==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + } + }, "node_modules/@aws-crypto/sha256-browser": { "version": "5.2.0", "resolved": "https://registry.npmjs.org/@aws-crypto/sha256-browser/-/sha256-browser-5.2.0.tgz", @@ -317,51 +338,51 @@ } }, "node_modules/@aws-sdk/client-cognito-identity": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.716.0.tgz", - "integrity": "sha512-tXMp76f1ZzrZtJwVPnLe28YINbNmwxv595Z6kpi9yc3nB/YUdeBUND8u1dgQd/sVNwZzmgcR6nyXnT+GQkeoUg==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-cognito-identity/-/client-cognito-identity-3.679.0.tgz", + "integrity": "sha512-vJzQ6QpaMu8itJMe3FH1/0rwMjL0ELh63iLTxiAmhiV/SvCwNNoSFLd2HdKxbV0Bg/x8lUiPVq3pl6+cxaIrEQ==", "license": "Apache-2.0", "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.716.0", - "@aws-sdk/client-sts": "3.716.0", - "@aws-sdk/core": "3.716.0", - "@aws-sdk/credential-provider-node": "3.716.0", - "@aws-sdk/middleware-host-header": "3.714.0", - "@aws-sdk/middleware-logger": "3.714.0", - "@aws-sdk/middleware-recursion-detection": "3.714.0", - "@aws-sdk/middleware-user-agent": "3.716.0", - "@aws-sdk/region-config-resolver": "3.714.0", - "@aws-sdk/types": "3.714.0", - "@aws-sdk/util-endpoints": "3.714.0", - "@aws-sdk/util-user-agent-browser": "3.714.0", - "@aws-sdk/util-user-agent-node": "3.716.0", - "@smithy/config-resolver": "^3.0.13", - "@smithy/core": "^2.5.5", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/hash-node": "^3.0.11", - "@smithy/invalid-dependency": "^3.0.11", - "@smithy/middleware-content-length": "^3.0.13", - "@smithy/middleware-endpoint": "^3.2.6", - "@smithy/middleware-retry": "^3.0.31", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.1", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", + "@aws-sdk/client-sso-oidc": "3.679.0", + "@aws-sdk/client-sts": "3.679.0", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/credential-provider-node": "3.679.0", + "@aws-sdk/middleware-host-header": "3.679.0", + "@aws-sdk/middleware-logger": "3.679.0", + "@aws-sdk/middleware-recursion-detection": "3.679.0", + "@aws-sdk/middleware-user-agent": "3.679.0", + "@aws-sdk/region-config-resolver": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@aws-sdk/util-user-agent-browser": "3.679.0", + "@aws-sdk/util-user-agent-node": "3.679.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.31", - "@smithy/util-defaults-mode-node": "^3.0.31", - "@smithy/util-endpoints": "^2.1.7", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" }, @@ -370,48 +391,48 @@ } }, "node_modules/@aws-sdk/client-sso": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.716.0.tgz", - "integrity": "sha512-5Nb0jJXce2TclbjG7WVPufwhgV1TRydz1QnsuBtKU0AdViEpr787YrZhPpGnNIM1Dx+R1H/tmAHZnOoohS6D8g==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso/-/client-sso-3.679.0.tgz", + "integrity": "sha512-/0cAvYnpOZTo/Y961F1kx2fhDDLUYZ0SQQ5/75gh3xVImLj7Zw+vp74ieqFbqWLYGMaq8z1Arr9A8zG95mbLdg==", "license": "Apache-2.0", "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.716.0", - "@aws-sdk/middleware-host-header": "3.714.0", - "@aws-sdk/middleware-logger": "3.714.0", - "@aws-sdk/middleware-recursion-detection": "3.714.0", - "@aws-sdk/middleware-user-agent": "3.716.0", - "@aws-sdk/region-config-resolver": "3.714.0", - "@aws-sdk/types": "3.714.0", - "@aws-sdk/util-endpoints": "3.714.0", - "@aws-sdk/util-user-agent-browser": "3.714.0", - "@aws-sdk/util-user-agent-node": "3.716.0", - "@smithy/config-resolver": "^3.0.13", - "@smithy/core": "^2.5.5", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/hash-node": "^3.0.11", - "@smithy/invalid-dependency": "^3.0.11", - "@smithy/middleware-content-length": "^3.0.13", - "@smithy/middleware-endpoint": "^3.2.6", - "@smithy/middleware-retry": "^3.0.31", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.1", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/middleware-host-header": "3.679.0", + "@aws-sdk/middleware-logger": "3.679.0", + "@aws-sdk/middleware-recursion-detection": "3.679.0", + "@aws-sdk/middleware-user-agent": "3.679.0", + "@aws-sdk/region-config-resolver": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@aws-sdk/util-user-agent-browser": "3.679.0", + "@aws-sdk/util-user-agent-node": "3.679.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.31", - "@smithy/util-defaults-mode-node": "^3.0.31", - "@smithy/util-endpoints": "^2.1.7", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" }, @@ -420,49 +441,49 @@ } }, "node_modules/@aws-sdk/client-sso-oidc": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.716.0.tgz", - "integrity": "sha512-lA4IB9FzR2KjH7EVCo+mHGFKqdViVyeBQEIX9oVratL/l7P0bMS1fMwgfHOc3ACazqNxBxDES7x08ZCp32y6Lw==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sso-oidc/-/client-sso-oidc-3.679.0.tgz", + "integrity": "sha512-/dBYWcCwbA/id4sFCIVZvf0UsvzHCC68SryxeNQk/PDkY9N4n5yRcMUkZDaEyQCjowc3kY4JOXp2AdUP037nhA==", "license": "Apache-2.0", "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/core": "3.716.0", - "@aws-sdk/credential-provider-node": "3.716.0", - "@aws-sdk/middleware-host-header": "3.714.0", - "@aws-sdk/middleware-logger": "3.714.0", - "@aws-sdk/middleware-recursion-detection": "3.714.0", - "@aws-sdk/middleware-user-agent": "3.716.0", - "@aws-sdk/region-config-resolver": "3.714.0", - "@aws-sdk/types": "3.714.0", - "@aws-sdk/util-endpoints": "3.714.0", - "@aws-sdk/util-user-agent-browser": "3.714.0", - "@aws-sdk/util-user-agent-node": "3.716.0", - "@smithy/config-resolver": "^3.0.13", - "@smithy/core": "^2.5.5", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/hash-node": "^3.0.11", - "@smithy/invalid-dependency": "^3.0.11", - "@smithy/middleware-content-length": "^3.0.13", - "@smithy/middleware-endpoint": "^3.2.6", - "@smithy/middleware-retry": "^3.0.31", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.1", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/credential-provider-node": "3.679.0", + "@aws-sdk/middleware-host-header": "3.679.0", + "@aws-sdk/middleware-logger": "3.679.0", + "@aws-sdk/middleware-recursion-detection": "3.679.0", + "@aws-sdk/middleware-user-agent": "3.679.0", + "@aws-sdk/region-config-resolver": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@aws-sdk/util-user-agent-browser": "3.679.0", + "@aws-sdk/util-user-agent-node": "3.679.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.31", - "@smithy/util-defaults-mode-node": "^3.0.31", - "@smithy/util-endpoints": "^2.1.7", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" }, @@ -470,54 +491,54 @@ "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.716.0" + "@aws-sdk/client-sts": "^3.679.0" } }, "node_modules/@aws-sdk/client-sts": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.716.0.tgz", - "integrity": "sha512-i4SVNsrdXudp8T4bkm7Fi3YWlRnvXCSwvNDqf6nLqSJxqr4CN3VlBELueDyjBK7TAt453/qSif+eNx+bHmwo4Q==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-sts/-/client-sts-3.679.0.tgz", + "integrity": "sha512-3CvrT8w1RjFu1g8vKA5Azfr5V83r2/b68Ock43WE003Bq/5Y38mwmYX7vk0fPHzC3qejt4YMAWk/C3fSKOy25g==", "license": "Apache-2.0", "optional": true, "dependencies": { "@aws-crypto/sha256-browser": "5.2.0", "@aws-crypto/sha256-js": "5.2.0", - "@aws-sdk/client-sso-oidc": "3.716.0", - "@aws-sdk/core": "3.716.0", - "@aws-sdk/credential-provider-node": "3.716.0", - "@aws-sdk/middleware-host-header": "3.714.0", - "@aws-sdk/middleware-logger": "3.714.0", - "@aws-sdk/middleware-recursion-detection": "3.714.0", - "@aws-sdk/middleware-user-agent": "3.716.0", - "@aws-sdk/region-config-resolver": "3.714.0", - "@aws-sdk/types": "3.714.0", - "@aws-sdk/util-endpoints": "3.714.0", - "@aws-sdk/util-user-agent-browser": "3.714.0", - "@aws-sdk/util-user-agent-node": "3.716.0", - "@smithy/config-resolver": "^3.0.13", - "@smithy/core": "^2.5.5", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/hash-node": "^3.0.11", - "@smithy/invalid-dependency": "^3.0.11", - "@smithy/middleware-content-length": "^3.0.13", - "@smithy/middleware-endpoint": "^3.2.6", - "@smithy/middleware-retry": "^3.0.31", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.1", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", + "@aws-sdk/client-sso-oidc": "3.679.0", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/credential-provider-node": "3.679.0", + "@aws-sdk/middleware-host-header": "3.679.0", + "@aws-sdk/middleware-logger": "3.679.0", + "@aws-sdk/middleware-recursion-detection": "3.679.0", + "@aws-sdk/middleware-user-agent": "3.679.0", + "@aws-sdk/region-config-resolver": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@aws-sdk/util-user-agent-browser": "3.679.0", + "@aws-sdk/util-user-agent-node": "3.679.0", + "@smithy/config-resolver": "^3.0.9", + "@smithy/core": "^2.4.8", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/hash-node": "^3.0.7", + "@smithy/invalid-dependency": "^3.0.7", + "@smithy/middleware-content-length": "^3.0.9", + "@smithy/middleware-endpoint": "^3.1.4", + "@smithy/middleware-retry": "^3.0.23", + "@smithy/middleware-serde": "^3.0.7", + "@smithy/middleware-stack": "^3.0.7", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/url-parser": "^3.0.7", "@smithy/util-base64": "^3.0.0", "@smithy/util-body-length-browser": "^3.0.0", "@smithy/util-body-length-node": "^3.0.0", - "@smithy/util-defaults-mode-browser": "^3.0.31", - "@smithy/util-defaults-mode-node": "^3.0.31", - "@smithy/util-endpoints": "^2.1.7", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", + "@smithy/util-defaults-mode-browser": "^3.0.23", + "@smithy/util-defaults-mode-node": "^3.0.23", + "@smithy/util-endpoints": "^2.1.3", + "@smithy/util-middleware": "^3.0.7", + "@smithy/util-retry": "^3.0.7", "@smithy/util-utf8": "^3.0.0", "tslib": "^2.6.2" }, @@ -526,21 +547,21 @@ } }, "node_modules/@aws-sdk/core": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.716.0.tgz", - "integrity": "sha512-5DkUiTrbyzO8/W4g7UFEqRFpuhgizayHI/Zbh0wtFMcot8801nJV+MP/YMhdjimlvAr/OqYB08FbGsPyWppMTw==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/core/-/core-3.679.0.tgz", + "integrity": "sha512-CS6PWGX8l4v/xyvX8RtXnBisdCa5+URzKd0L6GvHChype9qKUVxO/Gg6N/y43Hvg7MNWJt9FBPNWIxUB+byJwg==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/types": "3.714.0", - "@smithy/core": "^2.5.5", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/property-provider": "^3.1.11", - "@smithy/protocol-http": "^4.1.8", - "@smithy/signature-v4": "^4.2.4", - "@smithy/smithy-client": "^3.5.1", - "@smithy/types": "^3.7.2", - "@smithy/util-middleware": "^3.0.11", + "@aws-sdk/types": "3.679.0", + "@smithy/core": "^2.4.8", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/property-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.4", + "@smithy/signature-v4": "^4.2.0", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/util-middleware": "^3.0.7", "fast-xml-parser": "4.4.1", "tslib": "^2.6.2" }, @@ -549,16 +570,16 @@ } }, "node_modules/@aws-sdk/credential-provider-cognito-identity": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.716.0.tgz", - "integrity": "sha512-iHmyB3Z6KjAQcpWW01LRjqbOM2OFVfaiGH6tRylPvJN/GnlITLUnUZi/PBAFk1f+TZ94dQWN961c1L/LFCSg9Q==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-cognito-identity/-/credential-provider-cognito-identity-3.679.0.tgz", + "integrity": "sha512-XvWd6RPk7TA7tmqITT+NXvJ6ltJP8BUtLO1NAvja4HKExPKR9HAyoOeeH7KM3lVRED4e4LUnLb3fzteH20IXaA==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/client-cognito-identity": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/types": "^3.7.2", + "@aws-sdk/client-cognito-identity": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -566,16 +587,16 @@ } }, "node_modules/@aws-sdk/credential-provider-env": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.716.0.tgz", - "integrity": "sha512-JI2KQUnn2arICwP9F3CnqP1W3nAbm4+meQg/yOhp9X0DMzQiHrHRd4HIrK2vyVgi2/6hGhONY5uLF26yRTA7nQ==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-env/-/credential-provider-env-3.679.0.tgz", + "integrity": "sha512-EdlTYbzMm3G7VUNAMxr9S1nC1qUNqhKlAxFU8E7cKsAe8Bp29CD5HAs3POc56AVo9GC4yRIS+/mtlZSmrckzUA==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/core": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -583,21 +604,21 @@ } }, "node_modules/@aws-sdk/credential-provider-http": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.716.0.tgz", - "integrity": "sha512-CZ04pl2z7igQPysQyH2xKZHM3fLwkemxQbKOlje3TmiS1NwXvcKvERhp9PE/H23kOL7beTM19NMRog/Fka/rlw==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-http/-/credential-provider-http-3.679.0.tgz", + "integrity": "sha512-ZoKLubW5DqqV1/2a3TSn+9sSKg0T8SsYMt1JeirnuLJF0mCoYFUaWMyvxxKuxPoqvUsaycxKru4GkpJ10ltNBw==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/core": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/property-provider": "^3.1.11", - "@smithy/protocol-http": "^4.1.8", - "@smithy/smithy-client": "^3.5.1", - "@smithy/types": "^3.7.2", - "@smithy/util-stream": "^3.3.2", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/fetch-http-handler": "^3.2.9", + "@smithy/node-http-handler": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/protocol-http": "^4.1.4", + "@smithy/smithy-client": "^3.4.0", + "@smithy/types": "^3.5.0", + "@smithy/util-stream": "^3.1.9", "tslib": "^2.6.2" }, "engines": { @@ -605,50 +626,50 @@ } }, "node_modules/@aws-sdk/credential-provider-ini": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.716.0.tgz", - "integrity": "sha512-P37We2GtZvdROxiwP0zrpEL81/HuYK1qlYxp5VCj3uV+G4mG8UQN2gMIU/baYrpOQqa0h81RfyQGRFUjVaDVqw==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-ini/-/credential-provider-ini-3.679.0.tgz", + "integrity": "sha512-Rg7t8RwUzKcumpipG4neZqaeJ6DF+Bco1+FHn5BZB68jpvwvjBjcQUuWkxj18B6ctYHr1fkunnzeKEn/+vy7+w==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/core": "3.716.0", - "@aws-sdk/credential-provider-env": "3.716.0", - "@aws-sdk/credential-provider-http": "3.716.0", - "@aws-sdk/credential-provider-process": "3.716.0", - "@aws-sdk/credential-provider-sso": "3.716.0", - "@aws-sdk/credential-provider-web-identity": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@smithy/credential-provider-imds": "^3.2.8", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/credential-provider-env": "3.679.0", + "@aws-sdk/credential-provider-http": "3.679.0", + "@aws-sdk/credential-provider-process": "3.679.0", + "@aws-sdk/credential-provider-sso": "3.679.0", + "@aws-sdk/credential-provider-web-identity": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/credential-provider-imds": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.716.0" + "@aws-sdk/client-sts": "^3.679.0" } }, "node_modules/@aws-sdk/credential-provider-node": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.716.0.tgz", - "integrity": "sha512-FGQPK2uKfS53dVvoskN/s/t6m0Po24BGd1PzJdzHBFCOjxbZLM6+8mDMXeyi2hCLVVQOUcuW41kOgmJ0+zMbww==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-node/-/credential-provider-node-3.679.0.tgz", + "integrity": "sha512-E3lBtaqCte8tWs6Rkssc8sLzvGoJ10TLGvpkijOlz43wPd6xCRh1YLwg6zolf9fVFtEyUs/GsgymiASOyxhFtw==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/credential-provider-env": "3.716.0", - "@aws-sdk/credential-provider-http": "3.716.0", - "@aws-sdk/credential-provider-ini": "3.716.0", - "@aws-sdk/credential-provider-process": "3.716.0", - "@aws-sdk/credential-provider-sso": "3.716.0", - "@aws-sdk/credential-provider-web-identity": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@smithy/credential-provider-imds": "^3.2.8", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/credential-provider-env": "3.679.0", + "@aws-sdk/credential-provider-http": "3.679.0", + "@aws-sdk/credential-provider-ini": "3.679.0", + "@aws-sdk/credential-provider-process": "3.679.0", + "@aws-sdk/credential-provider-sso": "3.679.0", + "@aws-sdk/credential-provider-web-identity": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/credential-provider-imds": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -656,17 +677,17 @@ } }, "node_modules/@aws-sdk/credential-provider-process": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.716.0.tgz", - "integrity": "sha512-0spcu2MWVVHSTHH3WE2E//ttUJPwXRM3BCp+WyI41xLzpNu1Fd8zjOrDpEo0SnGUzsSiRTIJWgkuu/tqv9NJ2A==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-process/-/credential-provider-process-3.679.0.tgz", + "integrity": "sha512-u/p4TV8kQ0zJWDdZD4+vdQFTMhkDEJFws040Gm113VHa/Xo1SYOjbpvqeuFoz6VmM0bLvoOWjxB9MxnSQbwKpQ==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/core": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -674,19 +695,19 @@ } }, "node_modules/@aws-sdk/credential-provider-sso": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.716.0.tgz", - "integrity": "sha512-J2IA3WuCpRGGoZm6VHZVFCnrxXP+41iUWb9Ct/1spljegTa1XjiaZ5Jf3+Ubj7WKiyvP9/dgz1L0bu2bYEjliw==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-sso/-/credential-provider-sso-3.679.0.tgz", + "integrity": "sha512-SAtWonhi9asxn0ukEbcE81jkyanKgqpsrtskvYPpO9Z9KOednM4Cqt6h1bfcS9zaHjN2zu815Gv8O7WiV+F/DQ==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/client-sso": "3.716.0", - "@aws-sdk/core": "3.716.0", - "@aws-sdk/token-providers": "3.714.0", - "@aws-sdk/types": "3.714.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/client-sso": "3.679.0", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/token-providers": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -694,48 +715,48 @@ } }, "node_modules/@aws-sdk/credential-provider-web-identity": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.716.0.tgz", - "integrity": "sha512-vzgpWKs2gGXZGdbMKRFrMW4PqEFWkGvwWH2T7ZwQv9m+8lQ7P4Dk2uimqu0f37HZAbpn8HFMqRh4CaySjU354A==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-provider-web-identity/-/credential-provider-web-identity-3.679.0.tgz", + "integrity": "sha512-a74tLccVznXCaBefWPSysUcLXYJiSkeUmQGtalNgJ1vGkE36W5l/8czFiiowdWdKWz7+x6xf0w+Kjkjlj42Ung==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/core": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sts": "^3.716.0" + "@aws-sdk/client-sts": "^3.679.0" } }, "node_modules/@aws-sdk/credential-providers": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.716.0.tgz", - "integrity": "sha512-UsalnK1MMfbI8Chb7BFghUvXf+zdqqiZLpSJp9ytXe0/thoafsi2jo0pyFeU08uarU/YA3Usl15I4SdK5uQr1A==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/credential-providers/-/credential-providers-3.679.0.tgz", + "integrity": "sha512-ZjZZb6OERw/UKlSqcJ24AUJIf/ekDLPZrPpo0kPMV70EQ0GkBiklIZ8qULu9bEcI2I4UIapBKRiXTrK4gA6YHg==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/client-cognito-identity": "3.716.0", - "@aws-sdk/client-sso": "3.716.0", - "@aws-sdk/client-sts": "3.716.0", - "@aws-sdk/core": "3.716.0", - "@aws-sdk/credential-provider-cognito-identity": "3.716.0", - "@aws-sdk/credential-provider-env": "3.716.0", - "@aws-sdk/credential-provider-http": "3.716.0", - "@aws-sdk/credential-provider-ini": "3.716.0", - "@aws-sdk/credential-provider-node": "3.716.0", - "@aws-sdk/credential-provider-process": "3.716.0", - "@aws-sdk/credential-provider-sso": "3.716.0", - "@aws-sdk/credential-provider-web-identity": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@smithy/credential-provider-imds": "^3.2.8", - "@smithy/property-provider": "^3.1.11", - "@smithy/types": "^3.7.2", + "@aws-sdk/client-cognito-identity": "3.679.0", + "@aws-sdk/client-sso": "3.679.0", + "@aws-sdk/client-sts": "3.679.0", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/credential-provider-cognito-identity": "3.679.0", + "@aws-sdk/credential-provider-env": "3.679.0", + "@aws-sdk/credential-provider-http": "3.679.0", + "@aws-sdk/credential-provider-ini": "3.679.0", + "@aws-sdk/credential-provider-node": "3.679.0", + "@aws-sdk/credential-provider-process": "3.679.0", + "@aws-sdk/credential-provider-sso": "3.679.0", + "@aws-sdk/credential-provider-web-identity": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/credential-provider-imds": "^3.2.4", + "@smithy/property-provider": "^3.1.7", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -743,15 +764,15 @@ } }, "node_modules/@aws-sdk/middleware-host-header": { - "version": "3.714.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.714.0.tgz", - "integrity": "sha512-6l68kjNrh5QC8FGX3I3geBDavWN5Tg1RLHJ2HLA8ByGBtJyCwnz3hEkKfaxn0bBx0hF9DzbfjEOUF6cDqy2Kjg==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-host-header/-/middleware-host-header-3.679.0.tgz", + "integrity": "sha512-y176HuQ8JRY3hGX8rQzHDSbCl9P5Ny9l16z4xmaiLo+Qfte7ee4Yr3yaAKd7GFoJ3/Mhud2XZ37fR015MfYl2w==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/types": "3.714.0", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.679.0", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -759,14 +780,14 @@ } }, "node_modules/@aws-sdk/middleware-logger": { - "version": "3.714.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.714.0.tgz", - "integrity": "sha512-RkqHlMvQWUaRklU1bMfUuBvdWwxgUtEqpADaHXlGVj3vtEY2UgBjy+57CveC4MByqKIunNvVHBBbjrGVtwY7Lg==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-logger/-/middleware-logger-3.679.0.tgz", + "integrity": "sha512-0vet8InEj7nvIvGKk+ch7bEF5SyZ7Us9U7YTEgXPrBNStKeRUsgwRm0ijPWWd0a3oz2okaEwXsFl7G/vI0XiEA==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/types": "3.714.0", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.679.0", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -774,15 +795,15 @@ } }, "node_modules/@aws-sdk/middleware-recursion-detection": { - "version": "3.714.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.714.0.tgz", - "integrity": "sha512-AVU5ixnh93nqtsfgNc284oXsXaadyHGPHpql/jwgaaqQfEXjS/1/j3j9E/vpacfTTz2Vzo7hAOjnvrOXSEVDaA==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-recursion-detection/-/middleware-recursion-detection-3.679.0.tgz", + "integrity": "sha512-sQoAZFsQiW/LL3DfKMYwBoGjYDEnMbA9WslWN8xneCmBAwKo6IcSksvYs23PP8XMIoBGe2I2J9BSr654XWygTQ==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/types": "3.714.0", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.679.0", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -790,18 +811,18 @@ } }, "node_modules/@aws-sdk/middleware-user-agent": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.716.0.tgz", - "integrity": "sha512-FpAtT6nNKrYdkDZndutEraiRMf+TgDzAGvniqRtZ/YTPA+gIsWrsn+TwMKINR81lFC3nQfb9deS5CFtxd021Ew==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/middleware-user-agent/-/middleware-user-agent-3.679.0.tgz", + "integrity": "sha512-4hdeXhPDURPqQLPd9jCpUEo9fQITXl3NM3W1MwcJpE0gdUM36uXkQOYsTPeeU/IRCLVjK8Htlh2oCaM9iJrLCA==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/core": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@aws-sdk/util-endpoints": "3.714.0", - "@smithy/core": "^2.5.5", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", + "@aws-sdk/core": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@aws-sdk/util-endpoints": "3.679.0", + "@smithy/core": "^2.4.8", + "@smithy/protocol-http": "^4.1.4", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -809,17 +830,17 @@ } }, "node_modules/@aws-sdk/region-config-resolver": { - "version": "3.714.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.714.0.tgz", - "integrity": "sha512-HJzsQxgMOAzZrbf/YIqEx30or4tZK1oNAk6Wm6xecUQx+23JXIaePRu1YFUOLBBERQ4QBPpISFurZWBMZ5ibAw==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/region-config-resolver/-/region-config-resolver-3.679.0.tgz", + "integrity": "sha512-Ybx54P8Tg6KKq5ck7uwdjiKif7n/8g1x+V0V9uTjBjRWqaIgiqzXwKWoPj6NCNkE7tJNtqI4JrNxp/3S3HvmRw==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/types": "3.714.0", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.679.0", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/types": "^3.5.0", "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", + "@smithy/util-middleware": "^3.0.7", "tslib": "^2.6.2" }, "engines": { @@ -827,33 +848,33 @@ } }, "node_modules/@aws-sdk/token-providers": { - "version": "3.714.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.714.0.tgz", - "integrity": "sha512-vKN064aLE3kl+Zl16Ony3jltHnMddMBT7JRkP1L+lLywhA0PcAKxpdvComul/sTBWnbnwLnaS5NsDUhcWySH8A==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/token-providers/-/token-providers-3.679.0.tgz", + "integrity": "sha512-1/+Zso/x2jqgutKixYFQEGli0FELTgah6bm7aB+m2FAWH4Hz7+iMUsazg6nSWm714sG9G3h5u42Dmpvi9X6/hA==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/types": "3.714.0", - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.679.0", + "@smithy/property-provider": "^3.1.7", + "@smithy/shared-ini-file-loader": "^3.1.8", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { "node": ">=16.0.0" }, "peerDependencies": { - "@aws-sdk/client-sso-oidc": "^3.714.0" + "@aws-sdk/client-sso-oidc": "^3.679.0" } }, "node_modules/@aws-sdk/types": { - "version": "3.714.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.714.0.tgz", - "integrity": "sha512-ZjpP2gYbSFlxxaUDa1Il5AVvfggvUPbjzzB/l3q0gIE5Thd6xKW+yzEpt2mLZ5s5UaYSABZbF94g8NUOF4CVGA==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/types/-/types-3.679.0.tgz", + "integrity": "sha512-NwVq8YvInxQdJ47+zz4fH3BRRLC6lL+WLkvr242PVBbUOLRyK/lkwHlfiKUoeVIMyK5NF+up6TRg71t/8Bny6Q==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@smithy/types": "^3.7.2", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -861,15 +882,15 @@ } }, "node_modules/@aws-sdk/util-endpoints": { - "version": "3.714.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.714.0.tgz", - "integrity": "sha512-Xv+Z2lhe7w7ZZRsgBwBMZgGTVmS+dkkj2S13uNHAx9lhB5ovM8PhK5G/j28xYf6vIibeuHkRAbb7/ozdZIGR+A==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-endpoints/-/util-endpoints-3.679.0.tgz", + "integrity": "sha512-YL6s4Y/1zC45OvddvgE139fjeWSKKPgLlnfrvhVL7alNyY9n7beR4uhoDpNrt5mI6sn9qiBF17790o+xLAXjjg==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/types": "3.714.0", - "@smithy/types": "^3.7.2", - "@smithy/util-endpoints": "^2.1.7", + "@aws-sdk/types": "3.679.0", + "@smithy/types": "^3.5.0", + "@smithy/util-endpoints": "^2.1.3", "tslib": "^2.6.2" }, "engines": { @@ -877,9 +898,9 @@ } }, "node_modules/@aws-sdk/util-locate-window": { - "version": "3.693.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.693.0.tgz", - "integrity": "sha512-ttrag6haJLWABhLqtg1Uf+4LgHWIMOVSYL+VYZmAp2v4PUGOwWmWQH0Zk8RM7YuQcLfH/EoR72/Yxz6A4FKcuw==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-locate-window/-/util-locate-window-3.679.0.tgz", + "integrity": "sha512-zKTd48/ZWrCplkXpYDABI74rQlbR0DNHs8nH95htfSLj9/mWRSwaGptoxwcihaq/77vi/fl2X3y0a1Bo8bt7RA==", "license": "Apache-2.0", "optional": true, "dependencies": { @@ -890,29 +911,29 @@ } }, "node_modules/@aws-sdk/util-user-agent-browser": { - "version": "3.714.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.714.0.tgz", - "integrity": "sha512-OdJJ03cP9/MgIVToPJPCPUImbpZzTcwdIgbXC0tUQPJhbD7b7cB4LdnkhNHko+MptpOrCq4CPY/33EpOjRdofw==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-browser/-/util-user-agent-browser-3.679.0.tgz", + "integrity": "sha512-CusSm2bTBG1kFypcsqU8COhnYc6zltobsqs3nRrvYqYaOqtMnuE46K4XTWpnzKgwDejgZGOE+WYyprtAxrPvmQ==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/types": "3.714.0", - "@smithy/types": "^3.7.2", + "@aws-sdk/types": "3.679.0", + "@smithy/types": "^3.5.0", "bowser": "^2.11.0", "tslib": "^2.6.2" } }, "node_modules/@aws-sdk/util-user-agent-node": { - "version": "3.716.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.716.0.tgz", - "integrity": "sha512-3PqaXmQbxrtHKAsPCdp7kn5FrQktj8j3YyuNsqFZ8rWZeEQ88GWlsvE61PTsr2peYCKzpFqYVddef2x1axHU0w==", + "version": "3.679.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/util-user-agent-node/-/util-user-agent-node-3.679.0.tgz", + "integrity": "sha512-Bw4uXZ+NU5ed6TNfo4tBbhBSW+2eQxXYjYBGl5gLUNUpg2pDFToQAP6rXBFiwcG52V2ny5oLGiD82SoYuYkAVg==", "license": "Apache-2.0", "optional": true, "dependencies": { - "@aws-sdk/middleware-user-agent": "3.716.0", - "@aws-sdk/types": "3.714.0", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/types": "^3.7.2", + "@aws-sdk/middleware-user-agent": "3.679.0", + "@aws-sdk/types": "3.679.0", + "@smithy/node-config-provider": "^3.1.8", + "@smithy/types": "^3.5.0", "tslib": "^2.6.2" }, "engines": { @@ -928,15 +949,15 @@ } }, "node_modules/@azure/abort-controller": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-1.1.0.tgz", - "integrity": "sha512-TrRLIoSQVzfAJX9H1JeFjzAoDGcoK1IYX1UImfceTZpsyYfWr09Ss1aHW1y5TrrR3iq6RZLBwJ3E24uwPhwahw==", + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", + "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", "license": "MIT", "dependencies": { - "tslib": "^2.2.0" + "tslib": "^2.6.2" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/core-auth": { @@ -953,18 +974,6 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/core-auth/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@azure/core-client": { "version": "1.9.2", "resolved": "https://registry.npmjs.org/@azure/core-client/-/core-client-1.9.2.tgz", @@ -983,18 +992,6 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/core-client/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@azure/core-http-compat": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/@azure/core-http-compat/-/core-http-compat-2.1.2.tgz", @@ -1009,18 +1006,6 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/core-http-compat/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@azure/core-lro": { "version": "2.7.2", "resolved": "https://registry.npmjs.org/@azure/core-lro/-/core-lro-2.7.2.tgz", @@ -1036,18 +1021,6 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/core-lro/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@azure/core-paging": { "version": "1.6.2", "resolved": "https://registry.npmjs.org/@azure/core-paging/-/core-paging-1.6.2.tgz", @@ -1061,15 +1034,15 @@ } }, "node_modules/@azure/core-rest-pipeline": { - "version": "1.18.1", - "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.18.1.tgz", - "integrity": "sha512-/wS73UEDrxroUEVywEm7J0p2c+IIiVxyfigCGfsKvCxxCET4V/Hef2aURqltrXMRjNmdmt5IuOgIpl8f6xdO5A==", + "version": "1.17.0", + "resolved": "https://registry.npmjs.org/@azure/core-rest-pipeline/-/core-rest-pipeline-1.17.0.tgz", + "integrity": "sha512-62Vv8nC+uPId3j86XJ0WI+sBf0jlqTqPUFCBNrGtlaUeQUIXWV/D8GE5A1d+Qx8H7OQojn2WguC8kChD6v0shA==", "license": "MIT", "dependencies": { "@azure/abort-controller": "^2.0.0", "@azure/core-auth": "^1.8.0", "@azure/core-tracing": "^1.0.1", - "@azure/core-util": "^1.11.0", + "@azure/core-util": "^1.9.0", "@azure/logger": "^1.0.0", "http-proxy-agent": "^7.0.0", "https-proxy-agent": "^7.0.0", @@ -1079,27 +1052,6 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/core-rest-pipeline/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, - "node_modules/@azure/core-rest-pipeline/node_modules/agent-base": { - "version": "7.1.3", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.3.tgz", - "integrity": "sha512-jRR5wdylq8CkOe6hei19GGZnxM6rBGwFl3Bg0YItGDimvjGtAvdZk4Pu6Cl4u4Igsws4a1fd1Vq3ezrhn4KmFw==", - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, "node_modules/@azure/core-rest-pipeline/node_modules/http-proxy-agent": { "version": "7.0.2", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-7.0.2.tgz", @@ -1114,12 +1066,12 @@ } }, "node_modules/@azure/core-rest-pipeline/node_modules/https-proxy-agent": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.6.tgz", - "integrity": "sha512-vK9P5/iUfdl95AI+JVyUuIcVtd4ofvtrOr3HNtM2yxC9bnMbEdp3x01OhQNnjb8IJYi38VlTE3mBXwcfvywuSw==", + "version": "7.0.5", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz", + "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==", "license": "MIT", "dependencies": { - "agent-base": "^7.1.2", + "agent-base": "^7.0.2", "debug": "4" }, "engines": { @@ -1151,43 +1103,29 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/core-util/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@azure/identity": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-2.1.0.tgz", - "integrity": "sha512-BPDz1sK7Ul9t0l9YKLEa8PHqWU4iCfhGJ+ELJl6c8CP3TpJt2urNCbm0ZHsthmxRsYoMPbz2Dvzj30zXZVmAFw==", + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/@azure/identity/-/identity-4.5.0.tgz", + "integrity": "sha512-EknvVmtBuSIic47xkOqyNabAme0RYTw52BTMz8eBgU1ysTyMrD1uOoM+JdS0J/4Yfp98IBT3osqq3BfwSaNaGQ==", "license": "MIT", "dependencies": { - "@azure/abort-controller": "^1.0.0", - "@azure/core-auth": "^1.3.0", - "@azure/core-client": "^1.4.0", - "@azure/core-rest-pipeline": "^1.1.0", + "@azure/abort-controller": "^2.0.0", + "@azure/core-auth": "^1.9.0", + "@azure/core-client": "^1.9.2", + "@azure/core-rest-pipeline": "^1.17.0", "@azure/core-tracing": "^1.0.0", - "@azure/core-util": "^1.0.0", + "@azure/core-util": "^1.11.0", "@azure/logger": "^1.0.0", - "@azure/msal-browser": "^2.26.0", - "@azure/msal-common": "^7.0.0", - "@azure/msal-node": "^1.10.0", + "@azure/msal-browser": "^3.26.1", + "@azure/msal-node": "^2.15.0", "events": "^3.0.0", "jws": "^4.0.0", "open": "^8.0.0", "stoppable": "^1.1.0", - "tslib": "^2.2.0", - "uuid": "^8.3.0" + "tslib": "^2.2.0" }, "engines": { - "node": ">=12.0.0" + "node": ">=18.0.0" } }, "node_modules/@azure/identity/node_modules/jwa": { @@ -1230,18 +1168,6 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/keyvault-common/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@azure/keyvault-keys": { "version": "4.9.0", "resolved": "https://registry.npmjs.org/@azure/keyvault-keys/-/keyvault-keys-4.9.0.tgz", @@ -1265,18 +1191,6 @@ "node": ">=18.0.0" } }, - "node_modules/@azure/keyvault-keys/node_modules/@azure/abort-controller": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@azure/abort-controller/-/abort-controller-2.1.2.tgz", - "integrity": "sha512-nBrLsEWm4J2u5LpAPjxADTlq3trDgVZZXHNKabeXZtpq3d3AbN/KGO82R87rdDz5/lYB024rtEf10/q0urNgsA==", - "license": "MIT", - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=18.0.0" - } - }, "node_modules/@azure/logger": { "version": "1.1.4", "resolved": "https://registry.npmjs.org/@azure/logger/-/logger-1.1.4.tgz", @@ -1290,63 +1204,44 @@ } }, "node_modules/@azure/msal-browser": { - "version": "2.39.0", - "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-2.39.0.tgz", - "integrity": "sha512-kks/n2AJzKUk+DBqZhiD+7zeQGBl+WpSOQYzWy6hff3bU0ZrYFqr4keFLlzB5VKuKZog0X59/FGHb1RPBDZLVg==", + "version": "3.26.1", + "resolved": "https://registry.npmjs.org/@azure/msal-browser/-/msal-browser-3.26.1.tgz", + "integrity": "sha512-y78sr9g61aCAH9fcLO1um+oHFXc1/5Ap88RIsUSuzkm0BHzFnN+PXGaQeuM1h5Qf5dTnWNOd6JqkskkMPAhh7Q==", "license": "MIT", "dependencies": { - "@azure/msal-common": "13.3.3" + "@azure/msal-common": "14.15.0" }, "engines": { "node": ">=0.8.0" } }, - "node_modules/@azure/msal-browser/node_modules/@azure/msal-common": { - "version": "13.3.3", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-13.3.3.tgz", - "integrity": "sha512-n278DdCXKeiWhLwhEL7/u9HRMyzhUXLefeajiknf6AmEedoiOiv2r5aRJ7LXdT3NGPyubkdIbthaJlVtmuEqvA==", - "license": "MIT", - "engines": { - "node": ">=0.8.0" - } - }, "node_modules/@azure/msal-common": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-7.6.0.tgz", - "integrity": "sha512-XqfbglUTVLdkHQ8F9UQJtKseRr3sSnr9ysboxtoswvaMVaEfvyLtMoHv9XdKUfOc0qKGzNgRFd9yRjIWVepl6Q==", + "version": "14.15.0", + "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-14.15.0.tgz", + "integrity": "sha512-ImAQHxmpMneJ/4S8BRFhjt1MZ3bppmpRPYYNyzeQPeFN288YKbb8TmmISQEbtfkQ1BPASvYZU5doIZOPBAqENQ==", "license": "MIT", "engines": { "node": ">=0.8.0" } }, "node_modules/@azure/msal-node": { - "version": "1.18.4", - "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-1.18.4.tgz", - "integrity": "sha512-Kc/dRvhZ9Q4+1FSfsTFDME/v6+R2Y1fuMty/TfwqE5p9GTPw08BPbKgeWinE8JRHRp+LemjQbUZsn4Q4l6Lszg==", - "deprecated": "A newer major version of this library is available. Please upgrade to the latest available version.", + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@azure/msal-node/-/msal-node-2.15.0.tgz", + "integrity": "sha512-gVPW8YLz92ZeCibQH2QUw96odJoiM3k/ZPH3f2HxptozmH6+OnyyvKXo/Egg39HAM230akarQKHf0W74UHlh0Q==", "license": "MIT", "dependencies": { - "@azure/msal-common": "13.3.1", + "@azure/msal-common": "14.15.0", "jsonwebtoken": "^9.0.0", "uuid": "^8.3.0" }, "engines": { - "node": "10 || 12 || 14 || 16 || 18" - } - }, - "node_modules/@azure/msal-node/node_modules/@azure/msal-common": { - "version": "13.3.1", - "resolved": "https://registry.npmjs.org/@azure/msal-common/-/msal-common-13.3.1.tgz", - "integrity": "sha512-Lrk1ozoAtaP/cp53May3v6HtcFSVxdFrg2Pa/1xu5oIvsIwhxW6zSPibKefCOVgd5osgykMi5jjcZHv8XkzZEQ==", - "license": "MIT", - "engines": { - "node": ">=0.8.0" + "node": ">=16" } }, "node_modules/@babel/code-frame": { - "version": "7.26.2", - "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz", - "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.0.tgz", + "integrity": "sha512-INCKxTtbXtcNbUZ3YXutwMpEleqttcswhAdee7dhuoVrD2cnuc3PqtERBtxkX5nziX9vnBL8WXmSGwv8CuPV6g==", "dev": true, "license": "MIT", "dependencies": { @@ -1358,10 +1253,17 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/code-frame/node_modules/js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true, + "license": "MIT" + }, "node_modules/@babel/compat-data": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.3.tgz", - "integrity": "sha512-nHIxvKPniQXpmQLb0vhY3VaFb3S0YrTAwpOWJZh1wn3oJPjJk9Asva204PsBdmAE8vpzfHudT8DB0scYvy9q0g==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz", + "integrity": "sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==", "dev": true, "license": "MIT", "engines": { @@ -1409,44 +1311,15 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/eslint-parser": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.25.9.tgz", - "integrity": "sha512-5UXfgpK0j0Xr/xIdgdLEhOFxaDZ0bRPWJJchRpqOSur/3rZoPbqqki5mm0p4NE2cs28krBEiSM2MB7//afRSQQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1", - "eslint-visitor-keys": "^2.1.0", - "semver": "^6.3.1" - }, - "engines": { - "node": "^10.13.0 || ^12.13.0 || >=14.0.0" - }, - "peerDependencies": { - "@babel/core": "^7.11.0", - "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0" - } - }, - "node_modules/@babel/eslint-parser/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, "node_modules/@babel/generator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.3.tgz", - "integrity": "sha512-6FF/urZvD0sTeO7k6/B15pMLC4CHUv1426lzr3N01aHJTl046uCAh9LXW/fzeXXjPNCJ6iABW5XaWOsIZB93aQ==", + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz", + "integrity": "sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.26.3", - "@babel/types": "^7.26.3", + "@babel/parser": "^7.26.0", + "@babel/types": "^7.26.0", "@jridgewell/gen-mapping": "^0.3.5", "@jridgewell/trace-mapping": "^0.3.25", "jsesc": "^3.0.2" @@ -1485,6 +1358,16 @@ "node": ">=6.9.0" } }, + "node_modules/@babel/helper-compilation-targets/node_modules/lru-cache": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz", + "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==", + "dev": true, + "license": "ISC", + "dependencies": { + "yallist": "^3.0.2" + } + }, "node_modules/@babel/helper-compilation-targets/node_modules/semver": { "version": "6.3.1", "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", @@ -1495,6 +1378,13 @@ "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, + "license": "ISC" + }, "node_modules/@babel/helper-create-class-features-plugin": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz", @@ -1527,51 +1417,6 @@ "semver": "bin/semver.js" } }, - "node_modules/@babel/helper-create-regexp-features-plugin": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.26.3.tgz", - "integrity": "sha512-G7ZRb40uUgdKOQqPLjfD12ZmGA54PzqDFUv2BKImnC9QIfGhIHKvVML0oN8IUiDq4iRqpq74ABpvOaerfWdong==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "regexpu-core": "^6.2.0", - "semver": "^6.3.1" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, - "node_modules/@babel/helper-create-regexp-features-plugin/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" - } - }, - "node_modules/@babel/helper-define-polyfill-provider": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.3.tgz", - "integrity": "sha512-HK7Bi+Hj6H+VTHA3ZvBis7V/6hu9QuTrnMXNybfUf2iiuU/N97I8VjB+KbhFF8Rld/Lx5MzoCwPCpPjfK+n8Cg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.22.6", - "@babel/helper-plugin-utils": "^7.22.5", - "debug": "^4.1.1", - "lodash.debounce": "^4.0.8", - "resolve": "^1.14.2" - }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" - } - }, "node_modules/@babel/helper-member-expression-to-functions": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz", @@ -1641,24 +1486,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-remap-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz", - "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-wrap-function": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" - } - }, "node_modules/@babel/helper-replace-supers": { "version": "7.25.9", "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz", @@ -1721,21 +1548,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/helper-wrap-function": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz", - "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/template": "^7.25.9", - "@babel/traverse": "^7.25.9", - "@babel/types": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - } - }, "node_modules/@babel/helpers": { "version": "7.26.0", "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz", @@ -1751,13 +1563,13 @@ } }, "node_modules/@babel/parser": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.3.tgz", - "integrity": "sha512-WJ/CvmY8Mea8iDXo6a7RK2wbmJITT5fN3BEkRuFlxVyNx8jOKIIhmC4fSkTcPcf8JyavbBwIe6OpiCOBXt/IcA==", + "version": "7.26.1", + "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.1.tgz", + "integrity": "sha512-reoQYNiAJreZNsJzyrDNzFQ+IQ5JFiIzAHJg9bn94S3l+4++J7RsIhNMoB+lgP/9tpmiAQqspv+xfdxTSzREOw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/types": "^7.26.3" + "@babel/types": "^7.26.0" }, "bin": { "parser": "bin/babel-parser.js" @@ -1766,27 +1578,28 @@ "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": { + "node_modules/@babel/plugin-proposal-decorators": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz", - "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==", + "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.25.9.tgz", + "integrity": "sha512-smkNLL/O1ezy9Nhy4CNosc4Va+1wo5w4gzSZeLe6y6dM4mmHfYOCPolXQPHQxonZCF+ZyebxN9vqOolkYrSn5g==", "dev": true, "license": "MIT", "dependencies": { + "@babel/helper-create-class-features-plugin": "^7.25.9", "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" + "@babel/plugin-syntax-decorators": "^7.25.9" }, "engines": { "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": { + "node_modules/@babel/plugin-syntax-decorators": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz", - "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.25.9.tgz", + "integrity": "sha512-ryzI0McXUPJnRCvMo4lumIKZUzhYUO/ScI+Mz4YVaTLt04DHNSjEUjKVvbzQjZFLuod/cYEc07mJWhzl6v4DPg==", "dev": true, "license": "MIT", "dependencies": { @@ -1796,13 +1609,13 @@ "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz", - "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==", + "node_modules/@babel/plugin-syntax-import-attributes": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", + "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", "dev": true, "license": "MIT", "dependencies": { @@ -1812,50 +1625,31 @@ "node": ">=6.9.0" }, "peerDependencies": { - "@babel/core": "^7.0.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==", + "node_modules/@babel/plugin-syntax-import-meta": { + "version": "7.10.4", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", + "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.10.4" }, "peerDependencies": { - "@babel/core": "^7.13.0" + "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": { + "node_modules/@babel/plugin-syntax-jsx": { "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz", - "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", + "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" + "@babel/helper-plugin-utils": "^7.25.9" }, - "peerDependencies": { - "@babel/core": "^7.0.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, - "license": "MIT", "engines": { "node": ">=6.9.0" }, @@ -1863,53 +1657,34 @@ "@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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/plugin-syntax-bigint": { - "version": "7.8.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz", - "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==", + "node_modules/@babel/plugin-syntax-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", + "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "@babel/helper-plugin-utils": "^7.25.9" }, - "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, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.12.13" + "engines": { + "node": ">=6.9.0" }, "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==", + "node_modules/@babel/plugin-transform-typescript": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz", + "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" + "@babel/helper-annotate-as-pure": "^7.25.9", + "@babel/helper-create-class-features-plugin": "^7.25.9", + "@babel/helper-plugin-utils": "^7.25.9", + "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9", + "@babel/plugin-syntax-typescript": "^7.25.9" }, "engines": { "node": ">=6.9.0" @@ -1918,6515 +1693,4280 @@ "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-assertions": { + "node_modules/@babel/runtime": { "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz", - "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", + "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "regenerator-runtime": "^0.14.0" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-attributes": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz", - "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==", + "node_modules/@babel/template": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", + "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/code-frame": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/types": "^7.25.9" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-import-meta": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz", - "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==", + "node_modules/@babel/traverse": { + "version": "7.25.9", + "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz", + "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" + "@babel/code-frame": "^7.25.9", + "@babel/generator": "^7.25.9", + "@babel/parser": "^7.25.9", + "@babel/template": "^7.25.9", + "@babel/types": "^7.25.9", + "debug": "^4.3.1", + "globals": "^11.1.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6.9.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==", + "node_modules/@babel/traverse/node_modules/globals": { + "version": "11.12.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", + "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=4" } }, - "node_modules/@babel/plugin-syntax-jsx": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz", - "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==", + "node_modules/@babel/types": { + "version": "7.26.0", + "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz", + "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@babel/helper-string-parser": "^7.25.9", + "@babel/helper-validator-identifier": "^7.25.9" }, "engines": { "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" } }, - "node_modules/@babel/plugin-syntax-logical-assignment-operators": { - "version": "7.10.4", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz", - "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==", + "node_modules/@balena/dockerignore": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@balena/dockerignore/-/dockerignore-1.0.2.tgz", + "integrity": "sha512-wMue2Sy4GAVTk6Ic4tJVcnfdau+gx2EnG7S+uAEe+TWJFqE4YoWN4/H8MSLj4eYJKxGg26lZwboEniNiNwZQ6Q==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } + "license": "Apache-2.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==", + "node_modules/@csstools/css-parser-algorithms": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.7.1.tgz", + "integrity": "sha512-2SJS42gxmACHgikc1WGesXLIT8d/q2l0UFM7TaEeIzdFCE/FPMtTiizcPGGJtlPo2xuQzY09OhrLTzRxqJqwGw==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@csstools/css-tokenizer": "^2.4.1" } }, - "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==", + "node_modules/@csstools/css-tokenizer": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.4.1.tgz", + "integrity": "sha512-eQ9DIktFJBhGjioABJRtUucoWR2mwllurfnM8LuNGAqX3ViZXaUchqk+1s7jjtkFiT9ySdACsFEA3etErkALUg==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.10.4" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": "^14 || ^16 || >=18" } }, - "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==", + "node_modules/@csstools/media-query-list-parser": { + "version": "2.1.13", + "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.13.tgz", + "integrity": "sha512-XaHr+16KRU9Gf8XLi3q8kDlI18d5vzKSKCY510Vrtc9iNR0NJzbY9hhTmwhzYZj/ZwGL4VmB3TA9hJW0Um2qFA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@csstools/css-parser-algorithms": "^2.7.1", + "@csstools/css-tokenizer": "^2.4.1" } }, - "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==", + "node_modules/@csstools/selector-specificity": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.1.1.tgz", + "integrity": "sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/csstools" + }, + { + "type": "opencollective", + "url": "https://opencollective.com/csstools" + } + ], + "license": "MIT-0", + "engines": { + "node": "^14 || ^16 || >=18" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "postcss-selector-parser": "^6.0.13" } }, - "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==", + "node_modules/@es-joy/jsdoccomment": { + "version": "0.40.1", + "resolved": "https://registry.npmjs.org/@es-joy/jsdoccomment/-/jsdoccomment-0.40.1.tgz", + "integrity": "sha512-YORCdZSusAlBrFpZ77pJjc5r1bQs5caPWtAu+WWmiSo+8XaUzseapVrfAtiRFbQWnrBxxLLEwF6f6ZG/UgCQCg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.8.0" + "comment-parser": "1.4.0", + "esquery": "^1.5.0", + "jsdoc-type-pratt-parser": "~4.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=16" } }, - "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==", + "node_modules/@esbuild/aix-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", + "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, + "optional": true, + "os": [ + "aix" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "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==", + "node_modules/@esbuild/android-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", + "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.14.5" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-syntax-typescript": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz", - "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==", + "node_modules/@esbuild/android-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", + "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">=12" } }, - "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==", + "node_modules/@esbuild/android-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", + "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.18.6", - "@babel/helper-plugin-utils": "^7.18.6" - }, + "optional": true, + "os": [ + "android" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-arrow-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz", - "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==", + "node_modules/@esbuild/darwin-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", + "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-async-generator-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz", - "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==", + "node_modules/@esbuild/darwin-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", + "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-async-to-generator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz", - "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==", + "node_modules/@esbuild/freebsd-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", + "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-module-imports": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-remap-async-to-generator": "^7.25.9" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-block-scoped-functions": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz", - "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==", + "node_modules/@esbuild/freebsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", + "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "freebsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-block-scoping": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz", - "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==", + "node_modules/@esbuild/linux-arm": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", + "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", + "cpu": [ + "arm" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-class-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz", - "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==", + "node_modules/@esbuild/linux-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", + "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-class-static-block": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz", - "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==", + "node_modules/@esbuild/linux-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", + "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.12.0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-classes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz", - "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==", + "node_modules/@esbuild/linux-loong64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", + "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", + "cpu": [ + "loong64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9", - "@babel/traverse": "^7.25.9", - "globals": "^11.1.0" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-computed-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz", - "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==", + "node_modules/@esbuild/linux-mips64el": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", + "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", + "cpu": [ + "mips64el" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/template": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-destructuring": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz", - "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==", + "node_modules/@esbuild/linux-ppc64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", + "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", + "cpu": [ + "ppc64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-dotall-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz", - "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==", + "node_modules/@esbuild/linux-riscv64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", + "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-duplicate-keys": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz", - "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==", + "node_modules/@esbuild/linux-s390x": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", + "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", + "cpu": [ + "s390x" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==", + "node_modules/@esbuild/linux-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", + "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "linux" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-dynamic-import": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz", - "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==", + "node_modules/@esbuild/netbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", + "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "netbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-exponentiation-operator": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.26.3.tgz", - "integrity": "sha512-7CAHcQ58z2chuXPWblnn1K6rLDnDWieghSOEmqQsrBenH0P9InCUtOJYD89pvngljmZlJcz3fcmgYsXFNGa1ZQ==", + "node_modules/@esbuild/openbsd-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", + "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "openbsd" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-export-namespace-from": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz", - "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==", + "node_modules/@esbuild/sunos-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", + "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "sunos" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-for-of": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz", - "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==", + "node_modules/@esbuild/win32-arm64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", + "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-function-name": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz", - "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==", + "node_modules/@esbuild/win32-ia32": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", + "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-json-strings": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz", - "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==", + "node_modules/@esbuild/win32-x64": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", + "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, + "optional": true, + "os": [ + "win32" + ], "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz", - "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==", + "node_modules/@eslint-community/eslint-utils": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz", + "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "eslint-visitor-keys": "^3.4.3" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0" } }, - "node_modules/@babel/plugin-transform-logical-assignment-operators": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz", - "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==", + "node_modules/@eslint-community/regexpp": { + "version": "4.11.2", + "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.11.2.tgz", + "integrity": "sha512-2WwyTYNVaMNUWPZTOJdkax9iqTdirrApgTbk+Qoq5EPX6myqZvG8QGFRgdKmkjKVG6/G/a565vpPauHk0+hpBA==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^12.0.0 || ^14.0.0 || >=16.0.0" } }, - "node_modules/@babel/plugin-transform-member-expression-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz", - "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==", + "node_modules/@eslint/eslintrc": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", + "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "ajv": "^6.12.4", + "debug": "^4.3.2", + "espree": "^9.4.0", + "globals": "^13.19.0", + "ignore": "^5.2.0", + "import-fresh": "^3.2.1", + "js-yaml": "^4.1.0", + "minimatch": "^3.1.2", + "strip-json-comments": "^3.1.1" }, "engines": { - "node": ">=6.9.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/@babel/plugin-transform-modules-amd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz", - "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==", + "node_modules/@eslint/eslintrc/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==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/plugin-transform-modules-commonjs": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.26.3.tgz", - "integrity": "sha512-MgR55l4q9KddUDITEzEFYn5ZsGDXMSsU9E+kh7fjRXTIC3RHqfCo8RPRbyReYJh44HQ/yomFkqbOFohXvDCiIQ==", + "node_modules/@eslint/eslintrc/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@babel/helper-module-transforms": "^7.26.0", - "@babel/helper-plugin-utils": "^7.25.9" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "*" } }, - "node_modules/@babel/plugin-transform-modules-systemjs": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz", - "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==", + "node_modules/@fastify/busboy": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", + "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9", - "@babel/traverse": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=14" } }, - "node_modules/@babel/plugin-transform-modules-umd": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz", - "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==", + "node_modules/@fortawesome/fontawesome-common-types": { + "version": "0.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", + "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", "dev": true, + "hasInstallScript": true, "license": "MIT", - "dependencies": { - "@babel/helper-module-transforms": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-named-capturing-groups-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz", - "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==", - "dev": true, + "node_modules/@fortawesome/fontawesome-svg-core": { + "version": "1.2.36", + "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz", + "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", + "dev": true, + "hasInstallScript": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@fortawesome/fontawesome-common-types": "^0.2.36" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-new-target": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz", - "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==", + "node_modules/@fortawesome/free-regular-svg-icons": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz", + "integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==", "dev": true, - "license": "MIT", + "hasInstallScript": true, + "license": "(CC-BY-4.0 AND MIT)", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@fortawesome/fontawesome-common-types": "^0.2.36" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-nullish-coalescing-operator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz", - "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==", + "node_modules/@fortawesome/free-solid-svg-icons": { + "version": "5.15.4", + "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", + "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", "dev": true, - "license": "MIT", + "hasInstallScript": true, + "license": "(CC-BY-4.0 AND MIT)", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@fortawesome/fontawesome-common-types": "^0.2.36" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-numeric-separator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz", - "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==", + "node_modules/@fortawesome/vue-fontawesome": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.8.tgz", + "integrity": "sha512-yyHHAj4G8pQIDfaIsMvQpwKMboIZtcHTUvPqXjOHyldh1O1vZfH4W03VDPv5RvI9P6DLTzJQlmVgj9wCf7c2Fw==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@fortawesome/fontawesome-svg-core": "~1 || ~6", + "vue": ">= 3.0.0 < 4" } }, - "node_modules/@babel/plugin-transform-object-rest-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz", - "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==", - "dev": true, + "node_modules/@gar/promisify": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", + "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", "license": "MIT", + "optional": true + }, + "node_modules/@grpc/grpc-js": { + "version": "1.8.22", + "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.22.tgz", + "integrity": "sha512-oAjDdN7fzbUi+4hZjKG96MR6KTEubAeMpQEb+77qy+3r0Ua5xTFuie6JOLr4ZZgl5g+W5/uRTS2M1V8mVAFPuA==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9" + "@grpc/proto-loader": "^0.7.0", + "@types/node": ">=12.12.47" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "^8.13.0 || >=10.10.0" } }, - "node_modules/@babel/plugin-transform-object-super": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz", - "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==", - "dev": true, - "license": "MIT", + "node_modules/@grpc/proto-loader": { + "version": "0.7.13", + "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", + "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-replace-supers": "^7.25.9" + "lodash.camelcase": "^4.3.0", + "long": "^5.0.0", + "protobufjs": "^7.2.5", + "yargs": "^17.7.2" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "engines": { + "node": ">=6" } }, - "node_modules/@babel/plugin-transform-optional-catch-binding": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz", - "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==", + "node_modules/@hapi/hoek": { + "version": "9.3.0", + "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", + "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause" + }, + "node_modules/@hapi/topo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", + "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "@hapi/hoek": "^9.0.0" } }, - "node_modules/@babel/plugin-transform-optional-chaining": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz", - "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==", + "node_modules/@humanwhocodes/config-array": { + "version": "0.9.5", + "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", + "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", + "deprecated": "Use @eslint/config-array instead", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + "@humanwhocodes/object-schema": "^1.2.1", + "debug": "^4.1.1", + "minimatch": "^3.0.4" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=10.10.0" } }, - "node_modules/@babel/plugin-transform-parameters": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz", - "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==", + "node_modules/@humanwhocodes/config-array/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==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, - "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/@babel/plugin-transform-private-methods": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz", - "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==", + "node_modules/@humanwhocodes/config-array/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": "*" } }, - "node_modules/@babel/plugin-transform-private-property-in-object": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz", - "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==", + "node_modules/@humanwhocodes/object-schema": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", + "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", + "deprecated": "Use @eslint/object-schema instead", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/@intlify/core-base": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.2.2.tgz", + "integrity": "sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-annotate-as-pure": "^7.25.9", - "@babel/helper-create-class-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@intlify/devtools-if": "9.2.2", + "@intlify/message-compiler": "9.2.2", + "@intlify/shared": "9.2.2", + "@intlify/vue-devtools": "9.2.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 14" } }, - "node_modules/@babel/plugin-transform-property-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz", - "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==", + "node_modules/@intlify/devtools-if": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.2.2.tgz", + "integrity": "sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@intlify/shared": "9.2.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 14" } }, - "node_modules/@babel/plugin-transform-regenerator": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz", - "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==", + "node_modules/@intlify/message-compiler": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.2.2.tgz", + "integrity": "sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "regenerator-transform": "^0.15.2" + "@intlify/shared": "9.2.2", + "source-map": "0.6.1" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 14" } }, - "node_modules/@babel/plugin-transform-regexp-modifiers": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz", - "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==", + "node_modules/@intlify/message-compiler/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==", "dev": true, - "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, + "license": "BSD-3-Clause", "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=0.10.0" } }, - "node_modules/@babel/plugin-transform-reserved-words": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz", - "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==", + "node_modules/@intlify/shared": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.2.tgz", + "integrity": "sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 14" } }, - "node_modules/@babel/plugin-transform-shorthand-properties": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz", - "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==", + "node_modules/@intlify/vue-devtools": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.2.2.tgz", + "integrity": "sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "@intlify/core-base": "9.2.2", + "@intlify/shared": "9.2.2" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">= 14" } }, - "node_modules/@babel/plugin-transform-spread": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz", - "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==", - "dev": true, - "license": "MIT", + "node_modules/@isaacs/cliui": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", + "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", + "license": "ISC", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9" + "string-width": "^5.1.2", + "string-width-cjs": "npm:string-width@^4.2.0", + "strip-ansi": "^7.0.1", + "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", + "wrap-ansi": "^8.1.0", + "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=12" } }, - "node_modules/@babel/plugin-transform-sticky-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz", - "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/ansi-regex": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", + "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/ansi-regex?sponsor=1" } }, - "node_modules/@babel/plugin-transform-template-literals": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz", - "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/ansi-styles": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "license": "MIT", - "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/@babel/plugin-transform-typeof-symbol": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz", - "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/emoji-regex": { + "version": "9.2.2", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", + "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", + "license": "MIT" + }, + "node_modules/@isaacs/cliui/node_modules/string-width": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", + "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "eastasianwidth": "^0.2.0", + "emoji-regex": "^9.2.2", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/@babel/plugin-transform-unicode-escapes": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz", - "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/strip-ansi": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.25.9" + "ansi-regex": "^6.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, - "node_modules/@babel/plugin-transform-unicode-property-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz", - "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==", - "dev": true, + "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", + "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "ansi-styles": "^6.1.0", + "string-width": "^5.0.1", + "strip-ansi": "^7.0.1" }, "engines": { - "node": ">=6.9.0" + "node": ">=12" }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "funding": { + "url": "https://github.com/chalk/wrap-ansi?sponsor=1" } }, - "node_modules/@babel/plugin-transform-unicode-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz", - "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==", + "node_modules/@jridgewell/gen-mapping": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz", + "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" + "@jridgewell/set-array": "^1.2.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.24" }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" + "node": ">=6.0.0" } }, - "node_modules/@babel/plugin-transform-unicode-sets-regex": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz", - "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==", + "node_modules/@jridgewell/resolve-uri": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", + "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/helper-create-regexp-features-plugin": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "node": ">=6.0.0" } }, - "node_modules/@babel/preset-env": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz", - "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==", + "node_modules/@jridgewell/set-array": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", + "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/compat-data": "^7.26.0", - "@babel/helper-compilation-targets": "^7.25.9", - "@babel/helper-plugin-utils": "^7.25.9", - "@babel/helper-validator-option": "^7.25.9", - "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9", - "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9", - "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9", - "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9", - "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9", - "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2", - "@babel/plugin-syntax-import-assertions": "^7.26.0", - "@babel/plugin-syntax-import-attributes": "^7.26.0", - "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6", - "@babel/plugin-transform-arrow-functions": "^7.25.9", - "@babel/plugin-transform-async-generator-functions": "^7.25.9", - "@babel/plugin-transform-async-to-generator": "^7.25.9", - "@babel/plugin-transform-block-scoped-functions": "^7.25.9", - "@babel/plugin-transform-block-scoping": "^7.25.9", - "@babel/plugin-transform-class-properties": "^7.25.9", - "@babel/plugin-transform-class-static-block": "^7.26.0", - "@babel/plugin-transform-classes": "^7.25.9", - "@babel/plugin-transform-computed-properties": "^7.25.9", - "@babel/plugin-transform-destructuring": "^7.25.9", - "@babel/plugin-transform-dotall-regex": "^7.25.9", - "@babel/plugin-transform-duplicate-keys": "^7.25.9", - "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-dynamic-import": "^7.25.9", - "@babel/plugin-transform-exponentiation-operator": "^7.25.9", - "@babel/plugin-transform-export-namespace-from": "^7.25.9", - "@babel/plugin-transform-for-of": "^7.25.9", - "@babel/plugin-transform-function-name": "^7.25.9", - "@babel/plugin-transform-json-strings": "^7.25.9", - "@babel/plugin-transform-literals": "^7.25.9", - "@babel/plugin-transform-logical-assignment-operators": "^7.25.9", - "@babel/plugin-transform-member-expression-literals": "^7.25.9", - "@babel/plugin-transform-modules-amd": "^7.25.9", - "@babel/plugin-transform-modules-commonjs": "^7.25.9", - "@babel/plugin-transform-modules-systemjs": "^7.25.9", - "@babel/plugin-transform-modules-umd": "^7.25.9", - "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9", - "@babel/plugin-transform-new-target": "^7.25.9", - "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9", - "@babel/plugin-transform-numeric-separator": "^7.25.9", - "@babel/plugin-transform-object-rest-spread": "^7.25.9", - "@babel/plugin-transform-object-super": "^7.25.9", - "@babel/plugin-transform-optional-catch-binding": "^7.25.9", - "@babel/plugin-transform-optional-chaining": "^7.25.9", - "@babel/plugin-transform-parameters": "^7.25.9", - "@babel/plugin-transform-private-methods": "^7.25.9", - "@babel/plugin-transform-private-property-in-object": "^7.25.9", - "@babel/plugin-transform-property-literals": "^7.25.9", - "@babel/plugin-transform-regenerator": "^7.25.9", - "@babel/plugin-transform-regexp-modifiers": "^7.26.0", - "@babel/plugin-transform-reserved-words": "^7.25.9", - "@babel/plugin-transform-shorthand-properties": "^7.25.9", - "@babel/plugin-transform-spread": "^7.25.9", - "@babel/plugin-transform-sticky-regex": "^7.25.9", - "@babel/plugin-transform-template-literals": "^7.25.9", - "@babel/plugin-transform-typeof-symbol": "^7.25.9", - "@babel/plugin-transform-unicode-escapes": "^7.25.9", - "@babel/plugin-transform-unicode-property-regex": "^7.25.9", - "@babel/plugin-transform-unicode-regex": "^7.25.9", - "@babel/plugin-transform-unicode-sets-regex": "^7.25.9", - "@babel/preset-modules": "0.1.6-no-external-plugins", - "babel-plugin-polyfill-corejs2": "^0.4.10", - "babel-plugin-polyfill-corejs3": "^0.10.6", - "babel-plugin-polyfill-regenerator": "^0.6.1", - "core-js-compat": "^3.38.1", - "semver": "^6.3.1" - }, "engines": { - "node": ">=6.9.0" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0" - } - }, - "node_modules/@babel/preset-env/node_modules/semver": { - "version": "6.3.1", - "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz", - "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==", - "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "node": ">=6.0.0" } }, - "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==", + "node_modules/@jridgewell/source-map": { + "version": "0.3.6", + "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", + "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-plugin-utils": "^7.0.0", - "@babel/types": "^7.4.4", - "esutils": "^2.0.2" - }, - "peerDependencies": { - "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0" + "@jridgewell/gen-mapping": "^0.3.5", + "@jridgewell/trace-mapping": "^0.3.25" } }, - "node_modules/@babel/runtime": { - "version": "7.26.0", - "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz", - "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==", + "node_modules/@jridgewell/sourcemap-codec": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", + "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@jridgewell/trace-mapping": { + "version": "0.3.25", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", + "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", "dev": true, "license": "MIT", "dependencies": { - "regenerator-runtime": "^0.14.0" - }, - "engines": { - "node": ">=6.9.0" + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" } }, - "node_modules/@babel/runtime/node_modules/regenerator-runtime": { - "version": "0.14.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", - "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", + "node_modules/@js-joda/core": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.6.3.tgz", + "integrity": "sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==", + "license": "BSD-3-Clause" + }, + "node_modules/@kurkle/color": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz", + "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw==", "dev": true, "license": "MIT" }, - "node_modules/@babel/template": { - "version": "7.25.9", - "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz", - "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==", - "dev": true, + "node_modules/@louislam/ping": { + "version": "0.4.4-mod.1", + "resolved": "https://registry.npmjs.org/@louislam/ping/-/ping-0.4.4-mod.1.tgz", + "integrity": "sha512-uMq6qwL9/VYh2YBbDEhM7ZzJ8YON+juw/3k+28P3s9ue3uDMQ56MNPfywXoRpsxkU8RgjN0TDzEhQDzO1WisMw==", "license": "MIT", "dependencies": { - "@babel/code-frame": "^7.25.9", - "@babel/parser": "^7.25.9", - "@babel/types": "^7.25.9" + "command-exists": "~1.2.9", + "underscore": "~1.13.6" }, "engines": { - "node": ">=6.9.0" + "node": ">=4.0.0" } }, - "node_modules/@babel/traverse": { - "version": "7.26.4", - "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.26.4.tgz", - "integrity": "sha512-fH+b7Y4p3yqvApJALCPJcwb0/XaOSgtK4pzV6WVjPR5GLFQBRI7pfoX2V2iM48NXvX07NUxxm1Vw98YjqTcU5w==", - "dev": true, - "license": "MIT", + "node_modules/@louislam/sqlite3": { + "version": "15.1.6", + "resolved": "https://registry.npmjs.org/@louislam/sqlite3/-/sqlite3-15.1.6.tgz", + "integrity": "sha512-cVf7hcMrfywYnycatLvorngTFpL3BSWvEy7/NrEfcTyQX8xxj9fdeD553oCTv5fIAk85fluo6mzPq89V3YzrVA==", + "hasInstallScript": true, + "license": "BSD-3-Clause", "dependencies": { - "@babel/code-frame": "^7.26.2", - "@babel/generator": "^7.26.3", - "@babel/parser": "^7.26.3", - "@babel/template": "^7.25.9", - "@babel/types": "^7.26.3", - "debug": "^4.3.1", - "globals": "^11.1.0" + "@mapbox/node-pre-gyp": "^1.0.0", + "node-addon-api": "^4.2.0", + "tar": "^6.1.11" }, - "engines": { - "node": ">=6.9.0" + "optionalDependencies": { + "node-gyp": "8.x" + }, + "peerDependencies": { + "node-gyp": "8.x" + }, + "peerDependenciesMeta": { + "node-gyp": { + "optional": true + } } }, - "node_modules/@babel/types": { - "version": "7.26.3", - "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.3.tgz", - "integrity": "sha512-vN5p+1kl59GVKMvTHt55NzzmYVxprfJD+ql7U9NFIfKCBkYE55LYtS+WtPlaYOyzydrKI8Nezd+aZextrd+FMA==", - "dev": true, - "license": "MIT", + "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==", + "license": "BSD-3-Clause", "dependencies": { - "@babel/helper-string-parser": "^7.25.9", - "@babel/helper-validator-identifier": "^7.25.9" + "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" }, - "engines": { - "node": ">=6.9.0" + "bin": { + "node-pre-gyp": "bin/node-pre-gyp" } }, - "node_modules/@bcoe/v8-coverage": { - "version": "0.2.3", - "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz", - "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==", - "dev": true, - "license": "MIT" - }, - "node_modules/@colors/colors": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@colors/colors/-/colors-1.5.0.tgz", - "integrity": "sha512-ooWCrlZP11i8GImSjTHYHLkvFDP48nS4+204nGb1RiX/WXYHmJA2III9/e2DWVabCESdW7hBAEzHRqUn9OUVvQ==", - "dev": true, + "node_modules/@mongodb-js/saslprep": { + "version": "1.1.9", + "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", + "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", "license": "MIT", "optional": true, - "engines": { - "node": ">=0.1.90" + "dependencies": { + "sparse-bitfield": "^3.0.3" } }, - "node_modules/@csstools/css-parser-algorithms": { - "version": "2.7.1", - "resolved": "https://registry.npmjs.org/@csstools/css-parser-algorithms/-/css-parser-algorithms-2.7.1.tgz", - "integrity": "sha512-2SJS42gxmACHgikc1WGesXLIT8d/q2l0UFM7TaEeIzdFCE/FPMtTiizcPGGJtlPo2xuQzY09OhrLTzRxqJqwGw==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], + "node_modules/@noble/ciphers": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz", + "integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==", "license": "MIT", - "engines": { - "node": "^14 || ^16 || >=18" + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/@noble/curves": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", + "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", + "license": "MIT", + "dependencies": { + "@noble/hashes": "1.3.1" }, - "peerDependencies": { - "@csstools/css-tokenizer": "^2.4.1" + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@csstools/css-tokenizer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/@csstools/css-tokenizer/-/css-tokenizer-2.4.1.tgz", - "integrity": "sha512-eQ9DIktFJBhGjioABJRtUucoWR2mwllurfnM8LuNGAqX3ViZXaUchqk+1s7jjtkFiT9ySdACsFEA3etErkALUg==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], + "node_modules/@noble/hashes": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", + "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" + "node": ">= 16" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@csstools/media-query-list-parser": { - "version": "2.1.13", - "resolved": "https://registry.npmjs.org/@csstools/media-query-list-parser/-/media-query-list-parser-2.1.13.tgz", - "integrity": "sha512-XaHr+16KRU9Gf8XLi3q8kDlI18d5vzKSKCY510Vrtc9iNR0NJzbY9hhTmwhzYZj/ZwGL4VmB3TA9hJW0Um2qFA==", + "node_modules/@nodelib/fs.scandir": { + "version": "2.1.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", + "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], "license": "MIT", - "engines": { - "node": "^14 || ^16 || >=18" + "dependencies": { + "@nodelib/fs.stat": "2.0.5", + "run-parallel": "^1.1.9" }, - "peerDependencies": { - "@csstools/css-parser-algorithms": "^2.7.1", - "@csstools/css-tokenizer": "^2.4.1" + "engines": { + "node": ">= 8" } }, - "node_modules/@csstools/selector-specificity": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-3.1.1.tgz", - "integrity": "sha512-a7cxGcJ2wIlMFLlh8z2ONm+715QkPHiyJcxwQlKOz/03GPw1COpfhcmC9wm4xlZfp//jWHNNMwzjtqHXVWU9KA==", + "node_modules/@nodelib/fs.stat": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", + "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/csstools" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/csstools" - } - ], - "license": "MIT-0", + "license": "MIT", "engines": { - "node": "^14 || ^16 || >=18" - }, - "peerDependencies": { - "postcss-selector-parser": "^6.0.13" + "node": ">= 8" } }, - "node_modules/@cypress/request": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@cypress/request/-/request-3.0.7.tgz", - "integrity": "sha512-LzxlLEMbBOPYB85uXrDqvD4MgcenjRBLIns3zyhx7vTPj/0u2eQhzXvPiGcaJrV38Q9dbkExWp6cOHPJ+EtFYg==", + "node_modules/@nodelib/fs.walk": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", + "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "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": "~4.0.0", - "http-signature": "~1.4.0", - "is-typedarray": "~1.0.0", - "isstream": "~0.1.2", - "json-stringify-safe": "~5.0.1", - "mime-types": "~2.1.19", - "performance-now": "^2.1.0", - "qs": "6.13.1", - "safe-buffer": "^5.1.2", - "tough-cookie": "^5.0.0", - "tunnel-agent": "^0.6.0", - "uuid": "^8.3.2" + "@nodelib/fs.scandir": "2.1.5", + "fastq": "^1.6.0" }, "engines": { - "node": ">= 6" + "node": ">= 8" } }, - "node_modules/@cypress/request/node_modules/qs": { - "version": "6.13.1", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.1.tgz", - "integrity": "sha512-EJPeIn0CYrGu+hli1xilKAPXODtJ12T0sP63Ijx2/khC2JtuaN3JyNIpvmnkmaEtha9ocbG4A4cMcr+TvqvwQg==", - "dev": true, - "license": "BSD-3-Clause", + "node_modules/@npmcli/fs": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", + "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", + "license": "ISC", + "optional": true, "dependencies": { - "side-channel": "^1.0.6" + "@gar/promisify": "^1.0.1", + "semver": "^7.3.5" + } + }, + "node_modules/@npmcli/move-file": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", + "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", + "deprecated": "This functionality has been moved to @npmcli/fs", + "license": "MIT", + "optional": true, + "dependencies": { + "mkdirp": "^1.0.4", + "rimraf": "^3.0.2" }, "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=10" } }, - "node_modules/@cypress/xvfb": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/@cypress/xvfb/-/xvfb-1.2.4.tgz", - "integrity": "sha512-skbBzPggOVYCbnGgV+0dmBdW/s77ZkAOXIC1knS8NagwDjBrNC1LuXtQJeiN6l+m7lzmHtaoUw/ctJKdqkG57Q==", + "node_modules/@octokit/auth-token": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", + "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", "dev": true, "license": "MIT", "dependencies": { - "debug": "^3.1.0", - "lodash.once": "^4.1.1" + "@octokit/types": "^6.0.3" } }, - "node_modules/@cypress/xvfb/node_modules/debug": { - "version": "3.2.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz", - "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==", + "node_modules/@octokit/core": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", + "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.1" + "@octokit/auth-token": "^2.4.4", + "@octokit/graphql": "^4.5.8", + "@octokit/request": "^5.6.3", + "@octokit/request-error": "^2.0.5", + "@octokit/types": "^6.0.3", + "before-after-hook": "^2.2.0", + "universal-user-agent": "^6.0.0" } }, - "node_modules/@esbuild/aix-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.20.2.tgz", - "integrity": "sha512-D+EBOJHXdNZcLJRBkhENNG8Wji2kgc9AZ9KiPr1JuZjsNtyHzrsfLRrY0tk2H2aoFu6RANO1y1iPPUCDYWkb5g==", - "cpu": [ - "ppc64" - ], + "node_modules/@octokit/endpoint": { + "version": "6.0.12", + "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", + "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "aix" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@octokit/types": "^6.0.3", + "is-plain-object": "^5.0.0", + "universal-user-agent": "^6.0.0" } }, - "node_modules/@esbuild/android-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.20.2.tgz", - "integrity": "sha512-t98Ra6pw2VaDhqNWO2Oph2LXbz/EJcnLmKLGBJwEwXX/JAN83Fym1rU8l0JUWK6HkIbWONCSSatf4sf2NBRx/w==", - "cpu": [ - "arm" - ], + "node_modules/@octokit/graphql": { + "version": "4.8.0", + "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", + "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@octokit/request": "^5.6.0", + "@octokit/types": "^6.0.3", + "universal-user-agent": "^6.0.0" } }, - "node_modules/@esbuild/android-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.20.2.tgz", - "integrity": "sha512-mRzjLacRtl/tWU0SvD8lUEwb61yP9cqQo6noDZP/O8VkwafSYwZ4yWy24kan8jE/IMERpYncRt2dw438LP3Xmg==", - "cpu": [ - "arm64" - ], + "node_modules/@octokit/openapi-types": { + "version": "12.11.0", + "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", + "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" - } + "license": "MIT" }, - "node_modules/@esbuild/android-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.20.2.tgz", - "integrity": "sha512-btzExgV+/lMGDDa194CcUQm53ncxzeBrWJcncOBxuC6ndBkKxnHdFJn86mCIgTELsooUmwUm9FkhSp5HYu00Rg==", - "cpu": [ - "x64" - ], + "node_modules/@octokit/plugin-paginate-rest": { + "version": "2.21.3", + "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", + "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "android" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@octokit/types": "^6.40.0" + }, + "peerDependencies": { + "@octokit/core": ">=2" } }, - "node_modules/@esbuild/darwin-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.20.2.tgz", - "integrity": "sha512-4J6IRT+10J3aJH3l1yzEg9y3wkTDgDk7TSDFX+wKFiWjqWp/iCfLIYzGyasx9l0SAFPT1HwSCR+0w/h1ES/MjA==", - "cpu": [ - "arm64" - ], + "node_modules/@octokit/plugin-rest-endpoint-methods": { + "version": "5.16.2", + "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", + "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@octokit/types": "^6.39.0", + "deprecation": "^2.3.1" + }, + "peerDependencies": { + "@octokit/core": ">=3" } }, - "node_modules/@esbuild/darwin-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.20.2.tgz", - "integrity": "sha512-tBcXp9KNphnNH0dfhv8KYkZhjc+H3XBkF5DKtswJblV7KlT9EI2+jeA8DgBjp908WEuYll6pF+UStUCfEpdysA==", - "cpu": [ - "x64" - ], + "node_modules/@octokit/request": { + "version": "5.6.3", + "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", + "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@octokit/endpoint": "^6.0.1", + "@octokit/request-error": "^2.1.0", + "@octokit/types": "^6.16.1", + "is-plain-object": "^5.0.0", + "node-fetch": "^2.6.7", + "universal-user-agent": "^6.0.0" } }, - "node_modules/@esbuild/freebsd-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.20.2.tgz", - "integrity": "sha512-d3qI41G4SuLiCGCFGUrKsSeTXyWG6yem1KcGZVS+3FYlYhtNoNgYrWcvkOoaqMhwXSMrZRl69ArHsGJ9mYdbbw==", - "cpu": [ - "arm64" - ], + "node_modules/@octokit/request-error": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", + "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@octokit/types": "^6.0.3", + "deprecation": "^2.0.0", + "once": "^1.4.0" } }, - "node_modules/@esbuild/freebsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.20.2.tgz", - "integrity": "sha512-d+DipyvHRuqEeM5zDivKV1KuXn9WeRX6vqSqIDgwIfPQtwMP4jaDsQsDncjTDDsExT4lR/91OLjRo8bmC1e+Cw==", - "cpu": [ - "x64" - ], + "node_modules/@octokit/types": { + "version": "6.41.0", + "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", + "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ], - "engines": { - "node": ">=12" + "dependencies": { + "@octokit/openapi-types": "^12.11.0" } }, - "node_modules/@esbuild/linux-arm": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.20.2.tgz", - "integrity": "sha512-VhLPeR8HTMPccbuWWcEUD1Az68TqaTYyj6nfE4QByZIQEQVWBB8vup8PpR7y1QHL3CpcF6xd5WVBU/+SBEvGTg==", - "cpu": [ - "arm" - ], - "dev": true, + "node_modules/@pkgjs/parseargs": { + "version": "0.11.0", + "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", + "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", "license": "MIT", "optional": true, - "os": [ - "linux" - ], "engines": { - "node": ">=12" + "node": ">=14" } }, - "node_modules/@esbuild/linux-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.20.2.tgz", - "integrity": "sha512-9pb6rBjGvTFNira2FLIWqDk/uaf42sSyLE8j1rnUpuzsODBq7FvpwHYZxQ/It/8b+QOS1RYfqgGFNLRI+qlq2A==", - "cpu": [ - "arm64" - ], + "node_modules/@playwright/test": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/@playwright/test/-/test-1.39.0.tgz", + "integrity": "sha512-3u1iFqgzl7zr004bGPYiN/5EZpRUSFddQBra8Rqll5N0/vfpqlP9I9EXqAoGacuAbX6c9Ulg/Cjqglp5VkK6UQ==", + "deprecated": "Please update to the latest version of Playwright to test up-to-date browsers.", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], + "license": "Apache-2.0", + "dependencies": { + "playwright": "1.39.0" + }, + "bin": { + "playwright": "cli.js" + }, "engines": { - "node": ">=12" + "node": ">=16" } }, - "node_modules/@esbuild/linux-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.20.2.tgz", - "integrity": "sha512-o10utieEkNPFDZFQm9CoP7Tvb33UutoJqg3qKf1PWVeeJhJw0Q347PxMvBgVVFgouYLGIhFYG0UGdBumROyiig==", - "cpu": [ - "ia32" - ], + "node_modules/@polka/url": { + "version": "1.0.0-next.28", + "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.28.tgz", + "integrity": "sha512-8LduaNlMZGwdZ6qWrKlfa+2M4gahzFkprZiAt2TF8uS0qQgBizKXpXURqvTJ4WtmupWxaLqjRb2UCTe72mu+Aw==", "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "license": "MIT" }, - "node_modules/@esbuild/linux-loong64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.20.2.tgz", - "integrity": "sha512-PR7sp6R/UC4CFVomVINKJ80pMFlfDfMQMYynX7t1tNTeivQ6XdX5r2XovMmha/VjR1YN/HgHWsVcTRIMkymrgQ==", - "cpu": [ - "loong64" - ], + "node_modules/@popperjs/core": { + "version": "2.10.2", + "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz", + "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==", "dev": true, "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" } }, - "node_modules/@esbuild/linux-mips64el": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.20.2.tgz", - "integrity": "sha512-4BlTqeutE/KnOiTG5Y6Sb/Hw6hsBOZapOVF6njAESHInhlQAghVVZL1ZpIctBOoTFbQyGW+LsVYZ8lSSB3wkjA==", - "cpu": [ - "mips64el" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "node_modules/@protobufjs/aspromise": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", + "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", + "license": "BSD-3-Clause" }, - "node_modules/@esbuild/linux-ppc64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.20.2.tgz", - "integrity": "sha512-rD3KsaDprDcfajSKdn25ooz5J5/fWBylaaXkuotBDGnMnDP1Uv5DLAN/45qfnf3JDYyJv/ytGHQaziHUdyzaAg==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } + "node_modules/@protobufjs/base64": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", + "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", + "license": "BSD-3-Clause" }, - "node_modules/@esbuild/linux-riscv64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.20.2.tgz", - "integrity": "sha512-snwmBKacKmwTMmhLlz/3aH1Q9T8v45bKYGE3j26TsaOVtjIag4wLfWSiZykXzXuE1kbCE+zJRmwp+ZbIHinnVg==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" + "node_modules/@protobufjs/codegen": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", + "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/eventemitter": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", + "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", + "license": "BSD-3-Clause" + }, + "node_modules/@protobufjs/fetch": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", + "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", + "license": "BSD-3-Clause", + "dependencies": { + "@protobufjs/aspromise": "^1.1.1", + "@protobufjs/inquire": "^1.1.0" } }, - "node_modules/@esbuild/linux-s390x": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.20.2.tgz", - "integrity": "sha512-wcWISOobRWNm3cezm5HOZcYz1sKoHLd8VL1dl309DiixxVFoFe/o8HnwuIwn6sXre88Nwj+VwZUvJf4AFxkyrQ==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/linux-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.20.2.tgz", - "integrity": "sha512-1MdwI6OOTsfQfek8sLwgyjOXAu+wKhLEoaOLTjbijk6E2WONYpH9ZU2mNtR+lZ2B4uwr+usqGuVfFT9tMtGvGw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/netbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.20.2.tgz", - "integrity": "sha512-K8/DhBxcVQkzYc43yJXDSyjlFeHQJBiowJ0uVL6Tor3jGQfSGHNNJcWxNbOI8v5k82prYqzPuwkzHt3J1T1iZQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "netbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/openbsd-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.20.2.tgz", - "integrity": "sha512-eMpKlV0SThJmmJgiVyN9jTPJ2VBPquf6Kt/nAoo6DgHAoN57K15ZghiHaMvqjCye/uU4X5u3YSMgVBI1h3vKrQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "openbsd" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/sunos-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.20.2.tgz", - "integrity": "sha512-2UyFtRC6cXLyejf/YEld4Hajo7UHILetzE1vsRcGL3earZEW77JxrFjH4Ez2qaTiEfMgAXxfAZCm1fvM/G/o8w==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "sunos" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-arm64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.20.2.tgz", - "integrity": "sha512-GRibxoawM9ZCnDxnP3usoUDO9vUkpAxIIZ6GQI+IlVmr5kP3zUq+l17xELTHMWTWzjxa2guPNyrpq1GWmPvcGQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-ia32": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.20.2.tgz", - "integrity": "sha512-HfLOfn9YWmkSKRQqovpnITazdtquEW8/SoHW7pWpuEeguaZI4QnCRW6b+oZTztdBnZOS2hqJ6im/D5cPzBTTlQ==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@esbuild/win32-x64": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.20.2.tgz", - "integrity": "sha512-N49X4lJX27+l9jbLKSqZ6bKNjzQvHaT8IIFUy+YIqmXQdjYCToGWwOItDrfby14c78aDd5NHQl29xingXfCdLQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ], - "engines": { - "node": ">=12" - } - }, - "node_modules/@eslint/eslintrc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-1.4.1.tgz", - "integrity": "sha512-XXrH9Uarn0stsyldqDYq8r++mROmWRI1xKMXa640Bb//SY1+ECYX6VzT6Lcx5frD0V30XieqJ0oX9I2Xj5aoMA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ajv": "^6.12.4", - "debug": "^4.3.2", - "espree": "^9.4.0", - "globals": "^13.19.0", - "ignore": "^5.2.0", - "import-fresh": "^3.2.1", - "js-yaml": "^4.1.0", - "minimatch": "^3.1.2", - "strip-json-comments": "^3.1.1" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/@eslint/eslintrc/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "type-fest": "^0.20.2" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@eslint/eslintrc/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@fastify/busboy": { - "version": "2.1.1", - "resolved": "https://registry.npmjs.org/@fastify/busboy/-/busboy-2.1.1.tgz", - "integrity": "sha512-vBZP4NlzfOlerQTnba4aqZoMhE/a9HY7HRqoOPaETQcSQuWEIyZMHGfVu6w9wGtGK5fED5qRs2DteVCjOH60sA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/@fortawesome/fontawesome-common-types": { - "version": "0.2.36", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-common-types/-/fontawesome-common-types-0.2.36.tgz", - "integrity": "sha512-a/7BiSgobHAgBWeN7N0w+lAhInrGxksn13uK7231n2m8EDPE3BMCl9NZLTGrj9ZXfCmC6LM0QLqXidIizVQ6yg==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/fontawesome-svg-core": { - "version": "1.2.36", - "resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-svg-core/-/fontawesome-svg-core-1.2.36.tgz", - "integrity": "sha512-YUcsLQKYb6DmaJjIHdDWpBIGCcyE/W+p/LMGvjQem55Mm2XWVAP5kWTMKWLv9lwpCVjpLxPyOMOyUocP1GxrtA==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.36" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-regular-svg-icons": { - "version": "5.15.4", - "resolved": "https://registry.npmjs.org/@fortawesome/free-regular-svg-icons/-/free-regular-svg-icons-5.15.4.tgz", - "integrity": "sha512-9VNNnU3CXHy9XednJ3wzQp6SwNwT3XaM26oS4Rp391GsxVYA+0oDR2J194YCIWf7jNRCYKjUCOduxdceLrx+xw==", - "dev": true, - "hasInstallScript": true, - "license": "(CC-BY-4.0 AND MIT)", - "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.36" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/free-solid-svg-icons": { - "version": "5.15.4", - "resolved": "https://registry.npmjs.org/@fortawesome/free-solid-svg-icons/-/free-solid-svg-icons-5.15.4.tgz", - "integrity": "sha512-JLmQfz6tdtwxoihXLg6lT78BorrFyCf59SAwBM6qV/0zXyVeDygJVb3fk+j5Qat+Yvcxp1buLTY5iDh1ZSAQ8w==", - "dev": true, - "hasInstallScript": true, - "license": "(CC-BY-4.0 AND MIT)", - "dependencies": { - "@fortawesome/fontawesome-common-types": "^0.2.36" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@fortawesome/vue-fontawesome": { - "version": "3.0.8", - "resolved": "https://registry.npmjs.org/@fortawesome/vue-fontawesome/-/vue-fontawesome-3.0.8.tgz", - "integrity": "sha512-yyHHAj4G8pQIDfaIsMvQpwKMboIZtcHTUvPqXjOHyldh1O1vZfH4W03VDPv5RvI9P6DLTzJQlmVgj9wCf7c2Fw==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "@fortawesome/fontawesome-svg-core": "~1 || ~6", - "vue": ">= 3.0.0 < 4" - } - }, - "node_modules/@gar/promisify": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/@gar/promisify/-/promisify-1.1.3.tgz", - "integrity": "sha512-k2Ty1JcVojjJFwrg/ThKi2ujJ7XNLYaFGNB/bWT9wGR+oSMJHMa5w+CUq6p/pVrKeNNgA7pCqEcjSnHVoqJQFw==", - "license": "MIT", - "optional": true - }, - "node_modules/@grpc/grpc-js": { - "version": "1.8.22", - "resolved": "https://registry.npmjs.org/@grpc/grpc-js/-/grpc-js-1.8.22.tgz", - "integrity": "sha512-oAjDdN7fzbUi+4hZjKG96MR6KTEubAeMpQEb+77qy+3r0Ua5xTFuie6JOLr4ZZgl5g+W5/uRTS2M1V8mVAFPuA==", - "license": "Apache-2.0", - "dependencies": { - "@grpc/proto-loader": "^0.7.0", - "@types/node": ">=12.12.47" - }, - "engines": { - "node": "^8.13.0 || >=10.10.0" - } - }, - "node_modules/@grpc/proto-loader": { - "version": "0.7.13", - "resolved": "https://registry.npmjs.org/@grpc/proto-loader/-/proto-loader-0.7.13.tgz", - "integrity": "sha512-AiXO/bfe9bmxBjxxtYxFAXGZvMaN5s8kO+jBHAJCON8rJoB5YS/D6X7ZNc6XQkuHNmyl4CYaMI1fJ/Gn27RGGw==", - "license": "Apache-2.0", - "dependencies": { - "lodash.camelcase": "^4.3.0", - "long": "^5.0.0", - "protobufjs": "^7.2.5", - "yargs": "^17.7.2" - }, - "bin": { - "proto-loader-gen-types": "build/bin/proto-loader-gen-types.js" - }, - "engines": { - "node": ">=6" - } - }, - "node_modules/@hapi/hoek": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz", - "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@hapi/topo": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz", - "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@humanwhocodes/config-array": { - "version": "0.9.5", - "resolved": "https://registry.npmjs.org/@humanwhocodes/config-array/-/config-array-0.9.5.tgz", - "integrity": "sha512-ObyMyWxZiCu/yTisA7uzx81s40xR2fD5Cg/2Kq7G02ajkNubJf6BopgDTmDyc3U7sXpNKM8cYOw7s7Tyr+DnCw==", - "deprecated": "Use @eslint/config-array instead", - "dev": true, - "license": "Apache-2.0", - "dependencies": { - "@humanwhocodes/object-schema": "^1.2.1", - "debug": "^4.1.1", - "minimatch": "^3.0.4" - }, - "engines": { - "node": ">=10.10.0" - } - }, - "node_modules/@humanwhocodes/object-schema": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@humanwhocodes/object-schema/-/object-schema-1.2.1.tgz", - "integrity": "sha512-ZnQMnLV4e7hDlUvw8H+U8ASL02SS2Gn6+9Ac3wGGLIe7+je2AeAOxPY+izIPJDfFDb7eDjev0Us8MO1iFRN8hA==", - "deprecated": "Use @eslint/object-schema instead", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@intlify/core-base": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@intlify/core-base/-/core-base-9.2.2.tgz", - "integrity": "sha512-JjUpQtNfn+joMbrXvpR4hTF8iJQ2sEFzzK3KIESOx+f+uwIjgw20igOyaIdhfsVVBCds8ZM64MoeNSx+PHQMkA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@intlify/devtools-if": "9.2.2", - "@intlify/message-compiler": "9.2.2", - "@intlify/shared": "9.2.2", - "@intlify/vue-devtools": "9.2.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@intlify/devtools-if": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@intlify/devtools-if/-/devtools-if-9.2.2.tgz", - "integrity": "sha512-4ttr/FNO29w+kBbU7HZ/U0Lzuh2cRDhP8UlWOtV9ERcjHzuyXVZmjyleESK6eVP60tGC9QtQW9yZE+JeRhDHkg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@intlify/shared": "9.2.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@intlify/message-compiler": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@intlify/message-compiler/-/message-compiler-9.2.2.tgz", - "integrity": "sha512-IUrQW7byAKN2fMBe8z6sK6riG1pue95e5jfokn8hA5Q3Bqy4MBJ5lJAofUsawQJYHeoPJ7svMDyBaVJ4d0GTtA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@intlify/shared": "9.2.2", - "source-map": "0.6.1" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@intlify/shared": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@intlify/shared/-/shared-9.2.2.tgz", - "integrity": "sha512-wRwTpsslgZS5HNyM7uDQYZtxnbI12aGiBZURX3BTR9RFIKKRWpllTsgzHWvj3HKm3Y2Sh5LPC1r0PDCKEhVn9Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 14" - } - }, - "node_modules/@intlify/vue-devtools": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/@intlify/vue-devtools/-/vue-devtools-9.2.2.tgz", - "integrity": "sha512-+dUyqyCHWHb/UcvY1MlIpO87munedm3Gn6E9WWYdWrMuYLcoIoOEVDWSS8xSwtlPU+kA+MEQTP6Q1iI/ocusJg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@intlify/core-base": "9.2.2", - "@intlify/shared": "9.2.2" - }, - "engines": { - "node": ">= 14" - } - }, - "node_modules/@isaacs/cliui": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz", - "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==", - "license": "ISC", - "dependencies": { - "string-width": "^5.1.2", - "string-width-cjs": "npm:string-width@^4.2.0", - "strip-ansi": "^7.0.1", - "strip-ansi-cjs": "npm:strip-ansi@^6.0.1", - "wrap-ansi": "^8.1.0", - "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0" - }, - "engines": { - "node": ">=12" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-regex": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz", - "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-regex?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/ansi-styles": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", - "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", - "license": "MIT", - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/emoji-regex": { - "version": "9.2.2", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz", - "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==", - "license": "MIT" - }, - "node_modules/@isaacs/cliui/node_modules/string-width": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz", - "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==", - "license": "MIT", - "dependencies": { - "eastasianwidth": "^0.2.0", - "emoji-regex": "^9.2.2", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/@isaacs/cliui/node_modules/strip-ansi": { - "version": "7.1.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", - "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", - "license": "MIT", - "dependencies": { - "ansi-regex": "^6.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/strip-ansi?sponsor=1" - } - }, - "node_modules/@isaacs/cliui/node_modules/wrap-ansi": { - "version": "8.1.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz", - "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==", - "license": "MIT", - "dependencies": { - "ansi-styles": "^6.1.0", - "string-width": "^5.0.1", - "strip-ansi": "^7.0.1" - }, - "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/chalk/wrap-ansi?sponsor=1" - } - }, - "node_modules/@istanbuljs/load-nyc-config": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz", - "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==", - "dev": true, - "license": "ISC", - "dependencies": { - "camelcase": "^5.3.1", - "find-up": "^4.1.0", - "get-package-type": "^0.1.0", - "js-yaml": "^3.13.1", - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": { - "version": "1.0.10", - "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", - "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", - "dev": true, - "license": "MIT", - "dependencies": { - "sprintf-js": "~1.0.2" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": { - "version": "3.14.1", - "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz", - "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==", - "dev": true, - "license": "MIT", - "dependencies": { - "argparse": "^1.0.7", - "esprima": "^4.0.0" - }, - "bin": { - "js-yaml": "bin/js-yaml.js" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@istanbuljs/load-nyc-config/node_modules/sprintf-js": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", - "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@istanbuljs/schema": { - "version": "0.1.3", - "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz", - "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=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, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "@jest/console": "^29.7.0", - "@jest/reporters": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "ansi-escapes": "^4.2.1", - "chalk": "^4.0.0", - "ci-info": "^3.2.0", - "exit": "^0.1.2", - "graceful-fs": "^4.2.9", - "jest-changed-files": "^29.7.0", - "jest-config": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-resolve-dependencies": "^29.7.0", - "jest-runner": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "jest-watcher": "^29.7.0", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/core/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/@jest/environment": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz", - "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@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, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "@jest/types": "^29.6.3", - "@sinonjs/fake-timers": "^10.0.2", - "@types/node": "*", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" - }, - "engines": { - "node": "^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, - "license": "MIT", - "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, - "license": "MIT", - "dependencies": { - "@bcoe/v8-coverage": "^0.2.3", - "@jest/console": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@jridgewell/trace-mapping": "^0.3.18", - "@types/node": "*", - "chalk": "^4.0.0", - "collect-v8-coverage": "^1.0.0", - "exit": "^0.1.2", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "istanbul-lib-coverage": "^3.0.0", - "istanbul-lib-instrument": "^6.0.0", - "istanbul-lib-report": "^3.0.0", - "istanbul-lib-source-maps": "^4.0.0", - "istanbul-reports": "^3.1.3", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "jest-worker": "^29.7.0", - "slash": "^3.0.0", - "string-length": "^4.0.1", - "strip-ansi": "^6.0.0", - "v8-to-istanbul": "^9.0.1" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0" - }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } - } - }, - "node_modules/@jest/schemas": { - "version": "29.6.3", - "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz", - "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@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, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "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, - "license": "MIT", - "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.8", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.8.tgz", - "integrity": "sha512-imAbBGkb+ebQyxKgzv5Hu2nmROxoDOXHh80evxdoXNOrvAnVx7zimzc1Oo5h9RlfV4vPXaE2iM5pOFbvOCClWA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/set-array": "^1.2.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.24" - }, - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/resolve-uri": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz", - "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/set-array": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz", - "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6.0.0" - } - }, - "node_modules/@jridgewell/source-map": { - "version": "0.3.6", - "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz", - "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/gen-mapping": "^0.3.5", - "@jridgewell/trace-mapping": "^0.3.25" - } - }, - "node_modules/@jridgewell/sourcemap-codec": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz", - "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.25", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz", - "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jridgewell/resolve-uri": "^3.1.0", - "@jridgewell/sourcemap-codec": "^1.4.14" - } - }, - "node_modules/@js-joda/core": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@js-joda/core/-/core-5.6.3.tgz", - "integrity": "sha512-T1rRxzdqkEXcou0ZprN1q9yDRlvzCPLqmlNt5IIsGBzoEVgLCCYrKEwc84+TvsXuAc95VAZwtWD2zVsKPY4bcA==", - "license": "BSD-3-Clause" - }, - "node_modules/@kurkle/color": { - "version": "0.3.4", - "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.4.tgz", - "integrity": "sha512-M5UknZPHRu3DEDWoipU6sE8PdkZ6Z/S+v4dD+Ke8IaNlpdSQah50lz1KtcFBa2vsdOnwbbnxJwVM4wty6udA5w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@louislam/ping": { - "version": "0.4.4-mod.1", - "resolved": "https://registry.npmjs.org/@louislam/ping/-/ping-0.4.4-mod.1.tgz", - "integrity": "sha512-uMq6qwL9/VYh2YBbDEhM7ZzJ8YON+juw/3k+28P3s9ue3uDMQ56MNPfywXoRpsxkU8RgjN0TDzEhQDzO1WisMw==", - "license": "MIT", - "dependencies": { - "command-exists": "~1.2.9", - "underscore": "~1.13.6" - }, - "engines": { - "node": ">=4.0.0" - } - }, - "node_modules/@louislam/sqlite3": { - "version": "15.1.6", - "resolved": "https://registry.npmjs.org/@louislam/sqlite3/-/sqlite3-15.1.6.tgz", - "integrity": "sha512-cVf7hcMrfywYnycatLvorngTFpL3BSWvEy7/NrEfcTyQX8xxj9fdeD553oCTv5fIAk85fluo6mzPq89V3YzrVA==", - "hasInstallScript": true, - "license": "BSD-3-Clause", - "dependencies": { - "@mapbox/node-pre-gyp": "^1.0.0", - "node-addon-api": "^4.2.0", - "tar": "^6.1.11" - }, - "optionalDependencies": { - "node-gyp": "8.x" - }, - "peerDependencies": { - "node-gyp": "8.x" - }, - "peerDependenciesMeta": { - "node-gyp": { - "optional": true - } - } - }, - "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==", - "license": "BSD-3-Clause", - "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/@mongodb-js/saslprep": { - "version": "1.1.9", - "resolved": "https://registry.npmjs.org/@mongodb-js/saslprep/-/saslprep-1.1.9.tgz", - "integrity": "sha512-tVkljjeEaAhCqTzajSdgbQ6gE6f3oneVwa3iXR6csiEwXXOFsiC6Uh9iAjAhXPtqa/XMDHWjjeNH/77m/Yq2dw==", - "license": "MIT", - "optional": true, - "dependencies": { - "sparse-bitfield": "^3.0.3" - } - }, - "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": { - "version": "5.1.1-v1", - "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz", - "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "eslint-scope": "5.1.1" - } - }, - "node_modules/@noble/ciphers": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/@noble/ciphers/-/ciphers-0.2.0.tgz", - "integrity": "sha512-6YBxJDAapHSdd3bLDv6x2wRPwq4QFMUaB3HvljNBUTThDd12eSm7/3F+2lnfzx2jvM+S6Nsy0jEt9QbPqSwqRw==", - "license": "MIT", - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/curves": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@noble/curves/-/curves-1.1.0.tgz", - "integrity": "sha512-091oBExgENk/kGj3AZmtBDMpxQPDtxQABR2B9lb1JbVTs6ytdzZNwvhxQ4MWasRNEzlbEH8jCWFCwhF/Obj5AA==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "1.3.1" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@noble/hashes": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.3.1.tgz", - "integrity": "sha512-EbqwksQwz9xDRGfDST86whPBgM65E0OH/pCgqW0GBVzO22bNE+NuIbeTb714+IfSjU3aRk47EUvXIb5bTsenKA==", - "license": "MIT", - "engines": { - "node": ">= 16" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@nodelib/fs.scandir": { - "version": "2.1.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz", - "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "2.0.5", - "run-parallel": "^1.1.9" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.stat": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz", - "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 8" - } - }, - "node_modules/@nodelib/fs.walk": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz", - "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@nodelib/fs.scandir": "2.1.5", - "fastq": "^1.6.0" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/@npmcli/fs": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@npmcli/fs/-/fs-1.1.1.tgz", - "integrity": "sha512-8KG5RD0GVP4ydEzRn/I4BNDuxDtqVbOdm8675T49OIG/NGhaK0pjPX7ZcDlvKYbA+ulvVK3ztfcF4uBdOxuJbQ==", - "license": "ISC", - "optional": true, - "dependencies": { - "@gar/promisify": "^1.0.1", - "semver": "^7.3.5" - } - }, - "node_modules/@npmcli/move-file": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@npmcli/move-file/-/move-file-1.1.2.tgz", - "integrity": "sha512-1SUf/Cg2GzGDyaf15aR9St9TWlb+XvbZXWpDx8YKs7MLzMH/BCeopv+y9vzrzgkfykCGuWOlSu3mZhj2+FQcrg==", - "deprecated": "This functionality has been moved to @npmcli/fs", - "license": "MIT", - "optional": true, - "dependencies": { - "mkdirp": "^1.0.4", - "rimraf": "^3.0.2" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/@octokit/auth-token": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/@octokit/auth-token/-/auth-token-2.5.0.tgz", - "integrity": "sha512-r5FVUJCOLl19AxiuZD2VRZ/ORjp/4IN98Of6YJoJOkY75CIBuYfmiNHGrDwXr+aLGG55igl9QrxX3hbiXlLb+g==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^6.0.3" - } - }, - "node_modules/@octokit/core": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/@octokit/core/-/core-3.6.0.tgz", - "integrity": "sha512-7RKRKuA4xTjMhY+eG3jthb3hlZCsOwg3rztWh75Xc+ShDWOfDDATWbeZpAHBNRpm4Tv9WgBMOy1zEJYXG6NJ7Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/auth-token": "^2.4.4", - "@octokit/graphql": "^4.5.8", - "@octokit/request": "^5.6.3", - "@octokit/request-error": "^2.0.5", - "@octokit/types": "^6.0.3", - "before-after-hook": "^2.2.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/endpoint": { - "version": "6.0.12", - "resolved": "https://registry.npmjs.org/@octokit/endpoint/-/endpoint-6.0.12.tgz", - "integrity": "sha512-lF3puPwkQWGfkMClXb4k/eUT/nZKQfxinRWJrdZaJO85Dqwo/G0yOC434Jr2ojwafWJMYqFGFa5ms4jJUgujdA==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^6.0.3", - "is-plain-object": "^5.0.0", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/graphql": { - "version": "4.8.0", - "resolved": "https://registry.npmjs.org/@octokit/graphql/-/graphql-4.8.0.tgz", - "integrity": "sha512-0gv+qLSBLKF0z8TKaSKTsS39scVKF9dbMxJpj3U0vC7wjNWFuIpL/z76Qe2fiuCbDRcJSavkXsVtMS6/dtQQsg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/request": "^5.6.0", - "@octokit/types": "^6.0.3", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/openapi-types": { - "version": "12.11.0", - "resolved": "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-12.11.0.tgz", - "integrity": "sha512-VsXyi8peyRq9PqIz/tpqiL2w3w80OgVMwBHltTml3LmVvXiphgeqmY9mvBw9Wu7e0QWk/fqD37ux8yP5uVekyQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/@octokit/plugin-paginate-rest": { - "version": "2.21.3", - "resolved": "https://registry.npmjs.org/@octokit/plugin-paginate-rest/-/plugin-paginate-rest-2.21.3.tgz", - "integrity": "sha512-aCZTEf0y2h3OLbrgKkrfFdjRL6eSOo8komneVQJnYecAxIej7Bafor2xhuDJOIFau4pk0i/P28/XgtbyPF0ZHw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^6.40.0" - }, - "peerDependencies": { - "@octokit/core": ">=2" - } - }, - "node_modules/@octokit/plugin-rest-endpoint-methods": { - "version": "5.16.2", - "resolved": "https://registry.npmjs.org/@octokit/plugin-rest-endpoint-methods/-/plugin-rest-endpoint-methods-5.16.2.tgz", - "integrity": "sha512-8QFz29Fg5jDuTPXVtey05BLm7OB+M8fnvE64RNegzX7U+5NUXcOcnpTIK0YfSHBg8gYd0oxIq3IZTe9SfPZiRw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^6.39.0", - "deprecation": "^2.3.1" - }, - "peerDependencies": { - "@octokit/core": ">=3" - } - }, - "node_modules/@octokit/request": { - "version": "5.6.3", - "resolved": "https://registry.npmjs.org/@octokit/request/-/request-5.6.3.tgz", - "integrity": "sha512-bFJl0I1KVc9jYTe9tdGGpAMPy32dLBXXo1dS/YwSCTL/2nd9XeHsY616RE3HPXDVk+a+dBuzyz5YdlXwcDTr2A==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/endpoint": "^6.0.1", - "@octokit/request-error": "^2.1.0", - "@octokit/types": "^6.16.1", - "is-plain-object": "^5.0.0", - "node-fetch": "^2.6.7", - "universal-user-agent": "^6.0.0" - } - }, - "node_modules/@octokit/request-error": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/@octokit/request-error/-/request-error-2.1.0.tgz", - "integrity": "sha512-1VIvgXxs9WHSjicsRwq8PlR2LR2x6DwsJAaFgzdi0JfJoGSO8mYI/cHJQ+9FbN21aa+DrgNLnwObmyeSC8Rmpg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/types": "^6.0.3", - "deprecation": "^2.0.0", - "once": "^1.4.0" - } - }, - "node_modules/@octokit/types": { - "version": "6.41.0", - "resolved": "https://registry.npmjs.org/@octokit/types/-/types-6.41.0.tgz", - "integrity": "sha512-eJ2jbzjdijiL3B4PrSQaSjuF2sPEQPVCPzBvTHJD9Nz+9dw2SGH4K4xeQJ77YfTq5bRQ+bD8wT11JbeDPmxmGg==", - "dev": true, - "license": "MIT", - "dependencies": { - "@octokit/openapi-types": "^12.11.0" - } - }, - "node_modules/@pkgjs/parseargs": { - "version": "0.11.0", - "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz", - "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==", - "license": "MIT", - "optional": true, - "engines": { - "node": ">=14" - } - }, - "node_modules/@popperjs/core": { - "version": "2.10.2", - "resolved": "https://registry.npmjs.org/@popperjs/core/-/core-2.10.2.tgz", - "integrity": "sha512-IXf3XA7+XyN7CP9gGh/XB0UxVMlvARGEgGXLubFICsUMGz6Q+DU+i4gGlpOxTjKvXjkJDJC8YdqdKkDj9qZHEQ==", - "dev": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/popperjs" - } - }, - "node_modules/@protobufjs/aspromise": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/aspromise/-/aspromise-1.1.2.tgz", - "integrity": "sha512-j+gKExEuLmKwvz3OgROXtrJ2UG2x8Ch2YZUxahh+s1F2HZ+wAceUNLkvy6zKCPVRkU++ZWQrdxsUeQXmcg4uoQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/base64": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/base64/-/base64-1.1.2.tgz", - "integrity": "sha512-AZkcAA5vnN/v4PDqKyMR5lx7hZttPDgClv83E//FMNhR2TMcLUhfRUBHCmSl0oi9zMgDDqRUJkSxO3wm85+XLg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/codegen": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@protobufjs/codegen/-/codegen-2.0.4.tgz", - "integrity": "sha512-YyFaikqM5sH0ziFZCN3xDC7zeGaB/d0IUb9CATugHWbd1FRFwWwt4ld4OYMPWu5a3Xe01mGAULCdqhMlPl29Jg==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/eventemitter": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/eventemitter/-/eventemitter-1.1.0.tgz", - "integrity": "sha512-j9ednRT81vYJ9OfVuXG6ERSTdEL1xVsNgqpkxMsbIabzSo3goCjDIveeGv5d03om39ML71RdmrGNjG5SReBP/Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/fetch": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/fetch/-/fetch-1.1.0.tgz", - "integrity": "sha512-lljVXpqXebpsijW71PZaCYeIcE5on1w5DlQy5WH6GLbFryLUrBD4932W/E2BSpfRJWseIL4v/KPgBFxDOIdKpQ==", - "license": "BSD-3-Clause", - "dependencies": { - "@protobufjs/aspromise": "^1.1.1", - "@protobufjs/inquire": "^1.1.0" - } - }, - "node_modules/@protobufjs/float": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", - "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/inquire": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", - "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/path": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", - "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/pool": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", - "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", - "license": "BSD-3-Clause" - }, - "node_modules/@protobufjs/utf8": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", - "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", - "license": "BSD-3-Clause" - }, - "node_modules/@redis/bloom": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.1.0.tgz", - "integrity": "sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/client": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.4.2.tgz", - "integrity": "sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==", - "license": "MIT", - "dependencies": { - "cluster-key-slot": "1.1.1", - "generic-pool": "3.9.0", - "yallist": "4.0.0" - }, - "engines": { - "node": ">=14" - } - }, - "node_modules/@redis/client/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, - "node_modules/@redis/graph": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", - "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/json": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", - "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/search": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz", - "integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@redis/time-series": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", - "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", - "license": "MIT", - "peerDependencies": { - "@redis/client": "^1.0.0" - } - }, - "node_modules/@rollup/rollup-android-arm-eabi": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.28.1.tgz", - "integrity": "sha512-2aZp8AES04KI2dy3Ss6/MDjXbwBzj+i0GqKtWXgw2/Ma6E4jJvujryO6gJAghIRVz7Vwr9Gtl/8na3nDUKpraQ==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-android-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.28.1.tgz", - "integrity": "sha512-EbkK285O+1YMrg57xVA+Dp0tDBRB93/BZKph9XhMjezf6F4TpYjaUSuPt5J0fZXlSag0LmZAsTmdGGqPp4pQFA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "android" - ] - }, - "node_modules/@rollup/rollup-darwin-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.28.1.tgz", - "integrity": "sha512-prduvrMKU6NzMq6nxzQw445zXgaDBbMQvmKSJaxpaZ5R1QDM8w+eGxo6Y/jhT/cLoCvnZI42oEqf9KQNYz1fqQ==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-darwin-x64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.28.1.tgz", - "integrity": "sha512-WsvbOunsUk0wccO/TV4o7IKgloJ942hVFK1CLatwv6TJspcCZb9umQkPdvB7FihmdxgaKR5JyxDjWpCOp4uZlQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "darwin" - ] - }, - "node_modules/@rollup/rollup-freebsd-arm64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.28.1.tgz", - "integrity": "sha512-HTDPdY1caUcU4qK23FeeGxCdJF64cKkqajU0iBnTVxS8F7H/7BewvYoG+va1KPSL63kQ1PGNyiwKOfReavzvNA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-freebsd-x64": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.28.1.tgz", - "integrity": "sha512-m/uYasxkUevcFTeRSM9TeLyPe2QDuqtjkeoTpP9SW0XxUWfcYrGDMkO/m2tTw+4NMAF9P2fU3Mw4ahNvo7QmsQ==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "freebsd" - ] - }, - "node_modules/@rollup/rollup-linux-arm-gnueabihf": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.28.1.tgz", - "integrity": "sha512-QAg11ZIt6mcmzpNE6JZBpKfJaKkqTm1A9+y9O+frdZJEuhQxiugM05gnCWiANHj4RmbgeVJpTdmKRmH/a+0QbA==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm-musleabihf": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.28.1.tgz", - "integrity": "sha512-dRP9PEBfolq1dmMcFqbEPSd9VlRuVWEGSmbxVEfiq2cs2jlZAl0YNxFzAQS2OrQmsLBLAATDMb3Z6MFv5vOcXg==", - "cpu": [ - "arm" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.28.1.tgz", - "integrity": "sha512-uGr8khxO+CKT4XU8ZUH1TTEUtlktK6Kgtv0+6bIFSeiSlnGJHG1tSFSjm41uQ9sAO/5ULx9mWOz70jYLyv1QkA==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-arm64-musl": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.28.1.tgz", - "integrity": "sha512-QF54q8MYGAqMLrX2t7tNpi01nvq5RI59UBNx+3+37zoKX5KViPo/gk2QLhsuqok05sSCRluj0D00LzCwBikb0A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-loongarch64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-loongarch64-gnu/-/rollup-linux-loongarch64-gnu-4.28.1.tgz", - "integrity": "sha512-vPul4uodvWvLhRco2w0GcyZcdyBfpfDRgNKU+p35AWEbJ/HPs1tOUrkSueVbBS0RQHAf/A+nNtDpvw95PeVKOA==", - "cpu": [ - "loong64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.28.1.tgz", - "integrity": "sha512-pTnTdBuC2+pt1Rmm2SV7JWRqzhYpEILML4PKODqLz+C7Ou2apEV52h19CR7es+u04KlqplggmN9sqZlekg3R1A==", - "cpu": [ - "ppc64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-riscv64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.28.1.tgz", - "integrity": "sha512-vWXy1Nfg7TPBSuAncfInmAI/WZDd5vOklyLJDdIRKABcZWojNDY0NJwruY2AcnCLnRJKSaBgf/GiJfauu8cQZA==", - "cpu": [ - "riscv64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-s390x-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.28.1.tgz", - "integrity": "sha512-/yqC2Y53oZjb0yz8PVuGOQQNOTwxcizudunl/tFs1aLvObTclTwZ0JhXF2XcPT/zuaymemCDSuuUPXJJyqeDOg==", - "cpu": [ - "s390x" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-gnu": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.28.1.tgz", - "integrity": "sha512-fzgeABz7rrAlKYB0y2kSEiURrI0691CSL0+KXwKwhxvj92VULEDQLpBYLHpF49MSiPG4sq5CK3qHMnb9tlCjBw==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-linux-x64-musl": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.28.1.tgz", - "integrity": "sha512-xQTDVzSGiMlSshpJCtudbWyRfLaNiVPXt1WgdWTwWz9n0U12cI2ZVtWe/Jgwyv/6wjL7b66uu61Vg0POWVfz4g==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "linux" - ] - }, - "node_modules/@rollup/rollup-win32-arm64-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.28.1.tgz", - "integrity": "sha512-wSXmDRVupJstFP7elGMgv+2HqXelQhuNf+IS4V+nUpNVi/GUiBgDmfwD0UGN3pcAnWsgKG3I52wMOBnk1VHr/A==", - "cpu": [ - "arm64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-ia32-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.28.1.tgz", - "integrity": "sha512-ZkyTJ/9vkgrE/Rk9vhMXhf8l9D+eAhbAVbsGsXKy2ohmJaWg0LPQLnIxRdRp/bKyr8tXuPlXhIoGlEB5XpJnGA==", - "cpu": [ - "ia32" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@rollup/rollup-win32-x64-msvc": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.28.1.tgz", - "integrity": "sha512-ZvK2jBafvttJjoIdKm/Q/Bh7IJ1Ose9IBOwpOXcOvW3ikGTQGmKDgxTC6oCAzW6PynbkKP8+um1du81XJHZ0JA==", - "cpu": [ - "x64" - ], - "dev": true, - "license": "MIT", - "optional": true, - "os": [ - "win32" - ] - }, - "node_modules/@scure/base": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", - "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", - "funding": [ - { - "type": "individual", - "url": "https://paulmillr.com/funding/" - } - ], - "license": "MIT" - }, - "node_modules/@scure/bip32": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", - "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", - "license": "MIT", - "dependencies": { - "@noble/curves": "~1.1.0", - "@noble/hashes": "~1.3.1", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@scure/bip39": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", - "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", - "license": "MIT", - "dependencies": { - "@noble/hashes": "~1.3.0", - "@scure/base": "~1.1.0" - }, - "funding": { - "url": "https://paulmillr.com/funding/" - } - }, - "node_modules/@sideway/address": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", - "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@hapi/hoek": "^9.0.0" - } - }, - "node_modules/@sideway/formula": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", - "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@sideway/pinpoint": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", - "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", - "dev": true, - "license": "BSD-3-Clause" - }, - "node_modules/@sinclair/typebox": { - "version": "0.27.8", - "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz", - "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@sindresorhus/is": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", - "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/is?sponsor=1" - } - }, - "node_modules/@sinonjs/commons": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz", - "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "type-detect": "4.0.8" - } - }, - "node_modules/@sinonjs/fake-timers": { - "version": "10.3.0", - "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz", - "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "@sinonjs/commons": "^3.0.0" - } - }, - "node_modules/@smithy/abort-controller": { - "version": "3.1.9", - "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.9.tgz", - "integrity": "sha512-yiW0WI30zj8ZKoSYNx90no7ugVn3khlyH/z5W8qtKBtVE6awRALbhSG+2SAHA1r6bO/6M9utxYKVZ3PCJ1rWxw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/config-resolver": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.13.tgz", - "integrity": "sha512-Gr/qwzyPaTL1tZcq8WQyHhTZREER5R1Wytmz4WnVGL4onA3dNk6Btll55c8Vr58pLdvWZmtG8oZxJTw3t3q7Jg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/node-config-provider": "^3.1.12", - "@smithy/types": "^3.7.2", - "@smithy/util-config-provider": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/core": { - "version": "2.5.5", - "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.5.tgz", - "integrity": "sha512-G8G/sDDhXA7o0bOvkc7bgai6POuSld/+XhNnWAbpQTpLv2OZPvyqQ58tLPPlz0bSNsXktldDDREIv1LczFeNEw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/middleware-serde": "^3.0.11", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", - "@smithy/util-body-length-browser": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-stream": "^3.3.2", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/credential-provider-imds": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.8.tgz", - "integrity": "sha512-ZCY2yD0BY+K9iMXkkbnjo+08T2h8/34oHd0Jmh6BZUSZwaaGlGCyBT/3wnS7u7Xl33/EEfN4B6nQr3Gx5bYxgw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/node-config-provider": "^3.1.12", - "@smithy/property-provider": "^3.1.11", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/fetch-http-handler": { - "version": "4.1.2", - "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.1.2.tgz", - "integrity": "sha512-R7rU7Ae3ItU4rC0c5mB2sP5mJNbCfoDc8I5XlYjIZnquyUwec7fEo78F6DA3SmgJgkU1qTMcZJuGblxZsl10ZA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/protocol-http": "^4.1.8", - "@smithy/querystring-builder": "^3.0.11", - "@smithy/types": "^3.7.2", - "@smithy/util-base64": "^3.0.0", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/hash-node": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.11.tgz", - "integrity": "sha512-emP23rwYyZhQBvklqTtwetkQlqbNYirDiEEwXl2v0GYWMnCzxst7ZaRAnWuy28njp5kAH54lvkdG37MblZzaHA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/invalid-dependency": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.11.tgz", - "integrity": "sha512-NuQmVPEJjUX6c+UELyVz8kUx8Q539EDeNwbRyu4IIF8MeV7hUtq1FB3SHVyki2u++5XLMFqngeMKk7ccspnNyQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/is-array-buffer": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", - "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-content-length": { - "version": "3.0.13", - "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.13.tgz", - "integrity": "sha512-zfMhzojhFpIX3P5ug7jxTjfUcIPcGjcQYzB9t+rv0g1TX7B0QdwONW+ATouaLoD7h7LOw/ZlXfkq4xJ/g2TrIw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-endpoint": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.6.tgz", - "integrity": "sha512-WAqzyulvvSKrT5c6VrQelgNVNNO7BlTQW9Z+s9tcG6G5CaBS1YBpPtT3VuhXLQbewSiGi7oXQROwpw26EG9PLQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/core": "^2.5.5", - "@smithy/middleware-serde": "^3.0.11", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", - "@smithy/url-parser": "^3.0.11", - "@smithy/util-middleware": "^3.0.11", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-retry": { - "version": "3.0.31", - "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.31.tgz", - "integrity": "sha512-yq9wawrJLYHAYFpChLujxRN4My+SiKXvZk9Ml/CvTdRSA8ew+hvuR5LT+mjSlSBv3c4XJrkN8CWegkBaeD0Vrg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/node-config-provider": "^3.1.12", - "@smithy/protocol-http": "^4.1.8", - "@smithy/service-error-classification": "^3.0.11", - "@smithy/smithy-client": "^3.5.1", - "@smithy/types": "^3.7.2", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-retry": "^3.0.11", - "tslib": "^2.6.2", - "uuid": "^9.0.1" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-retry/node_modules/uuid": { - "version": "9.0.1", - "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", - "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", - "funding": [ - "https://github.com/sponsors/broofa", - "https://github.com/sponsors/ctavan" - ], - "license": "MIT", - "optional": true, - "bin": { - "uuid": "dist/bin/uuid" - } - }, - "node_modules/@smithy/middleware-serde": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.11.tgz", - "integrity": "sha512-KzPAeySp/fOoQA82TpnwItvX8BBURecpx6ZMu75EZDkAcnPtO6vf7q4aH5QHs/F1s3/snQaSFbbUMcFFZ086Mw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/middleware-stack": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.11.tgz", - "integrity": "sha512-1HGo9a6/ikgOMrTrWL/WiN9N8GSVYpuRQO5kjstAq4CvV59bjqnh7TbdXGQ4vxLD3xlSjfBjq5t1SOELePsLnA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/node-config-provider": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.12.tgz", - "integrity": "sha512-O9LVEu5J/u/FuNlZs+L7Ikn3lz7VB9hb0GtPT9MQeiBmtK8RSY3ULmsZgXhe6VAlgTw0YO+paQx4p8xdbs43vQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/property-provider": "^3.1.11", - "@smithy/shared-ini-file-loader": "^3.1.12", - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/node-http-handler": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.3.2.tgz", - "integrity": "sha512-t4ng1DAd527vlxvOfKFYEe6/QFBcsj7WpNlWTyjorwXXcKw3XlltBGbyHfSJ24QT84nF+agDha9tNYpzmSRZPA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/abort-controller": "^3.1.9", - "@smithy/protocol-http": "^4.1.8", - "@smithy/querystring-builder": "^3.0.11", - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/property-provider": { - "version": "3.1.11", - "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.11.tgz", - "integrity": "sha512-I/+TMc4XTQ3QAjXfOcUWbSS073oOEAxgx4aZy8jHaf8JQnRkq2SZWw8+PfDtBvLUjcGMdxl+YwtzWe6i5uhL/A==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/protocol-http": { - "version": "4.1.8", - "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.8.tgz", - "integrity": "sha512-hmgIAVyxw1LySOwkgMIUN0kjN8TG9Nc85LJeEmEE/cNEe2rkHDUWhnJf2gxcSRFLWsyqWsrZGw40ROjUogg+Iw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/querystring-builder": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.11.tgz", - "integrity": "sha512-u+5HV/9uJaeLj5XTb6+IEF/dokWWkEqJ0XiaRRogyREmKGUgZnNecLucADLdauWFKUNbQfulHFEZEdjwEBjXRg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "@smithy/util-uri-escape": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/querystring-parser": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.11.tgz", - "integrity": "sha512-Je3kFvCsFMnso1ilPwA7GtlbPaTixa3WwC+K21kmMZHsBEOZYQaqxcMqeFFoU7/slFjKDIpiiPydvdJm8Q/MCw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/service-error-classification": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.11.tgz", - "integrity": "sha512-QnYDPkyewrJzCyaeI2Rmp7pDwbUETe+hU8ADkXmgNusO1bgHBH7ovXJiYmba8t0fNfJx75fE8dlM6SEmZxheog==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/shared-ini-file-loader": { - "version": "3.1.12", - "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.12.tgz", - "integrity": "sha512-1xKSGI+U9KKdbG2qDvIR9dGrw3CNx+baqJfyr0igKEpjbHL5stsqAesYBzHChYHlelWtb87VnLWlhvfCz13H8Q==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/signature-v4": { - "version": "4.2.4", - "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.4.tgz", - "integrity": "sha512-5JWeMQYg81TgU4cG+OexAWdvDTs5JDdbEZx+Qr1iPbvo91QFGzjy0IkXAKaXUHqmKUJgSHK0ZxnCkgZpzkeNTA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-middleware": "^3.0.11", - "@smithy/util-uri-escape": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/smithy-client": { - "version": "3.5.1", - "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.5.1.tgz", - "integrity": "sha512-PmjskH4Os1Eh3rd5vSsa5uVelZ4DRu+N5CBEgb9AT96hQSJGWSEb6pGxKV/PtKQSIp9ft3+KvnT8ViMKaguzgA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/core": "^2.5.5", - "@smithy/middleware-endpoint": "^3.2.6", - "@smithy/middleware-stack": "^3.0.11", - "@smithy/protocol-http": "^4.1.8", - "@smithy/types": "^3.7.2", - "@smithy/util-stream": "^3.3.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/types": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.7.2.tgz", - "integrity": "sha512-bNwBYYmN8Eh9RyjS1p2gW6MIhSO2rl7X9QeLM8iTdcGRP+eDiIWDt66c9IysCc22gefKszZv+ubV9qZc7hdESg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/url-parser": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.11.tgz", - "integrity": "sha512-TmlqXkSk8ZPhfc+SQutjmFr5FjC0av3GZP4B/10caK1SbRwe/v+Wzu/R6xEKxoNqL+8nY18s1byiy6HqPG37Aw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/querystring-parser": "^3.0.11", - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/util-base64": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", - "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-body-length-browser": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", - "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.6.2" - } - }, - "node_modules/@smithy/util-body-length-node": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", - "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-buffer-from": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", - "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/is-array-buffer": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-config-provider": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", - "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-browser": { - "version": "3.0.31", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.31.tgz", - "integrity": "sha512-eO+zkbqrPnmsagqzrmF7IJrCoU2wTQXWVYxMPqA9Oue55kw9WEvhyuw2XQzTVTCRcYsg6KgmV3YYhLlWQJfK1A==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/property-provider": "^3.1.11", - "@smithy/smithy-client": "^3.5.1", - "@smithy/types": "^3.7.2", - "bowser": "^2.11.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@smithy/util-defaults-mode-node": { - "version": "3.0.31", - "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.31.tgz", - "integrity": "sha512-0/nJfpSpbGZOs6qs42wCe2TdjobbnnD4a3YUUlvTXSQqLy4qa63luDaV04hGvqSHP7wQ7/WGehbvHkDhMZd1MQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/config-resolver": "^3.0.13", - "@smithy/credential-provider-imds": "^3.2.8", - "@smithy/node-config-provider": "^3.1.12", - "@smithy/property-provider": "^3.1.11", - "@smithy/smithy-client": "^3.5.1", - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">= 10.0.0" - } - }, - "node_modules/@smithy/util-endpoints": { - "version": "2.1.7", - "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.7.tgz", - "integrity": "sha512-tSfcqKcN/Oo2STEYCABVuKgJ76nyyr6skGl9t15hs+YaiU06sgMkN7QYjo0BbVw+KT26zok3IzbdSOksQ4YzVw==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/node-config-provider": "^3.1.12", - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } - }, - "node_modules/@smithy/util-hex-encoding": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", - "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } + "node_modules/@protobufjs/float": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@protobufjs/float/-/float-1.0.2.tgz", + "integrity": "sha512-Ddb+kVXlXst9d+R9PfTIxh1EdNkgoRe5tOX6t01f1lYWOvJnSPDBlG241QLzcyPdoNTsblLUdujGSE4RzrTZGQ==", + "license": "BSD-3-Clause" }, - "node_modules/@smithy/util-middleware": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.11.tgz", - "integrity": "sha512-dWpyc1e1R6VoXrwLoLDd57U1z6CwNSdkM69Ie4+6uYh2GC7Vg51Qtan7ITzczuVpqezdDTKJGJB95fFvvjU/ow==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } + "node_modules/@protobufjs/inquire": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/inquire/-/inquire-1.1.0.tgz", + "integrity": "sha512-kdSefcPdruJiFMVSbn801t4vFK7KB/5gd2fYvrxhuJYg8ILrmn9SKSX2tZdV6V+ksulWqS7aXjBcRXl3wHoD9Q==", + "license": "BSD-3-Clause" }, - "node_modules/@smithy/util-retry": { - "version": "3.0.11", - "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.11.tgz", - "integrity": "sha512-hJUC6W7A3DQgaee3Hp9ZFcOxVDZzmBIRBPlUAk8/fSOEl7pE/aX7Dci0JycNOnm9Mfr0KV2XjIlUOcGWXQUdVQ==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/service-error-classification": "^3.0.11", - "@smithy/types": "^3.7.2", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } + "node_modules/@protobufjs/path": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/@protobufjs/path/-/path-1.1.2.tgz", + "integrity": "sha512-6JOcJ5Tm08dOHAbdR3GrvP+yUUfkjG5ePsHYczMFLq3ZmMkAD98cDgcT2iA1lJ9NVwFd4tH/iSSoe44YWkltEA==", + "license": "BSD-3-Clause" }, - "node_modules/@smithy/util-stream": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.3.2.tgz", - "integrity": "sha512-sInAqdiVeisUGYAv/FrXpmJ0b4WTFmciTRqzhb7wVuem9BHvhIG7tpiYHLDWrl2stOokNZpTTGqz3mzB2qFwXg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/fetch-http-handler": "^4.1.2", - "@smithy/node-http-handler": "^3.3.2", - "@smithy/types": "^3.7.2", - "@smithy/util-base64": "^3.0.0", - "@smithy/util-buffer-from": "^3.0.0", - "@smithy/util-hex-encoding": "^3.0.0", - "@smithy/util-utf8": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } + "node_modules/@protobufjs/pool": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/pool/-/pool-1.1.0.tgz", + "integrity": "sha512-0kELaGSIDBKvcgS4zkjz1PeddatrjYcmMWOlAuAPwAeccUrPHdUqo/J6LiymHHEiJT5NrF1UVwxY14f+fy4WQw==", + "license": "BSD-3-Clause" }, - "node_modules/@smithy/util-uri-escape": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", - "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" - } + "node_modules/@protobufjs/utf8": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@protobufjs/utf8/-/utf8-1.1.0.tgz", + "integrity": "sha512-Vvn3zZrhQZkkBE8LSuW3em98c0FwgO4nxzv6OdSxPKJIEKY2bGbHn+mhGIPerzI4twdxaP8/0+06HBpwf345Lw==", + "license": "BSD-3-Clause" }, - "node_modules/@smithy/util-utf8": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", - "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", - "license": "Apache-2.0", - "optional": true, - "dependencies": { - "@smithy/util-buffer-from": "^3.0.0", - "tslib": "^2.6.2" - }, - "engines": { - "node": ">=16.0.0" + "node_modules/@redis/bloom": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/bloom/-/bloom-1.1.0.tgz", + "integrity": "sha512-9QovlxmpRtvxVbN0UBcv8WfdSMudNZZTFqCsnBszcQXqaZb/TVe30ScgGEO7u1EAIacTPAo7/oCYjYAxiHLanQ==", + "license": "MIT", + "peerDependencies": { + "@redis/client": "^1.0.0" } }, - "node_modules/@socket.io/component-emitter": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", - "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", - "license": "MIT" - }, - "node_modules/@szmarczak/http-timer": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", - "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", + "node_modules/@redis/client": { + "version": "1.4.2", + "resolved": "https://registry.npmjs.org/@redis/client/-/client-1.4.2.tgz", + "integrity": "sha512-oUdEjE0I7JS5AyaAjkD3aOXn9NhO7XKyPyXEyrgFDu++VrVBHUPnV6dgEya9TcMuj5nIJRuCzCm8ZP+c9zCHPw==", "license": "MIT", "dependencies": { - "defer-to-connect": "^2.0.1" + "cluster-key-slot": "1.1.1", + "generic-pool": "3.9.0", + "yallist": "4.0.0" }, "engines": { - "node": ">=14.16" + "node": ">=14" } }, - "node_modules/@tediousjs/connection-string": { - "version": "0.3.0", - "resolved": "https://registry.npmjs.org/@tediousjs/connection-string/-/connection-string-0.3.0.tgz", - "integrity": "sha512-d/keJiNKfpHo+GmSB8QcsAwBx8h+V1UbdozA5TD+eSLXprNY53JAYub47J9evsSKWDdNG5uVj0FiMozLKuzowQ==", - "license": "MIT" - }, - "node_modules/@tootallnate/once": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", - "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", + "node_modules/@redis/graph": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/graph/-/graph-1.1.0.tgz", + "integrity": "sha512-16yZWngxyXPd+MJxeSr0dqh2AIOi8j9yXKcKCwVaKDbH3HTuETpDVPcLujhFYVPtYrngSco31BUcSa9TH31Gqg==", "license": "MIT", - "engines": { - "node": ">= 10" + "peerDependencies": { + "@redis/client": "^1.0.0" } }, - "node_modules/@types/accepts": { - "version": "1.3.7", - "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz", - "integrity": "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==", + "node_modules/@redis/json": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/json/-/json-1.0.4.tgz", + "integrity": "sha512-LUZE2Gdrhg0Rx7AN+cZkb1e6HjoSKaeeW8rYnt89Tly13GBI5eP4CwDVr+MY8BAYfCg4/N15OUrtLoona9uSgw==", "license": "MIT", - "dependencies": { - "@types/node": "*" + "peerDependencies": { + "@redis/client": "^1.0.0" } }, - "node_modules/@types/babel__core": { - "version": "7.20.5", - "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz", - "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==", - "dev": true, + "node_modules/@redis/search": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/@redis/search/-/search-1.1.0.tgz", + "integrity": "sha512-NyFZEVnxIJEybpy+YskjgOJRNsfTYqaPbK/Buv6W2kmFNaRk85JiqjJZA5QkRmWvGbyQYwoO5QfDi2wHskKrQQ==", "license": "MIT", - "dependencies": { - "@babel/parser": "^7.20.7", - "@babel/types": "^7.20.7", - "@types/babel__generator": "*", - "@types/babel__template": "*", - "@types/babel__traverse": "*" + "peerDependencies": { + "@redis/client": "^1.0.0" } }, - "node_modules/@types/babel__generator": { - "version": "7.6.8", - "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz", - "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==", - "dev": true, + "node_modules/@redis/time-series": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/@redis/time-series/-/time-series-1.0.4.tgz", + "integrity": "sha512-ThUIgo2U/g7cCuZavucQTQzA9g9JbDDY2f64u3AbAoz/8vE2lt2U37LamDUVChhaDA3IRT9R6VvJwqnUfTJzng==", "license": "MIT", - "dependencies": { - "@babel/types": "^7.0.0" + "peerDependencies": { + "@redis/client": "^1.0.0" } }, - "node_modules/@types/babel__template": { - "version": "7.4.4", - "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz", - "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==", + "node_modules/@rollup/pluginutils": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.1.3.tgz", + "integrity": "sha512-Pnsb6f32CD2W3uCaLZIzDmeFyQ2b8UWMFI7xtwUezpcGBDVDW6y9XgAWIlARiGAo6eNF5FK5aQTr0LFyNyqq5A==", "dev": true, "license": "MIT", "dependencies": { - "@babel/parser": "^7.1.0", - "@babel/types": "^7.0.0" + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } } }, - "node_modules/@types/babel__traverse": { - "version": "7.20.6", - "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz", - "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==", + "node_modules/@rollup/pluginutils/node_modules/picomatch": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.2.tgz", + "integrity": "sha512-M7BAV6Rlcy5u+m6oPhAPFgJTzAioX/6B0DxyvDlo9l8+T3nLKbrczg2WLUyzd45L8RqfUMyGPzekbMvX2Ldkwg==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/types": "^7.20.7" + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, - "node_modules/@types/body-parser": { - "version": "1.19.5", - "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", - "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", + "node_modules/@rollup/rollup-android-arm-eabi": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.24.0.tgz", + "integrity": "sha512-Q6HJd7Y6xdB48x8ZNVDOqsbh2uByBhgK8PiQgPhwkIw/HC/YX5Ghq2mQY5sRMZWHb3VsFkWooUVOZHKr7DmDIA==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/node": "*" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@types/bootstrap": { - "version": "5.1.13", - "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.1.13.tgz", - "integrity": "sha512-1hIIOgfkMlyQCQz/3ae53xr6ZN2d6EDj/n3G+Sh/LBsBUVigyDmnCbLwsaXJJ1GBGlkjgfXVoyIvEPowQw25xQ==", + "node_modules/@rollup/rollup-android-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.24.0.tgz", + "integrity": "sha512-ijLnS1qFId8xhKjT81uBHuuJp2lU4x2yxa4ctFPtG+MqEE6+C5f/+X/bStmxapgmwLwiL3ih122xv8kVARNAZA==", + "cpu": [ + "arm64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@popperjs/core": "^2.9.2" - } + "optional": true, + "os": [ + "android" + ] }, - "node_modules/@types/cacheable-request": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", - "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "node_modules/@rollup/rollup-darwin-arm64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.24.0.tgz", + "integrity": "sha512-bIv+X9xeSs1XCk6DVvkO+S/z8/2AMt/2lMqdQbMrmVpgFvXlmde9mLcbQpztXm1tajC3raFDqegsH18HQPMYtA==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@types/http-cache-semantics": "*", - "@types/keyv": "^3.1.4", - "@types/node": "*", - "@types/responselike": "^1.0.0" - } + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@types/connect": { - "version": "3.4.38", - "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", - "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", + "node_modules/@rollup/rollup-darwin-x64": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.24.0.tgz", + "integrity": "sha512-X6/nOwoFN7RT2svEQWUsW/5C/fYMBe4fnLK9DQk4SX4mgVBiTA9h64kjUYPvGQ0F/9xwJ5U5UfTbl6BEjaQdBQ==", + "cpu": [ + "x64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*" - } - }, - "node_modules/@types/content-disposition": { - "version": "0.5.8", - "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.8.tgz", - "integrity": "sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==", - "license": "MIT" - }, - "node_modules/@types/cookie": { - "version": "0.4.1", - "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", - "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", - "license": "MIT" + "optional": true, + "os": [ + "darwin" + ] }, - "node_modules/@types/cookies": { - "version": "0.9.0", - "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.9.0.tgz", - "integrity": "sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==", + "node_modules/@rollup/rollup-linux-arm-gnueabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.24.0.tgz", + "integrity": "sha512-0KXvIJQMOImLCVCz9uvvdPgfyWo93aHHp8ui3FrtOP57svqrF/roSSR5pjqL2hcMp0ljeGlU4q9o/rQaAQ3AYA==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@types/connect": "*", - "@types/express": "*", - "@types/keygrip": "*", - "@types/node": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/cors": { - "version": "2.8.17", - "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", - "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "node_modules/@rollup/rollup-linux-arm-musleabihf": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.24.0.tgz", + "integrity": "sha512-it2BW6kKFVh8xk/BnHfakEeoLPv8STIISekpoF+nBgWM4d55CZKc7T4Dx1pEbTnYm/xEKMgy1MNtYuoA8RFIWw==", + "cpu": [ + "arm" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/es-aggregate-error": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/es-aggregate-error/-/es-aggregate-error-1.0.6.tgz", - "integrity": "sha512-qJ7LIFp06h1QE1aVxbVd+zJP2wdaugYXYfd6JxsyRMrYHaxb6itXPogW2tz+ylUJ1n1b+JF1PHyYCfYHm0dvUg==", + "node_modules/@rollup/rollup-linux-arm64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.24.0.tgz", + "integrity": "sha512-i0xTLXjqap2eRfulFVlSnM5dEbTVque/3Pi4g2y7cxrs7+a9De42z4XxKLYJ7+OhE3IgxvfQM7vQc43bwTgPwA==", + "cpu": [ + "arm64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/estree": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", - "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", + "node_modules/@rollup/rollup-linux-arm64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.24.0.tgz", + "integrity": "sha512-9E6MKUJhDuDh604Qco5yP/3qn3y7SLXYuiC0Rpr89aMScS2UAmK1wHP2b7KAa1nSjWJc/f/Lc0Wl1L47qjiyQw==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" - }, - "node_modules/@types/express": { - "version": "4.17.21", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", - "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "license": "MIT", - "dependencies": { - "@types/body-parser": "*", - "@types/express-serve-static-core": "^4.17.33", - "@types/qs": "*", - "@types/serve-static": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/express-serve-static-core": { - "version": "4.19.6", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", - "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", + "node_modules/@rollup/rollup-linux-powerpc64le-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.24.0.tgz", + "integrity": "sha512-2XFFPJ2XMEiF5Zi2EBf4h73oR1V/lycirxZxHZNc93SqDN/IWhYYSYj8I9381ikUFXZrz2v7r2tOVk2NBwxrWw==", + "cpu": [ + "ppc64" + ], + "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*", - "@types/qs": "*", - "@types/range-parser": "*", - "@types/send": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/graceful-fs": { - "version": "4.1.9", - "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", - "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==", + "node_modules/@rollup/rollup-linux-riscv64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.24.0.tgz", + "integrity": "sha512-M3Dg4hlwuntUCdzU7KjYqbbd+BLq3JMAOhCKdBE3TcMGMZbKkDdJ5ivNdehOssMCIokNHFOsv7DO4rlEOfyKpg==", + "cpu": [ + "riscv64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/node": "*" - } + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/http-assert": { - "version": "1.5.6", - "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.6.tgz", - "integrity": "sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==", - "license": "MIT" + "node_modules/@rollup/rollup-linux-s390x-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.24.0.tgz", + "integrity": "sha512-mjBaoo4ocxJppTorZVKWFpy1bfFj9FeCMJqzlMQGjpNPY9JwQi7OuS1axzNIk0nMX6jSgy6ZURDZ2w0QW6D56g==", + "cpu": [ + "s390x" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/http-cache-semantics": { - "version": "4.0.4", - "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", - "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", - "license": "MIT" + "node_modules/@rollup/rollup-linux-x64-gnu": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.24.0.tgz", + "integrity": "sha512-ZXFk7M72R0YYFN5q13niV0B7G8/5dcQ9JDp8keJSfr3GoZeXEoMHP/HlvqROA3OMbMdfr19IjCeNAnPUG93b6A==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/http-errors": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", - "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", - "license": "MIT" + "node_modules/@rollup/rollup-linux-x64-musl": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.24.0.tgz", + "integrity": "sha512-w1i+L7kAXZNdYl+vFvzSZy8Y1arS7vMgIy8wusXJzRrPyof5LAb02KGr1PD2EkRcl73kHulIID0M501lN+vobQ==", + "cpu": [ + "x64" + ], + "dev": true, + "license": "MIT", + "optional": true, + "os": [ + "linux" + ] }, - "node_modules/@types/istanbul-lib-coverage": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz", - "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==", + "node_modules/@rollup/rollup-win32-arm64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.24.0.tgz", + "integrity": "sha512-VXBrnPWgBpVDCVY6XF3LEW0pOU51KbaHhccHw6AS6vBWIC60eqsH19DAeeObl+g8nKAz04QFdl/Cefta0xQtUQ==", + "cpu": [ + "arm64" + ], "dev": true, - "license": "MIT" + "license": "MIT", + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@types/istanbul-lib-report": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz", - "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==", + "node_modules/@rollup/rollup-win32-ia32-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.24.0.tgz", + "integrity": "sha512-xrNcGDU0OxVcPTH/8n/ShH4UevZxKIO6HJFK0e15XItZP2UcaiLFd5kiX7hJnqCbSztUF8Qot+JWBC/QXRPYWQ==", + "cpu": [ + "ia32" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/istanbul-lib-coverage": "*" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@types/istanbul-reports": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz", - "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==", + "node_modules/@rollup/rollup-win32-x64-msvc": { + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.24.0.tgz", + "integrity": "sha512-fbMkAF7fufku0N2dE5TBXcNlg0pt0cJue4xBRE2Qc5Vqikxr4VCgKj/ht6SMdFcOacVA9rqF70APJ8RN/4vMJw==", + "cpu": [ + "x64" + ], "dev": true, "license": "MIT", - "dependencies": { - "@types/istanbul-lib-report": "*" - } + "optional": true, + "os": [ + "win32" + ] }, - "node_modules/@types/keygrip": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.6.tgz", - "integrity": "sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==", + "node_modules/@scure/base": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/@scure/base/-/base-1.1.1.tgz", + "integrity": "sha512-ZxOhsSyxYwLJj3pLZCefNitxsj093tb2vq90mp2txoYeBqbcjDjqFhyM8eUjq/uFm6zJ+mUuqxlS2FkuSY1MTA==", + "funding": [ + { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + ], "license": "MIT" }, - "node_modules/@types/keyv": { - "version": "3.1.4", - "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", - "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "node_modules/@scure/bip32": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/@scure/bip32/-/bip32-1.3.1.tgz", + "integrity": "sha512-osvveYtyzdEVbt3OfwwXFr4P2iVBL5u1Q3q4ONBfDY/UpOuXmOlbgwc1xECEboY8wIays8Yt6onaWMUdUbfl0A==", "license": "MIT", "dependencies": { - "@types/node": "*" + "@noble/curves": "~1.1.0", + "@noble/hashes": "~1.3.1", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@types/koa": { - "version": "2.15.0", - "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.15.0.tgz", - "integrity": "sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==", + "node_modules/@scure/bip39": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/@scure/bip39/-/bip39-1.2.1.tgz", + "integrity": "sha512-Z3/Fsz1yr904dduJD0NpiyRHhRYHdcnyh73FZWiV+/qhWi83wNJ3NWolYqCEN+ZWsUz2TWwajJggcRE9r1zUYg==", "license": "MIT", "dependencies": { - "@types/accepts": "*", - "@types/content-disposition": "*", - "@types/cookies": "*", - "@types/http-assert": "*", - "@types/http-errors": "*", - "@types/keygrip": "*", - "@types/koa-compose": "*", - "@types/node": "*" + "@noble/hashes": "~1.3.0", + "@scure/base": "~1.1.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" } }, - "node_modules/@types/koa-compose": { - "version": "3.2.8", - "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.8.tgz", - "integrity": "sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==", - "license": "MIT", + "node_modules/@sideway/address": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz", + "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==", + "dev": true, + "license": "BSD-3-Clause", "dependencies": { - "@types/koa": "*" + "@hapi/hoek": "^9.0.0" } }, - "node_modules/@types/mime": { - "version": "1.3.5", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", - "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", - "license": "MIT" + "node_modules/@sideway/formula": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz", + "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==", + "dev": true, + "license": "BSD-3-Clause" }, - "node_modules/@types/minimist": { - "version": "1.2.5", - "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", - "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", + "node_modules/@sideway/pinpoint": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz", + "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==", "dev": true, - "license": "MIT" + "license": "BSD-3-Clause" }, - "node_modules/@types/node": { - "version": "22.10.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.2.tgz", - "integrity": "sha512-Xxr6BBRCAOQixvonOye19wnzyDiUtTeqldOOmj3CkeblonbccA12PFwlufvRdrpjXxqnmUaeiU5EOA+7s5diUQ==", + "node_modules/@sindresorhus/is": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/@sindresorhus/is/-/is-4.6.0.tgz", + "integrity": "sha512-t09vSN3MdfsyCHoFcTRCH/iUtG7OJ0CsjzB8cjAmKc/va/kIgeDI/TxsigdncE/4be734m0cvIYwNaV4i2XqAw==", "license": "MIT", - "dependencies": { - "undici-types": "~6.20.0" + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sindresorhus/is?sponsor=1" } }, - "node_modules/@types/normalize-package-data": { - "version": "2.4.4", - "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", - "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", - "dev": true, - "license": "MIT" + "node_modules/@smithy/abort-controller": { + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/@smithy/abort-controller/-/abort-controller-3.1.6.tgz", + "integrity": "sha512-0XuhuHQlEqbNQZp7QxxrFTdVWdwxch4vjxYgfInF91hZFkPxf9QDrdQka0KfxFMPqLNzSw0b95uGTrLliQUavQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/qs": { - "version": "6.9.17", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.17.tgz", - "integrity": "sha512-rX4/bPcfmvxHDv0XjfJELTTr+iB+tn032nPILqHm5wbthUUUuVtNGGqzhya9XUxjTP8Fpr0qYgSZZKxGY++svQ==", - "license": "MIT" + "node_modules/@smithy/config-resolver": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@smithy/config-resolver/-/config-resolver-3.0.10.tgz", + "integrity": "sha512-Uh0Sz9gdUuz538nvkPiyv1DZRX9+D15EKDtnQP5rYVAzM/dnYk3P8cg73jcxyOitPgT3mE3OVj7ky7sibzHWkw==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/node-config-provider": "^3.1.9", + "@smithy/types": "^3.6.0", + "@smithy/util-config-provider": "^3.0.0", + "@smithy/util-middleware": "^3.0.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/range-parser": { - "version": "1.2.7", - "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", - "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", - "license": "MIT" + "node_modules/@smithy/core": { + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/@smithy/core/-/core-2.5.1.tgz", + "integrity": "sha512-DujtuDA7BGEKExJ05W5OdxCoyekcKT3Rhg1ZGeiUWaz2BJIWXjZmsG/DIP4W48GHno7AQwRsaCb8NcBgH3QZpg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/middleware-serde": "^3.0.8", + "@smithy/protocol-http": "^4.1.5", + "@smithy/types": "^3.6.0", + "@smithy/util-body-length-browser": "^3.0.0", + "@smithy/util-middleware": "^3.0.8", + "@smithy/util-stream": "^3.2.1", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/responselike": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", - "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", - "license": "MIT", + "node_modules/@smithy/credential-provider-imds": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/credential-provider-imds/-/credential-provider-imds-3.2.5.tgz", + "integrity": "sha512-4FTQGAsuwqTzVMmiRVTn0RR9GrbRfkP0wfu/tXWVHd2LgNpTY0uglQpIScXK4NaEyXbB3JmZt8gfVqO50lP8wg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@types/node": "*" + "@smithy/node-config-provider": "^3.1.9", + "@smithy/property-provider": "^3.1.8", + "@smithy/types": "^3.6.0", + "@smithy/url-parser": "^3.0.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/send": { - "version": "0.17.4", - "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", - "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", - "license": "MIT", + "node_modules/@smithy/fetch-http-handler": { + "version": "3.2.9", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-3.2.9.tgz", + "integrity": "sha512-hYNVQOqhFQ6vOpenifFME546f0GfJn2OiQ3M0FDmuUu8V/Uiwy2wej7ZXxFBNqdx0R5DZAqWM1l6VRhGz8oE6A==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@types/mime": "^1", - "@types/node": "*" + "@smithy/protocol-http": "^4.1.4", + "@smithy/querystring-builder": "^3.0.7", + "@smithy/types": "^3.5.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" } }, - "node_modules/@types/serve-static": { - "version": "1.15.7", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", - "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", - "license": "MIT", + "node_modules/@smithy/hash-node": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/hash-node/-/hash-node-3.0.8.tgz", + "integrity": "sha512-tlNQYbfpWXHimHqrvgo14DrMAgUBua/cNoz9fMYcDmYej7MAmUcjav/QKQbFc3NrcPxeJ7QClER4tWZmfwoPng==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@types/http-errors": "*", - "@types/node": "*", - "@types/send": "*" + "@smithy/types": "^3.6.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/sinonjs__fake-timers": { - "version": "8.1.1", - "resolved": "https://registry.npmjs.org/@types/sinonjs__fake-timers/-/sinonjs__fake-timers-8.1.1.tgz", - "integrity": "sha512-0kSuKjAS0TrGLJ0M/+8MaFkGsQhZpB6pxOmvS3K8FYI72K//YmdfoW9X2qPsAKh1mkwxGD5zib9s1FIFed6E8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/sizzle": { - "version": "2.3.9", - "resolved": "https://registry.npmjs.org/@types/sizzle/-/sizzle-2.3.9.tgz", - "integrity": "sha512-xzLEyKB50yqCUPUJkIsrVvoWNfFUbIZI+RspLWt8u+tIW/BetMBZtgV2LY/2o+tYH8dRvQ+eoPf3NdhQCcLE2w==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/ssh2": { - "version": "1.15.1", - "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.1.tgz", - "integrity": "sha512-ZIbEqKAsi5gj35y4P4vkJYly642wIbY6PqoN0xiyQGshKUGXR9WQjF/iF9mXBQ8uBKy3ezfsCkcoHKhd0BzuDA==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/invalid-dependency": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/invalid-dependency/-/invalid-dependency-3.0.8.tgz", + "integrity": "sha512-7Qynk6NWtTQhnGTTZwks++nJhQ1O54Mzi7fz4PqZOiYXb4Z1Flpb2yRvdALoggTS8xjtohWUM+RygOtB30YL3Q==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@types/node": "^18.11.18" + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" } }, - "node_modules/@types/ssh2/node_modules/@types/node": { - "version": "18.19.68", - "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.68.tgz", - "integrity": "sha512-QGtpFH1vB99ZmTa63K4/FU8twThj4fuVSBkGddTp7uIL/cuoLWIUSL2RcOaigBhfR+hg5pgGkBnkoOxrTVBMKw==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/is-array-buffer": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/is-array-buffer/-/is-array-buffer-3.0.0.tgz", + "integrity": "sha512-+Fsu6Q6C4RSJiy81Y8eApjEB5gVtM+oFKTffg+jSuwtvomJJrhUJBu2zS8wjXSgH/g1MKEWrzyChTBe6clb5FQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "undici-types": "~5.26.4" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/ssh2/node_modules/undici-types": { - "version": "5.26.5", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", - "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@types/stack-utils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz", - "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==", - "dev": true, - "license": "MIT" + "node_modules/@smithy/middleware-content-length": { + "version": "3.0.10", + "resolved": "https://registry.npmjs.org/@smithy/middleware-content-length/-/middleware-content-length-3.0.10.tgz", + "integrity": "sha512-T4dIdCs1d/+/qMpwhJ1DzOhxCZjZHbHazEPJWdB4GDi2HjIZllVzeBEcdJUN0fomV8DURsgOyrbEUzg3vzTaOg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/protocol-http": "^4.1.5", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/webidl-conversions": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", - "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", - "license": "MIT" + "node_modules/@smithy/middleware-endpoint": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@smithy/middleware-endpoint/-/middleware-endpoint-3.2.1.tgz", + "integrity": "sha512-wWO3xYmFm6WRW8VsEJ5oU6h7aosFXfszlz3Dj176pTij6o21oZnzkCLzShfmRaaCHDkBXWBdO0c4sQAvLFP6zA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/core": "^2.5.1", + "@smithy/middleware-serde": "^3.0.8", + "@smithy/node-config-provider": "^3.1.9", + "@smithy/shared-ini-file-loader": "^3.1.9", + "@smithy/types": "^3.6.0", + "@smithy/url-parser": "^3.0.8", + "@smithy/util-middleware": "^3.0.8", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/whatwg-url": { - "version": "8.2.2", - "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", - "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", - "license": "MIT", + "node_modules/@smithy/middleware-retry": { + "version": "3.0.25", + "resolved": "https://registry.npmjs.org/@smithy/middleware-retry/-/middleware-retry-3.0.25.tgz", + "integrity": "sha512-m1F70cPaMBML4HiTgCw5I+jFNtjgz5z5UdGnUbG37vw6kh4UvizFYjqJGHvicfgKMkDL6mXwyPp5mhZg02g5sg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@types/node": "*", - "@types/webidl-conversions": "*" + "@smithy/node-config-provider": "^3.1.9", + "@smithy/protocol-http": "^4.1.5", + "@smithy/service-error-classification": "^3.0.8", + "@smithy/smithy-client": "^3.4.2", + "@smithy/types": "^3.6.0", + "@smithy/util-middleware": "^3.0.8", + "@smithy/util-retry": "^3.0.8", + "tslib": "^2.6.2", + "uuid": "^9.0.1" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/yargs": { - "version": "17.0.33", - "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz", - "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==", - "dev": true, + "node_modules/@smithy/middleware-retry/node_modules/uuid": { + "version": "9.0.1", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz", + "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==", + "funding": [ + "https://github.com/sponsors/broofa", + "https://github.com/sponsors/ctavan" + ], "license": "MIT", + "optional": true, + "bin": { + "uuid": "dist/bin/uuid" + } + }, + "node_modules/@smithy/middleware-serde": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-serde/-/middleware-serde-3.0.8.tgz", + "integrity": "sha512-Xg2jK9Wc/1g/MBMP/EUn2DLspN8LNt+GMe7cgF+Ty3vl+Zvu+VeZU5nmhveU+H8pxyTsjrAkci8NqY6OuvZnjA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@types/yargs-parser": "*" + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@types/yargs-parser": { - "version": "21.0.3", - "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz", - "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==", - "dev": true, - "license": "MIT" + "node_modules/@smithy/middleware-stack": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/middleware-stack/-/middleware-stack-3.0.8.tgz", + "integrity": "sha512-d7ZuwvYgp1+3682Nx0MD3D/HtkmZd49N3JUndYWQXfRZrYEnCWYc8BHcNmVsPAp9gKvlurdg/mubE6b/rPS9MA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" + } }, - "node_modules/@types/yauzl": { - "version": "2.10.3", - "resolved": "https://registry.npmjs.org/@types/yauzl/-/yauzl-2.10.3.tgz", - "integrity": "sha512-oJoftv0LSuaDZE3Le4DbKX+KS9G36NzOeSap90UIK0yMA/NhKJhqlSGtNDORNRaIbQfzjXDrQa0ytJ6mNRGz/Q==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/node-config-provider": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@smithy/node-config-provider/-/node-config-provider-3.1.9.tgz", + "integrity": "sha512-qRHoah49QJ71eemjuS/WhUXB+mpNtwHRWQr77J/m40ewBVVwvo52kYAmb7iuaECgGTTcYxHS4Wmewfwy++ueew==", + "license": "Apache-2.0", "optional": true, "dependencies": { - "@types/node": "*" + "@smithy/property-provider": "^3.1.8", + "@smithy/shared-ini-file-loader": "^3.1.9", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vitejs/plugin-legacy": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-legacy/-/plugin-legacy-4.1.1.tgz", - "integrity": "sha512-um3gbVouD2Q/g19C0qpDfHwveXDCAHzs8OC3e9g6aXpKoD1H14himgs7wkMnhAynBJy7QqUoZNAXDuqN8zLR2g==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/node-http-handler": { + "version": "3.2.5", + "resolved": "https://registry.npmjs.org/@smithy/node-http-handler/-/node-http-handler-3.2.5.tgz", + "integrity": "sha512-PkOwPNeKdvX/jCpn0A8n9/TyoxjGZB8WVoJmm9YzsnAgggTj4CrjpRHlTQw7dlLZ320n1mY1y+nTRUDViKi/3w==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/core": "^7.22.9", - "@babel/preset-env": "^7.22.9", - "browserslist": "^4.21.9", - "core-js": "^3.31.1", - "magic-string": "^0.30.1", - "regenerator-runtime": "^0.13.11", - "systemjs": "^6.14.1" + "@smithy/abort-controller": "^3.1.6", + "@smithy/protocol-http": "^4.1.5", + "@smithy/querystring-builder": "^3.0.8", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/property-provider": { + "version": "3.1.8", + "resolved": "https://registry.npmjs.org/@smithy/property-provider/-/property-provider-3.1.8.tgz", + "integrity": "sha512-ukNUyo6rHmusG64lmkjFeXemwYuKge1BJ8CtpVKmrxQxc6rhUX0vebcptFA9MmrGsnLhwnnqeH83VTU9hwOpjA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" + "engines": { + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/protocol-http": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/@smithy/protocol-http/-/protocol-http-4.1.5.tgz", + "integrity": "sha512-hsjtwpIemmCkm3ZV5fd/T0bPIugW1gJXwZ/hpuVubt2hEUApIoUTrf6qIdh9MAWlw0vjMrA1ztJLAwtNaZogvg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "terser": "^5.4.0", - "vite": "^4.0.0" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vitejs/plugin-legacy/node_modules/core-js": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.39.0.tgz", - "integrity": "sha512-raM0ew0/jJUqkJ0E6e8UDtl+y/7ktFivgWvqw8dNSQeNWoSDLvQ1H/RN3aPXB9tBd4/FhyR4RDPGhsNIMsAn7g==", - "dev": true, - "hasInstallScript": true, - "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "node_modules/@smithy/querystring-builder": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/querystring-builder/-/querystring-builder-3.0.8.tgz", + "integrity": "sha512-btYxGVqFUARbUrN6VhL9c3dnSviIwBYD9Rz1jHuN1hgh28Fpv2xjU1HeCeDJX68xctz7r4l1PBnFhGg1WBBPuA==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^3.6.0", + "@smithy/util-uri-escape": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vitejs/plugin-vue": { - "version": "4.2.3", - "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-4.2.3.tgz", - "integrity": "sha512-R6JDUfiZbJA9cMiguQ7jxALsgiprjBeHL5ikpXfJCH62pPHtI+JdJ5xWj6Ev73yXSlYl86+blXn1kZHQ7uElxw==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/querystring-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/querystring-parser/-/querystring-parser-3.0.8.tgz", + "integrity": "sha512-BtEk3FG7Ks64GAbt+JnKqwuobJNX8VmFLBsKIwWr1D60T426fGrV2L3YS5siOcUhhp6/Y6yhBw1PSPxA5p7qGg==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, "engines": { - "node": "^14.18.0 || >=16.0.0" + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/service-error-classification": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/service-error-classification/-/service-error-classification-3.0.8.tgz", + "integrity": "sha512-uEC/kCCFto83bz5ZzapcrgGqHOh/0r69sZ2ZuHlgoD5kYgXJEThCoTuw/y1Ub3cE7aaKdznb+jD9xRPIfIwD7g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/types": "^3.6.0" }, - "peerDependencies": { - "vite": "^4.0.0", - "vue": "^3.2.25" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vue/compiler-core": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.3.13.tgz", - "integrity": "sha512-bwi9HShGu7uaZLOErZgsH2+ojsEdsjerbf2cMXPwmvcgZfVPZ2BVZzCVnwZBxTAYd6Mzbmf6izcUNDkWnBBQ6A==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/shared-ini-file-loader": { + "version": "3.1.9", + "resolved": "https://registry.npmjs.org/@smithy/shared-ini-file-loader/-/shared-ini-file-loader-3.1.9.tgz", + "integrity": "sha512-/+OsJRNtoRbtsX0UpSgWVxFZLsJHo/4sTr+kBg/J78sr7iC+tHeOvOJrS5hCpVQ6sWBbhWLp1UNiuMyZhE6pmA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/shared": "3.3.13", - "estree-walker": "^2.0.2", - "source-map-js": "^1.0.2" + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vue/compiler-dom": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.3.13.tgz", - "integrity": "sha512-EYRDpbLadGtNL0Gph+HoKiYqXLqZ0xSSpR5Dvnu/Ep7ggaCbjRDIus1MMxTS2Qm0koXED4xSlvTZaTnI8cYAsw==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/signature-v4": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@smithy/signature-v4/-/signature-v4-4.2.1.tgz", + "integrity": "sha512-NsV1jF4EvmO5wqmaSzlnTVetemBS3FZHdyc5CExbDljcyJCEEkJr8ANu2JvtNbVg/9MvKAWV44kTrGS+Pi4INg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@vue/compiler-core": "3.3.13", - "@vue/shared": "3.3.13" + "@smithy/is-array-buffer": "^3.0.0", + "@smithy/protocol-http": "^4.1.5", + "@smithy/types": "^3.6.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-middleware": "^3.0.8", + "@smithy/util-uri-escape": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vue/compiler-sfc": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.3.13.tgz", - "integrity": "sha512-DQVmHEy/EKIgggvnGRLx21hSqnr1smUS9Aq8tfxiiot8UR0/pXKHN9k78/qQ7etyQTFj5em5nruODON7dBeumw==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/smithy-client": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/@smithy/smithy-client/-/smithy-client-3.4.2.tgz", + "integrity": "sha512-dxw1BDxJiY9/zI3cBqfVrInij6ShjpV4fmGHesGZZUiP9OSE/EVfdwdRz0PgvkEvrZHpsj2htRaHJfftE8giBA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/compiler-core": "3.3.13", - "@vue/compiler-dom": "3.3.13", - "@vue/compiler-ssr": "3.3.13", - "@vue/reactivity-transform": "3.3.13", - "@vue/shared": "3.3.13", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.5", - "postcss": "^8.4.32", - "source-map-js": "^1.0.2" + "@smithy/core": "^2.5.1", + "@smithy/middleware-endpoint": "^3.2.1", + "@smithy/middleware-stack": "^3.0.8", + "@smithy/protocol-http": "^4.1.5", + "@smithy/types": "^3.6.0", + "@smithy/util-stream": "^3.2.1", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vue/compiler-ssr": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.3.13.tgz", - "integrity": "sha512-d/P3bCeUGmkJNS1QUZSAvoCIW4fkOKK3l2deE7zrp0ypJEy+En2AcypIkqvcFQOcw3F0zt2VfMvNsA9JmExTaw==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/types": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/@smithy/types/-/types-3.6.0.tgz", + "integrity": "sha512-8VXK/KzOHefoC65yRgCn5vG1cysPJjHnOVt9d0ybFQSmJgQj152vMn4EkYhGuaOmnnZvCPav/KnYyE6/KsNZ2w==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@vue/compiler-dom": "3.3.13", - "@vue/shared": "3.3.13" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vue/devtools-api": { - "version": "6.6.4", - "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", - "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vue/reactivity": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.3.13.tgz", - "integrity": "sha512-fjzCxceMahHhi4AxUBzQqqVhuA21RJ0COaWTbIBl1PruGW1CeY97louZzLi4smpYx+CHfFPPU/CS8NybbGvPKQ==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/url-parser": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/url-parser/-/url-parser-3.0.8.tgz", + "integrity": "sha512-4FdOhwpTW7jtSFWm7SpfLGKIBC9ZaTKG5nBF0wK24aoQKQyDIKUw3+KFWCQ9maMzrgTJIuOvOnsV2lLGW5XjTg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@vue/shared": "3.3.13" + "@smithy/querystring-parser": "^3.0.8", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" } }, - "node_modules/@vue/reactivity-transform": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/reactivity-transform/-/reactivity-transform-3.3.13.tgz", - "integrity": "sha512-oWnydGH0bBauhXvh5KXUy61xr9gKaMbtsMHk40IK9M4gMuKPJ342tKFarY0eQ6jef8906m35q37wwA8DMZOm5Q==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-base64": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-base64/-/util-base64-3.0.0.tgz", + "integrity": "sha512-Kxvoh5Qtt0CDsfajiZOCpJxgtPHXOKwmM+Zy4waD43UoEMA+qPxxa98aE/7ZhdnBFZFXMOiBR5xbcaMhLtznQQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@babel/parser": "^7.23.5", - "@vue/compiler-core": "3.3.13", - "@vue/shared": "3.3.13", - "estree-walker": "^2.0.2", - "magic-string": "^0.30.5" + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vue/runtime-core": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.3.13.tgz", - "integrity": "sha512-1TzA5TvGuh2zUwMJgdfvrBABWZ7y8kBwBhm7BXk8rvdx2SsgcGfz2ruv2GzuGZNvL1aKnK8CQMV/jFOrxNQUMA==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-body-length-browser": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-browser/-/util-body-length-browser-3.0.0.tgz", + "integrity": "sha512-cbjJs2A1mLYmqmyVl80uoLTJhAcfzMOyPgjwAYusWKMdLeNtzmMz9YxNl3/jRLoxSS3wkqkf0jwNdtXWtyEBaQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@vue/reactivity": "3.3.13", - "@vue/shared": "3.3.13" + "tslib": "^2.6.2" } }, - "node_modules/@vue/runtime-dom": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.3.13.tgz", - "integrity": "sha512-JJkpE8R/hJKXqVTgUoODwS5wqKtOsmJPEqmp90PDVGygtJ4C0PtOkcEYXwhiVEmef6xeXcIlrT3Yo5aQ4qkHhQ==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-body-length-node": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-body-length-node/-/util-body-length-node-3.0.0.tgz", + "integrity": "sha512-Tj7pZ4bUloNUP6PzwhN7K386tmSmEET9QtQg0TgdNOnxhZvCssHji+oZTUIuzxECRfG8rdm2PMw2WCFs6eIYkA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@vue/runtime-core": "3.3.13", - "@vue/shared": "3.3.13", - "csstype": "^3.1.3" + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vue/server-renderer": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.3.13.tgz", - "integrity": "sha512-vSnN+nuf6iSqTL3Qgx/9A+BT+0Zf/VJOgF5uMZrKjYPs38GMYyAU1coDyBNHauehXDaP+zl73VhwWv0vBRBHcg==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-buffer-from": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-buffer-from/-/util-buffer-from-3.0.0.tgz", + "integrity": "sha512-aEOHCgq5RWFbP+UDPvPot26EJHjOC+bRgse5A8V3FSShqd5E5UN4qc7zkwsvJPPAVsf73QwYcHN1/gt/rtLwQA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "@vue/compiler-ssr": "3.3.13", - "@vue/shared": "3.3.13" + "@smithy/is-array-buffer": "^3.0.0", + "tslib": "^2.6.2" }, - "peerDependencies": { - "vue": "3.3.13" + "engines": { + "node": ">=16.0.0" } }, - "node_modules/@vue/shared": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.3.13.tgz", - "integrity": "sha512-/zYUwiHD8j7gKx2argXEMCUXVST6q/21DFU0sTfNX0URJroCe3b1UF6vLJ3lQDfLNIiiRl2ONp7Nh5UVWS6QnA==", - "dev": true, - "license": "MIT" - }, - "node_modules/@vuepic/vue-datepicker": { - "version": "3.4.8", - "resolved": "https://registry.npmjs.org/@vuepic/vue-datepicker/-/vue-datepicker-3.4.8.tgz", - "integrity": "sha512-nbuMA7IgjtT99LqcjSTSUcl7omTZSB+7vYSWQ9gQm31Frm/1wn54fT1Q0HaRD9nHXX982AACbqeND4K80SKONw==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-config-provider": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-config-provider/-/util-config-provider-3.0.0.tgz", + "integrity": "sha512-pbjk4s0fwq3Di/ANL+rCvJMKM5bzAQdE5S/6RL5NXgMExFAi6UgQMPOm5yPaIWPpr+EOXKXRonJ3FoxKf4mCJQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "date-fns": "^2.29.2" + "tslib": "^2.6.2" }, "engines": { - "node": ">=14" - }, - "peerDependencies": { - "vue": ">=3.2.0" + "node": ">=16.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==", - "license": "ISC" - }, - "node_modules/accepts": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", - "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", - "license": "MIT", + "node_modules/@smithy/util-defaults-mode-browser": { + "version": "3.0.25", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-browser/-/util-defaults-mode-browser-3.0.25.tgz", + "integrity": "sha512-fRw7zymjIDt6XxIsLwfJfYUfbGoO9CmCJk6rjJ/X5cd20+d2Is7xjU5Kt/AiDt6hX8DAf5dztmfP5O82gR9emA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "mime-types": "~2.1.34", - "negotiator": "0.6.3" + "@smithy/property-provider": "^3.1.8", + "@smithy/smithy-client": "^3.4.2", + "@smithy/types": "^3.6.0", + "bowser": "^2.11.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 0.6" + "node": ">= 10.0.0" } }, - "node_modules/accepts/node_modules/negotiator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", - "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", - "license": "MIT", + "node_modules/@smithy/util-defaults-mode-node": { + "version": "3.0.25", + "resolved": "https://registry.npmjs.org/@smithy/util-defaults-mode-node/-/util-defaults-mode-node-3.0.25.tgz", + "integrity": "sha512-H3BSZdBDiVZGzt8TG51Pd2FvFO0PAx/A0mJ0EH8a13KJ6iUCdYnw/Dk/MdC1kTd0eUuUGisDFaxXVXo4HHFL1g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/config-resolver": "^3.0.10", + "@smithy/credential-provider-imds": "^3.2.5", + "@smithy/node-config-provider": "^3.1.9", + "@smithy/property-provider": "^3.1.8", + "@smithy/smithy-client": "^3.4.2", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, "engines": { - "node": ">= 0.6" + "node": ">= 10.0.0" } }, - "node_modules/acorn": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz", - "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==", - "dev": true, - "license": "MIT", - "bin": { - "acorn": "bin/acorn" + "node_modules/@smithy/util-endpoints": { + "version": "2.1.4", + "resolved": "https://registry.npmjs.org/@smithy/util-endpoints/-/util-endpoints-2.1.4.tgz", + "integrity": "sha512-kPt8j4emm7rdMWQyL0F89o92q10gvCUa6sBkBtDJ7nV2+P7wpXczzOfoDJ49CKXe5CCqb8dc1W+ZdLlrKzSAnQ==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/node-config-provider": "^3.1.9", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=0.4.0" - } - }, - "node_modules/acorn-jsx": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", - "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", - "dev": true, - "license": "MIT", - "peerDependencies": { - "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + "node": ">=16.0.0" } }, - "node_modules/aedes": { - "version": "0.46.3", - "resolved": "https://registry.npmjs.org/aedes/-/aedes-0.46.3.tgz", - "integrity": "sha512-i3B+H74uNRhlqcs/JdrMp7e3daz4Cwls0x4yLcfjGXz2tIwnxhF6od4m86O6yyNdz/Gg3jfY3q0sc/Cz8qzg6g==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-hex-encoding": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-hex-encoding/-/util-hex-encoding-3.0.0.tgz", + "integrity": "sha512-eFndh1WEK5YMUYvy3lPlVmYY/fZcQE1D8oSf41Id2vCeIkKJXPcYDCZD+4+xViI6b1XSd7tE+s5AmXzz5ilabQ==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "aedes-packet": "^2.3.1", - "aedes-persistence": "^8.1.3", - "bulk-write-stream": "^2.0.1", - "end-of-stream": "^1.4.4", - "fastfall": "^1.5.1", - "fastparallel": "^2.4.1", - "fastseries": "^2.0.0", - "hyperid": "^3.0.0", - "mqemitter": "^4.5.0", - "mqtt-packet": "^7.1.2", - "readable-stream": "^3.6.0", - "retimer": "^3.0.0", - "reusify": "^1.0.4", - "uuid": "^8.3.2" + "tslib": "^2.6.2" }, "engines": { - "node": ">=12" + "node": ">=16.0.0" } }, - "node_modules/aedes-packet": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/aedes-packet/-/aedes-packet-2.3.1.tgz", - "integrity": "sha512-LqBd57uc2rui2RbjycW17dylglejG26mM4ewVXGNDnVp/SUHFVEgm7d1HTmYrnSkSCNoHti042qgcTwv/F+BtQ==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-middleware": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/util-middleware/-/util-middleware-3.0.8.tgz", + "integrity": "sha512-p7iYAPaQjoeM+AKABpYWeDdtwQNxasr4aXQEA/OmbOaug9V0odRVDy3Wx4ci8soljE/JXQo+abV0qZpW8NX0yA==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "mqtt-packet": "^6.3.0" + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=8" + "node": ">=16.0.0" } }, - "node_modules/aedes-packet/node_modules/mqtt-packet": { - "version": "6.10.0", - "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", - "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-retry": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/@smithy/util-retry/-/util-retry-3.0.8.tgz", + "integrity": "sha512-TCEhLnY581YJ+g1x0hapPz13JFqzmh/pMWL2KEFASC51qCfw3+Y47MrTmea4bUE5vsdxQ4F6/KFbUeSz22Q1ow==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "bl": "^4.0.2", - "debug": "^4.1.1", - "process-nextick-args": "^2.0.1" + "@smithy/service-error-classification": "^3.0.8", + "@smithy/types": "^3.6.0", + "tslib": "^2.6.2" + }, + "engines": { + "node": ">=16.0.0" } }, - "node_modules/aedes-persistence": { - "version": "8.1.3", - "resolved": "https://registry.npmjs.org/aedes-persistence/-/aedes-persistence-8.1.3.tgz", - "integrity": "sha512-VMCjEV+2g1TNJb/IlDEUy6SP9crT+QUhe2xc6UjyqrFNBNgTvHmOefXY7FxWrwmR2QA02vwg3+5p/JXkyg/Dkw==", - "dev": true, - "license": "MIT", + "node_modules/@smithy/util-stream": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/@smithy/util-stream/-/util-stream-3.2.1.tgz", + "integrity": "sha512-R3ufuzJRxSJbE58K9AEnL/uSZyVdHzud9wLS8tIbXclxKzoe09CRohj2xV8wpx5tj7ZbiJaKYcutMm1eYgz/0A==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "aedes-packet": "^2.3.1", - "from2": "^2.3.0", - "qlobber": "^5.0.3" + "@smithy/fetch-http-handler": "^4.0.0", + "@smithy/node-http-handler": "^3.2.5", + "@smithy/types": "^3.6.0", + "@smithy/util-base64": "^3.0.0", + "@smithy/util-buffer-from": "^3.0.0", + "@smithy/util-hex-encoding": "^3.0.0", + "@smithy/util-utf8": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">=10" + "node": ">=16.0.0" + } + }, + "node_modules/@smithy/util-stream/node_modules/@smithy/fetch-http-handler": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/@smithy/fetch-http-handler/-/fetch-http-handler-4.0.0.tgz", + "integrity": "sha512-MLb1f5tbBO2X6K4lMEKJvxeLooyg7guq48C2zKr4qM7F2Gpkz4dc+hdSgu77pCJ76jVqFBjZczHYAs6dp15N+g==", + "license": "Apache-2.0", + "optional": true, + "dependencies": { + "@smithy/protocol-http": "^4.1.5", + "@smithy/querystring-builder": "^3.0.8", + "@smithy/types": "^3.6.0", + "@smithy/util-base64": "^3.0.0", + "tslib": "^2.6.2" } }, - "node_modules/agent-base": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", - "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", - "license": "MIT", + "node_modules/@smithy/util-uri-escape": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-uri-escape/-/util-uri-escape-3.0.0.tgz", + "integrity": "sha512-LqR7qYLgZTD7nWLBecUi4aqolw8Mhza9ArpNEQ881MJJIU2sE5iHCK6TdyqqzcDLy0OPe10IY4T8ctVdtynubg==", + "license": "Apache-2.0", + "optional": true, "dependencies": { - "debug": "4" + "tslib": "^2.6.2" }, "engines": { - "node": ">= 6.0.0" + "node": ">=16.0.0" } }, - "node_modules/agentkeepalive": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", - "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", - "license": "MIT", + "node_modules/@smithy/util-utf8": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/@smithy/util-utf8/-/util-utf8-3.0.0.tgz", + "integrity": "sha512-rUeT12bxFnplYDe815GXbq/oixEGHfRFFtcTF3YdDi/JaENIM6aSYYLJydG83UNzLXeRI5K8abYd/8Sp/QM0kA==", + "license": "Apache-2.0", "optional": true, "dependencies": { - "humanize-ms": "^1.2.1" + "@smithy/util-buffer-from": "^3.0.0", + "tslib": "^2.6.2" }, "engines": { - "node": ">= 8.0.0" + "node": ">=16.0.0" } }, - "node_modules/aggregate-error": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", - "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", - "devOptional": true, + "node_modules/@socket.io/component-emitter": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/@socket.io/component-emitter/-/component-emitter-3.1.2.tgz", + "integrity": "sha512-9BCxFwvbGg/RsZK9tjXd8s4UcwR0MWeFQ1XEKIQVVvAGJyINdrqKMcTRyLoK8Rse1GjzLV9cwjWV1olXRWEXVA==", + "license": "MIT" + }, + "node_modules/@szmarczak/http-timer": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/@szmarczak/http-timer/-/http-timer-5.0.1.tgz", + "integrity": "sha512-+PmQX0PiAYPMeVYe237LJAYvOMYW1j2rH5YROyS3b4CTVJum34HfRvKvAzozHAQG0TnHNdUfY9nCeUyRAs//cw==", "license": "MIT", "dependencies": { - "clean-stack": "^2.0.0", - "indent-string": "^4.0.0" + "defer-to-connect": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">=14.16" } }, - "node_modules/ajv": { - "version": "6.12.6", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", - "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "node_modules/@tediousjs/connection-string": { + "version": "0.5.0", + "resolved": "https://registry.npmjs.org/@tediousjs/connection-string/-/connection-string-0.5.0.tgz", + "integrity": "sha512-7qSgZbincDDDFyRweCIEvZULFAw5iz/DeunhvuxpL31nfntX3P4Yd4HkHBRg9H8CdqY1e5WFN1PZIz/REL9MVQ==", + "license": "MIT" + }, + "node_modules/@testcontainers/hivemq": { + "version": "10.13.2", + "resolved": "https://registry.npmjs.org/@testcontainers/hivemq/-/hivemq-10.13.2.tgz", + "integrity": "sha512-TnCwVO3RJIRmYQLZoh8KHE6KMYtdnnO98r8qp/+1B37nXnD9OQNENC+W6h8gHwLSe4pgjyp9bzKGN7kttqDpnA==", "dev": true, "license": "MIT", "dependencies": { - "fast-deep-equal": "^3.1.1", - "fast-json-stable-stringify": "^2.0.0", - "json-schema-traverse": "^0.4.1", - "uri-js": "^4.2.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" + "testcontainers": "^10.13.2" } }, - "node_modules/anafanafo": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/anafanafo/-/anafanafo-2.0.0.tgz", - "integrity": "sha512-Nlfq7NC4AOkTJerWRIZcOAiMNtIDVIGWGvQ98O7Jl6Kr2Dk0dX5u4MqN778kSRTy5KRqchpLdF2RtLFEz9FVkQ==", + "node_modules/@testcontainers/rabbitmq": { + "version": "10.13.2", + "resolved": "https://registry.npmjs.org/@testcontainers/rabbitmq/-/rabbitmq-10.13.2.tgz", + "integrity": "sha512-npBKBnq3c6hETmxGZ/gVMke9cc1J/pcftNW9S3WidL48hxFBIPjYNM9FdTfWuoNER/8kuf4xJ8yCuJEYGH3ZAg==", + "dev": true, "license": "MIT", "dependencies": { - "char-width-table-consumer": "^1.0.0" + "testcontainers": "^10.13.2" } }, - "node_modules/ansi-colors": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", - "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", - "dev": true, + "node_modules/@tootallnate/once": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-2.0.0.tgz", + "integrity": "sha512-XCuKFP5PS55gnMVu3dty8KPatLqUoy/ZYzDzAGCQ8JNFCkLXzmI7vNHCR+XpbZaMWQK/vQubr7PkYq8g470J/A==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">= 10" } }, - "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, + "node_modules/@types/accepts": { + "version": "1.3.7", + "resolved": "https://registry.npmjs.org/@types/accepts/-/accepts-1.3.7.tgz", + "integrity": "sha512-Pay9fq2lM2wXPWbteBsRAGiWH2hig4ZE2asK+mm7kUzlxRTfL961rj89I6zV/E3PcIkDqyuBEcMxFT7rccugeQ==", "license": "MIT", "dependencies": { - "type-fest": "^0.21.3" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/ansi-regex": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", - "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", - "license": "MIT", - "engines": { - "node": ">=8" + "@types/node": "*" } }, - "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/@types/body-parser": { + "version": "1.19.5", + "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz", + "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==", "license": "MIT", "dependencies": { - "color-convert": "^2.0.1" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" + "@types/connect": "*", + "@types/node": "*" } }, - "node_modules/any-promise": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", - "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", - "license": "MIT" - }, - "node_modules/anymatch": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", - "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "node_modules/@types/bootstrap": { + "version": "5.1.13", + "resolved": "https://registry.npmjs.org/@types/bootstrap/-/bootstrap-5.1.13.tgz", + "integrity": "sha512-1hIIOgfkMlyQCQz/3ae53xr6ZN2d6EDj/n3G+Sh/LBsBUVigyDmnCbLwsaXJJ1GBGlkjgfXVoyIvEPowQw25xQ==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "normalize-path": "^3.0.0", - "picomatch": "^2.0.4" - }, - "engines": { - "node": ">= 8" + "@popperjs/core": "^2.9.2" } }, - "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==", - "license": "ISC" - }, - "node_modules/arch": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz", - "integrity": "sha512-Of/R0wqp83cgHozfIYLbBMnej79U/SVGOOyuB3VVFv1NRM/PSFMK12x9KVtiYzJqmnU5WR2qp0Z5rHb7sWGnFQ==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], - "license": "MIT" - }, - "node_modules/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==", - "deprecated": "This package is no longer supported.", - "license": "ISC", + "node_modules/@types/cacheable-request": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@types/cacheable-request/-/cacheable-request-6.0.3.tgz", + "integrity": "sha512-IQ3EbTzGxIigb1I3qPZc1rWJnH0BmSKv5QYTalEwweFvyBDLSAe24zP0le/hyi7ecGfZVlIVAg4BZqb8WBwKqw==", + "license": "MIT", "dependencies": { - "delegates": "^1.0.0", - "readable-stream": "^3.6.0" - }, - "engines": { - "node": ">=10" + "@types/http-cache-semantics": "*", + "@types/keyv": "^3.1.4", + "@types/node": "*", + "@types/responselike": "^1.0.0" } }, - "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==", - "dev": true, - "license": "Python-2.0" - }, - "node_modules/args-parser": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/args-parser/-/args-parser-1.3.0.tgz", - "integrity": "sha512-If3Zi4BSjlQIJ9fgAhSiKi0oJtgMzSqh0H4wvl7XSeO16FKx7QqaHld8lZeEajPX7y1C5qKKeNgyrfyvmjmjUQ==", - "license": "Apache-2.0" - }, - "node_modules/array-buffer-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz", - "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==", + "node_modules/@types/connect": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz", + "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "is-array-buffer": "^3.0.5" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/node": "*" } }, - "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/@types/content-disposition": { + "version": "0.5.8", + "resolved": "https://registry.npmjs.org/@types/content-disposition/-/content-disposition-0.5.8.tgz", + "integrity": "sha512-QVSSvno3dE0MgO76pJhmv4Qyi/j0Yk9pBp0Y7TJ2Tlj+KCgJWY6qX7nnxCOLkZ3VYRSIk1WTxCvwUSdx6CCLdg==", "license": "MIT" }, - "node_modules/array-union": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", - "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } + "node_modules/@types/cookie": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/@types/cookie/-/cookie-0.4.1.tgz", + "integrity": "sha512-XW/Aa8APYr6jSVVA1y/DEIZX0/GMKLEVekNG727R8cs56ahETkRAy/3DR7+fJyh7oUgGwNQaRfXCun0+KbWY7Q==", + "license": "MIT" }, - "node_modules/arraybuffer.prototype.slice": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz", - "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==", + "node_modules/@types/cookies": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/@types/cookies/-/cookies-0.9.0.tgz", + "integrity": "sha512-40Zk8qR147RABiQ7NQnBzWzDcjKzNrntB5BAmeGCb2p/MIyOE+4BVvc17wumsUqUw00bJYqoXFHYygQnEFh4/Q==", "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "is-array-buffer": "^3.0.4" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/connect": "*", + "@types/express": "*", + "@types/keygrip": "*", + "@types/node": "*" + } + }, + "node_modules/@types/cors": { + "version": "2.8.17", + "resolved": "https://registry.npmjs.org/@types/cors/-/cors-2.8.17.tgz", + "integrity": "sha512-8CGDvrBj1zgo2qE+oS3pOCyYNqCPryMWY2bGfwA0dcfopWGgxs+78df0Rs3rc9THP4JkOhLsAa+15VdpAqkcUA==", + "license": "MIT", + "dependencies": { + "@types/node": "*" } }, - "node_modules/arrify": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", - "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", + "node_modules/@types/docker-modem": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/@types/docker-modem/-/docker-modem-3.0.6.tgz", + "integrity": "sha512-yKpAGEuKRSS8wwx0joknWxsmLha78wNMe9R2S3UNsVOkZded8UqOrV8KoeDXoXsjndxwyF3eIhyClGbO1SEhEg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" + "dependencies": { + "@types/node": "*", + "@types/ssh2": "*" } }, - "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==", + "node_modules/@types/dockerode": { + "version": "3.3.31", + "resolved": "https://registry.npmjs.org/@types/dockerode/-/dockerode-3.3.31.tgz", + "integrity": "sha512-42R9eoVqJDSvVspV89g7RwRqfNExgievLNWoHkg7NoWIqAmavIbgQBb4oc0qRtHkxE+I3Xxvqv7qVXFABKPBTg==", "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": "~2.1.0" + "@types/docker-modem": "*", + "@types/node": "*", + "@types/ssh2": "*" } }, - "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==", + "node_modules/@types/estree": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz", + "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==", "dev": true, + "license": "MIT" + }, + "node_modules/@types/express": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.21.tgz", + "integrity": "sha512-ejlPM315qwLpaQlQDTjPdsUFSc6ZsP4AN6AlWnogPjQ7CVi7PYF3YVz+CY3jE2pwYf7E/7HlDAN0rV2GxTG0HQ==", "license": "MIT", - "engines": { - "node": ">=0.8" + "dependencies": { + "@types/body-parser": "*", + "@types/express-serve-static-core": "^4.17.33", + "@types/qs": "*", + "@types/serve-static": "*" } }, - "node_modules/astral-regex": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", - "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", - "dev": true, + "node_modules/@types/express-serve-static-core": { + "version": "4.19.6", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz", + "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "@types/node": "*", + "@types/qs": "*", + "@types/range-parser": "*", + "@types/send": "*" } }, - "node_modules/async": { - "version": "3.2.6", - "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", - "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", - "dev": true, + "node_modules/@types/http-assert": { + "version": "1.5.6", + "resolved": "https://registry.npmjs.org/@types/http-assert/-/http-assert-1.5.6.tgz", + "integrity": "sha512-TTEwmtjgVbYAzZYWyeHPrrtWnfVkm8tQkP8P21uQifPgMRgjrow3XDEYqucuC8SKZJT7pUnhU/JymvjggxO9vw==", "license": "MIT" }, - "node_modules/asynckit": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", - "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "node_modules/@types/http-cache-semantics": { + "version": "4.0.4", + "resolved": "https://registry.npmjs.org/@types/http-cache-semantics/-/http-cache-semantics-4.0.4.tgz", + "integrity": "sha512-1m0bIFVc7eJWyve9S0RnuRgcQqF/Xd5QsUZAZeQFr1Q3/p9JWoQQEqmVy+DPTNpGXwhgIetAoYF8JSc33q29QA==", "license": "MIT" }, - "node_modules/at-least-node": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz", - "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==", + "node_modules/@types/http-errors": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz", + "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==", + "license": "MIT" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", "dev": true, - "license": "ISC", - "engines": { - "node": ">= 4.0.0" + "license": "MIT" + }, + "node_modules/@types/keygrip": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/keygrip/-/keygrip-1.0.6.tgz", + "integrity": "sha512-lZuNAY9xeJt7Bx4t4dx0rYCDqGPW8RXhQZK1td7d4H6E9zYbLoOtjBvfwdTKpsyxQI/2jv+armjX/RW+ZNpXOQ==", + "license": "MIT" + }, + "node_modules/@types/keyv": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/@types/keyv/-/keyv-3.1.4.tgz", + "integrity": "sha512-BQ5aZNSCpj7D6K2ksrRCTmKRLEpnPvWDiLPfoGyhZ++8YtiK9d/3DBKPJgry359X/P1PfruyYwvnvwFjuEiEIg==", + "license": "MIT", + "dependencies": { + "@types/node": "*" } }, - "node_modules/available-typed-arrays": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", - "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", + "node_modules/@types/koa": { + "version": "2.15.0", + "resolved": "https://registry.npmjs.org/@types/koa/-/koa-2.15.0.tgz", + "integrity": "sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==", "license": "MIT", "dependencies": { - "possible-typed-array-names": "^1.0.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "@types/accepts": "*", + "@types/content-disposition": "*", + "@types/cookies": "*", + "@types/http-assert": "*", + "@types/http-errors": "*", + "@types/keygrip": "*", + "@types/koa-compose": "*", + "@types/node": "*" } }, - "node_modules/await-lock": { - "version": "2.2.2", - "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz", - "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==", + "node_modules/@types/koa-compose": { + "version": "3.2.8", + "resolved": "https://registry.npmjs.org/@types/koa-compose/-/koa-compose-3.2.8.tgz", + "integrity": "sha512-4Olc63RY+MKvxMwVknCUDhRQX1pFQoBZ/lXcRLP69PQkEpze/0cr8LNqJQe5NFb/b19DWi2a5bTi2VAlQzhJuA==", + "license": "MIT", + "dependencies": { + "@types/koa": "*" + } + }, + "node_modules/@types/mime": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz", + "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==", "license": "MIT" }, - "node_modules/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==", + "node_modules/@types/minimist": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz", + "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" + "license": "MIT" + }, + "node_modules/@types/node": { + "version": "20.17.1", + "resolved": "https://registry.npmjs.org/@types/node/-/node-20.17.1.tgz", + "integrity": "sha512-j2VlPv1NnwPJbaCNv69FO/1z4lId0QmGvpT41YxitRtWlg96g/j8qcv2RKsLKe2F6OJgyXhupN1Xo17b2m139Q==", + "license": "MIT", + "dependencies": { + "undici-types": "~6.19.2" } }, - "node_modules/aws4": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.13.2.tgz", - "integrity": "sha512-lHe62zvbTB5eEABUVi/AwVh0ZKY9rMMDhmm+eeyuuUQbQ3+J+fONVQOZyj+DdrvD4BY33uYniyRJ4UJIaSKAfw==", + "node_modules/@types/normalize-package-data": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz", + "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==", "dev": true, "license": "MIT" }, - "node_modules/axios": { - "version": "0.28.1", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.28.1.tgz", - "integrity": "sha512-iUcGA5a7p0mVb4Gm/sy+FSECNkPFT4y7wt6OM/CDpO/OnNCvSs3PoMG8ibrC9jRoGYU0gUK5pXVC4NPXq6lHRQ==", + "node_modules/@types/qs": { + "version": "6.9.16", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz", + "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==", + "license": "MIT" + }, + "node_modules/@types/range-parser": { + "version": "1.2.7", + "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz", + "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==", + "license": "MIT" + }, + "node_modules/@types/readable-stream": { + "version": "4.0.16", + "resolved": "https://registry.npmjs.org/@types/readable-stream/-/readable-stream-4.0.16.tgz", + "integrity": "sha512-Fvp+8OcU8PyV90KTk5tR/rI8OjD3MP5NUow5rjOsZo+9zxf4p4soJtK9j4V6yeG30TH6rZxqRaP4JLa8lNNTNQ==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.15.0", - "form-data": "^4.0.0", - "proxy-from-env": "^1.1.0" + "@types/node": "*", + "safe-buffer": "~5.1.1" } }, - "node_modules/axios-ntlm": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/axios-ntlm/-/axios-ntlm-1.3.0.tgz", - "integrity": "sha512-NPNsIMO1SGX5scs3ZWJqsV7iRLvET+DlRl94aZ7Sx14zA8RTQh9EDxsJmxB9cKjardKfp2Vge444uYYLfvWC0Q==", + "node_modules/@types/responselike": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/@types/responselike/-/responselike-1.0.3.tgz", + "integrity": "sha512-H/+L+UkTV33uf49PH5pCAUBVPNj2nDBXTN+qS1dOwyyg24l3CcicicCA7ca+HMvJBZcFgl5r8e+RR6elsb4Lyw==", "license": "MIT", "dependencies": { - "axios": "^0.21.3", - "dev-null": "^0.1.1" + "@types/node": "*" } }, - "node_modules/axios-ntlm/node_modules/axios": { - "version": "0.21.4", - "resolved": "https://registry.npmjs.org/axios/-/axios-0.21.4.tgz", - "integrity": "sha512-ut5vewkiu8jjGBdqpM44XxjuCjq9LAKeHVmoVfHVzy8eHgxxq8SbAVQNovDA8mVi05kP0Ea/n/UzcSHcTJQfNg==", + "node_modules/@types/semver": { + "version": "7.5.8", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-7.5.8.tgz", + "integrity": "sha512-I8EUhyrgfLrcTkzV3TSsGyl1tSuPrEDzr0yd5m90UgNxQkyDXULk3b6MlQqTCpZpNtWe1K0hzclnZkTcLBe2UQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/@types/send": { + "version": "0.17.4", + "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz", + "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==", "license": "MIT", "dependencies": { - "follow-redirects": "^1.14.0" + "@types/mime": "^1", + "@types/node": "*" } }, - "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, + "node_modules/@types/serve-static": { + "version": "1.15.7", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz", + "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==", "license": "MIT", "dependencies": { - "@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" + "@types/http-errors": "*", + "@types/node": "*", + "@types/send": "*" } }, - "node_modules/babel-plugin-add-module-exports": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz", - "integrity": "sha512-3AN/9V/rKuv90NG65m4tTHsI04XrCKsWbztIcW7a8H5iIN7WlvWucRtVV0V/rT4QvtA11n5Vmp20fLwfMWqp6g==", + "node_modules/@types/ssh2": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-1.15.1.tgz", + "integrity": "sha512-ZIbEqKAsi5gj35y4P4vkJYly642wIbY6PqoN0xiyQGshKUGXR9WQjF/iF9mXBQ8uBKy3ezfsCkcoHKhd0BzuDA==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@types/node": "^18.11.18" + } }, - "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==", + "node_modules/@types/ssh2-streams": { + "version": "0.1.12", + "resolved": "https://registry.npmjs.org/@types/ssh2-streams/-/ssh2-streams-0.1.12.tgz", + "integrity": "sha512-Sy8tpEmCce4Tq0oSOYdfqaBpA3hDM8SoxoFh5vzFsu2oL+znzGz8oVWW7xb4K920yYMUY+PIG31qZnFMfPWNCg==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "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" + "@types/node": "*" } }, - "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==", + "node_modules/@types/ssh2/node_modules/@types/node": { + "version": "18.19.59", + "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.59.tgz", + "integrity": "sha512-vizm2EqwV/7Zay+A6J3tGl9Lhr7CjZe2HmWS988sefiEmsyP9CeXEleho6i4hJk/8UtZAo0bWN4QPZZr83RxvQ==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "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" + "undici-types": "~5.26.4" } }, - "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==", + "node_modules/@types/ssh2/node_modules/undici-types": { + "version": "5.26.5", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz", + "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA==", "dev": true, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "license": "MIT" + }, + "node_modules/@types/webidl-conversions": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/@types/webidl-conversions/-/webidl-conversions-7.0.3.tgz", + "integrity": "sha512-CiJJvcRtIgzadHCYXw7dqEnMNRjhGZlYK05Mj9OyktqV8uVT8fD2BFOB7S1uwBE3Kj2Z+4UyPmFw/Ixgw/LAlA==", + "license": "MIT" + }, + "node_modules/@types/whatwg-url": { + "version": "8.2.2", + "resolved": "https://registry.npmjs.org/@types/whatwg-url/-/whatwg-url-8.2.2.tgz", + "integrity": "sha512-FtQu10RWgn3D9U4aazdwIE2yzphmTJREDqNdODHrbrZmmMqI0vMheC/6NE/J1Yveaj8H+ela+YwWTjq5PGmuhA==", + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/webidl-conversions": "*" } }, - "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==", + "node_modules/@typescript-eslint/eslint-plugin": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz", + "integrity": "sha512-oy9+hTPCUFpngkEZUSzbf9MxI65wbKFoQYsgPdILTfbUldp5ovUuphZVe4i30emU9M/kP+T64Di0mxl7dSw3MA==", "dev": true, "license": "MIT", "dependencies": { - "@babel/template": "^7.3.3", - "@babel/types": "^7.3.3", - "@types/babel__core": "^7.1.14", - "@types/babel__traverse": "^7.0.6" + "@eslint-community/regexpp": "^4.5.1", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/type-utils": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "graphemer": "^1.4.0", + "ignore": "^5.2.4", + "natural-compare": "^1.4.0", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "@typescript-eslint/parser": "^6.0.0 || ^6.0.0-alpha", + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/babel-plugin-polyfill-corejs2": { - "version": "0.4.12", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.12.tgz", - "integrity": "sha512-CPWT6BwvhrTO2d8QVorhTCQw9Y43zOu7G9HigcfxvepOU6b8o3tcWad6oVgZIsZCTt42FFv97aA7ZJsbM4+8og==", + "node_modules/@typescript-eslint/parser": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-6.21.0.tgz", + "integrity": "sha512-tbsV1jPne5CkFQCgPBcDOt30ItF7aJoZL997JSF7MhGQqOeT3svWRYxiqlfA5RUdlHN6Fi+EI9bxqbdyAUZjYQ==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "@babel/compat-data": "^7.22.6", - "@babel/helper-define-polyfill-provider": "^0.6.3", - "semver": "^6.3.1" + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "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, - "license": "ISC", - "bin": { - "semver": "bin/semver.js" + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/babel-plugin-polyfill-corejs3": { - "version": "0.10.6", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz", - "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==", + "node_modules/@typescript-eslint/scope-manager": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-6.21.0.tgz", + "integrity": "sha512-OwLUIWZJry80O99zvqXVEioyniJMa+d2GrqpUTqi5/v5D5rOrppJVBPa0yKCblcigC0/aYAzxxqQ1B+DS2RYsg==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.2", - "core-js-compat": "^3.38.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0" }, - "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/babel-plugin-polyfill-regenerator": { - "version": "0.6.3", - "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.3.tgz", - "integrity": "sha512-LiWSbl4CRSIa5x/JAU6jZiG9eit9w6mz+yVMFwDE83LAWvt0AfGBoZ7HS/mkhrKuh2ZlzfVZYKoLjXdqw6Yt7Q==", + "node_modules/@typescript-eslint/type-utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-6.21.0.tgz", + "integrity": "sha512-rZQI7wHfao8qMX3Rd3xqeYSMCL3SoiSQLBATSiVKARdFGCYSRvmViieZjqc58jKgs8Y8i9YvVVhRbHSTA4VBag==", "dev": true, "license": "MIT", "dependencies": { - "@babel/helper-define-polyfill-provider": "^0.6.3" + "@typescript-eslint/typescript-estree": "6.21.0", + "@typescript-eslint/utils": "6.21.0", + "debug": "^4.3.4", + "ts-api-utils": "^1.0.1" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" }, "peerDependencies": { - "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0" + "eslint": "^7.0.0 || ^8.0.0" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/babel-preset-current-node-syntax": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz", - "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==", + "node_modules/@typescript-eslint/types": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-6.21.0.tgz", + "integrity": "sha512-1kFmZ1rOm5epu9NZEZm1kckCDGj5UJEf7P1kliH4LKu/RkwpsfqqGmY2OOcUs18lSlQBKLDYBOGxRVtrMN5lpg==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/plugin-syntax-async-generators": "^7.8.4", - "@babel/plugin-syntax-bigint": "^7.8.3", - "@babel/plugin-syntax-class-properties": "^7.12.13", - "@babel/plugin-syntax-class-static-block": "^7.14.5", - "@babel/plugin-syntax-import-attributes": "^7.24.7", - "@babel/plugin-syntax-import-meta": "^7.10.4", - "@babel/plugin-syntax-json-strings": "^7.8.3", - "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4", - "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3", - "@babel/plugin-syntax-numeric-separator": "^7.10.4", - "@babel/plugin-syntax-object-rest-spread": "^7.8.3", - "@babel/plugin-syntax-optional-catch-binding": "^7.8.3", - "@babel/plugin-syntax-optional-chaining": "^7.8.3", - "@babel/plugin-syntax-private-property-in-object": "^7.14.5", - "@babel/plugin-syntax-top-level-await": "^7.14.5" + "engines": { + "node": "^16.0.0 || >=18.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "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==", + "node_modules/@typescript-eslint/typescript-estree": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-6.21.0.tgz", + "integrity": "sha512-6npJTkZcO+y2/kr+z0hc4HwNfrrP4kNYh57ek7yCNlrBjWQ1Y0OS7jiZTkgumrvkX5HkEKXFZkkdFNkaW2wmUQ==", "dev": true, - "license": "MIT", + "license": "BSD-2-Clause", "dependencies": { - "babel-plugin-jest-hoist": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0" + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/visitor-keys": "6.21.0", + "debug": "^4.3.4", + "globby": "^11.1.0", + "is-glob": "^4.0.3", + "minimatch": "9.0.3", + "semver": "^7.5.4", + "ts-api-utils": "^1.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^16.0.0 || >=18.0.0" }, - "peerDependencies": { - "@babel/core": "^7.0.0" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependenciesMeta": { + "typescript": { + "optional": true + } } }, - "node_modules/babel-runtime": { - "version": "6.26.0", - "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", - "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "node_modules/@typescript-eslint/utils": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-6.21.0.tgz", + "integrity": "sha512-NfWVaC8HP9T8cbKQxHcsJBY5YE1O33+jpMwN45qzWWaPDZgLIbo12toGMWnmhvCpd3sIxkpDw3Wv1B3dYrbDQQ==", "dev": true, "license": "MIT", "dependencies": { - "core-js": "^2.4.0", - "regenerator-runtime": "^0.11.0" + "@eslint-community/eslint-utils": "^4.4.0", + "@types/json-schema": "^7.0.12", + "@types/semver": "^7.5.0", + "@typescript-eslint/scope-manager": "6.21.0", + "@typescript-eslint/types": "6.21.0", + "@typescript-eslint/typescript-estree": "6.21.0", + "semver": "^7.5.4" + }, + "engines": { + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" + }, + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "node_modules/babel-runtime/node_modules/core-js": { - "version": "2.6.12", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", - "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", - "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", - "dev": true, - "hasInstallScript": true, - "license": "MIT" - }, - "node_modules/babel-runtime/node_modules/regenerator-runtime": { - "version": "0.11.1", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", - "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "node_modules/@typescript-eslint/visitor-keys": { + "version": "6.21.0", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-6.21.0.tgz", + "integrity": "sha512-JJtkDduxLi9bivAB+cYOVMtbkqdPOhZ+ZI5LC47MIRrDV4Yn2o+ZnW10Nkmr28xRpSpdJ6Sm42Hjf2+REYXm0A==", "dev": true, - "license": "MIT" - }, - "node_modules/badge-maker": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/badge-maker/-/badge-maker-3.3.1.tgz", - "integrity": "sha512-OO/PS7Zg2E6qaUWzHEHt21Q5VjcFBAJVA8ztgT/fIdSZFBUwoyeo0ZhA6V5tUM8Vcjq8DJl6jfGhpjESssyqMQ==", - "license": "CC0-1.0", + "license": "MIT", "dependencies": { - "anafanafo": "2.0.0", - "css-color-converter": "^2.0.0" - }, - "bin": { - "badge": "lib/badge-cli.js" + "@typescript-eslint/types": "6.21.0", + "eslint-visitor-keys": "^3.4.1" }, "engines": { - "node": ">= 10", - "npm": ">= 5" + "node": "^16.0.0 || >=18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/typescript-eslint" } }, - "node_modules/balanced-match": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", - "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", - "license": "MIT" - }, - "node_modules/barse": { - "version": "0.4.3", - "resolved": "https://registry.npmjs.org/barse/-/barse-0.4.3.tgz", - "integrity": "sha512-UEpvriJqAn8zuVinYICuKoPttZy3XxXEoqX/V2uYAL4zzJRuNzCK3+20nAu3YUIa2U7G53kf90wfBIp9/A+Odw==", + "node_modules/@vitejs/plugin-vue": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/@vitejs/plugin-vue/-/plugin-vue-5.0.5.tgz", + "integrity": "sha512-LOjm7XeIimLBZyzinBQ6OSm3UBCNVCpLkxGC0oWmm2YPzVZoxMsdvNVimLTBzpAnR9hl/yn1SHGuRfe6/Td9rQ==", + "dev": true, "license": "MIT", - "dependencies": { - "readable-stream": "~1.0.2" + "engines": { + "node": "^18.0.0 || >=20.0.0" + }, + "peerDependencies": { + "vite": "^5.0.0", + "vue": "^3.2.25" } }, - "node_modules/barse/node_modules/isarray": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", - "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "node_modules/@vue/babel-helper-vue-transform-on": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.2.5.tgz", + "integrity": "sha512-lOz4t39ZdmU4DJAa2hwPYmKc8EsuGa2U0L9KaZaOJUt0UwQNjNA3AZTq6uEivhOKhhG1Wvy96SvYBoFmCg3uuw==", + "dev": true, "license": "MIT" }, - "node_modules/barse/node_modules/readable-stream": { - "version": "1.0.34", - "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", - "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", + "node_modules/@vue/babel-plugin-jsx": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.2.5.tgz", + "integrity": "sha512-zTrNmOd4939H9KsRIGmmzn3q2zvv1mjxkYZHgqHZgDrXz5B1Q3WyGEjO2f+JrmKghvl1JIRcvo63LgM1kH5zFg==", + "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.1", - "isarray": "0.0.1", - "string_decoder": "~0.10.x" - } - }, - "node_modules/barse/node_modules/string_decoder": { - "version": "0.10.31", - "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", - "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", - "license": "MIT" - }, - "node_modules/base64-js": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", - "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/plugin-syntax-jsx": "^7.24.7", + "@babel/template": "^7.25.0", + "@babel/traverse": "^7.25.6", + "@babel/types": "^7.25.6", + "@vue/babel-helper-vue-transform-on": "1.2.5", + "@vue/babel-plugin-resolve-type": "1.2.5", + "html-tags": "^3.3.1", + "svg-tags": "^1.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.0.0-0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true } - ], - "license": "MIT" - }, - "node_modules/base64id": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", - "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", - "license": "MIT", - "engines": { - "node": "^4.5.0 || >= 5.9" } }, - "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/@vue/babel-plugin-resolve-type": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.2.5.tgz", + "integrity": "sha512-U/ibkQrf5sx0XXRnUZD1mo5F7PkpKyTbfXM3a3rC4YnUz6crHEz9Jg09jzzL6QYlXNto/9CePdOg/c87O4Nlfg==", + "dev": true, "license": "MIT", "dependencies": { - "safe-buffer": "5.1.2" + "@babel/code-frame": "^7.24.7", + "@babel/helper-module-imports": "^7.24.7", + "@babel/helper-plugin-utils": "^7.24.8", + "@babel/parser": "^7.25.6", + "@vue/compiler-sfc": "^3.5.3" }, - "engines": { - "node": ">= 0.8" + "peerDependencies": { + "@babel/core": "^7.0.0-0" } }, - "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==", - "license": "MIT" - }, - "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==", + "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-core": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.12.tgz", + "integrity": "sha512-ISyBTRMmMYagUxhcpyEH0hpXRd/KqDU4ymofPgl2XAkY9ZhQ+h0ovEZJIiPop13UmR/54oA2cgMDjgroRelaEw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "tweetnacl": "^0.14.3" + "@babel/parser": "^7.25.3", + "@vue/shared": "3.5.12", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" } }, - "node_modules/bcryptjs": { - "version": "2.4.3", - "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", - "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", - "license": "MIT" - }, - "node_modules/before-after-hook": { - "version": "2.2.3", - "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", - "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", - "dev": true, - "license": "Apache-2.0" - }, - "node_modules/binary-extensions": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", - "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-dom": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.12.tgz", + "integrity": "sha512-9G6PbJ03uwxLHKQ3P42cMTi85lDRvGLB2rSGOiQqtXELat6uI4n8cNz9yjfVHRPIu+MsK6TE418Giruvgptckg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/binary-search": { - "version": "1.3.6", - "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", - "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==", - "license": "CC0-1.0" - }, - "node_modules/bintrees": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", - "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==", - "license": "MIT" + "dependencies": { + "@vue/compiler-core": "3.5.12", + "@vue/shared": "3.5.12" + } }, - "node_modules/bl": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", - "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", + "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-sfc": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.12.tgz", + "integrity": "sha512-2k973OGo2JuAa5+ZlekuQJtitI5CgLMOwgl94BzMCsKZCX/xiqzJYzapl4opFogKHqwJk34vfsaKpfEhd1k5nw==", + "dev": true, "license": "MIT", "dependencies": { - "buffer": "^5.5.0", - "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "@babel/parser": "^7.25.3", + "@vue/compiler-core": "3.5.12", + "@vue/compiler-dom": "3.5.12", + "@vue/compiler-ssr": "3.5.12", + "@vue/shared": "3.5.12", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.11", + "postcss": "^8.4.47", + "source-map-js": "^1.2.0" } }, - "node_modules/blob-util": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/blob-util/-/blob-util-2.0.2.tgz", - "integrity": "sha512-T7JQa+zsXXEa6/8ZhHcQEW1UFfVM49Ts65uBkFL6fz2QmrElqmbajIDJvuA0tEhRe5eIjpV9ZF+0RfZR9voJFQ==", + "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/compiler-ssr": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.12.tgz", + "integrity": "sha512-eLwc7v6bfGBSM7wZOGPmRavSWzNFF6+PdRhE+VFJhNCgHiF8AM7ccoqcv5kBXA2eWUfigD7byekvf/JsOfKvPA==", "dev": true, - "license": "Apache-2.0" + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.5.12", + "@vue/shared": "3.5.12" + } }, - "node_modules/bluebird": { - "version": "3.7.2", - "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz", - "integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==", + "node_modules/@vue/babel-plugin-resolve-type/node_modules/@vue/shared": { + "version": "3.5.12", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.12.tgz", + "integrity": "sha512-L2RPSAwUFbgZH20etwrXyVyCBu9OxRSi8T/38QsvnkJyvq2LufW2lDCOzm7t/U9C1mkhJGWYfCuFBCmIuNivrg==", "dev": true, "license": "MIT" }, - "node_modules/body-parser": { - "version": "1.20.3", - "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", - "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", + "node_modules/@vue/compiler-core": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.4.38.tgz", + "integrity": "sha512-8IQOTCWnLFqfHzOGm9+P8OPSEDukgg3Huc92qSG49if/xI2SAwLHQO2qaPQbjCWPBcQoO1WYfXfTACUrWV3c5A==", + "dev": true, "license": "MIT", "dependencies": { - "bytes": "3.1.2", - "content-type": "~1.0.5", - "debug": "2.6.9", - "depd": "2.0.0", - "destroy": "1.2.0", - "http-errors": "2.0.0", - "iconv-lite": "0.4.24", - "on-finished": "2.4.1", - "qs": "6.13.0", - "raw-body": "2.5.2", - "type-is": "~1.6.18", - "unpipe": "1.0.0" - }, - "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" + "@babel/parser": "^7.24.7", + "@vue/shared": "3.4.38", + "entities": "^4.5.0", + "estree-walker": "^2.0.2", + "source-map-js": "^1.2.0" } }, - "node_modules/body-parser/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/@vue/compiler-dom": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.4.38.tgz", + "integrity": "sha512-Osc/c7ABsHXTsETLgykcOwIxFktHfGSUDkb05V61rocEfsFDcjDLH/IHJSNJP+/Sv9KeN2Lx1V6McZzlSb9EhQ==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "2.0.0" + "@vue/compiler-core": "3.4.38", + "@vue/shared": "3.4.38" } }, - "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==", + "node_modules/@vue/compiler-sfc": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.4.38.tgz", + "integrity": "sha512-s5QfZ+9PzPh3T5H4hsQDJtI8x7zdJaew/dCGgqZ2630XdzaZ3AD8xGZfBqpT8oaD/p2eedd+pL8tD5vvt5ZYJQ==", + "dev": true, "license": "MIT", "dependencies": { - "safer-buffer": ">= 2.1.2 < 3" - }, - "engines": { - "node": ">=0.10.0" + "@babel/parser": "^7.24.7", + "@vue/compiler-core": "3.4.38", + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38", + "estree-walker": "^2.0.2", + "magic-string": "^0.30.10", + "postcss": "^8.4.40", + "source-map-js": "^1.2.0" } }, - "node_modules/body-parser/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/@vue/compiler-ssr": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.4.38.tgz", + "integrity": "sha512-YXznKFQ8dxYpAz9zLuVvfcXhc31FSPFDcqr0kyujbOwNhlmaNvL2QfIy+RZeJgSn5Fk54CWoEUeW+NVBAogGaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/compiler-dom": "3.4.38", + "@vue/shared": "3.4.38" + } + }, + "node_modules/@vue/devtools-api": { + "version": "6.6.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-api/-/devtools-api-6.6.4.tgz", + "integrity": "sha512-sGhTPMuXqZ1rVOk32RylztWkfXTRhuS7vgAKv0zjqk8gbsHkJ7xfFf+jbySxt7tWObEJwyKaHMikV/WGDiQm8g==", + "dev": true, "license": "MIT" }, - "node_modules/body-parser/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", + "node_modules/@vue/devtools-core": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-core/-/devtools-core-7.5.4.tgz", + "integrity": "sha512-igB2iUKsCUrXkp0wKLn3n5X8jz3AgXWk7if0QpLu3Do16QmlTO0e+/VvTpX0ZbLMh8OOAxDKyfPvJMMO/4QJ5w==", + "dev": true, + "license": "MIT", "dependencies": { - "side-channel": "^1.0.6" - }, - "engines": { - "node": ">=0.6" + "@vue/devtools-kit": "^7.5.4", + "@vue/devtools-shared": "^7.5.4", + "mitt": "^3.0.1", + "nanoid": "^3.3.4", + "pathe": "^1.1.2", + "vite-hot-client": "^0.2.3" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "peerDependencies": { + "vue": "^3.0.0" } }, - "node_modules/boolbase": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", - "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", - "license": "ISC" + "node_modules/@vue/devtools-kit": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-kit/-/devtools-kit-7.5.4.tgz", + "integrity": "sha512-0i7WFgc1B2TL52tstn82zlb9opSA0aIiHfkUYFXtZb8CIpmlFMTkHtgwVl6PMWNBj3LNhYou1YJCLpCYvJYYoA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-shared": "^7.5.4", + "birpc": "^0.2.19", + "hookable": "^5.5.3", + "mitt": "^3.0.1", + "perfect-debounce": "^1.0.0", + "speakingurl": "^14.0.1", + "superjson": "^2.2.1" + } }, - "node_modules/bootstrap": { - "version": "5.1.3", - "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", - "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", + "node_modules/@vue/devtools-shared": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/@vue/devtools-shared/-/devtools-shared-7.5.4.tgz", + "integrity": "sha512-dwuq4YmwTyLc7eBOqX63s3JB8il7qnKsNgENglSMkUPwiItHkVAYYfPESN1rxSdYkl1RCux1l5TBidYqfUDNAA==", "dev": true, "license": "MIT", - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/bootstrap" - }, - "peerDependencies": { - "@popperjs/core": "^2.10.2" + "dependencies": { + "rfdc": "^1.4.1" } }, - "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/@vue/reactivity": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/reactivity/-/reactivity-3.4.38.tgz", + "integrity": "sha512-4vl4wMMVniLsSYYeldAKzbk72+D3hUnkw9z8lDeJacTxAkXeDAP1uE9xr2+aKIN0ipOL8EG2GPouVTH6yF7Gnw==", + "dev": true, "license": "MIT", - "optional": true + "dependencies": { + "@vue/shared": "3.4.38" + } }, - "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==", + "node_modules/@vue/runtime-core": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/runtime-core/-/runtime-core-3.4.38.tgz", + "integrity": "sha512-21z3wA99EABtuf+O3IhdxP0iHgkBs1vuoCAsCKLVJPEjpVqvblwBnTj42vzHRlWDCyxu9ptDm7sI2ZMcWrQqlA==", + "dev": true, "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0", - "concat-map": "0.0.1" + "@vue/reactivity": "3.4.38", + "@vue/shared": "3.4.38" } }, - "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "node_modules/@vue/runtime-dom": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/runtime-dom/-/runtime-dom-3.4.38.tgz", + "integrity": "sha512-afZzmUreU7vKwKsV17H1NDThEEmdYI+GCAK/KY1U957Ig2NATPVjCROv61R19fjZNzMmiU03n79OMnXyJVN0UA==", "dev": true, "license": "MIT", "dependencies": { - "fill-range": "^7.1.1" - }, - "engines": { - "node": ">=8" + "@vue/reactivity": "3.4.38", + "@vue/runtime-core": "3.4.38", + "@vue/shared": "3.4.38", + "csstype": "^3.1.3" } }, - "node_modules/browserslist": { - "version": "4.24.3", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.3.tgz", - "integrity": "sha512-1CPmv8iobE2fyRMV97dAcMVegvvWKxmq94hkLiAkUGwKVTyDLw33K+ZxiFrREKmmps4rIw6grcCFCnTMSZ/YiA==", + "node_modules/@vue/server-renderer": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/server-renderer/-/server-renderer-3.4.38.tgz", + "integrity": "sha512-NggOTr82FbPEkkUvBm4fTGcwUY8UuTsnWC/L2YZBmvaQ4C4Jl/Ao4HHTB+l7WnFCt5M/dN3l0XLuyjzswGYVCA==", "dev": true, - "funding": [ - { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" - }, - { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/browserslist" - }, - { - "type": "github", - "url": "https://github.com/sponsors/ai" - } - ], "license": "MIT", "dependencies": { - "caniuse-lite": "^1.0.30001688", - "electron-to-chromium": "^1.5.73", - "node-releases": "^2.0.19", - "update-browserslist-db": "^1.1.1" - }, - "bin": { - "browserslist": "cli.js" + "@vue/compiler-ssr": "3.4.38", + "@vue/shared": "3.4.38" }, - "engines": { - "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + "peerDependencies": { + "vue": "3.4.38" } }, - "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==", + "node_modules/@vue/shared": { + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.4.38.tgz", + "integrity": "sha512-q0xCiLkuWWQLzVrecPb0RMsNWyxICOjPrcrwxTUEHb1fsnvni4dcuyG7RT/Ie7VPTvnjzIaWzRMUBsrqNj/hhw==", "dev": true, - "license": "Apache-2.0", + "license": "MIT" + }, + "node_modules/@vuepic/vue-datepicker": { + "version": "3.4.8", + "resolved": "https://registry.npmjs.org/@vuepic/vue-datepicker/-/vue-datepicker-3.4.8.tgz", + "integrity": "sha512-nbuMA7IgjtT99LqcjSTSUcl7omTZSB+7vYSWQ9gQm31Frm/1wn54fT1Q0HaRD9nHXX982AACbqeND4K80SKONw==", + "dev": true, + "license": "MIT", "dependencies": { - "node-int64": "^0.4.0" + "date-fns": "^2.29.2" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "vue": ">=3.2.0" } }, - "node_modules/bson": { - "version": "4.7.2", - "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", - "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", - "license": "Apache-2.0", + "node_modules/@vvo/tzdb": { + "version": "6.147.0", + "resolved": "https://registry.npmjs.org/@vvo/tzdb/-/tzdb-6.147.0.tgz", + "integrity": "sha512-naptD2MNHejOzUzqGAIR0KoDwQq0SNH07Z/HqbGF8c9JpednT/UHSfa6vfAR1velUUe64UwRGaOiVDEs7JrbYw==", + "license": "MIT" + }, + "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==", + "license": "ISC" + }, + "node_modules/abort-controller": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz", + "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==", + "license": "MIT", "dependencies": { - "buffer": "^5.6.0" + "event-target-shim": "^5.0.0" }, "engines": { - "node": ">=6.9.0" + "node": ">=6.5" } }, - "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" - } - ], + "node_modules/accepts": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz", + "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==", "license": "MIT", "dependencies": { - "base64-js": "^1.3.1", - "ieee754": "^1.1.13" + "mime-types": "~2.1.34", + "negotiator": "0.6.3" + }, + "engines": { + "node": ">= 0.6" } }, - "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==", + "node_modules/acorn": { + "version": "8.13.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.13.0.tgz", + "integrity": "sha512-8zSiw54Oxrdym50NlZ9sUusyO1Z1ZchgRLWRaK6c86XJFClyCgFKetdowBg5bKxyp/u+CDBJG4Mpp0m3HLZl9w==", + "dev": true, + "license": "MIT", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/acorn-jsx": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz", + "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==", + "dev": true, + "license": "MIT", + "peerDependencies": { + "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0" + } + }, + "node_modules/aedes": { + "version": "0.46.3", + "resolved": "https://registry.npmjs.org/aedes/-/aedes-0.46.3.tgz", + "integrity": "sha512-i3B+H74uNRhlqcs/JdrMp7e3daz4Cwls0x4yLcfjGXz2tIwnxhF6od4m86O6yyNdz/Gg3jfY3q0sc/Cz8qzg6g==", "dev": true, "license": "MIT", + "dependencies": { + "aedes-packet": "^2.3.1", + "aedes-persistence": "^8.1.3", + "bulk-write-stream": "^2.0.1", + "end-of-stream": "^1.4.4", + "fastfall": "^1.5.1", + "fastparallel": "^2.4.1", + "fastseries": "^2.0.0", + "hyperid": "^3.0.0", + "mqemitter": "^4.5.0", + "mqtt-packet": "^7.1.2", + "readable-stream": "^3.6.0", + "retimer": "^3.0.0", + "reusify": "^1.0.4", + "uuid": "^8.3.2" + }, "engines": { - "node": "*" + "node": ">=12" } }, - "node_modules/buffer-equal-constant-time": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", - "license": "BSD-3-Clause" - }, - "node_modules/buffer-from": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", - "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", - "license": "MIT" - }, - "node_modules/buildcheck": { - "version": "0.0.6", - "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", - "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", + "node_modules/aedes-packet": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/aedes-packet/-/aedes-packet-2.3.1.tgz", + "integrity": "sha512-LqBd57uc2rui2RbjycW17dylglejG26mM4ewVXGNDnVp/SUHFVEgm7d1HTmYrnSkSCNoHti042qgcTwv/F+BtQ==", "dev": true, - "optional": true, + "license": "MIT", + "dependencies": { + "mqtt-packet": "^6.3.0" + }, "engines": { - "node": ">=10.0.0" + "node": ">=8" } }, - "node_modules/bulk-write-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/bulk-write-stream/-/bulk-write-stream-2.0.1.tgz", - "integrity": "sha512-XWOLjgHtpDasHfwM8oO4df1JoZwa7/OwTsXDzh4rUTo+9CowzeOFBZz43w+H14h1fyq+xl28tVIBrdjcjj4Gug==", + "node_modules/aedes-packet/node_modules/mqtt-packet": { + "version": "6.10.0", + "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", + "integrity": "sha512-ja8+mFKIHdB1Tpl6vac+sktqy3gA8t9Mduom1BA75cI+R9AHnZOiaBQwpGiWnaVJLDGRdNhQmFaAqd7tkKSMGA==", "dev": true, "license": "MIT", "dependencies": { - "inherits": "^2.0.3", - "readable-stream": "^3.1.1" + "bl": "^4.0.2", + "debug": "^4.1.1", + "process-nextick-args": "^2.0.1" } }, - "node_modules/bytes": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", - "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "node_modules/aedes-persistence": { + "version": "8.1.3", + "resolved": "https://registry.npmjs.org/aedes-persistence/-/aedes-persistence-8.1.3.tgz", + "integrity": "sha512-VMCjEV+2g1TNJb/IlDEUy6SP9crT+QUhe2xc6UjyqrFNBNgTvHmOefXY7FxWrwmR2QA02vwg3+5p/JXkyg/Dkw==", + "dev": true, "license": "MIT", + "dependencies": { + "aedes-packet": "^2.3.1", + "from2": "^2.3.0", + "qlobber": "^5.0.3" + }, "engines": { - "node": ">= 0.8" + "node": ">=10" } }, - "node_modules/cacache": { - "version": "15.3.0", - "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", - "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", - "license": "ISC", - "optional": true, + "node_modules/agent-base": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz", + "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==", + "license": "MIT", "dependencies": { - "@npmcli/fs": "^1.0.0", - "@npmcli/move-file": "^1.0.1", - "chownr": "^2.0.0", - "fs-minipass": "^2.0.0", - "glob": "^7.1.4", - "infer-owner": "^1.0.4", - "lru-cache": "^6.0.0", - "minipass": "^3.1.1", - "minipass-collect": "^1.0.2", - "minipass-flush": "^1.0.5", - "minipass-pipeline": "^1.2.2", - "mkdirp": "^1.0.3", - "p-map": "^4.0.0", - "promise-inflight": "^1.0.1", - "rimraf": "^3.0.2", - "ssri": "^8.0.1", - "tar": "^6.0.2", - "unique-filename": "^1.1.1" + "debug": "^4.3.4" }, "engines": { - "node": ">= 10" + "node": ">= 14" } }, - "node_modules/cacache/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", + "node_modules/agentkeepalive": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz", + "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==", + "license": "MIT", "optional": true, "dependencies": { - "yallist": "^4.0.0" + "humanize-ms": "^1.2.1" }, "engines": { - "node": ">=10" + "node": ">= 8.0.0" } }, - "node_modules/cacache/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC", - "optional": true - }, - "node_modules/cacheable-lookup": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.0.4.tgz", - "integrity": "sha512-mbcDEZCkv2CZF4G01kr8eBd/5agkt9oCqz75tJMSIsquvRZ2sL6Hi5zGVKi/0OSC9oO1GHfJ2AV0ZIOY9vye0A==", + "node_modules/aggregate-error": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/aggregate-error/-/aggregate-error-3.1.0.tgz", + "integrity": "sha512-4I7Td01quW/RpocfNayFdFVk1qSuoh0E7JrbRJ16nH01HhKFQ88INq9Sd+nd72zqRySlr9BmDA8xlEJ6vJMrYA==", "license": "MIT", + "optional": true, + "dependencies": { + "clean-stack": "^2.0.0", + "indent-string": "^4.0.0" + }, "engines": { - "node": ">=10.6.0" + "node": ">=8" } }, - "node_modules/cacheable-request": { - "version": "7.0.4", - "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", - "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "node_modules/ajv": { + "version": "6.12.6", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz", + "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==", + "dev": true, "license": "MIT", "dependencies": { - "clone-response": "^1.0.2", - "get-stream": "^5.1.0", - "http-cache-semantics": "^4.0.0", - "keyv": "^4.0.0", - "lowercase-keys": "^2.0.0", - "normalize-url": "^6.0.1", - "responselike": "^2.0.0" + "fast-deep-equal": "^3.1.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" }, - "engines": { - "node": ">=8" + "funding": { + "type": "github", + "url": "https://github.com/sponsors/epoberezkin" } }, - "node_modules/cacheable-request/node_modules/lowercase-keys": { + "node_modules/anafanafo": { "version": "2.0.0", - "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", - "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", + "resolved": "https://registry.npmjs.org/anafanafo/-/anafanafo-2.0.0.tgz", + "integrity": "sha512-Nlfq7NC4AOkTJerWRIZcOAiMNtIDVIGWGvQ98O7Jl6Kr2Dk0dX5u4MqN778kSRTy5KRqchpLdF2RtLFEz9FVkQ==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "char-width-table-consumer": "^1.0.0" } }, - "node_modules/cachedir": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/cachedir/-/cachedir-2.4.0.tgz", - "integrity": "sha512-9EtFOZR8g22CL7BWjJ9BUx1+A/djkofnyW3aOXZORNW2kxoUpx2h+uN2cOqwPmFhnpVmxg+KW2OjOSgChTEvsQ==", - "dev": true, + "node_modules/ansi-regex": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz", + "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==", "license": "MIT", "engines": { - "node": ">=6" + "node": ">=8" } }, - "node_modules/call-bind": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz", - "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==", + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.0", - "es-define-property": "^1.0.0", - "get-intrinsic": "^1.2.4", - "set-function-length": "^1.2.2" + "color-convert": "^2.0.1" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/ansi-styles?sponsor=1" } }, - "node_modules/call-bind-apply-helpers": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.1.tgz", - "integrity": "sha512-BhYE+WDaywFg2TBWYNXAE+8B1ATnThNBqXHP5nQu0jWJdVvY2hvkpyB3qOmtmDePiS5/BDQ8wASEWGMWRG148g==", - "license": "MIT", + "node_modules/any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==", + "license": "MIT" + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dev": true, + "license": "ISC", "dependencies": { - "es-errors": "^1.3.0", - "function-bind": "^1.1.2" + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" }, "engines": { - "node": ">= 0.4" + "node": ">= 8" } }, - "node_modules/call-bound": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.3.tgz", - "integrity": "sha512-YTd+6wGlNlPxSuri7Y6X8tY2dmm12UMH66RpKMhiX6rsk5wXXnYgbUcOt8kiS31/AjfoTOvCsE+w8nZQLQnzHA==", + "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==", + "license": "ISC" + }, + "node_modules/archiver": { + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/archiver/-/archiver-7.0.1.tgz", + "integrity": "sha512-ZcbTaIqJOfCc03QwD468Unz/5Ir8ATtvAHsK+FdXbDIbGfihqh9mrvdcYunQzqn4HrvWWaFyaxJhGZagaJJpPQ==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "get-intrinsic": "^1.2.6" + "archiver-utils": "^5.0.2", + "async": "^3.2.4", + "buffer-crc32": "^1.0.0", + "readable-stream": "^4.0.0", + "readdir-glob": "^1.1.2", + "tar-stream": "^3.0.0", + "zip-stream": "^6.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 14" } }, - "node_modules/callsites": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", - "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", + "node_modules/archiver-utils": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/archiver-utils/-/archiver-utils-5.0.2.tgz", + "integrity": "sha512-wuLJMmIBQYCsGZgYLTy5FIB2pF6Lfb6cXMSF8Qywwk3t20zWnAi7zLcQFdKQmIB8wyZpY5ER38x08GbwtR2cLA==", "dev": true, "license": "MIT", + "dependencies": { + "glob": "^10.0.0", + "graceful-fs": "^4.2.0", + "is-stream": "^2.0.1", + "lazystream": "^1.0.0", + "lodash": "^4.17.15", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" + }, "engines": { - "node": ">=6" + "node": ">= 14" } }, - "node_modules/camelcase": { - "version": "5.3.1", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz", - "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==", + "node_modules/archiver-utils/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/camelcase-keys": { - "version": "7.0.2", - "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", - "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "node_modules/archiver-utils/node_modules/glob": { + "version": "10.4.5", + "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz", + "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "camelcase": "^6.3.0", - "map-obj": "^4.1.0", - "quick-lru": "^5.1.1", - "type-fest": "^1.2.1" + "foreground-child": "^3.1.0", + "jackspeak": "^3.1.2", + "minimatch": "^9.0.4", + "minipass": "^7.1.2", + "package-json-from-dist": "^1.0.0", + "path-scurry": "^1.11.1" }, - "engines": { - "node": ">=12" + "bin": { + "glob": "dist/esm/bin.mjs" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/camelcase-keys/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/archiver-utils/node_modules/minimatch": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", + "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", "dev": true, - "license": "MIT", + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/camelcase-keys/node_modules/type-fest": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", - "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "node_modules/archiver-utils/node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", "dev": true, - "license": "(MIT OR CC0-1.0)", + "license": "ISC", "engines": { - "node": ">=10" + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/archiver-utils/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/caniuse-lite": { - "version": "1.0.30001690", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001690.tgz", - "integrity": "sha512-5ExiE3qQN6oF8Clf8ifIDcMRCRE/dMGcETG/XGMD8/XiXm6HXQgQTh1yZYLXXpSOsEUlJm1Xr7kGULZTuGtP/w==", + "node_modules/archiver/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, "funding": [ { - "type": "opencollective", - "url": "https://opencollective.com/browserslist" + "type": "github", + "url": "https://github.com/sponsors/feross" }, { - "type": "tidelift", - "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + "type": "patreon", + "url": "https://www.patreon.com/feross" }, { - "type": "github", - "url": "https://github.com/sponsors/ai" + "type": "consulting", + "url": "https://feross.org/support" } ], - "license": "CC-BY-4.0" - }, - "node_modules/caseless": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", - "integrity": "sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==", - "dev": true, - "license": "Apache-2.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==", - "dev": true, "license": "MIT", "dependencies": { - "ansi-styles": "^4.1.0", - "supports-color": "^7.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/chalk?sponsor=1" + "base64-js": "^1.3.1", + "ieee754": "^1.2.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==", + "node_modules/archiver/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dev": true, "license": "MIT", "dependencies": { - "has-flag": "^4.0.0" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "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==", + "node_modules/are-docs-informative": { + "version": "0.0.2", + "resolved": "https://registry.npmjs.org/are-docs-informative/-/are-docs-informative-0.0.2.tgz", + "integrity": "sha512-ixiS0nLNNG5jNQzgZJNoUpBKdo9yTYZMGJ+QgT2jmjR7G7+QHRCc4v6LQ3NgE7EBJq+o0ams3waJwkrlBom8Ig==", "dev": true, "license": "MIT", + "engines": { + "node": ">=14" + } + }, + "node_modules/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==", + "deprecated": "This package is no longer supported.", + "license": "ISC", + "dependencies": { + "delegates": "^1.0.0", + "readable-stream": "^3.6.0" + }, "engines": { "node": ">=10" } }, - "node_modules/char-width-table-consumer": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/char-width-table-consumer/-/char-width-table-consumer-1.0.0.tgz", - "integrity": "sha512-Fz4UD0LBpxPgL9i29CJ5O4KANwaMnX/OhhbxzvNa332h+9+nRKyeuLw4wA51lt/ex67+/AdsoBQJF3kgX2feYQ==", + "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==", + "dev": true, + "license": "Python-2.0" + }, + "node_modules/args-parser": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/args-parser/-/args-parser-1.3.0.tgz", + "integrity": "sha512-If3Zi4BSjlQIJ9fgAhSiKi0oJtgMzSqh0H4wvl7XSeO16FKx7QqaHld8lZeEajPX7y1C5qKKeNgyrfyvmjmjUQ==", + "license": "Apache-2.0" + }, + "node_modules/array-buffer-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz", + "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==", + "dev": true, "license": "MIT", "dependencies": { - "binary-search": "^1.3.5" + "call-bind": "^1.0.5", + "is-array-buffer": "^3.0.4" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/chardet": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.4.0.tgz", - "integrity": "sha512-NpwMDdSIprbYx1CLnfbxEIarI0Z+s9MssEgggMNheGM+WD68yOhV7IEA/3r6tr0yTRgQD0HuZJDw32s99i6L+A==", + "node_modules/array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==", "license": "MIT" }, - "node_modules/chart.js": { - "version": "4.2.1", - "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.2.1.tgz", - "integrity": "sha512-6YbpQ0nt3NovAgOzbkSSeeAQu/3za1319dPUQTXn9WcOpywM8rGKxJHrhS8V8xEkAlk8YhEfjbuAPfUyp6jIsw==", + "node_modules/array-union": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz", + "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==", "dev": true, "license": "MIT", - "dependencies": { - "@kurkle/color": "^0.3.0" - }, "engines": { - "pnpm": "^7.0.0" + "node": ">=8" } }, - "node_modules/chartjs-adapter-dayjs-4": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/chartjs-adapter-dayjs-4/-/chartjs-adapter-dayjs-4-1.0.4.tgz", - "integrity": "sha512-yy9BAYW4aNzPVrCWZetbILegTRb7HokhgospPoC3b5iZ5qdlqNmXts2KdSp6AqnjkPAp/YWyHDxLvIvwt5x81w==", + "node_modules/arraybuffer.prototype.slice": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz", + "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==", "dev": true, "license": "MIT", + "dependencies": { + "array-buffer-byte-length": "^1.0.1", + "call-bind": "^1.0.5", + "define-properties": "^1.2.1", + "es-abstract": "^1.22.3", + "es-errors": "^1.2.1", + "get-intrinsic": "^1.2.3", + "is-array-buffer": "^3.0.4", + "is-shared-array-buffer": "^1.0.2" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, - "peerDependencies": { - "chart.js": ">=4.0.1", - "dayjs": "^1.9.7" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/check-more-types": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/check-more-types/-/check-more-types-2.24.0.tgz", - "integrity": "sha512-Pj779qHxV2tuapviy1bSZNEL1maXr13bPYpsvSDB68HlYcYuhlDrmGd63i0JHMCLKzc7rUSNIrpdJlhVlNwrxA==", + "node_modules/arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha512-3CYzex9M9FGQjCGMGyi6/31c8GJbgb0qGyrx5HWxPd0aCwh4cB2YjMb2Xf9UuoogrMrlO9cTqnB5rI5GHZTcUA==", "dev": true, "license": "MIT", "engines": { - "node": ">= 0.8.0" + "node": ">=0.10.0" } }, - "node_modules/check-password-strength": { - "version": "2.0.10", - "resolved": "https://registry.npmjs.org/check-password-strength/-/check-password-strength-2.0.10.tgz", - "integrity": "sha512-HRM5ICPmtnNtLnTv2QrfVkq1IxI9z3bzYpDJ1k5ixwD9HtJGHuv265R6JmHOV6r8wLhQMlULnIUVpkrC2yaiCw==", + "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==", + "dev": true, + "license": "MIT", + "dependencies": { + "safer-buffer": "~2.1.0" + } + }, + "node_modules/asn1-ber": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/asn1-ber/-/asn1-ber-1.2.2.tgz", + "integrity": "sha512-CbNem/7hxrjSiOAOOTX4iZxu+0m3jiLqlsERQwwPM1IDR/22M8IPpA1VVndCLw5KtjRYyRODbvAEIfuTogNDng==", "license": "MIT" }, - "node_modules/cheerio": { - "version": "1.0.0-rc.12", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.12.tgz", - "integrity": "sha512-VqR8m68vM46BNnuZ5NtnGBKIE/DfN0cRIzg9n40EIq9NOv90ayxLBXA8fXC5gquFRGJSTRqBq25Jt2ECLR431Q==", + "node_modules/astral-regex": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-2.0.0.tgz", + "integrity": "sha512-Z7tMw1ytTXt5jqMcOP+OQteU1VuNK9Y02uuJtKQ1Sv69jXQKKg5cibLwGJow8yzZP+eAc18EmLGPal0bp36rvQ==", + "dev": true, "license": "MIT", - "dependencies": { - "cheerio-select": "^2.1.0", - "dom-serializer": "^2.0.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "htmlparser2": "^8.0.1", - "parse5": "^7.0.0", - "parse5-htmlparser2-tree-adapter": "^7.0.0" - }, "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + "node": ">=8" } }, - "node_modules/cheerio-select": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", - "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", - "license": "BSD-2-Clause", - "dependencies": { - "boolbase": "^1.0.0", - "css-select": "^5.1.0", - "css-what": "^6.1.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" - } + "node_modules/async": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz", + "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==", + "dev": true, + "license": "MIT" + }, + "node_modules/async-lock": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/async-lock/-/async-lock-1.4.1.tgz", + "integrity": "sha512-Az2ZTpuytrtqENulXwO3GGv1Bztugx6TT37NIo7imr/Qo0gsYiGtSdBa2B6fsXhTpVZDNfu1Qn3pk531e3q+nQ==", + "dev": true, + "license": "MIT" }, - "node_modules/chokidar": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", - "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "node_modules/asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==", + "license": "MIT" + }, + "node_modules/available-typed-arrays": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz", + "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==", "dev": true, "license": "MIT", "dependencies": { - "anymatch": "~3.1.2", - "braces": "~3.0.2", - "glob-parent": "~5.1.2", - "is-binary-path": "~2.1.0", - "is-glob": "~4.0.1", - "normalize-path": "~3.0.0", - "readdirp": "~3.6.0" + "possible-typed-array-names": "^1.0.0" }, "engines": { - "node": ">= 8.10.0" + "node": ">= 0.4" }, "funding": { - "url": "https://paulmillr.com/funding/" - }, - "optionalDependencies": { - "fsevents": "~2.3.2" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/chokidar/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", - "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" - } + "node_modules/await-lock": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/await-lock/-/await-lock-2.2.2.tgz", + "integrity": "sha512-aDczADvlvTGajTDjcjpJMqRkOF6Qdz3YbPZm/PyW6tKPkx2hlYBzxMhEywM/tU72HrVZjgl5VCdRuMlA7pZ8Gw==", + "license": "MIT" }, - "node_modules/chownr": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", - "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", - "license": "ISC", + "node_modules/aws-ssl-profiles": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/aws-ssl-profiles/-/aws-ssl-profiles-1.1.2.tgz", + "integrity": "sha512-NZKeq9AfyQvEeNlN0zSYAaWrmBffJh3IELMZfRpJVWgrpEbtEpnjvzqBPf+mxoI287JohRDoa+/nsfqqiZmF6g==", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 6.0.0" } }, - "node_modules/chroma-js": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", - "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==", - "license": "(BSD-3-Clause AND Apache-2.0)" - }, - "node_modules/ci-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-4.1.0.tgz", - "integrity": "sha512-HutrvTNsF48wnxkzERIXOe5/mlcfFcbfCmwcg6CJnizbSue78AbDt+1cgl26zwn61WFxhcPykPfZrbqjGmBb4A==", - "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], + "node_modules/axios": { + "version": "0.28.1", + "resolved": "https://registry.npmjs.org/axios/-/axios-0.28.1.tgz", + "integrity": "sha512-iUcGA5a7p0mVb4Gm/sy+FSECNkPFT4y7wt6OM/CDpO/OnNCvSs3PoMG8ibrC9jRoGYU0gUK5pXVC4NPXq6lHRQ==", "license": "MIT", - "engines": { - "node": ">=8" + "dependencies": { + "follow-redirects": "^1.15.0", + "form-data": "^4.0.0", + "proxy-from-env": "^1.1.0" } }, - "node_modules/cjs-module-lexer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz", - "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==", + "node_modules/b4a": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/b4a/-/b4a-1.6.7.tgz", + "integrity": "sha512-OnAYlL5b7LEkALw87fUVafQw5rVR9RjwGd4KUwNQ6DrrNmaVaUCgLipfVlzrPQ4tWOR9P0IXGNOx50jYCCdSJg==", + "dev": true, + "license": "Apache-2.0" + }, + "node_modules/babel-plugin-add-module-exports": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/babel-plugin-add-module-exports/-/babel-plugin-add-module-exports-0.2.1.tgz", + "integrity": "sha512-3AN/9V/rKuv90NG65m4tTHsI04XrCKsWbztIcW7a8H5iIN7WlvWucRtVV0V/rT4QvtA11n5Vmp20fLwfMWqp6g==", "dev": true, "license": "MIT" }, - "node_modules/clean-stack": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", - "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", - "devOptional": true, + "node_modules/babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==", + "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" } }, - "node_modules/cli-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz", - "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==", + "node_modules/babel-runtime/node_modules/core-js": { + "version": "2.6.12", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz", + "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==", + "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.", "dev": true, - "license": "MIT", + "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/babel-runtime/node_modules/regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==", + "dev": true, + "license": "MIT" + }, + "node_modules/badge-maker": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/badge-maker/-/badge-maker-3.3.1.tgz", + "integrity": "sha512-OO/PS7Zg2E6qaUWzHEHt21Q5VjcFBAJVA8ztgT/fIdSZFBUwoyeo0ZhA6V5tUM8Vcjq8DJl6jfGhpjESssyqMQ==", + "license": "CC0-1.0", "dependencies": { - "restore-cursor": "^3.1.0" + "anafanafo": "2.0.0", + "css-color-converter": "^2.0.0" + }, + "bin": { + "badge": "lib/badge-cli.js" }, "engines": { - "node": ">=8" + "node": ">= 10", + "npm": ">= 5" } }, - "node_modules/cli-table3": { - "version": "0.6.5", - "resolved": "https://registry.npmjs.org/cli-table3/-/cli-table3-0.6.5.tgz", - "integrity": "sha512-+W/5efTR7y5HRD7gACw9yQjqMVvEMLBHmboM/kPWam+H+Hmyrgjh6YncVKK122YZkXrLudzTuAukUw9FnMf7IQ==", + "node_modules/balanced-match": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz", + "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==", + "license": "MIT" + }, + "node_modules/bare-events": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/bare-events/-/bare-events-2.5.0.tgz", + "integrity": "sha512-/E8dDe9dsbLyh2qrZ64PEPadOQ0F4gbl1sUJOrmph7xOiIxfY8vwab/4bFLh4Y88/Hk/ujKcrQKc+ps0mv873A==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-fs": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/bare-fs/-/bare-fs-2.3.5.tgz", + "integrity": "sha512-SlE9eTxifPDJrT6YgemQ1WGFleevzwY+XAP1Xqgl56HtcrisC2CHCZ2tq6dBpcH2TnNxwUEUGhweo+lrQtYuiw==", + "dev": true, + "license": "Apache-2.0", + "optional": true, "dependencies": { - "string-width": "^4.2.0" - }, - "engines": { - "node": "10.* || >= 12.*" - }, - "optionalDependencies": { - "@colors/colors": "1.5.0" + "bare-events": "^2.0.0", + "bare-path": "^2.0.0", + "bare-stream": "^2.0.0" } }, - "node_modules/cli-truncate": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-2.1.0.tgz", - "integrity": "sha512-n8fOixwDD6b/ObinzTrp1ZKFzbgvKZvuz/TvejnLn1aQfC6r52XEx85FmuC+3HI+JM7coBRXUvNqEU2PHVrHpg==", + "node_modules/bare-os": { + "version": "2.4.4", + "resolved": "https://registry.npmjs.org/bare-os/-/bare-os-2.4.4.tgz", + "integrity": "sha512-z3UiI2yi1mK0sXeRdc4O1Kk8aOa/e+FNWZcTiPB/dfTWyLypuE99LibgRaQki914Jq//yAWylcAt+mknKdixRQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", + "optional": true + }, + "node_modules/bare-path": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/bare-path/-/bare-path-2.1.3.tgz", + "integrity": "sha512-lh/eITfU8hrj9Ru5quUp0Io1kJWIk1bTjzo7JH1P5dWmQ2EL4hFUlfI8FonAhSlgIfhn63p84CDY/x+PisgcXA==", + "dev": true, + "license": "Apache-2.0", + "optional": true, "dependencies": { - "slice-ansi": "^3.0.0", - "string-width": "^4.2.0" - }, - "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "bare-os": "^2.1.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==", - "license": "ISC", + "node_modules/bare-stream": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/bare-stream/-/bare-stream-2.3.2.tgz", + "integrity": "sha512-EFZHSIBkDgSHIwj2l2QZfP4U5OcD4xFAOwhSb/vlr9PIqyGJGvB/nfClJbcnh3EY4jtPE4zsb5ztae96bVF79A==", + "dev": true, + "license": "Apache-2.0", + "optional": true, "dependencies": { - "string-width": "^4.2.0", - "strip-ansi": "^6.0.1", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=12" + "streamx": "^2.20.0" } }, - "node_modules/clone-response": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", - "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", + "node_modules/barse": { + "version": "0.4.3", + "resolved": "https://registry.npmjs.org/barse/-/barse-0.4.3.tgz", + "integrity": "sha512-UEpvriJqAn8zuVinYICuKoPttZy3XxXEoqX/V2uYAL4zzJRuNzCK3+20nAu3YUIa2U7G53kf90wfBIp9/A+Odw==", "license": "MIT", "dependencies": { - "mimic-response": "^1.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "readable-stream": "~1.0.2" } }, - "node_modules/cluster-key-slot": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", - "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10.0" - } + "node_modules/barse/node_modules/isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==", + "license": "MIT" }, - "node_modules/co": { - "version": "4.6.0", - "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", - "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==", - "dev": true, + "node_modules/barse/node_modules/readable-stream": { + "version": "1.0.34", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz", + "integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==", "license": "MIT", - "engines": { - "iojs": ">= 1.0.0", - "node": ">= 0.12.0" + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" } }, - "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/barse/node_modules/string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==", "license": "MIT" }, - "node_modules/color-convert": { + "node_modules/base64-js": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/base64-js/-/base64-js-1.5.1.tgz", + "integrity": "sha512-AKpaYlHn8t4SVbOHCy+b5+KKgvR4vrsD8vbvrbiQJps7fKDTkjkDry6ji0rUJjC0kzbNePLwzxq8iypo41qeWA==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" + }, + "node_modules/base64id": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/base64id/-/base64id-2.0.0.tgz", + "integrity": "sha512-lGe34o6EHj9y3Kts9R4ZYs/Gr+6N7MCaMlIFA3F1R2O5/m7K06AxfSeO5530PEERE6/WyEg3lsuyw4GHlPZHog==", + "license": "MIT", + "engines": { + "node": "^4.5.0 || >= 5.9" + } + }, + "node_modules/basic-auth": { "version": "2.0.1", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz", - "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", "license": "MIT", "dependencies": { - "color-name": "~1.1.4" + "safe-buffer": "5.1.2" }, "engines": { - "node": ">=7.0.0" + "node": ">= 0.8" } }, - "node_modules/color-name": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", - "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", - "license": "MIT" - }, - "node_modules/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==", - "license": "ISC", - "bin": { - "color-support": "bin.js" + "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==", + "dev": true, + "license": "BSD-3-Clause", + "dependencies": { + "tweetnacl": "^0.14.3" } }, - "node_modules/colord": { - "version": "2.9.3", - "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", - "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", - "dev": true, + "node_modules/bcryptjs": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/bcryptjs/-/bcryptjs-2.4.3.tgz", + "integrity": "sha512-V/Hy/X9Vt7f3BbPJEi8BdVFMByHi+jNXrYkW3huaybV/kQ0KJg0Y6PkEMbn+zeT+i+SiKZ/HMqJGIIt4LZDqNQ==", "license": "MIT" }, - "node_modules/colorette": { - "version": "2.0.20", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz", - "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==", + "node_modules/before-after-hook": { + "version": "2.2.3", + "resolved": "https://registry.npmjs.org/before-after-hook/-/before-after-hook-2.2.3.tgz", + "integrity": "sha512-NzUnlZexiaH/46WDhANlyR2bXRopNg4F/zuSA3OpZnllCUgRaOF2znDioDWrmbNVsuZk6l9pMquQB38cfBZwkQ==", "dev": true, - "license": "MIT" + "license": "Apache-2.0" }, - "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==", + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "dev": true, "license": "MIT", - "dependencies": { - "delayed-stream": "~1.0.0" - }, "engines": { - "node": ">= 0.8" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/command-exists": { - "version": "1.2.9", - "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", - "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "node_modules/binary-search": { + "version": "1.3.6", + "resolved": "https://registry.npmjs.org/binary-search/-/binary-search-1.3.6.tgz", + "integrity": "sha512-nbE1WxOTTrUWIfsfZ4aHGYu5DOuNkbxGokjV6Z2kxfJK3uaAb8zNK1muzOeipoLHZjInT4Br88BHpzevc681xA==", + "license": "CC0-1.0" + }, + "node_modules/bintrees": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bintrees/-/bintrees-1.0.2.tgz", + "integrity": "sha512-VOMgTMwjAaUG580SXn3LacVgjurrbMme7ZZNYGSSV7mmtY6QQRh0Eg3pwIcntQ77DErK1L0NxkbetjcoXzVwKw==", "license": "MIT" }, - "node_modules/commander": { - "version": "6.2.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", - "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "node_modules/birpc": { + "version": "0.2.19", + "resolved": "https://registry.npmjs.org/birpc/-/birpc-0.2.19.tgz", + "integrity": "sha512-5WeXXAvTmitV1RqJFppT5QtUiz2p1mRSYU000Jkft5ZUCLJIk4uQriYNO50HknxKwM6jd8utNc66K1qGIwwWBQ==", + "dev": true, "license": "MIT", - "engines": { - "node": ">= 6" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/commist": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", - "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", + "node_modules/bl": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz", + "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==", "license": "MIT", "dependencies": { - "leven": "^2.1.0", - "minimist": "^1.1.0" - } - }, - "node_modules/commist/node_modules/leven": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", - "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==", - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/common-tags": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/common-tags/-/common-tags-1.8.2.tgz", - "integrity": "sha512-gk/Z852D2Wtb//0I+kRFNKKE9dIIVirjoqPoA1wJU+XePVXZfGeBpk45+A1rKO4Q43prqWBNY/MiIeRLbPWUaA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4.0.0" + "buffer": "^5.5.0", + "inherits": "^2.0.4", + "readable-stream": "^3.4.0" } }, - "node_modules/compare-versions": { - "version": "3.6.0", - "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", - "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", - "license": "MIT" - }, - "node_modules/compressible": { - "version": "2.0.18", - "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", - "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", + "node_modules/body-parser": { + "version": "1.20.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.3.tgz", + "integrity": "sha512-7rAxByjUMqQ3/bHJy7D6OGXvx/MMc4IqBn/X0fcM1QUcAItpZrBEYhWGem+tzXH90c+G01ypMcYJBO9Y30203g==", "license": "MIT", "dependencies": { - "mime-db": ">= 1.43.0 < 2" + "bytes": "3.1.2", + "content-type": "~1.0.5", + "debug": "2.6.9", + "depd": "2.0.0", + "destroy": "1.2.0", + "http-errors": "2.0.0", + "iconv-lite": "0.4.24", + "on-finished": "2.4.1", + "qs": "6.13.0", + "raw-body": "2.5.2", + "type-is": "~1.6.18", + "unpipe": "1.0.0" }, "engines": { - "node": ">= 0.6" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/compression": { - "version": "1.7.5", - "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.5.tgz", - "integrity": "sha512-bQJ0YRck5ak3LgtnpKkiabX5pNF7tMUh1BSy2ZBOTh0Dim0BUu6aPPwByIns6/A5Prh8PufSPerMDUklpzes2Q==", + "node_modules/body-parser/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", "license": "MIT", - "dependencies": { - "bytes": "3.1.2", - "compressible": "~2.0.18", - "debug": "2.6.9", - "negotiator": "~0.6.4", - "on-headers": "~1.0.2", - "safe-buffer": "5.2.1", - "vary": "~1.1.2" - }, "engines": { - "node": ">= 0.8.0" + "node": ">= 0.8" } }, - "node_modules/compression/node_modules/debug": { + "node_modules/body-parser/node_modules/debug": { "version": "2.6.9", "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", @@ -8435,1597 +5975,1434 @@ "ms": "2.0.0" } }, - "node_modules/compression/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" - }, - "node_modules/concat-map": { - "version": "0.0.1", - "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", - "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", - "license": "MIT" - }, - "node_modules/concat-stream": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", - "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", - "engines": [ - "node >= 6.0" - ], - "license": "MIT", - "dependencies": { - "buffer-from": "^1.0.0", - "inherits": "^2.0.3", - "readable-stream": "^3.0.2", - "typedarray": "^0.0.6" - } - }, - "node_modules/concurrently": { - "version": "7.6.0", - "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", - "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "date-fns": "^2.29.1", - "lodash": "^4.17.21", - "rxjs": "^7.0.0", - "shell-quote": "^1.7.3", - "spawn-command": "^0.0.2-1", - "supports-color": "^8.1.0", - "tree-kill": "^1.2.2", - "yargs": "^17.3.1" - }, - "bin": { - "conc": "dist/bin/concurrently.js", - "concurrently": "dist/bin/concurrently.js" - }, - "engines": { - "node": "^12.20.0 || ^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==", - "license": "ISC" - }, - "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/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==", "license": "MIT", "dependencies": { - "safe-buffer": "5.2.1" + "safer-buffer": ">= 2.1.2 < 3" }, "engines": { - "node": ">= 0.6" - } - }, - "node_modules/content-type": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", - "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": ">=0.10.0" } }, - "node_modules/convert-source-map": { + "node_modules/body-parser/node_modules/ms": { "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, + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", "license": "MIT" }, - "node_modules/cookie": { - "version": "0.7.1", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", - "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", - "license": "MIT", + "node_modules/body-parser/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", + "dependencies": { + "side-channel": "^1.0.6" + }, "engines": { - "node": ">= 0.6" + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cookie-signature": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", - "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", - "license": "MIT" + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==", + "license": "ISC" }, - "node_modules/core-js": { - "version": "3.26.1", - "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz", - "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==", + "node_modules/bootstrap": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/bootstrap/-/bootstrap-5.1.3.tgz", + "integrity": "sha512-fcQztozJ8jToQWXxVuEyXWW+dSo8AiXWKwiSSrKWsRB/Qt+Ewwza+JWoLKiTuQLaEPhdNAJ7+Dosc9DOIqNy7Q==", "dev": true, - "hasInstallScript": true, "license": "MIT", "funding": { "type": "opencollective", - "url": "https://opencollective.com/core-js" + "url": "https://opencollective.com/bootstrap" + }, + "peerDependencies": { + "@popperjs/core": "^2.10.2" } }, - "node_modules/core-js-compat": { - "version": "3.39.0", - "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.39.0.tgz", - "integrity": "sha512-VgEUx3VwlExr5no0tXlBt+silBvhTryPwCXRI2Id1PN8WTKu7MreethvddqOubrYxkFdv/RnYrqlv1sFNAUelw==", - "dev": true, + "node_modules/bowser": { + "version": "2.11.0", + "resolved": "https://registry.npmjs.org/bowser/-/bowser-2.11.0.tgz", + "integrity": "sha512-AlcaJBi/pqqJBIQ8U9Mcpc9i8Aqxn88Skv5d+xBX006BY5u8N3mGLHa5Lgppa7L/HfwgwLgZ6NYs+Ag6uUmJRA==", + "license": "MIT", + "optional": true + }, + "node_modules/brace-expansion": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "license": "MIT", "dependencies": { - "browserslist": "^4.24.2" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/core-js" + "balanced-match": "^1.0.0" } }, - "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==", - "license": "MIT" - }, - "node_modules/cors": { - "version": "2.8.5", - "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", - "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dev": true, "license": "MIT", "dependencies": { - "object-assign": "^4", - "vary": "^1" + "fill-range": "^7.1.1" }, "engines": { - "node": ">= 0.10" + "node": ">=8" } }, - "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==", + "node_modules/browserslist": { + "version": "4.24.2", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz", + "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==", "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], "license": "MIT", "dependencies": { - "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" + "caniuse-lite": "^1.0.30001669", + "electron-to-chromium": "^1.5.41", + "node-releases": "^2.0.18", + "update-browserslist-db": "^1.1.1" }, - "peerDependencies": { - "typescript": ">=4.9.5" + "bin": { + "browserslist": "cli.js" }, - "peerDependenciesMeta": { - "typescript": { - "optional": true - } + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" } }, - "node_modules/cpu-features": { - "version": "0.0.10", - "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", - "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", - "dev": true, - "hasInstallScript": true, - "optional": true, + "node_modules/bson": { + "version": "4.7.2", + "resolved": "https://registry.npmjs.org/bson/-/bson-4.7.2.tgz", + "integrity": "sha512-Ry9wCtIZ5kGqkJoi6aD8KjxFZEx78guTQDnpXWiNthsxzrxAK/i8E6pCHAIZTbaEFWcOCvbecMukfK7XUvyLpQ==", + "license": "Apache-2.0", "dependencies": { - "buildcheck": "~0.0.6", - "nan": "^2.19.0" + "buffer": "^5.6.0" }, "engines": { - "node": ">=10.0.0" + "node": ">=6.9.0" } }, - "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, + "node_modules/buffer": { + "version": "5.7.1", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz", + "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT", "dependencies": { - "@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" - }, + "base64-js": "^1.3.1", + "ieee754": "^1.1.13" + } + }, + "node_modules/buffer-crc32": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/buffer-crc32/-/buffer-crc32-1.0.0.tgz", + "integrity": "sha512-Db1SbgBS/fg/392AblrMJk97KggmvYhr4pB5ZIMTWtaivCPMWLkmb7m21cJvpvgK+J3nsU2CmmixNBZx4vFj/w==", + "dev": true, + "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8.0.0" } }, - "node_modules/croner": { - "version": "6.0.7", - "resolved": "https://registry.npmjs.org/croner/-/croner-6.0.7.tgz", - "integrity": "sha512-k3Xx3Rcclfr60Yx4TmvsF3Yscuiql8LSvYLaphTsaq5Hk8La4Z/udmUANMOTKpgGGroI2F6/XOr9cU9OFkYluQ==", + "node_modules/buffer-equal-constant-time": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", + "integrity": "sha512-zRpUiDwd/xk6ADqPMATG8vc9VPrkck7T07OIx0gnjmJAnHnTVXNQG3vfvWNuiZIkwu9KrKdA1iJKfsfTVxE6NA==", + "license": "BSD-3-Clause" + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==", + "license": "MIT" + }, + "node_modules/buildcheck": { + "version": "0.0.6", + "resolved": "https://registry.npmjs.org/buildcheck/-/buildcheck-0.0.6.tgz", + "integrity": "sha512-8f9ZJCUXyT1M35Jx7MkBgmBMo3oHTTBIPLiY9xyL0pl3T5RwcPEY8cUHr5LBNfu/fk6c2T4DJZuVM/8ZZT2D2A==", + "dev": true, + "optional": true, + "engines": { + "node": ">=10.0.0" + } + }, + "node_modules/builtin-modules": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-3.3.0.tgz", + "integrity": "sha512-zhaCDicdLuWN5UbN5IMnFqNMhNfo919sH85y2/ea+5Yg9TsTkeZxpL+JLbp6cgYFS4sRLp3YV4S6yDuqVWHYOw==", + "dev": true, "license": "MIT", "engines": { - "node": ">=6.0" + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cronstrue": { - "version": "2.24.0", - "resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-2.24.0.tgz", - "integrity": "sha512-A1of24mAGz+OWrdGsxT9BOnDqn2ba182hie8Jx0UcEC2t+ZKtfAJxaFntKUgR7sIisU297fgHBSlNhMIfvAkSA==", + "node_modules/bulk-write-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/bulk-write-stream/-/bulk-write-stream-2.0.1.tgz", + "integrity": "sha512-XWOLjgHtpDasHfwM8oO4df1JoZwa7/OwTsXDzh4rUTo+9CowzeOFBZz43w+H14h1fyq+xl28tVIBrdjcjj4Gug==", "dev": true, "license": "MIT", - "bin": { - "cronstrue": "bin/cli.js" + "dependencies": { + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" } }, - "node_modules/cross-env": { - "version": "7.0.3", - "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", - "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.1" - }, - "bin": { - "cross-env": "src/bin/cross-env.js", - "cross-env-shell": "src/bin/cross-env-shell.js" + "run-applescript": "^7.0.0" }, "engines": { - "node": ">=10.14", - "npm": ">=6", - "yarn": ">=1" + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cross-spawn": { - "version": "7.0.6", - "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz", - "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==", + "node_modules/byline": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/byline/-/byline-5.0.0.tgz", + "integrity": "sha512-s6webAy+R4SR8XVuJWt2V2rGvhnrhxN+9S15GNuTK3wKPOXFF6RNc+8ug2XhH+2s4f+uudG4kUVYmYOQWL2g0Q==", + "dev": true, "license": "MIT", - "dependencies": { - "path-key": "^3.1.0", - "shebang-command": "^2.0.0", - "which": "^2.0.1" - }, "engines": { - "node": ">= 8" + "node": ">=0.10.0" } }, - "node_modules/css-color-converter": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/css-color-converter/-/css-color-converter-2.0.0.tgz", - "integrity": "sha512-oLIG2soZz3wcC3aAl/7Us5RS8Hvvc6I8G8LniF/qfMmrm7fIKQ8RIDDRZeKyGL2SrWfNqYspuLShbnjBMVWm8g==", + "node_modules/bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==", "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/cacache": { + "version": "15.3.0", + "resolved": "https://registry.npmjs.org/cacache/-/cacache-15.3.0.tgz", + "integrity": "sha512-VVdYzXEn+cnbXpFgWs5hTT7OScegHVmLhJIR8Ufqk3iFD6A6j5iSX1KuBTfNEv4tdJWE2PzA6IVFtcLC7fN9wQ==", + "license": "ISC", + "optional": true, "dependencies": { - "color-convert": "^0.5.2", - "color-name": "^1.1.4", - "css-unit-converter": "^1.1.2" + "@npmcli/fs": "^1.0.0", + "@npmcli/move-file": "^1.0.1", + "chownr": "^2.0.0", + "fs-minipass": "^2.0.0", + "glob": "^7.1.4", + "infer-owner": "^1.0.4", + "lru-cache": "^6.0.0", + "minipass": "^3.1.1", + "minipass-collect": "^1.0.2", + "minipass-flush": "^1.0.5", + "minipass-pipeline": "^1.2.2", + "mkdirp": "^1.0.3", + "p-map": "^4.0.0", + "promise-inflight": "^1.0.1", + "rimraf": "^3.0.2", + "ssri": "^8.0.1", + "tar": "^6.0.2", + "unique-filename": "^1.1.1" + }, + "engines": { + "node": ">= 10" } }, - "node_modules/css-color-converter/node_modules/color-convert": { - "version": "0.5.3", - "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", - "integrity": "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling==" - }, - "node_modules/css-functions-list": { - "version": "3.2.3", - "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", - "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", - "dev": true, + "node_modules/cacheable-lookup": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/cacheable-lookup/-/cacheable-lookup-6.1.0.tgz", + "integrity": "sha512-KJ/Dmo1lDDhmW2XDPMo+9oiy/CeqosPguPCrgcVzKyZrL6pM1gU2GmPY/xo6OQPTUaA/c0kwHuywB4E6nmT9ww==", "license": "MIT", "engines": { - "node": ">=12 || >=16" + "node": ">=10.6.0" } }, - "node_modules/css-select": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", - "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", - "license": "BSD-2-Clause", + "node_modules/cacheable-request": { + "version": "7.0.4", + "resolved": "https://registry.npmjs.org/cacheable-request/-/cacheable-request-7.0.4.tgz", + "integrity": "sha512-v+p6ongsrp0yTGbJXjgxPow2+DL93DASP4kXCDKb8/bwRtt9OEF3whggkkDkGNzgcWy2XaF4a8nZglC7uElscg==", + "license": "MIT", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.1.0", - "domhandler": "^5.0.2", - "domutils": "^3.0.1", - "nth-check": "^2.0.1" + "clone-response": "^1.0.2", + "get-stream": "^5.1.0", + "http-cache-semantics": "^4.0.0", + "keyv": "^4.0.0", + "lowercase-keys": "^2.0.0", + "normalize-url": "^6.0.1", + "responselike": "^2.0.0" }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "engines": { + "node": ">=8" } }, - "node_modules/css-tree": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", - "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", - "dev": true, + "node_modules/cacheable-request/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==", "license": "MIT", "dependencies": { - "mdn-data": "2.0.30", - "source-map-js": "^1.0.1" + "pump": "^3.0.0" }, "engines": { - "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" - } - }, - "node_modules/css-unit-converter": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", - "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==", - "license": "MIT" - }, - "node_modules/css-what": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", - "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">= 6" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/cssesc": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", - "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", - "dev": true, + "node_modules/cacheable-request/node_modules/lowercase-keys": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/lowercase-keys/-/lowercase-keys-2.0.0.tgz", + "integrity": "sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA==", "license": "MIT", - "bin": { - "cssesc": "bin/cssesc" - }, "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/csstype": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", - "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", - "dev": true, - "license": "MIT" - }, - "node_modules/cypress": { - "version": "13.17.0", - "resolved": "https://registry.npmjs.org/cypress/-/cypress-13.17.0.tgz", - "integrity": "sha512-5xWkaPurwkIljojFidhw8lFScyxhtiFHl/i/3zov+1Z5CmY4t9tjIdvSXfu82Y3w7wt0uR9KkucbhkVvJZLQSA==", - "dev": true, - "hasInstallScript": true, + "node_modules/call-bind": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz", + "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==", "license": "MIT", "dependencies": { - "@cypress/request": "^3.0.6", - "@cypress/xvfb": "^1.2.4", - "@types/sinonjs__fake-timers": "8.1.1", - "@types/sizzle": "^2.3.2", - "arch": "^2.2.0", - "blob-util": "^2.0.2", - "bluebird": "^3.7.2", - "buffer": "^5.7.1", - "cachedir": "^2.3.0", - "chalk": "^4.1.0", - "check-more-types": "^2.24.0", - "ci-info": "^4.0.0", - "cli-cursor": "^3.1.0", - "cli-table3": "~0.6.1", - "commander": "^6.2.1", - "common-tags": "^1.8.0", - "dayjs": "^1.10.4", - "debug": "^4.3.4", - "enquirer": "^2.3.6", - "eventemitter2": "6.4.7", - "execa": "4.1.0", - "executable": "^4.1.1", - "extract-zip": "2.0.1", - "figures": "^3.2.0", - "fs-extra": "^9.1.0", - "getos": "^3.2.1", - "is-installed-globally": "~0.4.0", - "lazy-ass": "^1.6.0", - "listr2": "^3.8.3", - "lodash": "^4.17.21", - "log-symbols": "^4.0.0", - "minimist": "^1.2.8", - "ospath": "^1.2.2", - "pretty-bytes": "^5.6.0", - "process": "^0.11.10", - "proxy-from-env": "1.0.0", - "request-progress": "^3.0.0", - "semver": "^7.5.3", - "supports-color": "^8.1.1", - "tmp": "~0.2.3", - "tree-kill": "1.2.2", - "untildify": "^4.0.0", - "yauzl": "^2.10.0" - }, - "bin": { - "cypress": "bin/cypress" + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "get-intrinsic": "^1.2.4", + "set-function-length": "^1.2.1" }, "engines": { - "node": "^16.0.0 || ^18.0.0 || >=20.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/cypress/node_modules/proxy-from-env": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.0.0.tgz", - "integrity": "sha512-F2JHgJQ1iqwnHDcQjVBsq3n/uoaFL+iPW/eAeL7kVxy/2RrWaN4WroKjjvbsoRtv0ftelNyC01bjRhn/bhcf4A==", + "node_modules/callsites": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz", + "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==", "dev": true, - "license": "MIT" + "license": "MIT", + "engines": { + "node": ">=6" + } }, - "node_modules/dashdash": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", - "integrity": "sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==", + "node_modules/camelcase": { + "version": "6.3.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", + "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", "dev": true, "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0" - }, "engines": { - "node": ">=0.10" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/data-view-buffer": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz", - "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==", + "node_modules/camelcase-keys": { + "version": "7.0.2", + "resolved": "https://registry.npmjs.org/camelcase-keys/-/camelcase-keys-7.0.2.tgz", + "integrity": "sha512-Rjs1H+A9R+Ig+4E/9oyB66UC5Mj9Xq3N//vcLf2WzgdTi/3gUu3Z9KoqmlrEG4VuuLK8wJHofxzdQXz/knhiYg==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" + "camelcase": "^6.3.0", + "map-obj": "^4.1.0", + "quick-lru": "^5.1.1", + "type-fest": "^1.2.1" }, "engines": { - "node": ">= 0.4" + "node": ">=12" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/data-view-byte-length": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz", - "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.2" - }, + "node_modules/camelcase-keys/node_modules/type-fest": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", + "integrity": "sha512-yGSza74xk0UG8k+pLh5oeoYirvIiWo5t0/o3zHHAO2tRDiZcxWP7fywNlXhqb6/r6sWvwi+RsyQMWhVLe4BVuA==", + "dev": true, + "license": "(MIT OR CC0-1.0)", "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/inspect-js" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/data-view-byte-offset": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz", - "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==", + "node_modules/caniuse-lite": { + "version": "1.0.30001671", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001671.tgz", + "integrity": "sha512-jocyVaSSfXg2faluE6hrWkMgDOiULBMca4QLtDT39hw1YxaIPHWc1CcTCKkPmHgGH6tKji6ZNbMSmUAvENf2/A==", + "dev": true, + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "license": "CC-BY-4.0" + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "is-data-view": "^1.0.1" + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/chalk/chalk?sponsor=1" } }, - "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/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==", "dev": true, "license": "MIT", "dependencies": { - "@babel/runtime": "^7.21.0" + "has-flag": "^4.0.0" }, "engines": { - "node": ">=0.11" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/date-fns" + "node": ">=8" } }, - "node_modules/dayjs": { - "version": "1.11.13", - "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", - "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "node_modules/char-width-table-consumer": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/char-width-table-consumer/-/char-width-table-consumer-1.0.0.tgz", + "integrity": "sha512-Fz4UD0LBpxPgL9i29CJ5O4KANwaMnX/OhhbxzvNa332h+9+nRKyeuLw4wA51lt/ex67+/AdsoBQJF3kgX2feYQ==", + "license": "MIT", + "dependencies": { + "binary-search": "^1.3.5" + } + }, + "node_modules/chardet": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-1.4.0.tgz", + "integrity": "sha512-NpwMDdSIprbYx1CLnfbxEIarI0Z+s9MssEgggMNheGM+WD68yOhV7IEA/3r6tr0yTRgQD0HuZJDw32s99i6L+A==", "license": "MIT" }, - "node_modules/debug": { - "version": "4.4.0", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.0.tgz", - "integrity": "sha512-6WTZ/IxCY/T6BALoZHaE4ctp9xm+Z5kY/pzYaCHRFeyVhojxlrm+46y68HA6hr0TcwEssoxNiDEUJQjfPZ/RYA==", + "node_modules/chart.js": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.2.1.tgz", + "integrity": "sha512-6YbpQ0nt3NovAgOzbkSSeeAQu/3za1319dPUQTXn9WcOpywM8rGKxJHrhS8V8xEkAlk8YhEfjbuAPfUyp6jIsw==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "@kurkle/color": "^0.3.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "pnpm": "^7.0.0" } }, - "node_modules/decamelize": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", - "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", + "node_modules/chartjs-adapter-dayjs-4": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/chartjs-adapter-dayjs-4/-/chartjs-adapter-dayjs-4-1.0.4.tgz", + "integrity": "sha512-yy9BAYW4aNzPVrCWZetbILegTRb7HokhgospPoC3b5iZ5qdlqNmXts2KdSp6AqnjkPAp/YWyHDxLvIvwt5x81w==", "dev": true, "license": "MIT", "engines": { "node": ">=10" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "peerDependencies": { + "chart.js": ">=4.0.1", + "dayjs": "^1.9.7" } }, - "node_modules/decamelize-keys": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", - "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", - "dev": true, + "node_modules/check-password-strength": { + "version": "2.0.10", + "resolved": "https://registry.npmjs.org/check-password-strength/-/check-password-strength-2.0.10.tgz", + "integrity": "sha512-HRM5ICPmtnNtLnTv2QrfVkq1IxI9z3bzYpDJ1k5ixwD9HtJGHuv265R6JmHOV6r8wLhQMlULnIUVpkrC2yaiCw==", + "license": "MIT" + }, + "node_modules/cheerio": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz", + "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==", "license": "MIT", "dependencies": { - "decamelize": "^1.1.0", - "map-obj": "^1.0.0" + "cheerio-select": "^2.1.0", + "dom-serializer": "^2.0.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "encoding-sniffer": "^0.2.0", + "htmlparser2": "^9.1.0", + "parse5": "^7.1.2", + "parse5-htmlparser2-tree-adapter": "^7.0.0", + "parse5-parser-stream": "^7.1.2", + "undici": "^6.19.5", + "whatwg-mimetype": "^4.0.0" }, "engines": { - "node": ">=0.10.0" + "node": ">=18.17" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "node_modules/decamelize-keys/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==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" + "node_modules/cheerio-select": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz", + "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==", + "license": "BSD-2-Clause", + "dependencies": { + "boolbase": "^1.0.0", + "css-select": "^5.1.0", + "css-what": "^6.1.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/decamelize-keys/node_modules/map-obj": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", - "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", - "dev": true, + "node_modules/cheerio/node_modules/undici": { + "version": "6.20.1", + "resolved": "https://registry.npmjs.org/undici/-/undici-6.20.1.tgz", + "integrity": "sha512-AjQF1QsmqfJys+LXfGTNum+qw4S88CojRInG/6t31W/1fk6G59s92bnAvGz5Cmur+kQv2SURXEvvudLmbrE8QA==", "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">=18.17" } }, - "node_modules/decompress-response": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", - "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dev": true, "license": "MIT", "dependencies": { - "mimic-response": "^3.1.0" + "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": ">=10" + "node": ">= 8.10.0" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/decompress-response/node_modules/mimic-response": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", - "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", - "license": "MIT", - "engines": { - "node": ">=10" + "url": "https://paulmillr.com/funding/" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "optionalDependencies": { + "fsevents": "~2.3.2" } }, - "node_modules/dedent": { - "version": "1.5.3", - "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz", - "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==", + "node_modules/chokidar/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", "dev": true, - "license": "MIT", - "peerDependencies": { - "babel-plugin-macros": "^3.1.0" + "license": "ISC", + "dependencies": { + "is-glob": "^4.0.1" }, - "peerDependenciesMeta": { - "babel-plugin-macros": { - "optional": true - } - } - }, - "node_modules/deep-is": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", - "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/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, - "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "node_modules/defer-to-connect": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", - "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", - "license": "MIT", + "node_modules/chownr": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-2.0.0.tgz", + "integrity": "sha512-bIomtDF5KGpdogkLd9VspvFzk9KfpyyGlS8YFVZl7TGPBHL5snIOnxeshwVgPteQ9b4Eydl+pVbIyE1DcvCWgQ==", + "license": "ISC", "engines": { "node": ">=10" } }, - "node_modules/define-data-property": { - "version": "1.1.4", - "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", - "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", - "license": "MIT", - "dependencies": { - "es-define-property": "^1.0.0", - "es-errors": "^1.3.0", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "node_modules/chroma-js": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-2.4.2.tgz", + "integrity": "sha512-U9eDw6+wt7V8z5NncY2jJfZa+hUH8XEj8FQHgFJTrUFnJfXYf4Ml4adI2vXZOjqRDpFWtYVWypDfZwnJ+HIR4A==", + "license": "(BSD-3-Clause AND Apache-2.0)" }, - "node_modules/define-lazy-prop": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", - "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "node_modules/clean-stack": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/clean-stack/-/clean-stack-2.2.0.tgz", + "integrity": "sha512-4diC9HaTE+KRAMWhDhrGOECgWZxoevMc5TlkObMqNSsVU62PYzXZ/SMTjzyGAFF1YusgxGcSWTEXBhp0CPwQ1A==", "license": "MIT", + "optional": true, "engines": { - "node": ">=8" + "node": ">=6" } }, - "node_modules/define-properties": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", - "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", - "license": "MIT", + "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==", + "license": "ISC", "dependencies": { - "define-data-property": "^1.0.1", - "has-property-descriptors": "^1.0.0", - "object-keys": "^1.1.1" + "string-width": "^4.2.0", + "strip-ansi": "^6.0.1", + "wrap-ansi": "^7.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=12" } }, - "node_modules/delay": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", - "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", - "dev": true, + "node_modules/clone-response": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/clone-response/-/clone-response-1.0.3.tgz", + "integrity": "sha512-ROoL94jJH2dUVML2Y/5PEDNaSHgeOdSDicUyS7izcF63G6sTc/FTjLub4b8Il9S8S0beOfYt0TaA5qvFK+w0wA==", "license": "MIT", - "engines": { - "node": ">=10" + "dependencies": { + "mimic-response": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/delayed-stream": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", - "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "node_modules/cluster-key-slot": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/cluster-key-slot/-/cluster-key-slot-1.1.1.tgz", + "integrity": "sha512-rwHwUfXL40Chm1r08yrhU3qpUvdVlgkKNeyeGPOxnW8/SyVDvgRaed/Uz54AqWNaTCAThlj6QAs3TZcKI0xDEw==", + "license": "Apache-2.0", + "engines": { + "node": ">=0.10.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==", "license": "MIT", + "dependencies": { + "color-name": "~1.1.4" + }, "engines": { - "node": ">=0.4.0" + "node": ">=7.0.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/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==", "license": "MIT" }, - "node_modules/denque": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", - "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", - "license": "Apache-2.0", - "engines": { - "node": ">=0.10" + "node_modules/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==", + "license": "ISC", + "bin": { + "color-support": "bin.js" } }, - "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/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==", + "dev": true, + "license": "MIT" + }, + "node_modules/colorette": { + "version": "2.0.19", + "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", + "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", + "license": "MIT" + }, + "node_modules/combined-stream": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz", + "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==", "license": "MIT", + "dependencies": { + "delayed-stream": "~1.0.0" + }, "engines": { "node": ">= 0.8" } }, - "node_modules/deprecation": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", - "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", - "dev": true, - "license": "ISC" + "node_modules/command-exists": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/command-exists/-/command-exists-1.2.9.tgz", + "integrity": "sha512-LTQ/SGc+s0Xc0Fu5WaKnR0YiygZkm9eKFvyS+fRsU7/ZWFF8ykFM6Pc9aCVf1+xasOOZpO3BAVgVrKvsqKHV7w==", + "license": "MIT" }, - "node_modules/destroy": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", - "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "node_modules/commander": { + "version": "10.0.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", + "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", "license": "MIT", "engines": { - "node": ">= 0.8", - "npm": "1.2.8000 || >= 1.4.16" - } - }, - "node_modules/detect-libc": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", - "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", - "license": "Apache-2.0", - "engines": { - "node": ">=8" + "node": ">=14" } }, - "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==", + "node_modules/comment-parser": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/comment-parser/-/comment-parser-1.4.0.tgz", + "integrity": "sha512-QLyTNiZ2KDOibvFPlZ6ZngVsZ/0gYnE6uTXi5aoDg8ed3AkJAz4sEje3Y8a29hQ1s6A99MZXe47fLAXQ1rTqaw==", "dev": true, "license": "MIT", "engines": { - "node": ">=8" + "node": ">= 12.0.0" } }, - "node_modules/dev-null": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", - "integrity": "sha512-nMNZG0zfMgmdv8S5O0TM5cpwNbGKRGPCxVsr0SmA3NZZy9CYBbuNLL0PD3Acx9e5LIUgwONXtM9kM6RlawPxEQ==", - "license": "MIT" - }, - "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, + "node_modules/commist": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/commist/-/commist-1.1.0.tgz", + "integrity": "sha512-rraC8NXWOEjhADbZe9QBNzLAN5Q3fsTPQtBV+fEVj6xKIgDgNiEVE6ZNfHpZOqfQ21YUzfVNUXLOEZquYvQPPg==", "license": "MIT", - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "dependencies": { + "leven": "^2.1.0", + "minimist": "^1.1.0" } }, - "node_modules/dijkstrajs": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", - "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", - "dev": true, + "node_modules/compare-versions": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/compare-versions/-/compare-versions-3.6.0.tgz", + "integrity": "sha512-W6Af2Iw1z4CB7q4uU4hv646dW9GQuBM+YpC0UvUCWSD8w90SJjp+ujJuXaEMtAXBtSqGfMPuFOVn4/+FlaqfBA==", "license": "MIT" }, - "node_modules/dir-glob": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", - "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", + "node_modules/compress-commons": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/compress-commons/-/compress-commons-6.0.2.tgz", + "integrity": "sha512-6FqVXeETqWPoGcfzrXb37E50NP0LXT8kAMu5ooZayhWWdgEY4lBEEcbQNXtkuKQsGduxiIcI4gOTsxTmuq/bSg==", "dev": true, "license": "MIT", "dependencies": { - "path-type": "^4.0.0" + "crc-32": "^1.2.0", + "crc32-stream": "^6.0.0", + "is-stream": "^2.0.1", + "normalize-path": "^3.0.0", + "readable-stream": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">= 14" } }, - "node_modules/dns2": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/dns2/-/dns2-2.0.5.tgz", - "integrity": "sha512-dznYrQU+Txcz++klGLBY9YR3WLOGHTy2vAKAqF+yYw1KaKFm5f5Y4jbbFEvohJf8YtZ0J2SzZlZx2k6LV4zJqQ==", + "node_modules/compress-commons/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, - "license": "MIT" + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } }, - "node_modules/doctrine": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", - "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "node_modules/compress-commons/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "esutils": "^2.0.2" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=6.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/dom-serializer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", - "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", + "node_modules/compressible": { + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz", + "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==", "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.2", - "entities": "^4.2.0" + "mime-db": ">= 1.43.0 < 2" }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "engines": { + "node": ">= 0.6" } }, - "node_modules/domelementtype": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", - "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fb55" - } - ], - "license": "BSD-2-Clause" - }, - "node_modules/domhandler": { - "version": "5.0.3", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", - "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", - "license": "BSD-2-Clause", + "node_modules/compression": { + "version": "1.7.4", + "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz", + "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==", + "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0" + "accepts": "~1.3.5", + "bytes": "3.0.0", + "compressible": "~2.0.16", + "debug": "2.6.9", + "on-headers": "~1.0.2", + "safe-buffer": "5.1.2", + "vary": "~1.1.2" }, "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" + "node": ">= 0.8.0" } }, - "node_modules/dompurify": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", - "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==", - "dev": true, - "license": "(MPL-2.0 OR Apache-2.0)" - }, - "node_modules/domutils": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", - "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", - "license": "BSD-2-Clause", + "node_modules/compression/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "license": "MIT", "dependencies": { - "dom-serializer": "^2.0.0", - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3" - }, - "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" + "ms": "2.0.0" } }, - "node_modules/dotenv": { - "version": "16.0.3", - "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", - "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=12" - } + "node_modules/compression/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" }, - "node_modules/dunder-proto": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", - "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "node_modules/concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==", + "license": "MIT" + }, + "node_modules/concat-stream": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/concat-stream/-/concat-stream-2.0.0.tgz", + "integrity": "sha512-MWufYdFw53ccGjCA+Ol7XJYpAlW6/prSMzuPOTRnJGcGzuhLn4Scrz7qf6o8bROZ514ltazcIFJZevcfbo0x7A==", + "engines": [ + "node >= 6.0" + ], "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "es-errors": "^1.3.0", - "gopd": "^1.2.0" - }, - "engines": { - "node": ">= 0.4" + "buffer-from": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.0.2", + "typedarray": "^0.0.6" } }, - "node_modules/duplexify": { - "version": "4.1.3", - "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", - "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "node_modules/concurrently": { + "version": "7.6.0", + "resolved": "https://registry.npmjs.org/concurrently/-/concurrently-7.6.0.tgz", + "integrity": "sha512-BKtRgvcJGeZ4XttiDiNcFiRlxoAeZOseqUvyYRUp/Vtd+9p1ULmeoSqGsDA+2ivdeDFpqrJvGvmI+StKfKl5hw==", + "dev": true, "license": "MIT", "dependencies": { - "end-of-stream": "^1.4.1", - "inherits": "^2.0.3", - "readable-stream": "^3.1.1", - "stream-shift": "^1.0.2" + "chalk": "^4.1.0", + "date-fns": "^2.29.1", + "lodash": "^4.17.21", + "rxjs": "^7.0.0", + "shell-quote": "^1.7.3", + "spawn-command": "^0.0.2-1", + "supports-color": "^8.1.0", + "tree-kill": "^1.2.2", + "yargs": "^17.3.1" + }, + "bin": { + "conc": "dist/bin/concurrently.js", + "concurrently": "dist/bin/concurrently.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.0 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/open-cli-tools/concurrently?sponsor=1" } }, - "node_modules/eastasianwidth": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", - "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", - "license": "MIT" + "node_modules/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==", + "license": "ISC" }, - "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==", - "dev": true, + "node_modules/content-disposition": { + "version": "0.5.4", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz", + "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==", "license": "MIT", "dependencies": { - "jsbn": "~0.1.0", - "safer-buffer": "^2.1.0" + "safe-buffer": "5.2.1" + }, + "engines": { + "node": ">= 0.6" } }, - "node_modules/ecc-jsbn/node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true, + "node_modules/content-disposition/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], "license": "MIT" }, - "node_modules/ecdsa-sig-formatter": { - "version": "1.0.11", - "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", - "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", - "license": "Apache-2.0", - "dependencies": { - "safe-buffer": "^5.0.1" + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "license": "MIT", + "engines": { + "node": ">= 0.6" } }, - "node_modules/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==", - "license": "MIT" - }, - "node_modules/electron-to-chromium": { - "version": "1.5.75", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.75.tgz", - "integrity": "sha512-Lf3++DumRE/QmweGjU+ZcKqQ+3bKkU/qjaKYhIJKEOhgIO9Xs6IiAQFkfFoj+RhgDk4LUeNsLo6plExHqSyu6Q==", + "node_modules/convert-source-map": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz", + "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "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, + "node_modules/cookie": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.1.tgz", + "integrity": "sha512-6DnInpx7SJ2AK3+CTUE/ZM0vWTUboZCegxhC2xiIydHR9jNuTAASBrfEpHhiGOZw/nX51bHt6YQl8jsGo4y/0w==", "license": "MIT", "engines": { - "node": ">=12" - }, - "funding": { - "url": "https://github.com/sindresorhus/emittery?sponsor=1" + "node": ">= 0.6" } }, - "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/cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==", "license": "MIT" }, - "node_modules/encodeurl": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", - "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "node_modules/copy-anything": { + "version": "3.0.5", + "resolved": "https://registry.npmjs.org/copy-anything/-/copy-anything-3.0.5.tgz", + "integrity": "sha512-yCEafptTtb4bk7GLEQoM8KVJpxAfdBJYaXyzQEgQQQgYrZiDp8SJmGKlYza6CYjEDNstAdNdKA3UuoULlEbS6w==", + "dev": true, "license": "MIT", + "dependencies": { + "is-what": "^4.1.8" + }, "engines": { - "node": ">= 0.8" + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" } }, - "node_modules/encoding": { - "version": "0.1.13", - "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", - "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "node_modules/core-js": { + "version": "3.26.1", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.26.1.tgz", + "integrity": "sha512-21491RRQVzUn0GGM9Z1Jrpr6PNPxPi+Za8OM9q4tksTSnlbXXGKK1nXNg/QvwFYettXvSX6zWKCtHHfjN4puyA==", + "dev": true, + "hasInstallScript": true, "license": "MIT", - "optional": true, - "dependencies": { - "iconv-lite": "^0.6.2" + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/core-js" } }, - "node_modules/end-of-stream": { - "version": "1.4.4", - "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", - "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "license": "MIT", - "dependencies": { - "once": "^1.4.0" - } + "node_modules/core-util-is": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz", + "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==", + "license": "MIT" }, - "node_modules/engine.io": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", - "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "node_modules/cors": { + "version": "2.8.5", + "resolved": "https://registry.npmjs.org/cors/-/cors-2.8.5.tgz", + "integrity": "sha512-KIHbLJqu73RGr/hnbrO9uBeixNGuvSQjul/jdFvS/KFSIH1hWVd1ng7zOHx+YrEfInLG7q4n6GHQ9cDtxv/P6g==", "license": "MIT", "dependencies": { - "@types/cookie": "^0.4.1", - "@types/cors": "^2.8.12", - "@types/node": ">=10.0.0", - "accepts": "~1.3.4", - "base64id": "2.0.0", - "cookie": "~0.7.2", - "cors": "~2.8.5", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1" + "object-assign": "^4", + "vary": "^1" }, "engines": { - "node": ">=10.2.0" - } - }, - "node_modules/engine.io-client": { - "version": "6.6.2", - "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz", - "integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==", - "license": "MIT", - "dependencies": { - "@socket.io/component-emitter": "~3.1.0", - "debug": "~4.3.1", - "engine.io-parser": "~5.2.1", - "ws": "~8.17.1", - "xmlhttprequest-ssl": "~2.1.1" + "node": ">= 0.10" } }, - "node_modules/engine.io-client/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/cosmiconfig": { + "version": "8.3.6", + "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz", + "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "import-fresh": "^3.3.0", + "js-yaml": "^4.1.0", + "parse-json": "^5.2.0", + "path-type": "^4.0.0" }, "engines": { - "node": ">=6.0" + "node": ">=14" }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/engine.io-client/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" + "funding": { + "url": "https://github.com/sponsors/d-fischer" }, "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" + "typescript": ">=4.9.5" }, "peerDependenciesMeta": { - "bufferutil": { - "optional": true - }, - "utf-8-validate": { + "typescript": { "optional": true } } }, - "node_modules/engine.io-parser": { - "version": "5.2.3", - "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", - "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", - "license": "MIT", + "node_modules/cpu-features": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/cpu-features/-/cpu-features-0.0.10.tgz", + "integrity": "sha512-9IkYqtX3YHPCzoVg1Py+o9057a3i0fp7S530UWokCSaFVTc7CwXPRiOjRjBQQ18ZCNafx78YfnG+HALxtVmOGA==", + "dev": true, + "hasInstallScript": true, + "optional": true, + "dependencies": { + "buildcheck": "~0.0.6", + "nan": "^2.19.0" + }, "engines": { "node": ">=10.0.0" } }, - "node_modules/engine.io/node_modules/cookie": { - "version": "0.7.2", - "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", - "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", - "license": "MIT", + "node_modules/crc-32": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/crc-32/-/crc-32-1.2.2.tgz", + "integrity": "sha512-ROmzCKrTnOwybPcJApAA6WBWij23HVfGVNKqqrZpuyZOHqK2CwHSvpGuyt/UNNvaIjEd8X5IFGp4Mh+Ie1IHJQ==", + "dev": true, + "license": "Apache-2.0", + "bin": { + "crc32": "bin/crc32.njs" + }, "engines": { - "node": ">= 0.6" + "node": ">=0.8" } }, - "node_modules/engine.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", + "node_modules/crc32-stream": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/crc32-stream/-/crc32-stream-6.0.0.tgz", + "integrity": "sha512-piICUB6ei4IlTv1+653yq5+KoqfBYmj9bw6LqXoOneTMDXk5nM1qt12mFW1caG3LlJXEKW1Bp0WggEmIfQB34g==", + "dev": true, "license": "MIT", "dependencies": { - "ms": "^2.1.3" + "crc-32": "^1.2.0", + "readable-stream": "^4.0.0" }, "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } + "node": ">= 14" } }, - "node_modules/engine.io/node_modules/ws": { - "version": "8.17.1", - "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", - "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", - "license": "MIT", - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "bufferutil": "^4.0.1", - "utf-8-validate": ">=5.0.2" - }, - "peerDependenciesMeta": { - "bufferutil": { - "optional": true + "node_modules/crc32-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" }, - "utf-8-validate": { - "optional": true + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" } }, - "node_modules/enquirer": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/enquirer/-/enquirer-2.4.1.tgz", - "integrity": "sha512-rRqJg/6gd538VHvR3PSrdRBb/1Vy2YfzHqzvbhGIQpDRKIa4FgV/54b5Q1xYSxOOwKvjXweS26E0Q+nAMwp2pQ==", + "node_modules/crc32-stream/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", "dev": true, "license": "MIT", "dependencies": { - "ansi-colors": "^4.1.1", - "strip-ansi": "^6.0.1" + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=8.6" - } - }, - "node_modules/entities": { - "version": "4.5.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", - "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", - "license": "BSD-2-Clause", - "engines": { - "node": ">=0.12" - }, - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" } }, - "node_modules/env-paths": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", - "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "node_modules/croner": { + "version": "8.1.2", + "resolved": "https://registry.npmjs.org/croner/-/croner-8.1.2.tgz", + "integrity": "sha512-ypfPFcAXHuAZRCzo3vJL6ltENzniTjwe/qsLleH1V2/7SRDjgvRQyrLmumFTLmjFax4IuSxfGXEn79fozXcJog==", "license": "MIT", - "optional": true, "engines": { - "node": ">=6" + "node": ">=18.0" } }, - "node_modules/err-code": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", - "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", - "license": "MIT", - "optional": true - }, - "node_modules/error-ex": { - "version": "1.3.2", - "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", - "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "node_modules/cronstrue": { + "version": "2.24.0", + "resolved": "https://registry.npmjs.org/cronstrue/-/cronstrue-2.24.0.tgz", + "integrity": "sha512-A1of24mAGz+OWrdGsxT9BOnDqn2ba182hie8Jx0UcEC2t+ZKtfAJxaFntKUgR7sIisU297fgHBSlNhMIfvAkSA==", "dev": true, "license": "MIT", - "dependencies": { - "is-arrayish": "^0.2.1" + "bin": { + "cronstrue": "bin/cli.js" } }, - "node_modules/es-abstract": { - "version": "1.23.6", - "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.6.tgz", - "integrity": "sha512-Ifco6n3yj2tMZDWNLyloZrytt9lqqlwvS83P3HtaETR0NUOYnIULGGHpktqYGObGy+8wc1okO25p8TjemhImvA==", + "node_modules/cross-env": { + "version": "7.0.3", + "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz", + "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==", + "dev": true, "license": "MIT", "dependencies": { - "array-buffer-byte-length": "^1.0.1", - "arraybuffer.prototype.slice": "^1.0.4", - "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "data-view-buffer": "^1.0.1", - "data-view-byte-length": "^1.0.1", - "data-view-byte-offset": "^1.0.0", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "es-set-tostringtag": "^2.0.3", - "es-to-primitive": "^1.3.0", - "function.prototype.name": "^1.1.7", - "get-intrinsic": "^1.2.6", - "get-symbol-description": "^1.0.2", - "globalthis": "^1.0.4", - "gopd": "^1.2.0", - "has-property-descriptors": "^1.0.2", - "has-proto": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "internal-slot": "^1.1.0", - "is-array-buffer": "^3.0.4", - "is-callable": "^1.2.7", - "is-data-view": "^1.0.2", - "is-negative-zero": "^2.0.3", - "is-regex": "^1.2.1", - "is-shared-array-buffer": "^1.0.3", - "is-string": "^1.1.1", - "is-typed-array": "^1.1.13", - "is-weakref": "^1.1.0", - "math-intrinsics": "^1.0.0", - "object-inspect": "^1.13.3", - "object-keys": "^1.1.1", - "object.assign": "^4.1.5", - "regexp.prototype.flags": "^1.5.3", - "safe-array-concat": "^1.1.3", - "safe-regex-test": "^1.1.0", - "string.prototype.trim": "^1.2.10", - "string.prototype.trimend": "^1.0.9", - "string.prototype.trimstart": "^1.0.8", - "typed-array-buffer": "^1.0.2", - "typed-array-byte-length": "^1.0.1", - "typed-array-byte-offset": "^1.0.3", - "typed-array-length": "^1.0.7", - "unbox-primitive": "^1.0.2", - "which-typed-array": "^1.1.16" + "cross-spawn": "^7.0.1" }, - "engines": { - "node": ">= 0.4" + "bin": { + "cross-env": "src/bin/cross-env.js", + "cross-env-shell": "src/bin/cross-env-shell.js" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10.14", + "npm": ">=6", + "yarn": ">=1" } }, - "node_modules/es-aggregate-error": { - "version": "1.0.13", - "resolved": "https://registry.npmjs.org/es-aggregate-error/-/es-aggregate-error-1.0.13.tgz", - "integrity": "sha512-KkzhUUuD2CUMqEc8JEqsXEMDHzDPE8RCjZeUBitsnB1eNcAJWQPiciKsMXe3Yytj4Flw1XLl46Qcf9OxvZha7A==", + "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==", "license": "MIT", "dependencies": { - "define-data-property": "^1.1.4", - "define-properties": "^1.2.1", - "es-abstract": "^1.23.2", - "es-errors": "^1.3.0", - "function-bind": "^1.1.2", - "globalthis": "^1.0.3", - "has-property-descriptors": "^1.0.2", - "set-function-name": "^2.0.2" + "path-key": "^3.1.0", + "shebang-command": "^2.0.0", + "which": "^2.0.1" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 8" } }, - "node_modules/es-define-property": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", - "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "node_modules/css-color-converter": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/css-color-converter/-/css-color-converter-2.0.0.tgz", + "integrity": "sha512-oLIG2soZz3wcC3aAl/7Us5RS8Hvvc6I8G8LniF/qfMmrm7fIKQ8RIDDRZeKyGL2SrWfNqYspuLShbnjBMVWm8g==", "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "color-convert": "^0.5.2", + "color-name": "^1.1.4", + "css-unit-converter": "^1.1.2" } }, - "node_modules/es-errors": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", - "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "node_modules/css-color-converter/node_modules/color-convert": { + "version": "0.5.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-0.5.3.tgz", + "integrity": "sha512-RwBeO/B/vZR3dfKL1ye/vx8MHZ40ugzpyfeVG5GsiuGnrlMWe2o8wxBbLCpw9CsxV+wHuzYlCiWnybrIA0ling==" + }, + "node_modules/css-functions-list": { + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/css-functions-list/-/css-functions-list-3.2.3.tgz", + "integrity": "sha512-IQOkD3hbR5KrN93MtcYuad6YPuTSUhntLHDuLEbFWE+ff2/XSZNdZG+LcbbIW5AXKg/WFIfYItIzVoHngHXZzA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=12 || >=16" } }, - "node_modules/es-object-atoms": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", - "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", - "license": "MIT", + "node_modules/css-select": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz", + "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==", + "license": "BSD-2-Clause", "dependencies": { - "es-errors": "^1.3.0" + "boolbase": "^1.0.0", + "css-what": "^6.1.0", + "domhandler": "^5.0.2", + "domutils": "^3.0.1", + "nth-check": "^2.0.1" }, - "engines": { - "node": ">= 0.4" + "funding": { + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/es-set-tostringtag": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", - "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", + "node_modules/css-tree": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-2.3.1.tgz", + "integrity": "sha512-6Fv1DV/TYw//QF5IzQdqsNDjx/wc8TrMBZsqjL9eW01tWb7R7k/mq+/VXfJCl7SoD5emsJop9cOByJZfs8hYIw==", + "dev": true, "license": "MIT", "dependencies": { - "get-intrinsic": "^1.2.4", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.1" + "mdn-data": "2.0.30", + "source-map-js": "^1.0.1" }, "engines": { - "node": ">= 0.4" + "node": "^10 || ^12.20.0 || ^14.13.0 || >=15.0.0" } }, - "node_modules/es-to-primitive": { - "version": "1.3.0", - "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz", - "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==", - "license": "MIT", - "dependencies": { - "is-callable": "^1.2.7", - "is-date-object": "^1.0.5", - "is-symbol": "^1.0.4" - }, + "node_modules/css-unit-converter": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz", + "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==", + "license": "MIT" + }, + "node_modules/css-what": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz", + "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==", + "license": "BSD-2-Clause", "engines": { - "node": ">= 0.4" + "node": ">= 6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/esbuild": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", - "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", "dev": true, - "hasInstallScript": true, "license": "MIT", "bin": { - "esbuild": "bin/esbuild" - }, - "engines": { - "node": ">=12" + "cssesc": "bin/cssesc" }, - "optionalDependencies": { - "@esbuild/aix-ppc64": "0.20.2", - "@esbuild/android-arm": "0.20.2", - "@esbuild/android-arm64": "0.20.2", - "@esbuild/android-x64": "0.20.2", - "@esbuild/darwin-arm64": "0.20.2", - "@esbuild/darwin-x64": "0.20.2", - "@esbuild/freebsd-arm64": "0.20.2", - "@esbuild/freebsd-x64": "0.20.2", - "@esbuild/linux-arm": "0.20.2", - "@esbuild/linux-arm64": "0.20.2", - "@esbuild/linux-ia32": "0.20.2", - "@esbuild/linux-loong64": "0.20.2", - "@esbuild/linux-mips64el": "0.20.2", - "@esbuild/linux-ppc64": "0.20.2", - "@esbuild/linux-riscv64": "0.20.2", - "@esbuild/linux-s390x": "0.20.2", - "@esbuild/linux-x64": "0.20.2", - "@esbuild/netbsd-x64": "0.20.2", - "@esbuild/openbsd-x64": "0.20.2", - "@esbuild/sunos-x64": "0.20.2", - "@esbuild/win32-arm64": "0.20.2", - "@esbuild/win32-ia32": "0.20.2", - "@esbuild/win32-x64": "0.20.2" - } - }, - "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", "engines": { - "node": ">=6" + "node": ">=4" } }, - "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/csstype": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz", + "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==", + "dev": true, "license": "MIT" }, - "node_modules/escape-string-regexp": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", - "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", + "node_modules/data-view-buffer": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz", + "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==", "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" + }, "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint": { - "version": "8.14.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz", - "integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==", - "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", + "node_modules/data-view-byte-length": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz", + "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==", "dev": true, "license": "MIT", "dependencies": { - "@eslint/eslintrc": "^1.2.2", - "@humanwhocodes/config-array": "^0.9.2", - "ajv": "^6.10.0", - "chalk": "^4.0.0", - "cross-spawn": "^7.0.2", - "debug": "^4.3.2", - "doctrine": "^3.0.0", - "escape-string-regexp": "^4.0.0", - "eslint-scope": "^7.1.1", - "eslint-utils": "^3.0.0", - "eslint-visitor-keys": "^3.3.0", - "espree": "^9.3.1", - "esquery": "^1.4.0", - "esutils": "^2.0.2", - "fast-deep-equal": "^3.1.3", - "file-entry-cache": "^6.0.1", - "functional-red-black-tree": "^1.0.1", - "glob-parent": "^6.0.1", - "globals": "^13.6.0", - "ignore": "^5.2.0", - "import-fresh": "^3.0.0", - "imurmurhash": "^0.1.4", - "is-glob": "^4.0.0", - "js-yaml": "^4.1.0", - "json-stable-stringify-without-jsonify": "^1.0.1", - "levn": "^0.4.1", - "lodash.merge": "^4.6.2", - "minimatch": "^3.0.4", - "natural-compare": "^1.4.0", - "optionator": "^0.9.1", - "regexpp": "^3.2.0", - "strip-ansi": "^6.0.1", - "strip-json-comments": "^3.1.0", - "text-table": "^0.2.0", - "v8-compile-cache": "^2.0.3" - }, - "bin": { - "eslint": "bin/eslint.js" + "call-bind": "^1.0.7", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-plugin-vue": { - "version": "8.7.1", - "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", - "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", + "node_modules/data-view-byte-offset": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz", + "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==", "dev": true, "license": "MIT", "dependencies": { - "eslint-utils": "^3.0.0", - "natural-compare": "^1.4.0", - "nth-check": "^2.0.1", - "postcss-selector-parser": "^6.0.9", - "semver": "^7.3.5", - "vue-eslint-parser": "^8.0.1" + "call-bind": "^1.0.6", + "es-errors": "^1.3.0", + "is-data-view": "^1.0.1" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, - "peerDependencies": { - "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/eslint-scope": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", - "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==", + "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==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^4.1.1" + "@babel/runtime": "^7.21.0" }, "engines": { - "node": ">=8.0.0" + "node": ">=0.11" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/date-fns" } }, - "node_modules/eslint-utils": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", - "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", - "dev": true, + "node_modules/dayjs": { + "version": "1.11.13", + "resolved": "https://registry.npmjs.org/dayjs/-/dayjs-1.11.13.tgz", + "integrity": "sha512-oaMBel6gjolK862uaPQOVTA7q3TZhuSvuMQAAglQDOWYO9A91IrAOUJEyKVlqJlHE0vq5p5UXxzdPfMH/x6xNg==", + "license": "MIT" + }, + "node_modules/debug": { + "version": "4.3.7", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", + "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", "license": "MIT", "dependencies": { - "eslint-visitor-keys": "^2.0.0" + "ms": "^2.1.3" }, "engines": { - "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" - }, - "funding": { - "url": "https://github.com/sponsors/mysticatea" + "node": ">=6.0" }, - "peerDependencies": { - "eslint": ">=5" + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, - "node_modules/eslint-visitor-keys": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", - "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "node_modules/decamelize": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-5.0.1.tgz", + "integrity": "sha512-VfxadyCECXgQlkoEAjeghAr5gY3Hf+IKjKb+X8tGVDtveCjN+USwprd2q3QXBR9T1+x2DG0XZF5/w+7HAtSaXA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "node_modules/decamelize-keys": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/decamelize-keys/-/decamelize-keys-1.1.1.tgz", + "integrity": "sha512-WiPxgEirIV0/eIOMcnFBA3/IJZAZqKnwAwWyvvdi4lsr1WCN22nhdf/3db3DoZcUjTV2SqfzIwNyp6y2xs3nmg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" + "decamelize": "^1.1.0", + "map-obj": "^1.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=0.10.0" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/decamelize-keys/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==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/decamelize-keys/node_modules/map-obj": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-1.0.1.tgz", + "integrity": "sha512-7N/q3lyZ+LVCp7PzuxrJr4KMbBE2hW7BT7YNia330OFxIf4d3r5zVpicP2650l7CPN6RM9zOJRl3NGpqSiw3Eg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=0.10.0" } }, - "node_modules/eslint/node_modules/globals": { - "version": "13.24.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", - "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", - "dev": true, + "node_modules/decompress-response": { + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/decompress-response/-/decompress-response-6.0.0.tgz", + "integrity": "sha512-aW35yZM6Bb/4oJlZncMH2LCoZtJXTRxES17vE3hoRiowU2kWHaJKFkSBDnDR+cm9J+9QhXmREyIfv0pji9ejCQ==", "license": "MIT", "dependencies": { - "type-fest": "^0.20.2" + "mimic-response": "^3.1.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/eslint/node_modules/type-fest": { - "version": "0.20.2", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", - "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", - "dev": true, - "license": "(MIT OR CC0-1.0)", + "node_modules/decompress-response/node_modules/mimic-response": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/mimic-response/-/mimic-response-3.1.0.tgz", + "integrity": "sha512-z0yWI+4FDrrweS8Zmt4Ej5HdJmky15+L2e6Wgn3+iK5fWzb6T3fhNFq2+MeTRb064c6Wr4N/wv0DzQTjNzHNGQ==", + "license": "MIT", "engines": { "node": ">=10" }, @@ -10033,1453 +7410,1742 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esm": { - "version": "3.2.25", - "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", - "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", - "license": "MIT", - "engines": { - "node": ">=6" - } + "node_modules/deep-is": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz", + "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==", + "dev": true, + "license": "MIT" }, - "node_modules/espree": { - "version": "9.6.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", - "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "node_modules/default-browser": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz", + "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "dependencies": { - "acorn": "^8.9.0", - "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.1" + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">=18" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/espree/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", + "node_modules/default-browser-id": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz", + "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defer-to-connect": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/defer-to-connect/-/defer-to-connect-2.0.1.tgz", + "integrity": "sha512-4tvttepXG1VaYGrRibk5EwJd1t4udunSOVMdLSAL6mId1ix438oPwPZMALY41FCijukO1L0twNcGsdzS7dHgDg==", + "license": "MIT", + "engines": { + "node": ">=10" + } + }, + "node_modules/define-data-property": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz", + "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==", + "license": "MIT", + "dependencies": { + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "gopd": "^1.0.1" + }, "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + "node": ">= 0.4" }, "funding": { - "url": "https://opencollective.com/eslint" + "url": "https://github.com/sponsors/ljharb" } }, - "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==", - "dev": true, - "license": "BSD-2-Clause", - "bin": { - "esparse": "bin/esparse.js", - "esvalidate": "bin/esvalidate.js" - }, + "node_modules/define-lazy-prop": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz", + "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==", + "license": "MIT", "engines": { - "node": ">=4" + "node": ">=8" } }, - "node_modules/esquery": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", - "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", + "node_modules/define-properties": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz", + "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "estraverse": "^5.1.0" + "define-data-property": "^1.0.1", + "has-property-descriptors": "^1.0.0", + "object-keys": "^1.1.1" }, "engines": { - "node": ">=0.10" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/esquery/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "node_modules/delay": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/delay/-/delay-5.0.0.tgz", + "integrity": "sha512-ReEBKkIfe4ya47wlPYf/gu5ib6yUG0/Aez0JQZQz94kiWtRQvZIQbTiehsnwHvLSWJnQdhVeqYue7Id1dKr0qw==", "dev": true, - "license": "BSD-2-Clause", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/esrecurse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", - "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "estraverse": "^5.2.0" - }, + "node_modules/delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">=0.4.0" } }, - "node_modules/esrecurse/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha512-bd2L678uiWATM6m5Z1VzNCErI3jiGzt6HGY8OVICs40JQq/HALfbyNJmp0UDakEY4pMMaN0Ly5om/B1VI/+xfQ==", + "license": "MIT" + }, + "node_modules/denque": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/denque/-/denque-2.1.0.tgz", + "integrity": "sha512-HVQE3AAb/pxF8fQAoiqpvg9i3evqug3hoiwakOyZAwJm+6vZehbkYXZ0l4JxS+I3QxM97v5aaRNhj8v5oBhekw==", + "license": "Apache-2.0", "engines": { - "node": ">=4.0" + "node": ">=0.10" } }, - "node_modules/estraverse": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz", - "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "license": "MIT", "engines": { - "node": ">=4.0" + "node": ">= 0.8" } }, - "node_modules/estree-walker": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", - "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", + "node_modules/deprecation": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/deprecation/-/deprecation-2.3.1.tgz", + "integrity": "sha512-xmHIy4F3scKVwMsQ4WnVaS8bHOx0DmVwRywosKhaILI0ywMDWPtBSku2HNxRvF7jtwDRsoEwYQSfbxj8b7RlJQ==", "dev": true, - "license": "MIT" + "license": "ISC" }, - "node_modules/esutils": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", - "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", - "dev": true, - "license": "BSD-2-Clause", + "node_modules/destroy": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz", + "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==", + "license": "MIT", "engines": { - "node": ">=0.10.0" + "node": ">= 0.8", + "npm": "1.2.8000 || >= 1.4.16" } }, - "node_modules/etag": { - "version": "1.8.1", - "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", - "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", - "license": "MIT", + "node_modules/detect-libc": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz", + "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==", + "license": "Apache-2.0", "engines": { - "node": ">= 0.6" + "node": ">=8" } }, - "node_modules/event-to-promise": { - "version": "0.7.0", - "resolved": "https://registry.npmjs.org/event-to-promise/-/event-to-promise-0.7.0.tgz", - "integrity": "sha512-VOBBfyaADfe378ZzG0tgkzmsvzUyeU5arehrFzNRt5yaASUDshgctTwSrPI17ocAwR3+YftsxRClHF+GBKFByQ==", - "deprecated": "Use promise-toolbox/fromEvent instead", + "node_modules/dev-null": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/dev-null/-/dev-null-0.1.1.tgz", + "integrity": "sha512-nMNZG0zfMgmdv8S5O0TM5cpwNbGKRGPCxVsr0SmA3NZZy9CYBbuNLL0PD3Acx9e5LIUgwONXtM9kM6RlawPxEQ==", "license": "MIT" }, - "node_modules/eventemitter2": { - "version": "6.4.7", - "resolved": "https://registry.npmjs.org/eventemitter2/-/eventemitter2-6.4.7.tgz", - "integrity": "sha512-tYUSVOGeQPKt/eC1ABfhHy5Xd96N3oIijJvN3O9+TsC28T5V9yX9oEfEK5faP0EFSNVOG97qtAS68GBrQB2hDg==", + "node_modules/dijkstrajs": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/dijkstrajs/-/dijkstrajs-1.0.3.tgz", + "integrity": "sha512-qiSlmBq9+BCdCA/L46dw8Uy93mloxsPSbwnm5yrKn2vMPiy8KyAskTF6zuV/j5BMsmOGZDPs7KjU+mjb670kfA==", "dev": true, "license": "MIT" }, - "node_modules/events": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", - "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", - "license": "MIT", - "engines": { - "node": ">=0.8.x" - } - }, - "node_modules/execa": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/execa/-/execa-4.1.0.tgz", - "integrity": "sha512-j5W0//W7f8UxAn8hXVnwG8tLwdiUy4FJLcSupCg6maBYZDpyBvTApK7KyuI4bKj8KOh1r2YH+6ucuYtJv1bTZA==", + "node_modules/dir-glob": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz", + "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.0", - "get-stream": "^5.0.0", - "human-signals": "^1.1.1", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.0", - "onetime": "^5.1.0", - "signal-exit": "^3.0.2", - "strip-final-newline": "^2.0.0" + "path-type": "^4.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "node": ">=8" } }, - "node_modules/executable": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/executable/-/executable-4.1.1.tgz", - "integrity": "sha512-8iA79xD3uAch729dUG8xaaBBFGaEa0wdD2VkYLFHwlqosEj/jT66AzcreRDSgV7ehnNLBW2WR5jIXwGKjVdTLg==", + "node_modules/dns2": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/dns2/-/dns2-2.0.5.tgz", + "integrity": "sha512-dznYrQU+Txcz++klGLBY9YR3WLOGHTy2vAKAqF+yYw1KaKFm5f5Y4jbbFEvohJf8YtZ0J2SzZlZx2k6LV4zJqQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/docker-compose": { + "version": "0.24.8", + "resolved": "https://registry.npmjs.org/docker-compose/-/docker-compose-0.24.8.tgz", + "integrity": "sha512-plizRs/Vf15H+GCVxq2EUvyPK7ei9b/cVesHvjnX4xaXjM9spHe2Ytq0BitndFgvTJ3E3NljPNUEl7BAN43iZw==", "dev": true, "license": "MIT", "dependencies": { - "pify": "^2.2.0" + "yaml": "^2.2.2" }, "engines": { - "node": ">=4" + "node": ">= 6.0.0" } }, - "node_modules/exit": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz", - "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==", + "node_modules/docker-modem": { + "version": "3.0.8", + "resolved": "https://registry.npmjs.org/docker-modem/-/docker-modem-3.0.8.tgz", + "integrity": "sha512-f0ReSURdM3pcKPNS30mxOHSbaFLcknGmQjwSfmbcdOw1XWKXVhukM3NJHhr7NpY9BIyyWQb0EBo3KQvvuU5egQ==", "dev": true, + "license": "Apache-2.0", + "dependencies": { + "debug": "^4.1.1", + "readable-stream": "^3.5.0", + "split-ca": "^1.0.1", + "ssh2": "^1.11.0" + }, "engines": { - "node": ">= 0.8.0" + "node": ">= 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==", + "node_modules/dockerode": { + "version": "3.3.5", + "resolved": "https://registry.npmjs.org/dockerode/-/dockerode-3.3.5.tgz", + "integrity": "sha512-/0YNa3ZDNeLr/tSckmD69+Gq+qVNhvKfAHNeZJBnp7EOP6RGKV8ORrJHkUn20So5wU+xxT7+1n5u8PjHbfjbSA==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "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" + "@balena/dockerignore": "^1.0.2", + "docker-modem": "^3.0.0", + "tar-fs": "~2.0.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 8.0" } }, - "node_modules/express": { - "version": "4.21.2", - "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", - "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", + "node_modules/dockerode/node_modules/chownr": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz", + "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==", + "dev": true, + "license": "ISC" + }, + "node_modules/dockerode/node_modules/tar-fs": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-2.0.1.tgz", + "integrity": "sha512-6tzWDMeroL87uF/+lin46k+Q+46rAJ0SyPGz7OW7wTgblI273hsBqk2C1j0/xNadNLKDTUL9BukSjB7cwgmlPA==", + "dev": true, "license": "MIT", "dependencies": { - "accepts": "~1.3.8", - "array-flatten": "1.1.1", - "body-parser": "1.20.3", - "content-disposition": "0.5.4", - "content-type": "~1.0.4", - "cookie": "0.7.1", - "cookie-signature": "1.0.6", - "debug": "2.6.9", - "depd": "2.0.0", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "etag": "~1.8.1", - "finalhandler": "1.3.1", - "fresh": "0.5.2", - "http-errors": "2.0.0", - "merge-descriptors": "1.0.3", - "methods": "~1.1.2", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "path-to-regexp": "0.1.12", - "proxy-addr": "~2.0.7", - "qs": "6.13.0", - "range-parser": "~1.2.1", - "safe-buffer": "5.2.1", - "send": "0.19.0", - "serve-static": "1.16.2", - "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" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/express" + "chownr": "^1.1.1", + "mkdirp-classic": "^0.5.2", + "pump": "^3.0.0", + "tar-stream": "^2.0.0" } }, - "node_modules/express-basic-auth": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz", - "integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==", + "node_modules/dockerode/node_modules/tar-stream": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-2.2.0.tgz", + "integrity": "sha512-ujeqbceABgwMZxEJnk2HDY2DlnUZ+9oEcb1KzTVfYHio0UE6dG71n60d8D2I4qNvleWrrXpmjpt7vZeF1LnMZQ==", + "dev": true, "license": "MIT", "dependencies": { - "basic-auth": "^2.0.1" + "bl": "^4.0.3", + "end-of-stream": "^1.4.1", + "fs-constants": "^1.0.0", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1" + }, + "engines": { + "node": ">=6" } }, - "node_modules/express-static-gzip": { - "version": "2.1.8", - "resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.8.tgz", - "integrity": "sha512-g8tiJuI9Y9Ffy59ehVXvqb0hhP83JwZiLxzanobPaMbkB5qBWA8nuVgd+rcd5qzH3GkgogTALlc0BaADYwnMbQ==", - "license": "MIT", + "node_modules/doctrine": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz", + "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==", + "dev": true, + "license": "Apache-2.0", "dependencies": { - "serve-static": "^1.16.2" + "esutils": "^2.0.2" + }, + "engines": { + "node": ">=6.0.0" } }, - "node_modules/express/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/dom-serializer": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz", + "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==", "license": "MIT", "dependencies": { - "ms": "2.0.0" + "domelementtype": "^2.3.0", + "domhandler": "^5.0.2", + "entities": "^4.2.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/express/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", - "license": "MIT" + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "BSD-2-Clause" }, - "node_modules/express/node_modules/qs": { - "version": "6.13.0", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", - "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", - "license": "BSD-3-Clause", + "node_modules/domhandler": { + "version": "5.0.3", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz", + "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==", + "license": "BSD-2-Clause", "dependencies": { - "side-channel": "^1.0.6" + "domelementtype": "^2.3.0" }, "engines": { - "node": ">=0.6" + "node": ">= 4" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/extend": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", - "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==", + "node_modules/dompurify": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.1.7.tgz", + "integrity": "sha512-VaTstWtsneJY8xzy7DekmYWEOZcmzIe3Qb3zPd4STve1OBTa+e+WmS1ITQec1fZYXI3HCsOZZiSMpG6oxoWMWQ==", "dev": true, - "license": "MIT" + "license": "(MPL-2.0 OR Apache-2.0)" }, - "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==", - "dev": true, + "node_modules/domutils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "license": "BSD-2-Clause", "dependencies": { - "debug": "^4.1.1", - "get-stream": "^5.1.0", - "yauzl": "^2.10.0" - }, - "bin": { - "extract-zip": "cli.js" + "dom-serializer": "^2.0.0", + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3" }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "16.0.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.0.3.tgz", + "integrity": "sha512-7GO6HghkA5fYG9TYnNxi14/7K9f5occMlp3zXAuSxn7CKCxt9xbNWG7yF8hTCSUchlfWSe3uLmlPfigevRItzQ==", + "license": "BSD-2-Clause", "engines": { - "node": ">= 10.17.0" - }, - "optionalDependencies": { - "@types/yauzl": "^2.9.1" + "node": ">=12" } }, - "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==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], + "node_modules/duplexify": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/duplexify/-/duplexify-4.1.3.tgz", + "integrity": "sha512-M3BmBhwJRZsSx38lZyhE53Csddgzl5R7xGJNk7CVddZD6CcmwMCH8J+7AprIrQKH7TonKxaCjcv27Qmf+sQ+oA==", + "license": "MIT", + "dependencies": { + "end-of-stream": "^1.4.1", + "inherits": "^2.0.3", + "readable-stream": "^3.1.1", + "stream-shift": "^1.0.2" + } + }, + "node_modules/eastasianwidth": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz", + "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==", "license": "MIT" }, - "node_modules/fast-deep-equal": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", - "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", - "dev": true, + "node_modules/ecdsa-sig-formatter": { + "version": "1.0.11", + "resolved": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.11.tgz", + "integrity": "sha512-nagl3RYrbNv6kQkeJIpt6NJZy8twLB/2vtz6yN9Z4vRKHN4/QZJIEbqohALSgwKdnksuY3k5Addp5lg8sVoVcQ==", + "license": "Apache-2.0", + "dependencies": { + "safe-buffer": "^5.0.1" + } + }, + "node_modules/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==", "license": "MIT" }, - "node_modules/fast-glob": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", - "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "node_modules/electron-to-chromium": { + "version": "1.5.47", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.47.tgz", + "integrity": "sha512-zS5Yer0MOYw4rtK2iq43cJagHZ8sXN0jDHDKzB+86gSBSAI4v07S97mcq+Gs2vclAxSh1j7vOAHxSVgduiiuVQ==", "dev": true, + "license": "ISC" + }, + "node_modules/emoji-regex": { + "version": "8.0.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz", + "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==", + "license": "MIT" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", "license": "MIT", - "dependencies": { - "@nodelib/fs.stat": "^2.0.2", - "@nodelib/fs.walk": "^1.2.3", - "glob-parent": "^5.1.2", - "merge2": "^1.3.0", - "micromatch": "^4.0.4" - }, "engines": { - "node": ">=8.6.0" + "node": ">= 0.8" } }, - "node_modules/fast-glob/node_modules/glob-parent": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", - "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", - "dev": true, - "license": "ISC", + "node_modules/encoding": { + "version": "0.1.13", + "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.13.tgz", + "integrity": "sha512-ETBauow1T35Y/WZMkio9jiM0Z5xjHHmJ4XmjZOq1l/dXz3lr2sRn87nJy20RupqSh1F2m3HHPSp8ShIPQJrJ3A==", + "license": "MIT", + "optional": true, "dependencies": { - "is-glob": "^4.0.1" - }, - "engines": { - "node": ">= 6" + "iconv-lite": "^0.6.2" } }, - "node_modules/fast-json-stable-stringify": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", - "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", - "dev": true, - "license": "MIT" + "node_modules/encoding-sniffer": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz", + "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==", + "license": "MIT", + "dependencies": { + "iconv-lite": "^0.6.3", + "whatwg-encoding": "^3.1.1" + }, + "funding": { + "url": "https://github.com/fb55/encoding-sniffer?sponsor=1" + } }, - "node_modules/fast-levenshtein": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", - "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", - "dev": true, - "license": "MIT" + "node_modules/end-of-stream": { + "version": "1.4.4", + "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", + "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", + "license": "MIT", + "dependencies": { + "once": "^1.4.0" + } }, - "node_modules/fast-uri": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", - "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", - "dev": true, - "license": "BSD-3-Clause" + "node_modules/engine.io": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io/-/engine.io-6.6.2.tgz", + "integrity": "sha512-gmNvsYi9C8iErnZdVcJnvCpSKbWTt1E8+JZo8b+daLninywUWi5NQ5STSHZ9rFjFO7imNcvb8Pc5pe/wMR5xEw==", + "license": "MIT", + "dependencies": { + "@types/cookie": "^0.4.1", + "@types/cors": "^2.8.12", + "@types/node": ">=10.0.0", + "accepts": "~1.3.4", + "base64id": "2.0.0", + "cookie": "~0.7.2", + "cors": "~2.8.5", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1" + }, + "engines": { + "node": ">=10.2.0" + } }, - "node_modules/fast-xml-parser": { - "version": "4.4.1", - "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", - "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/NaturalIntelligence" - }, - { - "type": "paypal", - "url": "https://paypal.me/naturalintelligence" - } - ], + "node_modules/engine.io-client": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/engine.io-client/-/engine.io-client-6.6.2.tgz", + "integrity": "sha512-TAr+NKeoVTjEVW8P3iHguO1LO6RlUz9O5Y8o7EY0fU+gY1NYqas7NN3slpFtbXEsLMHk0h90fJMfKjRkQ0qUIw==", "license": "MIT", - "optional": true, "dependencies": { - "strnum": "^1.0.5" + "@socket.io/component-emitter": "~3.1.0", + "debug": "~4.3.1", + "engine.io-parser": "~5.2.1", + "ws": "~8.17.1", + "xmlhttprequest-ssl": "~2.1.1" + } + }, + "node_modules/engine.io-client/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" }, - "bin": { - "fxparser": "src/cli/cli.js" + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/fastest-levenshtein": { - "version": "1.0.16", - "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", - "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", - "dev": true, + "node_modules/engine.io-parser": { + "version": "5.2.3", + "resolved": "https://registry.npmjs.org/engine.io-parser/-/engine.io-parser-5.2.3.tgz", + "integrity": "sha512-HqD3yTBfnBxIrbnM1DoD6Pcq8NECnh8d4As1Qgh0z5Gg3jRRIqijury0CL3ghu/edArpUYiYqQiDUQBIs4np3Q==", "license": "MIT", "engines": { - "node": ">= 4.9.1" + "node": ">=10.0.0" } }, - "node_modules/fastfall": { - "version": "1.5.1", - "resolved": "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz", - "integrity": "sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==", - "dev": true, + "node_modules/engine.io/node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", "license": "MIT", - "dependencies": { - "reusify": "^1.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">= 0.6" } }, - "node_modules/fastparallel": { - "version": "2.4.1", - "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.1.tgz", - "integrity": "sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4", - "xtend": "^4.0.2" + "node_modules/engine.io/node_modules/ws": { + "version": "8.17.1", + "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", + "integrity": "sha512-6XQFvXTkbfUOZOKKILFG1PDK2NDQs4azKQl26T0YS5CxqWLgXajbPZ+h4gZekJyRqFU8pvnbAbbs/3TgRPy+GQ==", + "license": "MIT", + "engines": { + "node": ">=10.0.0" + }, + "peerDependencies": { + "bufferutil": "^4.0.1", + "utf-8-validate": ">=5.0.2" + }, + "peerDependenciesMeta": { + "bufferutil": { + "optional": true + }, + "utf-8-validate": { + "optional": true + } } }, - "node_modules/fastq": { - "version": "1.17.1", - "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", - "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", - "dev": true, - "license": "ISC", - "dependencies": { - "reusify": "^1.0.4" + "node_modules/entities": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz", + "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==", + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.12" + }, + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/fastseries": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-2.0.0.tgz", - "integrity": "sha512-XBU9RXeoYc2/VnvMhplAxEmZLfIk7cvTBu+xwoBuTI8pL19E03cmca17QQycKIdxgwCeFA/a4u27gv1h3ya5LQ==", - "dev": true, - "license": "ISC" + "node_modules/env-paths": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/env-paths/-/env-paths-2.2.1.tgz", + "integrity": "sha512-+h1lkLKhZMTYjog1VEpJNG7NZJWcuc2DDk/qsqSTRRCOXiLjeQ1d1/udrUGhqMxUgAlwKNZ0cf2uqan5GLuS2A==", + "license": "MIT", + "optional": true, + "engines": { + "node": ">=6" + } }, - "node_modules/favico.js": { - "version": "0.3.10", - "resolved": "https://registry.npmjs.org/favico.js/-/favico.js-0.3.10.tgz", - "integrity": "sha512-S5KvqAOczRjlyjQPPZPSlUEybBkfBgKosY/pzTIxkvKgigB+DkITvIEI70dxQarbv4PZ+UD77QzquCAcU/6LHQ==", - "dev": true, - "license": "MIT" + "node_modules/err-code": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/err-code/-/err-code-2.0.3.tgz", + "integrity": "sha512-2bmlRpNKBxT/CRmPOlyISQpNj+qSeYvcym/uT0Jx2bMOlKLtSy1ZmLuVxSEKKyor/N5yhvp/ZiG1oE3DEYMSFA==", + "license": "MIT", + "optional": true }, - "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==", + "node_modules/error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", "dev": true, - "license": "Apache-2.0", + "license": "MIT", "dependencies": { - "bser": "2.1.1" + "is-arrayish": "^0.2.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==", + "node_modules/error-stack-parser-es": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/error-stack-parser-es/-/error-stack-parser-es-0.1.5.tgz", + "integrity": "sha512-xHku1X40RO+fO8yJ8Wh2f2rZWVjqyhb1zgq1yZ8aZRQkv6OOKhKWRUaht3eSCUbAOBaKIgM+ykwFLE+QUxgGeg==", "dev": true, "license": "MIT", - "dependencies": { - "pend": "~1.2.0" + "funding": { + "url": "https://github.com/sponsors/antfu" } }, - "node_modules/figures": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz", - "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==", + "node_modules/es-abstract": { + "version": "1.23.3", + "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz", + "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==", "dev": true, "license": "MIT", "dependencies": { - "escape-string-regexp": "^1.0.5" + "array-buffer-byte-length": "^1.0.1", + "arraybuffer.prototype.slice": "^1.0.3", + "available-typed-arrays": "^1.0.7", + "call-bind": "^1.0.7", + "data-view-buffer": "^1.0.1", + "data-view-byte-length": "^1.0.1", + "data-view-byte-offset": "^1.0.0", + "es-define-property": "^1.0.0", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.0.0", + "es-set-tostringtag": "^2.0.3", + "es-to-primitive": "^1.2.1", + "function.prototype.name": "^1.1.6", + "get-intrinsic": "^1.2.4", + "get-symbol-description": "^1.0.2", + "globalthis": "^1.0.3", + "gopd": "^1.0.1", + "has-property-descriptors": "^1.0.2", + "has-proto": "^1.0.3", + "has-symbols": "^1.0.3", + "hasown": "^2.0.2", + "internal-slot": "^1.0.7", + "is-array-buffer": "^3.0.4", + "is-callable": "^1.2.7", + "is-data-view": "^1.0.1", + "is-negative-zero": "^2.0.3", + "is-regex": "^1.1.4", + "is-shared-array-buffer": "^1.0.3", + "is-string": "^1.0.7", + "is-typed-array": "^1.1.13", + "is-weakref": "^1.0.2", + "object-inspect": "^1.13.1", + "object-keys": "^1.1.1", + "object.assign": "^4.1.5", + "regexp.prototype.flags": "^1.5.2", + "safe-array-concat": "^1.1.2", + "safe-regex-test": "^1.0.3", + "string.prototype.trim": "^1.2.9", + "string.prototype.trimend": "^1.0.8", + "string.prototype.trimstart": "^1.0.8", + "typed-array-buffer": "^1.0.2", + "typed-array-byte-length": "^1.0.1", + "typed-array-byte-offset": "^1.0.2", + "typed-array-length": "^1.0.6", + "unbox-primitive": "^1.0.2", + "which-typed-array": "^1.1.15" }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/figures/node_modules/escape-string-regexp": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", - "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==", - "dev": true, + "node_modules/es-define-property": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz", + "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==", "license": "MIT", + "dependencies": { + "get-intrinsic": "^1.2.4" + }, "engines": { - "node": ">=0.8.0" + "node": ">= 0.4" } }, - "node_modules/file-entry-cache": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", - "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "license": "MIT", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz", + "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==", "dev": true, "license": "MIT", "dependencies": { - "flat-cache": "^3.0.4" + "es-errors": "^1.3.0" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": ">= 0.4" } }, - "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "node_modules/es-set-tostringtag": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz", + "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==", "dev": true, "license": "MIT", "dependencies": { - "to-regex-range": "^5.0.1" + "get-intrinsic": "^1.2.4", + "has-tostringtag": "^1.0.2", + "hasown": "^2.0.1" }, "engines": { - "node": ">=8" + "node": ">= 0.4" } }, - "node_modules/finalhandler": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", - "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", + "node_modules/es-to-primitive": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz", + "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==", + "dev": true, "license": "MIT", "dependencies": { - "debug": "2.6.9", - "encodeurl": "~2.0.0", - "escape-html": "~1.0.3", - "on-finished": "2.4.1", - "parseurl": "~1.3.3", - "statuses": "2.0.1", - "unpipe": "~1.0.0" + "is-callable": "^1.1.4", + "is-date-object": "^1.0.1", + "is-symbol": "^1.0.2" }, "engines": { - "node": ">= 0.8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/esbuild": { + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.20.2.tgz", + "integrity": "sha512-WdOOppmUNU+IbZ0PaDiTst80zjnrOkyJNHoKupIcVyU8Lvla3Ugx94VzkQ32Ijqd7UhHJy75gNWDMUekcrSJ6g==", + "dev": true, + "hasInstallScript": true, + "license": "MIT", + "bin": { + "esbuild": "bin/esbuild" + }, + "engines": { + "node": ">=12" + }, + "optionalDependencies": { + "@esbuild/aix-ppc64": "0.20.2", + "@esbuild/android-arm": "0.20.2", + "@esbuild/android-arm64": "0.20.2", + "@esbuild/android-x64": "0.20.2", + "@esbuild/darwin-arm64": "0.20.2", + "@esbuild/darwin-x64": "0.20.2", + "@esbuild/freebsd-arm64": "0.20.2", + "@esbuild/freebsd-x64": "0.20.2", + "@esbuild/linux-arm": "0.20.2", + "@esbuild/linux-arm64": "0.20.2", + "@esbuild/linux-ia32": "0.20.2", + "@esbuild/linux-loong64": "0.20.2", + "@esbuild/linux-mips64el": "0.20.2", + "@esbuild/linux-ppc64": "0.20.2", + "@esbuild/linux-riscv64": "0.20.2", + "@esbuild/linux-s390x": "0.20.2", + "@esbuild/linux-x64": "0.20.2", + "@esbuild/netbsd-x64": "0.20.2", + "@esbuild/openbsd-x64": "0.20.2", + "@esbuild/sunos-x64": "0.20.2", + "@esbuild/win32-arm64": "0.20.2", + "@esbuild/win32-ia32": "0.20.2", + "@esbuild/win32-x64": "0.20.2" } }, - "node_modules/finalhandler/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/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", "license": "MIT", - "dependencies": { - "ms": "2.0.0" + "engines": { + "node": ">=6" } }, - "node_modules/finalhandler/node_modules/ms": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", "license": "MIT" }, - "node_modules/find-up": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", - "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "node_modules/escape-string-regexp": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz", + "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==", "dev": true, "license": "MIT", - "dependencies": { - "locate-path": "^5.0.0", - "path-exists": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/flat-cache": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", - "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "node_modules/eslint": { + "version": "8.14.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.14.0.tgz", + "integrity": "sha512-3/CE4aJX7LNEiE3i6FeodHmI/38GZtWCsAtsymScmzYapx8q1nVVb+eLcLSzATmCPXw5pT4TqVs1E0OmxAd9tw==", + "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.", "dev": true, "license": "MIT", "dependencies": { - "flatted": "^3.2.9", - "keyv": "^4.5.3", - "rimraf": "^3.0.2" + "@eslint/eslintrc": "^1.2.2", + "@humanwhocodes/config-array": "^0.9.2", + "ajv": "^6.10.0", + "chalk": "^4.0.0", + "cross-spawn": "^7.0.2", + "debug": "^4.3.2", + "doctrine": "^3.0.0", + "escape-string-regexp": "^4.0.0", + "eslint-scope": "^7.1.1", + "eslint-utils": "^3.0.0", + "eslint-visitor-keys": "^3.3.0", + "espree": "^9.3.1", + "esquery": "^1.4.0", + "esutils": "^2.0.2", + "fast-deep-equal": "^3.1.3", + "file-entry-cache": "^6.0.1", + "functional-red-black-tree": "^1.0.1", + "glob-parent": "^6.0.1", + "globals": "^13.6.0", + "ignore": "^5.2.0", + "import-fresh": "^3.0.0", + "imurmurhash": "^0.1.4", + "is-glob": "^4.0.0", + "js-yaml": "^4.1.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.4.1", + "lodash.merge": "^4.6.2", + "minimatch": "^3.0.4", + "natural-compare": "^1.4.0", + "optionator": "^0.9.1", + "regexpp": "^3.2.0", + "strip-ansi": "^6.0.1", + "strip-json-comments": "^3.1.0", + "text-table": "^0.2.0", + "v8-compile-cache": "^2.0.3" + }, + "bin": { + "eslint": "bin/eslint.js" }, "engines": { - "node": "^10.12.0 || >=12.0.0" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/flatted": { - "version": "3.3.2", - "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.2.tgz", - "integrity": "sha512-AiwGJM8YcNOaobumgtng+6NHuOqC3A7MixFeDafM3X9cIUM+xUXoS5Vfgf+OihAYe20fxqNM9yPBXJzRtZ/4eA==", + "node_modules/eslint-plugin-jsdoc": { + "version": "46.4.6", + "resolved": "https://registry.npmjs.org/eslint-plugin-jsdoc/-/eslint-plugin-jsdoc-46.4.6.tgz", + "integrity": "sha512-z4SWYnJfOqftZI+b3RM9AtWL1vF/sLWE/LlO9yOKDof9yN2+n3zOdOJTGX/pRE/xnPsooOLG2Rq6e4d+XW3lNw==", "dev": true, - "license": "ISC" - }, - "node_modules/follow-redirects": { - "version": "1.15.9", - "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", - "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/RubenVerborgh" - } - ], - "license": "MIT", + "license": "BSD-3-Clause", + "dependencies": { + "@es-joy/jsdoccomment": "~0.40.1", + "are-docs-informative": "^0.0.2", + "comment-parser": "1.4.0", + "debug": "^4.3.4", + "escape-string-regexp": "^4.0.0", + "esquery": "^1.5.0", + "is-builtin-module": "^3.2.1", + "semver": "^7.5.4", + "spdx-expression-parse": "^3.0.1" + }, "engines": { - "node": ">=4.0" + "node": ">=16" }, - "peerDependenciesMeta": { - "debug": { - "optional": true - } + "peerDependencies": { + "eslint": "^7.0.0 || ^8.0.0" } }, - "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==", + "node_modules/eslint-plugin-vue": { + "version": "8.7.1", + "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-8.7.1.tgz", + "integrity": "sha512-28sbtm4l4cOzoO1LtzQPxfxhQABararUb1JtqusQqObJpWX2e/gmVyeYVfepizPFne0Q5cILkYGiBoV36L12Wg==", + "dev": true, "license": "MIT", "dependencies": { - "is-callable": "^1.1.3" - } - }, - "node_modules/foreground-child": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", - "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", - "license": "ISC", - "dependencies": { - "cross-spawn": "^7.0.0", - "signal-exit": "^4.0.1" + "eslint-utils": "^3.0.0", + "natural-compare": "^1.4.0", + "nth-check": "^2.0.1", + "postcss-selector-parser": "^6.0.9", + "semver": "^7.3.5", + "vue-eslint-parser": "^8.0.1" }, "engines": { - "node": ">=14" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependencies": { + "eslint": "^6.2.0 || ^7.0.0 || ^8.0.0" } }, - "node_modules/foreground-child/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "license": "ISC", + "node_modules/eslint-scope": { + "version": "7.2.2", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", + "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", + "dev": true, + "license": "BSD-2-Clause", + "dependencies": { + "esrecurse": "^4.3.0", + "estraverse": "^5.2.0" + }, "engines": { - "node": ">=14" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/isaacs" + "url": "https://opencollective.com/eslint" } }, - "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==", + "node_modules/eslint-utils": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-3.0.0.tgz", + "integrity": "sha512-uuQC43IGctw68pJA1RgbQS8/NP7rch6Cwd4j3ZBtgo4/8Flj4eGE7ZYSZRN3iq5pVUv6GPdW5Z1RFleo84uLDA==", "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "*" - } - }, - "node_modules/form-data": { - "version": "4.0.1", - "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", - "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "license": "MIT", "dependencies": { - "asynckit": "^0.4.0", - "combined-stream": "^1.0.8", - "mime-types": "^2.1.12" + "eslint-visitor-keys": "^2.0.0" }, "engines": { - "node": ">= 6" - } - }, - "node_modules/form-data-encoder": { - "version": "1.7.1", - "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz", - "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==", - "license": "MIT" - }, - "node_modules/forwarded": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", - "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", - "license": "MIT", - "engines": { - "node": ">= 0.6" + "node": "^10.0.0 || ^12.0.0 || >= 14.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/mysticatea" + }, + "peerDependencies": { + "eslint": ">=5" } }, - "node_modules/fresh": { - "version": "0.5.2", - "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", - "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", - "license": "MIT", + "node_modules/eslint-utils/node_modules/eslint-visitor-keys": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz", + "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==", + "dev": true, + "license": "Apache-2.0", "engines": { - "node": ">= 0.6" + "node": ">=10" } }, - "node_modules/from2": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", - "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", + "node_modules/eslint-visitor-keys": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", + "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", "dev": true, - "license": "MIT", - "dependencies": { - "inherits": "^2.0.1", - "readable-stream": "^2.0.0" + "license": "Apache-2.0", + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/from2/node_modules/isarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", - "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/from2/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==", + "node_modules/eslint/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==", "dev": true, "license": "MIT", "dependencies": { - "core-util-is": "~1.0.0", - "inherits": "~2.0.3", - "isarray": "~1.0.0", - "process-nextick-args": "~2.0.0", - "safe-buffer": "~5.1.1", - "string_decoder": "~1.1.1", - "util-deprecate": "~1.0.1" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" } }, - "node_modules/from2/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/eslint/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", "dev": true, - "license": "MIT" + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" + }, + "engines": { + "node": "*" + } }, - "node_modules/from2/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==", - "dev": true, + "node_modules/esm": { + "version": "3.2.25", + "resolved": "https://registry.npmjs.org/esm/-/esm-3.2.25.tgz", + "integrity": "sha512-U1suiZ2oDVWv4zPO56S0NcR5QriEahGtdN2OR6FiOG4WJvcjBVFB0qI4+eKoWFH483PKGuLuu6V8Z4T5g63UVA==", "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/espree": { + "version": "9.6.1", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.6.1.tgz", + "integrity": "sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "safe-buffer": "~5.1.0" + "acorn": "^8.9.0", + "acorn-jsx": "^5.3.2", + "eslint-visitor-keys": "^3.4.1" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + }, + "funding": { + "url": "https://opencollective.com/eslint" } }, - "node_modules/fs-extra": { - "version": "9.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz", - "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==", + "node_modules/esquery": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz", + "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==", "dev": true, - "license": "MIT", + "license": "BSD-3-Clause", "dependencies": { - "at-least-node": "^1.0.0", - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" + "estraverse": "^5.1.0" }, "engines": { - "node": ">=10" + "node": ">=0.10" } }, - "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==", - "license": "ISC", + "node_modules/esrecurse": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz", + "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==", + "dev": true, + "license": "BSD-2-Clause", "dependencies": { - "minipass": "^3.0.0" + "estraverse": "^5.2.0" }, "engines": { - "node": ">= 8" + "node": ">=4.0" } }, - "node_modules/fs.realpath": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", - "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==", - "license": "ISC" + "node_modules/estraverse": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", + "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=4.0" + } }, - "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/estree-walker": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz", + "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==", "dev": true, - "hasInstallScript": true, + "license": "MIT" + }, + "node_modules/esutils": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz", + "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==", + "dev": true, + "license": "BSD-2-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", "license": "MIT", - "optional": true, - "os": [ - "darwin" - ], "engines": { - "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + "node": ">= 0.6" } }, - "node_modules/function-bind": { - "version": "1.1.2", - "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", - "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "node_modules/event-target-shim": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz", + "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==", "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=6" } }, - "node_modules/function.prototype.name": { - "version": "1.1.8", - "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz", - "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==", + "node_modules/event-to-promise": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/event-to-promise/-/event-to-promise-0.7.0.tgz", + "integrity": "sha512-VOBBfyaADfe378ZzG0tgkzmsvzUyeU5arehrFzNRt5yaASUDshgctTwSrPI17ocAwR3+YftsxRClHF+GBKFByQ==", + "deprecated": "Use promise-toolbox/fromEvent instead", + "license": "MIT" + }, + "node_modules/events": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz", + "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==", + "license": "MIT", + "engines": { + "node": ">=0.8.x" + } + }, + "node_modules/execa": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/execa/-/execa-8.0.1.tgz", + "integrity": "sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "define-properties": "^1.2.1", - "functions-have-names": "^1.2.3", - "hasown": "^2.0.2", - "is-callable": "^1.2.7" + "cross-spawn": "^7.0.3", + "get-stream": "^8.0.1", + "human-signals": "^5.0.0", + "is-stream": "^3.0.0", + "merge-stream": "^2.0.0", + "npm-run-path": "^5.1.0", + "onetime": "^6.0.0", + "signal-exit": "^4.1.0", + "strip-final-newline": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=16.17" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sindresorhus/execa?sponsor=1" } }, - "node_modules/functional-red-black-tree": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", - "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "node_modules/execa/node_modules/get-stream": { + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-8.0.1.tgz", + "integrity": "sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA==", "dev": true, - "license": "MIT" - }, - "node_modules/functions-have-names": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", - "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "license": "MIT", + "engines": { + "node": ">=16" + }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/gamedig": { - "version": "4.3.2", - "resolved": "https://registry.npmjs.org/gamedig/-/gamedig-4.3.2.tgz", - "integrity": "sha512-TjYwybvy8HNAhkv2EJccd5HROIiMeMriWmeX8vT8m5Ibat5JMzVpugzsD8L8XZVrOfiXnVg/9DhWYM8k/VG/vw==", + "node_modules/execa/node_modules/is-stream": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-3.0.0.tgz", + "integrity": "sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA==", + "dev": true, "license": "MIT", - "dependencies": { - "cheerio": "1.0.0-rc.10", - "gbxremote": "0.2.1", - "got": "12.1.0", - "iconv-lite": "0.6.3", - "long": "5.2.0", - "minimist": "1.2.6", - "punycode": "2.1.1", - "seek-bzip": "2.0.0", - "varint": "6.0.0" - }, - "bin": { - "gamedig": "bin/gamedig.js" + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/execa/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", "engines": { - "node": ">=14.0.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/gamedig/node_modules/cheerio": { - "version": "1.0.0-rc.10", - "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", - "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", + "node_modules/express": { + "version": "4.21.1", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.1.tgz", + "integrity": "sha512-YSFlK1Ee0/GC8QaO91tHcDxJiE/X4FbpAyQWkxAvG6AXCuR65YzK8ua6D9hvi/TzUfZMpc+BwuM1IPw8fmQBiQ==", "license": "MIT", "dependencies": { - "cheerio-select": "^1.5.0", - "dom-serializer": "^1.3.2", - "domhandler": "^4.2.0", - "htmlparser2": "^6.1.0", - "parse5": "^6.0.1", - "parse5-htmlparser2-tree-adapter": "^6.0.1", - "tslib": "^2.2.0" + "accepts": "~1.3.8", + "array-flatten": "1.1.1", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", + "content-type": "~1.0.4", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "2.0.0", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", + "merge-descriptors": "1.0.3", + "methods": "~1.1.2", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "path-to-regexp": "0.1.10", + "proxy-addr": "~2.0.7", + "qs": "6.13.0", + "range-parser": "~1.2.1", + "safe-buffer": "5.2.1", + "send": "0.19.0", + "serve-static": "1.16.2", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "type-is": "~1.6.18", + "utils-merge": "1.0.1", + "vary": "~1.1.2" }, "engines": { - "node": ">= 6" - }, - "funding": { - "url": "https://github.com/cheeriojs/cheerio?sponsor=1" + "node": ">= 0.10.0" } }, - "node_modules/gamedig/node_modules/cheerio-select": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", - "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", - "license": "BSD-2-Clause", + "node_modules/express-basic-auth": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/express-basic-auth/-/express-basic-auth-1.2.1.tgz", + "integrity": "sha512-L6YQ1wQ/mNjVLAmK3AG1RK6VkokA1BIY6wmiH304Xtt/cLTps40EusZsU1Uop+v9lTDPxdtzbFmdXfFO3KEnwA==", + "license": "MIT", "dependencies": { - "css-select": "^4.3.0", - "css-what": "^6.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.3.1", - "domutils": "^2.8.0" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "basic-auth": "^2.0.1" } }, - "node_modules/gamedig/node_modules/css-select": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", - "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", - "license": "BSD-2-Clause", + "node_modules/express-static-gzip": { + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/express-static-gzip/-/express-static-gzip-2.1.8.tgz", + "integrity": "sha512-g8tiJuI9Y9Ffy59ehVXvqb0hhP83JwZiLxzanobPaMbkB5qBWA8nuVgd+rcd5qzH3GkgogTALlc0BaADYwnMbQ==", + "license": "MIT", "dependencies": { - "boolbase": "^1.0.0", - "css-what": "^6.0.1", - "domhandler": "^4.3.1", - "domutils": "^2.8.0", - "nth-check": "^2.0.1" - }, - "funding": { - "url": "https://github.com/sponsors/fb55" + "serve-static": "^1.16.2" } }, - "node_modules/gamedig/node_modules/dom-serializer": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", - "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "node_modules/express/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.2.0", - "entities": "^2.0.0" - }, - "funding": { - "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + "ms": "2.0.0" } }, - "node_modules/gamedig/node_modules/domhandler": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", - "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", - "license": "BSD-2-Clause", + "node_modules/express/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/express/node_modules/qs": { + "version": "6.13.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.13.0.tgz", + "integrity": "sha512-+38qI9SOr8tfZ4QmJNplMUxqjbe7LKvvZgWdExBOmd+egZTtjLB67Gu0HRX3u/XOq7UU2Nx6nsjvS16Z9uwfpg==", + "license": "BSD-3-Clause", "dependencies": { - "domelementtype": "^2.2.0" + "side-channel": "^1.0.6" }, "engines": { - "node": ">= 4" - }, - "funding": { - "url": "https://github.com/fb55/domhandler?sponsor=1" - } - }, - "node_modules/gamedig/node_modules/domutils": { - "version": "2.8.0", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", - "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", - "license": "BSD-2-Clause", - "dependencies": { - "dom-serializer": "^1.0.1", - "domelementtype": "^2.2.0", - "domhandler": "^4.2.0" + "node": ">=0.6" }, "funding": { - "url": "https://github.com/fb55/domutils?sponsor=1" - } - }, - "node_modules/gamedig/node_modules/entities": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", - "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", - "license": "BSD-2-Clause", - "funding": { - "url": "https://github.com/fb55/entities?sponsor=1" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/gamedig/node_modules/htmlparser2": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", - "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", + "node_modules/express/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", "funding": [ - "https://github.com/fb55/htmlparser2?sponsor=1", { "type": "github", - "url": "https://github.com/sponsors/fb55" + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" } ], - "license": "MIT", - "dependencies": { - "domelementtype": "^2.0.1", - "domhandler": "^4.0.0", - "domutils": "^2.5.2", - "entities": "^2.0.0" - } - }, - "node_modules/gamedig/node_modules/long": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/long/-/long-5.2.0.tgz", - "integrity": "sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==", - "license": "Apache-2.0" + "license": "MIT" }, - "node_modules/gamedig/node_modules/minimist": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", - "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "node_modules/fast-deep-equal": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz", + "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==", + "dev": true, "license": "MIT" }, - "node_modules/gamedig/node_modules/parse5": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", - "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "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==", + "dev": true, "license": "MIT" }, - "node_modules/gamedig/node_modules/parse5-htmlparser2-tree-adapter": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", - "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", + "node_modules/fast-glob": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz", + "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==", + "dev": true, "license": "MIT", "dependencies": { - "parse5": "^6.0.1" + "@nodelib/fs.stat": "^2.0.2", + "@nodelib/fs.walk": "^1.2.3", + "glob-parent": "^5.1.2", + "merge2": "^1.3.0", + "micromatch": "^4.0.4" + }, + "engines": { + "node": ">=8.6.0" } }, - "node_modules/gauge": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", - "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", - "deprecated": "This package is no longer supported.", + "node_modules/fast-glob/node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dev": true, "license": "ISC", "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" + "is-glob": "^4.0.1" }, "engines": { - "node": ">=10" + "node": ">= 6" } }, - "node_modules/gbxremote": { - "version": "0.2.1", - "resolved": "https://registry.npmjs.org/gbxremote/-/gbxremote-0.2.1.tgz", - "integrity": "sha512-SMehu6Y6ndq2Qgp9VxAb8Np3f+UUD+RWoW2SAMaxzGS96rWXyr4T1GGkecO0HHtxeH1m7pEh4FJWB8a/6aM2XQ==", + "node_modules/fast-json-stable-stringify": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz", + "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==", + "dev": true, + "license": "MIT" + }, + "node_modules/fast-uri": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz", + "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw==", + "dev": true, + "license": "BSD-3-Clause" + }, + "node_modules/fast-xml-parser": { + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.4.1.tgz", + "integrity": "sha512-xkjOecfnKGkSsOwtZ5Pz7Us/T6mrbPQrq0nh+aCO5V9nk5NLWmasAHumTKjiPJPWANe+kAZ84Jc8ooJkzZ88Sw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/NaturalIntelligence" + }, + { + "type": "paypal", + "url": "https://paypal.me/naturalintelligence" + } + ], + "license": "MIT", + "optional": true, "dependencies": { - "any-promise": "^1.1.0", - "barse": "~0.4.2", - "event-to-promise": "^0.7.0", - "string-to-stream": "^1.0.1", - "xmlrpc": "^1.3.1" + "strnum": "^1.0.5" + }, + "bin": { + "fxparser": "src/cli/cli.js" + } + }, + "node_modules/fastest-levenshtein": { + "version": "1.0.16", + "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz", + "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 4.9.1" + } + }, + "node_modules/fastfall": { + "version": "1.5.1", + "resolved": "https://registry.npmjs.org/fastfall/-/fastfall-1.5.1.tgz", + "integrity": "sha512-KH6p+Z8AKPXnmA7+Iz2Lh8ARCMr+8WNPVludm1LGkZoD2MjY6LVnRMtTKhkdzI+jr0RzQWXKzKyBJm1zoHEL4Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "reusify": "^1.0.0" }, "engines": { - "node": ">=0.10" + "node": ">=0.10.0" } }, - "node_modules/generate-function": { - "version": "2.3.1", - "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", - "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", - "license": "MIT", + "node_modules/fastparallel": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/fastparallel/-/fastparallel-2.4.1.tgz", + "integrity": "sha512-qUmhxPgNHmvRjZKBFUNI0oZuuH9OlSIOXmJ98lhKPxMZZ7zS/Fi0wRHOihDSz0R1YiIOjxzOY4bq65YTcdBi2Q==", + "dev": true, + "license": "ISC", "dependencies": { - "is-property": "^1.0.2" + "reusify": "^1.0.4", + "xtend": "^4.0.2" } }, - "node_modules/generic-pool": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", - "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", + "node_modules/fastq": { + "version": "1.17.1", + "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz", + "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==", + "dev": true, + "license": "ISC", + "dependencies": { + "reusify": "^1.0.4" + } + }, + "node_modules/fastseries": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fastseries/-/fastseries-2.0.0.tgz", + "integrity": "sha512-XBU9RXeoYc2/VnvMhplAxEmZLfIk7cvTBu+xwoBuTI8pL19E03cmca17QQycKIdxgwCeFA/a4u27gv1h3ya5LQ==", + "dev": true, + "license": "ISC" + }, + "node_modules/favico.js": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/favico.js/-/favico.js-0.3.10.tgz", + "integrity": "sha512-S5KvqAOczRjlyjQPPZPSlUEybBkfBgKosY/pzTIxkvKgigB+DkITvIEI70dxQarbv4PZ+UD77QzquCAcU/6LHQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/feed": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/feed/-/feed-4.2.2.tgz", + "integrity": "sha512-u5/sxGfiMfZNtJ3OvQpXcvotFpYkL0n9u9mM2vkui2nGo8b4wvDkJ8gAkYqbA8QpGyFCv3RK0Z+Iv+9veCS9bQ==", "license": "MIT", + "dependencies": { + "xml-js": "^1.6.11" + }, "engines": { - "node": ">= 4" + "node": ">=0.4.0" } }, - "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==", + "node_modules/file-entry-cache": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-6.0.1.tgz", + "integrity": "sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg==", "dev": true, "license": "MIT", + "dependencies": { + "flat-cache": "^3.0.4" + }, "engines": { - "node": ">=6.9.0" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/get-caller-file": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", - "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", - "license": "ISC", + "node_modules/fill-range": { + "version": "7.1.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", + "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", + "dev": true, + "license": "MIT", + "dependencies": { + "to-regex-range": "^5.0.1" + }, "engines": { - "node": "6.* || 8.* || >= 10.*" + "node": ">=8" } }, - "node_modules/get-intrinsic": { - "version": "1.2.6", - "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.6.tgz", - "integrity": "sha512-qxsEs+9A+u85HhllWJJFicJfPDhRmjzoYdl64aMWW9yRIJmSyxdn8IEkuIM530/7T+lv0TIHd8L6Q/ra0tEoeA==", + "node_modules/finalhandler": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.1.tgz", + "integrity": "sha512-6BN9trH7bp3qvnrRyzsBz+g3lZxTNZTbVO2EV1CS0WIcDbawYVdYvGflME/9QP0h0pYlCDBCTjYa9nZzMDpyxQ==", "license": "MIT", "dependencies": { - "call-bind-apply-helpers": "^1.0.1", - "dunder-proto": "^1.0.0", - "es-define-property": "^1.0.1", - "es-errors": "^1.3.0", - "es-object-atoms": "^1.0.0", - "function-bind": "^1.1.2", - "gopd": "^1.2.0", - "has-symbols": "^1.1.0", - "hasown": "^2.0.2", - "math-intrinsics": "^1.0.0" + "debug": "2.6.9", + "encodeurl": "~2.0.0", + "escape-html": "~1.0.3", + "on-finished": "2.4.1", + "parseurl": "~1.3.3", + "statuses": "2.0.1", + "unpipe": "~1.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 0.8" } }, - "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==", + "node_modules/finalhandler/node_modules/debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", "license": "MIT", - "engines": { - "node": ">=8.0.0" + "dependencies": { + "ms": "2.0.0" } }, - "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==", + "node_modules/finalhandler/node_modules/ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==", + "license": "MIT" + }, + "node_modules/find-up": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", + "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", + "dev": true, "license": "MIT", "dependencies": { - "pump": "^3.0.0" + "locate-path": "^6.0.0", + "path-exists": "^4.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/get-symbol-description": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz", - "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==", + "node_modules/flat-cache": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-3.2.0.tgz", + "integrity": "sha512-CYcENa+FtcUKLmhhqyctpclsq7QF38pKjZHsGNiSQF5r4FtoKDWabFDl3hzaEQMvT1LHEysw5twgLvpYYb4vbw==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6" + "flatted": "^3.2.9", + "keyv": "^4.5.3", + "rimraf": "^3.0.2" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": "^10.12.0 || >=12.0.0" } }, - "node_modules/getopts": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", - "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==", - "license": "MIT" - }, - "node_modules/getos": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/getos/-/getos-3.2.1.tgz", - "integrity": "sha512-U56CfOK17OKgTVqozZjUKNdkfEv6jk5WISBJ8SHoagjE6L69zOwl3Z+O8myjY9MEW3i2HPWQBt/LTbCgcC973Q==", + "node_modules/flatted": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz", + "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==", "dev": true, + "license": "ISC" + }, + "node_modules/follow-redirects": { + "version": "1.15.9", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz", + "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==", + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], "license": "MIT", - "dependencies": { - "async": "^3.2.0" + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } } }, - "node_modules/getpass": { - "version": "0.1.7", - "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", - "integrity": "sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==", + "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==", "dev": true, "license": "MIT", "dependencies": { - "assert-plus": "^1.0.0" + "is-callable": "^1.1.3" } }, - "node_modules/glob": { - "version": "7.2.3", - "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", - "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", - "deprecated": "Glob versions prior to v9 are no longer supported", + "node_modules/foreground-child": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz", + "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==", "license": "ISC", "dependencies": { - "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" + "cross-spawn": "^7.0.0", + "signal-exit": "^4.0.1" }, "engines": { - "node": "*" + "node": ">=14" }, "funding": { "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/glob-parent": { - "version": "6.0.2", - "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", - "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", - "dev": true, + "node_modules/foreground-child/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", "license": "ISC", - "dependencies": { - "is-glob": "^4.0.3" - }, "engines": { - "node": ">=10.13.0" + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/global-dirs": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/global-dirs/-/global-dirs-3.0.1.tgz", - "integrity": "sha512-NBcGGFbBA9s1VzD41QXDG+3++t9Mn5t1FpLdhESY6oKY4gYTFpX4wO3sqGUa0Srjtbfj3szX0RnemmrVRUdULA==", - "dev": true, + "node_modules/form-data": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz", + "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==", "license": "MIT", "dependencies": { - "ini": "2.0.0" + "asynckit": "^0.4.0", + "combined-stream": "^1.0.8", + "mime-types": "^2.1.12" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 6" } }, - "node_modules/global-modules": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", - "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", - "dev": true, + "node_modules/form-data-encoder": { + "version": "1.7.1", + "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.1.tgz", + "integrity": "sha512-EFRDrsMm/kyqbTQocNvRXMLjc7Es2Vk+IQFx/YW7hkUH1eBl4J1fqiP34l74Yt0pFLCNpc06fkbVk00008mzjg==", + "license": "MIT" + }, + "node_modules/forwarded": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz", + "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==", + "license": "MIT", + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==", "license": "MIT", - "dependencies": { - "global-prefix": "^3.0.0" - }, "engines": { - "node": ">=6" + "node": ">= 0.6" } }, - "node_modules/global-prefix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", - "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "node_modules/from2": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz", + "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==", "dev": true, "license": "MIT", "dependencies": { - "ini": "^1.3.5", - "kind-of": "^6.0.2", - "which": "^1.3.1" - }, - "engines": { - "node": ">=6" + "inherits": "^2.0.1", + "readable-stream": "^2.0.0" } }, - "node_modules/global-prefix/node_modules/ini": { - "version": "1.3.8", - "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", - "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", + "node_modules/from2/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", "dev": true, - "license": "ISC" + "license": "MIT" }, - "node_modules/global-prefix/node_modules/which": { - "version": "1.3.1", - "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", - "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "node_modules/from2/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==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "isexe": "^2.0.0" - }, - "bin": { - "which": "bin/which" + "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/globals": { - "version": "11.12.0", - "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz", - "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==", + "node_modules/from2/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==", "dev": true, "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/globalthis": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", - "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", - "license": "MIT", "dependencies": { - "define-properties": "^1.2.1", - "gopd": "^1.0.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "safe-buffer": "~5.1.0" } }, - "node_modules/globby": { - "version": "11.1.0", - "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", - "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "node_modules/fs-constants": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs-constants/-/fs-constants-1.0.0.tgz", + "integrity": "sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==", + "dev": true, + "license": "MIT" + }, + "node_modules/fs-extra": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", + "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", "dev": true, "license": "MIT", "dependencies": { - "array-union": "^2.1.0", - "dir-glob": "^3.0.1", - "fast-glob": "^3.2.9", - "ignore": "^5.2.0", - "merge2": "^1.4.1", - "slash": "^3.0.0" + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=12" } }, - "node_modules/globjoin": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", - "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", + "node_modules/fs-extra/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", "dev": true, - "license": "MIT" - }, - "node_modules/gopd": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", - "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", "license": "MIT", "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 10.0.0" } }, - "node_modules/got": { - "version": "12.1.0", - "resolved": "https://registry.npmjs.org/got/-/got-12.1.0.tgz", - "integrity": "sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==", - "license": "MIT", + "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==", + "license": "ISC", "dependencies": { - "@sindresorhus/is": "^4.6.0", - "@szmarczak/http-timer": "^5.0.1", - "@types/cacheable-request": "^6.0.2", - "@types/responselike": "^1.0.0", - "cacheable-lookup": "^6.0.4", - "cacheable-request": "^7.0.2", - "decompress-response": "^6.0.0", - "form-data-encoder": "1.7.1", - "get-stream": "^6.0.1", - "http2-wrapper": "^2.1.10", - "lowercase-keys": "^3.0.0", - "p-cancelable": "^3.0.0", - "responselike": "^2.0.0" - }, - "engines": { - "node": ">=14.16" + "minipass": "^3.0.0" }, - "funding": { - "url": "https://github.com/sindresorhus/got?sponsor=1" - } - }, - "node_modules/got/node_modules/get-stream": { - "version": "6.0.1", - "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", - "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", - "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 8" } }, - "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==", - "devOptional": 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==", "license": "ISC" }, - "node_modules/hard-rejection": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", - "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "node_modules/fsevents": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz", + "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==", "dev": true, + "hasInstallScript": true, "license": "MIT", + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=6" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, - "node_modules/has-bigints": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz", - "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==", + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/function.prototype.name": { + "version": "1.1.6", + "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz", + "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.2", + "define-properties": "^1.2.0", + "es-abstract": "^1.22.1", + "functions-have-names": "^1.2.3" + }, "engines": { "node": ">= 0.4" }, @@ -11487,161 +9153,155 @@ "url": "https://github.com/sponsors/ljharb" } }, - "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/functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==", + "dev": true, + "license": "MIT" + }, + "node_modules/functions-have-names": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz", + "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==", "dev": true, "license": "MIT", - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/has-property-descriptors": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", - "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", + "node_modules/gamedig": { + "version": "4.3.2", + "resolved": "https://registry.npmjs.org/gamedig/-/gamedig-4.3.2.tgz", + "integrity": "sha512-TjYwybvy8HNAhkv2EJccd5HROIiMeMriWmeX8vT8m5Ibat5JMzVpugzsD8L8XZVrOfiXnVg/9DhWYM8k/VG/vw==", "license": "MIT", "dependencies": { - "es-define-property": "^1.0.0" + "cheerio": "1.0.0-rc.10", + "gbxremote": "0.2.1", + "got": "12.1.0", + "iconv-lite": "0.6.3", + "long": "5.2.0", + "minimist": "1.2.6", + "punycode": "2.1.1", + "seek-bzip": "2.0.0", + "varint": "6.0.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "bin": { + "gamedig": "bin/gamedig.js" + }, + "engines": { + "node": ">=14.0.0" } }, - "node_modules/has-proto": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz", - "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==", + "node_modules/gamedig/node_modules/cheerio": { + "version": "1.0.0-rc.10", + "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0-rc.10.tgz", + "integrity": "sha512-g0J0q/O6mW8z5zxQ3A8E8J1hUgp4SMOvEoW/x84OwyHKe/Zccz83PVT4y5Crcr530FV6NgmKI1qvGTKVl9XXVw==", "license": "MIT", "dependencies": { - "dunder-proto": "^1.0.0" + "cheerio-select": "^1.5.0", + "dom-serializer": "^1.3.2", + "domhandler": "^4.2.0", + "htmlparser2": "^6.1.0", + "parse5": "^6.0.1", + "parse5-htmlparser2-tree-adapter": "^6.0.1", + "tslib": "^2.2.0" }, "engines": { - "node": ">= 0.4" + "node": ">= 6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/cheeriojs/cheerio?sponsor=1" } }, - "node_modules/has-symbols": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", - "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", - "license": "MIT", - "engines": { - "node": ">= 0.4" + "node_modules/gamedig/node_modules/cheerio-select": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-1.6.0.tgz", + "integrity": "sha512-eq0GdBvxVFbqWgmCm7M3XGs1I8oLy/nExUnh6oLqmBditPO9AqQJrkslDpMun/hZ0yyTs8L0m85OHp4ho6Qm9g==", + "license": "BSD-2-Clause", + "dependencies": { + "css-select": "^4.3.0", + "css-what": "^6.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.3.1", + "domutils": "^2.8.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/fb55" } }, - "node_modules/has-tostringtag": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", - "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", - "license": "MIT", + "node_modules/gamedig/node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "license": "BSD-2-Clause", "dependencies": { - "has-symbols": "^1.0.3" - }, - "engines": { - "node": ">= 0.4" + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/fb55" } }, - "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==", - "license": "ISC" - }, - "node_modules/hasown": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", - "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "node_modules/gamedig/node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", "license": "MIT", "dependencies": { - "function-bind": "^1.1.2" + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" }, - "engines": { - "node": ">= 0.4" - } - }, - "node_modules/help-me": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", - "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", - "license": "MIT", - "dependencies": { - "glob": "^7.1.6", - "readable-stream": "^3.6.0" + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" } }, - "node_modules/hoek": { - "version": "6.1.3", - "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", - "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", - "deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.", - "license": "BSD-3-Clause" - }, - "node_modules/hosted-git-info": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", - "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", - "dev": true, - "license": "ISC", + "node_modules/gamedig/node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "license": "BSD-2-Clause", "dependencies": { - "lru-cache": "^6.0.0" + "domelementtype": "^2.2.0" }, "engines": { - "node": ">=10" + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" } }, - "node_modules/hosted-git-info/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==", - "dev": true, - "license": "ISC", + "node_modules/gamedig/node_modules/domutils": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", + "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==", + "license": "BSD-2-Clause", "dependencies": { - "yallist": "^4.0.0" + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" }, - "engines": { - "node": ">=10" + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" } }, - "node_modules/hosted-git-info/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "dev": true, - "license": "ISC" - }, - "node_modules/html-escaper": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", - "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", - "license": "MIT" - }, - "node_modules/html-tags": { - "version": "3.3.1", - "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", - "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - }, + "node_modules/gamedig/node_modules/entities": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz", + "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==", + "license": "BSD-2-Clause", "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/fb55/entities?sponsor=1" } }, - "node_modules/htmlparser2": { - "version": "8.0.2", - "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", - "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", + "node_modules/gamedig/node_modules/htmlparser2": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz", + "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==", "funding": [ "https://github.com/fb55/htmlparser2?sponsor=1", { @@ -11651,215 +9311,140 @@ ], "license": "MIT", "dependencies": { - "domelementtype": "^2.3.0", - "domhandler": "^5.0.3", - "domutils": "^3.0.1", - "entities": "^4.4.0" - } - }, - "node_modules/http-cache-semantics": { - "version": "4.1.1", - "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", - "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", - "license": "BSD-2-Clause" - }, - "node_modules/http-errors": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", - "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", - "license": "MIT", - "dependencies": { - "depd": "2.0.0", - "inherits": "2.0.4", - "setprototypeof": "1.2.0", - "statuses": "2.0.1", - "toidentifier": "1.0.1" - }, - "engines": { - "node": ">= 0.8" - } - }, - "node_modules/http-graceful-shutdown": { - "version": "3.1.13", - "resolved": "https://registry.npmjs.org/http-graceful-shutdown/-/http-graceful-shutdown-3.1.13.tgz", - "integrity": "sha512-Ci5LRufQ8AtrQ1U26AevS8QoMXDOhnAHCJI3eZu1com7mZGHxREmw3dNj85ftpQokQCvak8nI2pnFS8zyM1M+Q==", - "license": "MIT", - "dependencies": { - "debug": "^4.3.4" - }, - "engines": { - "node": ">=4.0.0" + "domelementtype": "^2.0.1", + "domhandler": "^4.0.0", + "domutils": "^2.5.2", + "entities": "^2.0.0" } }, - "node_modules/http-proxy-agent": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", - "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", - "license": "MIT", - "dependencies": { - "@tootallnate/once": "2", - "agent-base": "6", - "debug": "4" - }, - "engines": { - "node": ">= 6" - } + "node_modules/gamedig/node_modules/long": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/long/-/long-5.2.0.tgz", + "integrity": "sha512-9RTUNjK60eJbx3uz+TEGF7fUr29ZDxR5QzXcyDpeSfeH28S9ycINflOgOlppit5U+4kNTe83KQnMEerw7GmE8w==", + "license": "Apache-2.0" }, - "node_modules/http-signature": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.4.0.tgz", - "integrity": "sha512-G5akfn7eKbpDN+8nPS/cb57YeA1jLTVxjpCj7tmm3QKPdyDy7T+qSC40e9ptydSWvkwjSXw1VbkpyEm39ukeAg==", - "dev": true, - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "jsprim": "^2.0.2", - "sshpk": "^1.18.0" - }, - "engines": { - "node": ">=0.10" - } + "node_modules/gamedig/node_modules/parse5": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz", + "integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==", + "license": "MIT" }, - "node_modules/http2-wrapper": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", - "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", + "node_modules/gamedig/node_modules/parse5-htmlparser2-tree-adapter": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz", + "integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==", "license": "MIT", "dependencies": { - "quick-lru": "^5.1.1", - "resolve-alpn": "^1.2.0" - }, - "engines": { - "node": ">=10.19.0" + "parse5": "^6.0.1" } }, - "node_modules/https-proxy-agent": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", - "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", - "license": "MIT", + "node_modules/gauge": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-3.0.2.tgz", + "integrity": "sha512-+5J6MS/5XksCuXq++uFRsnUd7Ovu1XenbeuIuNRJxYWjgQbPuFhT14lAvsWfqfAmnwluf1OwMjz39HjfLPci0Q==", + "deprecated": "This package is no longer supported.", + "license": "ISC", "dependencies": { - "agent-base": "6", - "debug": "4" + "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": ">= 6" + "node": ">=10" } }, - "node_modules/human-signals": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz", - "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==", - "dev": true, - "license": "Apache-2.0", + "node_modules/gbxremote": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/gbxremote/-/gbxremote-0.2.1.tgz", + "integrity": "sha512-SMehu6Y6ndq2Qgp9VxAb8Np3f+UUD+RWoW2SAMaxzGS96rWXyr4T1GGkecO0HHtxeH1m7pEh4FJWB8a/6aM2XQ==", + "dependencies": { + "any-promise": "^1.1.0", + "barse": "~0.4.2", + "event-to-promise": "^0.7.0", + "string-to-stream": "^1.0.1", + "xmlrpc": "^1.3.1" + }, "engines": { - "node": ">=8.12.0" + "node": ">=0.10" } }, - "node_modules/humanize-ms": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", - "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", + "node_modules/generate-function": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/generate-function/-/generate-function-2.3.1.tgz", + "integrity": "sha512-eeB5GfMNeevm/GRYq20ShmsaGcmI81kIX2K9XQx5miC8KdHaC6Jm0qQ8ZNeGOi7wYB8OsdxKs+Y2oVuTFuVwKQ==", "license": "MIT", - "optional": true, "dependencies": { - "ms": "^2.0.0" + "is-property": "^1.0.2" } }, - "node_modules/hyperid": { - "version": "3.3.0", - "resolved": "https://registry.npmjs.org/hyperid/-/hyperid-3.3.0.tgz", - "integrity": "sha512-7qhCVT4MJIoEsNcbhglhdmBKb09QtcmJNiIQGq7js/Khf5FtQQ9bzcAuloeqBeee7XD7JqDeve9KNlQya5tSGQ==", - "dev": true, + "node_modules/generic-pool": { + "version": "3.9.0", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.9.0.tgz", + "integrity": "sha512-hymDOu5B53XvN4QT9dBmZxPX4CWhBPPLguTZ9MMFeFa/Kg0xWVfylOVNlJji/E7yTZWFd/q9GO5TxDLq156D7g==", "license": "MIT", - "dependencies": { - "buffer": "^5.2.1", - "uuid": "^8.3.2", - "uuid-parse": "^1.1.0" + "engines": { + "node": ">= 4" } }, - "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==", + "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, "license": "MIT", - "dependencies": { - "safer-buffer": ">= 2.1.2 < 3.0.0" - }, "engines": { - "node": ">=0.10.0" + "node": ">=6.9.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" - } - ], - "license": "BSD-3-Clause" - }, - "node_modules/ignore": { - "version": "5.3.2", - "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", - "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", - "dev": true, - "license": "MIT", + "node_modules/get-caller-file": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz", + "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==", + "license": "ISC", "engines": { - "node": ">= 4" + "node": "6.* || 8.* || >= 10.*" } }, - "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==", - "dev": true, + "node_modules/get-intrinsic": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz", + "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==", "license": "MIT", "dependencies": { - "parent-module": "^1.0.0", - "resolve-from": "^4.0.0" + "es-errors": "^1.3.0", + "function-bind": "^1.1.2", + "has-proto": "^1.0.1", + "has-symbols": "^1.0.3", + "hasown": "^2.0.0" }, "engines": { - "node": ">=6" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/import-lazy": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", - "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", - "dev": true, + "node_modules/get-package-type": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz", + "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==", "license": "MIT", "engines": { - "node": ">=8" + "node": ">=8.0.0" } }, - "node_modules/import-local": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz", - "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==", + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", "dev": true, "license": "MIT", - "dependencies": { - "pkg-dir": "^4.2.0", - "resolve-cwd": "^3.0.0" - }, - "bin": { - "import-local-fixture": "fixtures/cli.js" - }, "engines": { "node": ">=8" }, @@ -11867,136 +9452,171 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/imurmurhash": { - "version": "0.1.4", - "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", - "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", - "devOptional": true, + "node_modules/get-port-please": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/get-port-please/-/get-port-please-3.1.2.tgz", + "integrity": "sha512-Gxc29eLs1fbn6LQ4jSU4vXjlwyZhF5HsGuMAa7gqBP4Rw4yxxltyDUuF5MBclFzDTXO+ACchGQoeela4DSfzdQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/get-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz", + "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==", "license": "MIT", "engines": { - "node": ">=0.8.19" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/indent-string": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", - "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", - "devOptional": true, + "node_modules/get-symbol-description": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz", + "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==", + "dev": true, "license": "MIT", + "dependencies": { + "call-bind": "^1.0.5", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.4" + }, "engines": { - "node": ">=8" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/infer-owner": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", - "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", - "license": "ISC", - "optional": true + "node_modules/getopts": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/getopts/-/getopts-2.3.0.tgz", + "integrity": "sha512-5eDf9fuSXwxBL6q5HX+dhDj+dslFGWzU5thZ9kNKUkcPtaPdatmUFKwHFrLb/uf/WpA4BHET+AX3Scl56cAjpA==", + "license": "MIT" }, - "node_modules/inflight": { - "version": "1.0.6", - "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", - "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", - "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "node_modules/glob": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz", + "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==", + "deprecated": "Glob versions prior to v9 are no longer supported", "license": "ISC", "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.1.1", "once": "^1.3.0", - "wrappy": "1" + "path-is-absolute": "^1.0.0" + }, + "engines": { + "node": "*" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/inherits": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", - "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", - "license": "ISC" - }, - "node_modules/ini": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/ini/-/ini-2.0.0.tgz", - "integrity": "sha512-7PnF4oN3CvZF23ADhA5wRaYEQpJ8qygSkbtTXWBeXWXmEVRXK+1ITciHWwHhsjv1TmW0MgacIv6hEi5pX5NQdA==", + "node_modules/glob-parent": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz", + "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==", "dev": true, "license": "ISC", + "dependencies": { + "is-glob": "^4.0.3" + }, "engines": { - "node": ">=10" + "node": ">=10.13.0" } }, - "node_modules/internal-slot": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz", - "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==", + "node_modules/glob/node_modules/brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "license": "MIT", "dependencies": { - "es-errors": "^1.3.0", - "hasown": "^2.0.2", - "side-channel": "^1.1.0" + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "node_modules/glob/node_modules/minimatch": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", + "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "license": "ISC", + "dependencies": { + "brace-expansion": "^1.1.7" }, "engines": { - "node": ">= 0.4" + "node": "*" } }, - "node_modules/interpret": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", - "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "node_modules/global-modules": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz", + "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==", + "dev": true, "license": "MIT", + "dependencies": { + "global-prefix": "^3.0.0" + }, "engines": { - "node": ">= 0.10" + "node": ">=6" } }, - "node_modules/ip-address": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", - "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", + "node_modules/global-prefix": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz", + "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==", + "dev": true, "license": "MIT", "dependencies": { - "jsbn": "1.1.0", - "sprintf-js": "^1.1.3" + "ini": "^1.3.5", + "kind-of": "^6.0.2", + "which": "^1.3.1" }, "engines": { - "node": ">= 12" + "node": ">=6" } }, - "node_modules/ipaddr.js": { - "version": "1.9.1", - "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", - "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", - "license": "MIT", - "engines": { - "node": ">= 0.10" + "node_modules/global-prefix/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dev": true, + "license": "ISC", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" } }, - "node_modules/is-array-buffer": { - "version": "3.0.5", - "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz", - "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==", + "node_modules/globals": { + "version": "13.24.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-13.24.0.tgz", + "integrity": "sha512-AhO5QUcj8llrbG09iWhPU2B204J1xnPeL8kQmVorSsy+Sjj1sk8gIyh6cUocGmH4L0UuhAJy+hJMRA4mgA4mFQ==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" + "type-fest": "^0.20.2" }, "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/globalthis": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz", + "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==", "dev": true, - "license": "MIT" - }, - "node_modules/is-async-function": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.0.0.tgz", - "integrity": "sha512-Y1JXKrfykRJGdlDwdKlLpLyMIiWqWvuSd17TvZk68PLAOGOoF4Xyav1z0Xhoi+gCYjZVeC5SI+hYFOfvXmGRCA==", "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "define-properties": "^1.2.1", + "gopd": "^1.0.1" }, "engines": { "node": ">= 0.4" @@ -12005,103 +9625,134 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-bigint": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz", - "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==", + "node_modules/globby": { + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz", + "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==", + "dev": true, "license": "MIT", "dependencies": { - "has-bigints": "^1.0.2" + "array-union": "^2.1.0", + "dir-glob": "^3.0.1", + "fast-glob": "^3.2.9", + "ignore": "^5.2.0", + "merge2": "^1.4.1", + "slash": "^3.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=10" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "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/globjoin": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/globjoin/-/globjoin-0.1.4.tgz", + "integrity": "sha512-xYfnw62CKG8nLkZBfWbhWwDw02CHty86jfPcc2cr3ZfeuK9ysoVPPEUxf21bAD/rWAgk52SuBrLJlefNy8mvFg==", "dev": true, + "license": "MIT" + }, + "node_modules/gopd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz", + "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==", "license": "MIT", "dependencies": { - "binary-extensions": "^2.0.0" + "get-intrinsic": "^1.1.3" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-boolean-object": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.1.tgz", - "integrity": "sha512-l9qO6eFlUETHtuihLcYOaLKByJ1f+N4kthcU9YjHy3N+B3hWv0y/2Nd0mu/7lTFnRQHTrSdXF50HQ3bl5fEnng==", + "node_modules/got": { + "version": "12.1.0", + "resolved": "https://registry.npmjs.org/got/-/got-12.1.0.tgz", + "integrity": "sha512-hBv2ty9QN2RdbJJMK3hesmSkFTjVIHyIDDbssCKnSmq62edGgImJWD10Eb1k77TiV1bxloxqcFAVK8+9pkhOig==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" + "@sindresorhus/is": "^4.6.0", + "@szmarczak/http-timer": "^5.0.1", + "@types/cacheable-request": "^6.0.2", + "@types/responselike": "^1.0.0", + "cacheable-lookup": "^6.0.4", + "cacheable-request": "^7.0.2", + "decompress-response": "^6.0.0", + "form-data-encoder": "1.7.1", + "get-stream": "^6.0.1", + "http2-wrapper": "^2.1.10", + "lowercase-keys": "^3.0.0", + "p-cancelable": "^3.0.0", + "responselike": "^2.0.0" }, "engines": { - "node": ">= 0.4" + "node": ">=14.16" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sindresorhus/got?sponsor=1" } }, - "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==", + "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==", + "devOptional": true, + "license": "ISC" + }, + "node_modules/graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true, + "license": "MIT" + }, + "node_modules/hard-rejection": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hard-rejection/-/hard-rejection-2.1.0.tgz", + "integrity": "sha512-VIZB+ibDhx7ObhAe7OVtoEbuP4h/MuOTHJ+J8h/eBXotJYl0fBgR72xDFCKgIh22OJZIOVNxBMWuhAr10r8HdA==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" - }, + "node": ">=6" + } + }, + "node_modules/has-bigints": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz", + "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==", + "dev": true, + "license": "MIT", "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-core-module": { - "version": "2.16.0", - "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.0.tgz", - "integrity": "sha512-urTSINYfAYgcbLb0yDQ6egFm6h3Mo1DcF9EkyXSRjjzdHbsulg01qhwWuXdOoUBuTkbQ80KDboXa0vFJ+BDH+g==", + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "dev": true, "license": "MIT", - "dependencies": { - "hasown": "^2.0.2" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-data-view": { + "node_modules/has-property-descriptors": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz", - "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==", + "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz", + "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "is-typed-array": "^1.1.13" - }, - "engines": { - "node": ">= 0.4" + "es-define-property": "^1.0.0" }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-date-object": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz", - "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==", + "node_modules/has-proto": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz", + "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==", "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "has-tostringtag": "^1.0.2" - }, "engines": { "node": ">= 0.4" }, @@ -12109,38 +9760,26 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-docker": { - "version": "2.2.1", - "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", - "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", + "node_modules/has-symbols": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz", + "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==", "license": "MIT", - "bin": { - "is-docker": "cli.js" - }, "engines": { - "node": ">=8" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "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/has-tostringtag": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz", + "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==", "dev": true, "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/is-finalizationregistry": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz", - "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==", - "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "has-symbols": "^1.0.3" }, "engines": { "node": ">= 0.4" @@ -12149,1150 +9788,899 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-fullwidth-code-point": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", - "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", - "license": "MIT", - "engines": { - "node": ">=8" - } - }, - "node_modules/is-generator-fn": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz", - "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } + "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==", + "license": "ISC" }, - "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==", + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", "license": "MIT", "dependencies": { - "has-tostringtag": "^1.0.0" + "function-bind": "^1.1.2" }, "engines": { "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/is-glob": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", - "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", - "dev": true, + "node_modules/help-me": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/help-me/-/help-me-3.0.0.tgz", + "integrity": "sha512-hx73jClhyk910sidBB7ERlnhMlFsJJIBqSVMFDwPN8o2v9nmp5KgLq1Xz1Bf1fCMMZ6mPrX159iG0VLy/fPMtQ==", "license": "MIT", "dependencies": { - "is-extglob": "^2.1.1" - }, - "engines": { - "node": ">=0.10.0" + "glob": "^7.1.6", + "readable-stream": "^3.6.0" } }, - "node_modules/is-installed-globally": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/is-installed-globally/-/is-installed-globally-0.4.0.tgz", - "integrity": "sha512-iwGqO3J21aaSkC7jWnHP/difazwS7SFeIqxv6wEtLU8Y5KlzFTjyqcSIT0d8s4+dDhKytsk9PJZ2BkS5eZwQRQ==", + "node_modules/hoek": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/hoek/-/hoek-6.1.3.tgz", + "integrity": "sha512-YXXAAhmF9zpQbC7LEcREFtXfGq5K1fmd+4PHkBq8NUqmzW3G+Dq10bI/i0KucLRwss3YYFQ0fSfoxBZYiGUqtQ==", + "deprecated": "This module has moved and is now available at @hapi/hoek. Please update your dependencies as this version is no longer maintained an may contain bugs and security issues.", + "license": "BSD-3-Clause" + }, + "node_modules/hookable": { + "version": "5.5.3", + "resolved": "https://registry.npmjs.org/hookable/-/hookable-5.5.3.tgz", + "integrity": "sha512-Yc+BQe8SvoXH1643Qez1zqLRmbA5rCL+sSmk6TVos0LWVfNIB7PGncdlId77WzLGSIB5KaWgTaNTs2lNVEI6VQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/hosted-git-info": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-4.1.0.tgz", + "integrity": "sha512-kyCuEOWjJqZuDbRHzL8V93NzQhwIB71oFWSyzVo+KPZI+pnQPPxucdkrOZvkLRnrf5URsQM+IJ09Dw29cRALIA==", "dev": true, - "license": "MIT", + "license": "ISC", "dependencies": { - "global-dirs": "^3.0.0", - "is-path-inside": "^3.0.2" + "lru-cache": "^6.0.0" }, "engines": { "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-lambda": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", - "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", - "license": "MIT", - "optional": true + "node_modules/html-escaper": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-3.0.3.tgz", + "integrity": "sha512-RuMffC89BOWQoY0WKGpIhn5gX3iI54O6nRA0yC124NYVtzjmFWBIiFd8M0x+ZdX0P9R4lADg1mgP8C7PxGOWuQ==", + "license": "MIT" }, - "node_modules/is-map": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz", - "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==", + "node_modules/html-tags": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.3.1.tgz", + "integrity": "sha512-ztqyC3kLto0e9WbNp0aeP+M3kTt+nbaIveGmUxAtZa+8iFgKLUOD4YKM5j+f3QD89bra7UeumolZHKuOXnTmeQ==", + "dev": true, "license": "MIT", "engines": { - "node": ">= 0.4" + "node": ">=8" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-negative-zero": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", - "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", + "node_modules/htmlparser2": { + "version": "9.1.0", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz", + "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==", + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], "license": "MIT", - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.1.0", + "entities": "^4.5.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, - "license": "MIT", - "engines": { - "node": ">=0.12.0" - } + "node_modules/http-cache-semantics": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/http-cache-semantics/-/http-cache-semantics-4.1.1.tgz", + "integrity": "sha512-er295DKPVsV82j5kw1Gjt+ADA/XYHsajl82cGNQG2eyoPkvgUhX+nDIyelzhIWbbsXP39EHcI6l5tYs2FYqYXQ==", + "license": "BSD-2-Clause" }, - "node_modules/is-number-object": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz", - "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==", + "node_modules/http-cookie-agent": { + "version": "5.0.4", + "resolved": "https://registry.npmjs.org/http-cookie-agent/-/http-cookie-agent-5.0.4.tgz", + "integrity": "sha512-OtvikW69RvfyP6Lsequ0fN5R49S+8QcS9zwd58k6VSr6r57T8G29BkPdyrBcSwLq6ExLs9V+rBlfxu7gDstJag==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" + "agent-base": "^7.1.0" }, "engines": { - "node": ">= 0.4" + "node": ">=14.18.0 <15.0.0 || >=16.0.0" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/3846masa" + }, + "peerDependencies": { + "deasync": "^0.1.26", + "tough-cookie": "^4.0.0", + "undici": "^5.11.0" + }, + "peerDependenciesMeta": { + "deasync": { + "optional": true + }, + "undici": { + "optional": true + } } }, - "node_modules/is-path-inside": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-3.0.3.tgz", - "integrity": "sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ==", - "dev": true, + "node_modules/http-errors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.0.tgz", + "integrity": "sha512-FtwrG/euBzaEjYeRqOgly7G0qviiXoJWnvEH2Z1plBdXgbyjv34pHTSb9zoeHMyDy33+DWy5Wt9Wo+TURtOYSQ==", "license": "MIT", + "dependencies": { + "depd": "2.0.0", + "inherits": "2.0.4", + "setprototypeof": "1.2.0", + "statuses": "2.0.1", + "toidentifier": "1.0.1" + }, "engines": { - "node": ">=8" + "node": ">= 0.8" } }, - "node_modules/is-plain-obj": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", - "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", - "dev": true, + "node_modules/http-graceful-shutdown": { + "version": "3.1.13", + "resolved": "https://registry.npmjs.org/http-graceful-shutdown/-/http-graceful-shutdown-3.1.13.tgz", + "integrity": "sha512-Ci5LRufQ8AtrQ1U26AevS8QoMXDOhnAHCJI3eZu1com7mZGHxREmw3dNj85ftpQokQCvak8nI2pnFS8zyM1M+Q==", "license": "MIT", + "dependencies": { + "debug": "^4.3.4" + }, "engines": { - "node": ">=0.10.0" + "node": ">=4.0.0" } }, - "node_modules/is-plain-object": { + "node_modules/http-proxy-agent": { "version": "5.0.0", - "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", - "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", - "dev": true, + "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-5.0.0.tgz", + "integrity": "sha512-n2hY8YdoRE1i7r6M0w9DIw5GgZN0G25P8zLCRQ8rjXtTU3vsNFBI/vWK/UIeE6g5MUUz6avwAPXmL6Fy9D/90w==", "license": "MIT", + "dependencies": { + "@tootallnate/once": "2", + "agent-base": "6", + "debug": "4" + }, "engines": { - "node": ">=0.10.0" + "node": ">= 6" } }, - "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==", - "license": "MIT" - }, - "node_modules/is-regex": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz", - "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==", + "node_modules/http-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "gopd": "^1.2.0", - "has-tostringtag": "^1.0.2", - "hasown": "^2.0.2" + "debug": "4" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">= 6.0.0" } }, - "node_modules/is-set": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz", - "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==", + "node_modules/http2-wrapper": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/http2-wrapper/-/http2-wrapper-2.2.1.tgz", + "integrity": "sha512-V5nVw1PAOgfI3Lmeaj2Exmeg7fenjhRUgz1lPSezy1CuhPYbgQtbQj4jZfEAEMlaL+vupsvhjqCyjzob0yxsmQ==", "license": "MIT", - "engines": { - "node": ">= 0.4" + "dependencies": { + "quick-lru": "^5.1.1", + "resolve-alpn": "^1.2.0" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">=10.19.0" } }, - "node_modules/is-shared-array-buffer": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz", - "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==", + "node_modules/https-proxy-agent": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-5.0.1.tgz", + "integrity": "sha512-dFcAjpTQFgoLMzC2VwU+C/CbS7uRL0lWmxDITmqm7C+7F0Odmj6s9l6alZc6AELXhrnggM2CeWSXHGOdX2YtwA==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.3" + "agent-base": "6", + "debug": "4" }, "engines": { - "node": ">= 0.4" + "node": ">= 6" + } + }, + "node_modules/https-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "engines": { + "node": ">= 6.0.0" } }, - "node_modules/is-stream": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", - "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", + "node_modules/human-signals": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-5.0.0.tgz", + "integrity": "sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ==", "dev": true, - "license": "MIT", + "license": "Apache-2.0", "engines": { - "node": ">=8" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">=16.17.0" } }, - "node_modules/is-string": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz", - "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==", + "node_modules/humanize-ms": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz", + "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==", "license": "MIT", + "optional": true, "dependencies": { - "call-bound": "^1.0.3", - "has-tostringtag": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "ms": "^2.0.0" } }, - "node_modules/is-symbol": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz", - "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==", + "node_modules/hyperid": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/hyperid/-/hyperid-3.3.0.tgz", + "integrity": "sha512-7qhCVT4MJIoEsNcbhglhdmBKb09QtcmJNiIQGq7js/Khf5FtQQ9bzcAuloeqBeee7XD7JqDeve9KNlQya5tSGQ==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", - "has-symbols": "^1.1.0", - "safe-regex-test": "^1.1.0" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "buffer": "^5.2.1", + "uuid": "^8.3.2", + "uuid-parse": "^1.1.0" } }, - "node_modules/is-typed-array": { - "version": "1.1.15", - "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz", - "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==", + "node_modules/iconv-lite": { + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz", + "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==", "license": "MIT", "dependencies": { - "which-typed-array": "^1.1.16" + "safer-buffer": ">= 2.1.2 < 3.0.0" }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.10.0" } }, - "node_modules/is-typedarray": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", - "integrity": "sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==", - "dev": true, - "license": "MIT" + "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" + } + ], + "license": "BSD-3-Clause" }, - "node_modules/is-unicode-supported": { - "version": "0.1.0", - "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz", - "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==", + "node_modules/ignore": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz", + "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 4" } }, - "node_modules/is-weakmap": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz", - "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==", + "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==", + "dev": true, "license": "MIT", + "dependencies": { + "parent-module": "^1.0.0", + "resolve-from": "^4.0.0" + }, "engines": { - "node": ">= 0.4" + "node": ">=6" }, "funding": { - "url": "https://github.com/sponsors/ljharb" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/is-weakref": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.0.tgz", - "integrity": "sha512-SXM8Nwyys6nT5WP6pltOwKytLV7FqQ4UiibxVmW+EIosHcmCqkkjViTb5SNssDlkCiEYRP1/pdWUKVvZBmsR2Q==", + "node_modules/import-lazy": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/import-lazy/-/import-lazy-4.0.0.tgz", + "integrity": "sha512-rKtvo6a868b5Hu3heneU+L4yEQ4jYKLtjpnPeUdK7h0yzXGmyBTypknlkCvHFBqfX9YlorEiMM6Dnq/5atfHkw==", + "dev": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=8" } }, - "node_modules/is-weakset": { - "version": "2.0.4", - "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz", - "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==", + "node_modules/imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==", + "devOptional": true, "license": "MIT", - "dependencies": { - "call-bound": "^1.0.3", - "get-intrinsic": "^1.2.6" - }, "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" + "node": ">=0.8.19" } }, - "node_modules/is-wsl": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", - "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", + "node_modules/indent-string": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz", + "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==", "license": "MIT", - "dependencies": { - "is-docker": "^2.0.0" - }, + "optional": true, "engines": { "node": ">=8" } }, - "node_modules/isarray": { - "version": "2.0.5", - "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", - "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", - "license": "MIT" + "node_modules/infer-owner": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz", + "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==", + "license": "ISC", + "optional": true }, - "node_modules/isemail": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", - "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", - "license": "BSD-3-Clause", + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "license": "ISC", "dependencies": { - "punycode": "2.x.x" - }, - "engines": { - "node": ">=4.0.0" + "once": "^1.3.0", + "wrappy": "1" } }, - "node_modules/isexe": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==", "license": "ISC" }, - "node_modules/isomorphic-ws": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", - "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", - "license": "MIT", - "peerDependencies": { - "ws": "*" - } - }, - "node_modules/isstream": { - "version": "0.1.2", - "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", - "integrity": "sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==", - "dev": true, - "license": "MIT" - }, - "node_modules/istanbul-lib-coverage": { - "version": "3.2.2", - "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz", - "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==", + "node_modules/ini": { + "version": "1.3.8", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz", + "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==", "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">=8" - } + "license": "ISC" }, - "node_modules/istanbul-lib-instrument": { - "version": "6.0.3", - "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz", - "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==", + "node_modules/internal-slot": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz", + "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "@babel/core": "^7.23.9", - "@babel/parser": "^7.23.9", - "@istanbuljs/schema": "^0.1.3", - "istanbul-lib-coverage": "^3.2.0", - "semver": "^7.5.4" + "es-errors": "^1.3.0", + "hasown": "^2.0.0", + "side-channel": "^1.0.4" }, "engines": { - "node": ">=10" + "node": ">= 0.4" } }, - "node_modules/istanbul-lib-report": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz", - "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "istanbul-lib-coverage": "^3.0.0", - "make-dir": "^4.0.0", - "supports-color": "^7.1.0" - }, + "node_modules/interpret": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/interpret/-/interpret-2.2.0.tgz", + "integrity": "sha512-Ju0Bz/cEia55xDwUWEa8+olFpCiQoypjnQySseKtmjNrnps3P+xfpUmGr90T7yjlVJmOtybRvPXhKMbHr+fWnw==", + "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.10" } }, - "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, + "node_modules/ip-address": { + "version": "9.0.5", + "resolved": "https://registry.npmjs.org/ip-address/-/ip-address-9.0.5.tgz", + "integrity": "sha512-zHtQzGojZXTwZTHQqra+ETKd4Sn3vgi7uBmlPoXVWZqYvuKmtI0l/VZTjqGmJY9x88GGOaZ9+G9ES8hC4T4X8g==", "license": "MIT", "dependencies": { - "semver": "^7.5.3" + "jsbn": "1.1.0", + "sprintf-js": "^1.1.3" }, "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "node": ">= 12" } }, - "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, + "node_modules/ipaddr.js": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz", + "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==", "license": "MIT", - "dependencies": { - "has-flag": "^4.0.0" - }, "engines": { - "node": ">=8" + "node": ">= 0.10" } }, - "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==", + "node_modules/is-array-buffer": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz", + "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==", "dev": true, - "license": "BSD-3-Clause", + "license": "MIT", "dependencies": { - "debug": "^4.1.1", - "istanbul-lib-coverage": "^3.0.0", - "source-map": "^0.6.1" + "call-bind": "^1.0.2", + "get-intrinsic": "^1.2.1" }, "engines": { - "node": ">=10" - } - }, - "node_modules/istanbul-reports": { - "version": "3.1.7", - "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz", - "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==", - "dev": true, - "license": "BSD-3-Clause", - "dependencies": { - "html-escaper": "^2.0.0", - "istanbul-lib-report": "^3.0.0" + "node": ">= 0.4" }, - "engines": { - "node": ">=8" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/istanbul-reports/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==", + "node_modules/is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==", "dev": true, "license": "MIT" }, - "node_modules/jackspeak": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", - "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", - "license": "BlueOak-1.0.0", + "node_modules/is-bigint": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz", + "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==", + "dev": true, + "license": "MIT", "dependencies": { - "@isaacs/cliui": "^8.0.2" + "has-bigints": "^1.0.1" }, "funding": { - "url": "https://github.com/sponsors/isaacs" - }, - "optionalDependencies": { - "@pkgjs/parseargs": "^0.11.0" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest": { - "version": "29.6.4", - "resolved": "https://registry.npmjs.org/jest/-/jest-29.6.4.tgz", - "integrity": "sha512-tEFhVQFF/bzoYV1YuGyzLPZ6vlPrdfvDmmAxudA1dLEuiztqg2Rkx20vkKY32xiDROcD2KXlgZ7Cu8RPeEHRKw==", + "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, "license": "MIT", "dependencies": { - "@jest/core": "^29.6.4", - "@jest/types": "^29.6.3", - "import-local": "^3.0.2", - "jest-cli": "^29.6.4" - }, - "bin": { - "jest": "bin/jest.js" + "binary-extensions": "^2.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": ">=8" } }, - "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==", + "node_modules/is-boolean-object": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz", + "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==", "dev": true, "license": "MIT", "dependencies": { - "execa": "^5.0.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-changed-files/node_modules/execa": { - "version": "5.1.1", - "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz", - "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==", + "node_modules/is-builtin-module": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/is-builtin-module/-/is-builtin-module-3.2.1.tgz", + "integrity": "sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==", "dev": true, "license": "MIT", "dependencies": { - "cross-spawn": "^7.0.3", - "get-stream": "^6.0.0", - "human-signals": "^2.1.0", - "is-stream": "^2.0.0", - "merge-stream": "^2.0.0", - "npm-run-path": "^4.0.1", - "onetime": "^5.1.2", - "signal-exit": "^3.0.3", - "strip-final-newline": "^2.0.0" + "builtin-modules": "^3.3.0" }, "engines": { - "node": ">=10" + "node": ">=6" }, "funding": { - "url": "https://github.com/sindresorhus/execa?sponsor=1" + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-changed-files/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==", + "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==", "dev": true, "license": "MIT", "engines": { - "node": ">=10" + "node": ">= 0.4" }, "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-changed-files/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, - "license": "Apache-2.0", + "node_modules/is-core-module": { + "version": "2.15.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz", + "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==", + "license": "MIT", + "dependencies": { + "hasown": "^2.0.2" + }, "engines": { - "node": ">=10.17.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/is-data-view": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz", + "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==", "dev": true, "license": "MIT", "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/expect": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "co": "^4.6.0", - "dedent": "^1.0.0", - "is-generator-fn": "^2.0.0", - "jest-each": "^29.7.0", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "p-limit": "^3.1.0", - "pretty-format": "^29.7.0", - "pure-rand": "^6.0.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" + "is-typed-array": "^1.1.13" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/is-date-object": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz", + "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==", "dev": true, "license": "MIT", "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" - }, - "bin": { - "jest": "bin/jest.js" + "has-tostringtag": "^1.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" + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "node-notifier": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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, + "node_modules/is-docker": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz", + "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "license": "MIT", - "dependencies": { - "@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" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "peerDependencies": { - "@types/node": "*", - "ts-node": ">=9.0.0" + "node": ">=8" }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "ts-node": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/jest-config/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "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, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", "engines": { - "node": ">=8" + "node": ">=0.10.0" } }, - "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, + "node_modules/is-fullwidth-code-point": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz", + "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==", "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "diff-sequences": "^29.6.3", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "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==", + "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, "license": "MIT", "dependencies": { - "detect-newline": "^3.0.0" + "is-extglob": "^2.1.1" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "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==", + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "chalk": "^4.0.0", - "jest-get-type": "^29.6.3", - "jest-util": "^29.7.0", - "pretty-format": "^29.7.0" + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/is-inside-container/node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", "dev": true, "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-mock": "^29.7.0", - "jest-util": "^29.7.0" + "bin": { + "is-docker": "cli.js" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/is-lambda": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-lambda/-/is-lambda-1.0.1.tgz", + "integrity": "sha512-z7CMFGNrENq5iFB9Bqo64Xk6Y9sg+epq1myIcdHaGnbMTYOxvzsEtdYqQUylB7LxfkvgrrjP32T6Ywciio9UIQ==", + "license": "MIT", + "optional": true + }, + "node_modules/is-negative-zero": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz", + "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==", "dev": true, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "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, "license": "MIT", - "dependencies": { - "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" - }, - "optionalDependencies": { - "fsevents": "^2.3.2" + "node": ">=0.12.0" } }, - "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==", + "node_modules/is-number-object": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz", + "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==", "dev": true, "license": "MIT", "dependencies": { - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/is-plain-obj": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz", + "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==", "dev": true, "license": "MIT", - "dependencies": { - "chalk": "^4.0.0", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "pretty-format": "^29.7.0" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "node_modules/jest-message-util": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz", - "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==", + "node_modules/is-plain-object": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-5.0.0.tgz", + "integrity": "sha512-VRSzKkbMm5jMDoKLbltAkFQ5Qr7VDiTFGXxYFXXowVj387GeGNOCsOH6Msy00SGZ3Fp84b1Naa1psqgcCIEP5Q==", "dev": true, "license": "MIT", - "dependencies": { - "@babel/code-frame": "^7.12.13", - "@jest/types": "^29.6.3", - "@types/stack-utils": "^2.0.0", - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "micromatch": "^4.0.4", - "pretty-format": "^29.7.0", - "slash": "^3.0.0", - "stack-utils": "^2.0.3" - }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=0.10.0" } }, - "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==", + "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==", + "license": "MIT" + }, + "node_modules/is-regex": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz", + "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==", "dev": true, "license": "MIT", "dependencies": { - "@jest/types": "^29.6.3", - "@types/node": "*", - "jest-util": "^29.7.0" + "call-bind": "^1.0.2", + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/is-shared-array-buffer": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz", + "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==", "dev": true, "license": "MIT", - "engines": { - "node": ">=6" + "dependencies": { + "call-bind": "^1.0.7" }, - "peerDependencies": { - "jest-resolve": "*" + "engines": { + "node": ">= 0.4" }, - "peerDependenciesMeta": { - "jest-resolve": { - "optional": true - } + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/is-stream": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz", + "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==", "dev": true, "license": "MIT", "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, - "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==", + "node_modules/is-string": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz", + "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.0.0", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-pnp-resolver": "^1.2.2", - "jest-util": "^29.7.0", - "jest-validate": "^29.7.0", - "resolve": "^1.20.0", - "resolve.exports": "^2.0.0", - "slash": "^3.0.0" + "has-tostringtag": "^1.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/is-symbol": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz", + "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==", "dev": true, "license": "MIT", "dependencies": { - "jest-regex-util": "^29.6.3", - "jest-snapshot": "^29.7.0" + "has-symbols": "^1.0.2" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-runner": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz", - "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==", + "node_modules/is-typed-array": { + "version": "1.1.13", + "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz", + "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==", "dev": true, "license": "MIT", "dependencies": { - "@jest/console": "^29.7.0", - "@jest/environment": "^29.7.0", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "emittery": "^0.13.1", - "graceful-fs": "^4.2.9", - "jest-docblock": "^29.7.0", - "jest-environment-node": "^29.7.0", - "jest-haste-map": "^29.7.0", - "jest-leak-detector": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-resolve": "^29.7.0", - "jest-runtime": "^29.7.0", - "jest-util": "^29.7.0", - "jest-watcher": "^29.7.0", - "jest-worker": "^29.7.0", - "p-limit": "^3.1.0", - "source-map-support": "0.5.13" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-runtime": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz", - "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/environment": "^29.7.0", - "@jest/fake-timers": "^29.7.0", - "@jest/globals": "^29.7.0", - "@jest/source-map": "^29.6.3", - "@jest/test-result": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "@types/node": "*", - "chalk": "^4.0.0", - "cjs-module-lexer": "^1.0.0", - "collect-v8-coverage": "^1.0.0", - "glob": "^7.1.3", - "graceful-fs": "^4.2.9", - "jest-haste-map": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-mock": "^29.7.0", - "jest-regex-util": "^29.6.3", - "jest-resolve": "^29.7.0", - "jest-snapshot": "^29.7.0", - "jest-util": "^29.7.0", - "slash": "^3.0.0", - "strip-bom": "^4.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/jest-snapshot": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz", - "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==", - "dev": true, - "license": "MIT", - "dependencies": { - "@babel/core": "^7.11.6", - "@babel/generator": "^7.7.2", - "@babel/plugin-syntax-jsx": "^7.7.2", - "@babel/plugin-syntax-typescript": "^7.7.2", - "@babel/types": "^7.3.3", - "@jest/expect-utils": "^29.7.0", - "@jest/transform": "^29.7.0", - "@jest/types": "^29.6.3", - "babel-preset-current-node-syntax": "^1.0.0", - "chalk": "^4.0.0", - "expect": "^29.7.0", - "graceful-fs": "^4.2.9", - "jest-diff": "^29.7.0", - "jest-get-type": "^29.6.3", - "jest-matcher-utils": "^29.7.0", - "jest-message-util": "^29.7.0", - "jest-util": "^29.7.0", - "natural-compare": "^1.4.0", - "pretty-format": "^29.7.0", - "semver": "^7.5.3" + "which-typed-array": "^1.1.14" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "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==", + "node_modules/is-weakref": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz", + "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==", "dev": true, "license": "MIT", "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" + "call-bind": "^1.0.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/jest-util/node_modules/ci-info": { - "version": "3.9.0", - "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz", - "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==", + "node_modules/is-what": { + "version": "4.1.16", + "resolved": "https://registry.npmjs.org/is-what/-/is-what-4.1.16.tgz", + "integrity": "sha512-ZhMwEosbFJkA0YhFnNDgTM4ZxDRsS6HqTo7qsZM08fehyRYIYa0yHu5R6mgo1n/8MgaPBXiPimPD77baVFYg+A==", "dev": true, - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/sibiraj-s" - } - ], "license": "MIT", "engines": { - "node": ">=8" + "node": ">=12.13" + }, + "funding": { + "url": "https://github.com/sponsors/mesqueeb" } }, - "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, + "node_modules/is-wsl": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz", + "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==", "license": "MIT", "dependencies": { - "@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" + "is-docker": "^2.0.0" }, "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "node": ">=8" } }, - "node_modules/jest-validate/node_modules/camelcase": { - "version": "6.3.0", - "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz", - "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==", + "node_modules/isarray": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz", + "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==", "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" + "license": "MIT" + }, + "node_modules/isemail": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/isemail/-/isemail-3.2.0.tgz", + "integrity": "sha512-zKqkK+O+dGqevc93KNsbZ/TqTUFd46MwWjYOoMrjIMZ51eU7DtQG3Wmd9SQQT7i7RVnuTPEiYEWHU3MSbxC1Tg==", + "license": "BSD-3-Clause", + "dependencies": { + "punycode": "2.x.x" }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" + "engines": { + "node": ">=4.0.0" } }, - "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, + "node_modules/isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", + "license": "ISC" + }, + "node_modules/isomorphic-ws": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/isomorphic-ws/-/isomorphic-ws-5.0.0.tgz", + "integrity": "sha512-muId7Zzn9ywDsyXgTIafTry2sV3nySZeUDe6YedVd1Hvuuep5AsIlqK+XefWpYTyJG5e503F2xIuT2lcU6rCSw==", "license": "MIT", - "dependencies": { - "@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": "^14.15.0 || ^16.10.0 || >=18.0.0" + "peerDependencies": { + "ws": "*" } }, - "node_modules/jest-worker": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz", - "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==", - "dev": true, - "license": "MIT", + "node_modules/jackspeak": { + "version": "3.4.3", + "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz", + "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==", + "license": "BlueOak-1.0.0", "dependencies": { - "@types/node": "*", - "jest-util": "^29.7.0", - "merge-stream": "^2.0.0", - "supports-color": "^8.0.0" + "@isaacs/cliui": "^8.0.2" }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" + "funding": { + "url": "https://github.com/sponsors/isaacs" + }, + "optionalDependencies": { + "@pkgjs/parseargs": "^0.11.0" } }, "node_modules/joi": { @@ -13333,9 +10721,9 @@ } }, "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==", + "version": "8.0.3", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", + "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==", "dev": true, "license": "MIT" }, @@ -13352,18 +10740,22 @@ "js-yaml": "bin/js-yaml.js" } }, - "node_modules/jsbi": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/jsbi/-/jsbi-4.3.0.tgz", - "integrity": "sha512-SnZNcinB4RIcnEyZqFPdGPVgrg2AcnykiBy0sHVJQKHYeaLUvi3Exj+iaPpLnFVkDPZIV4U0yvgC9/R4uEAZ9g==", - "license": "Apache-2.0" - }, "node_modules/jsbn": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-1.1.0.tgz", "integrity": "sha512-4bYVV3aAMtDTTu4+xsDYa6sy9GyJ69/amsu9sYF2zqjiEoZA5xJi3BrfX3uY+/IekIu7MwdObdbDWpoZdBv3/A==", "license": "MIT" }, + "node_modules/jsdoc-type-pratt-parser": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsdoc-type-pratt-parser/-/jsdoc-type-pratt-parser-4.0.0.tgz", + "integrity": "sha512-YtOli5Cmzy3q4dP26GraSOeAhqecewG04hoO8DY56CH4KJ9Fvv5qKWUCCo3HZob7esJQHCv6/+bnTy72xZZaVQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12.0.0" + } + }, "node_modules/jsesc": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz", @@ -13389,13 +10781,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-schema": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz", - "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==", - "dev": true, - "license": "(AFL-2.1 OR BSD-3-Clause)" - }, "node_modules/json-schema-traverse": { "version": "0.4.1", "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", @@ -13410,13 +10795,6 @@ "dev": true, "license": "MIT" }, - "node_modules/json-stringify-safe": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", - "integrity": "sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==", - "dev": true, - "license": "ISC" - }, "node_modules/json5": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz", @@ -13431,9 +10809,9 @@ } }, "node_modules/jsonata": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.6.tgz", - "integrity": "sha512-WhQB5tXQ32qjkx2GYHFw2XbL90u+LLzjofAYwi+86g6SyZeXHz9F1Q0amy3dWRYczshOC3Haok9J4pOCgHtwyQ==", + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/jsonata/-/jsonata-2.0.5.tgz", + "integrity": "sha512-wEse9+QLIIU5IaCgtJCPsFi/H4F3qcikWzF4bAELZiRz08ohfx3Q6CjDRf4ZPF5P/92RI3KIHtb7u3jqPaHXdQ==", "license": "MIT", "engines": { "node": ">= 8" @@ -13452,6 +10830,16 @@ "graceful-fs": "^4.1.6" } }, + "node_modules/jsonfile/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, "node_modules/jsonwebtoken": { "version": "9.0.2", "resolved": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-9.0.2.tgz", @@ -13474,22 +10862,6 @@ "npm": ">=6" } }, - "node_modules/jsprim": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-2.0.2.tgz", - "integrity": "sha512-gqXddjPqQ6G40VdnI6T6yObEC+pDNvyP95wdQhkWkg7crHH3km5qP1FsOXEkzEQwnz6gz5qGTn1c2Y52wP3OyQ==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "1.0.0", - "extsprintf": "1.3.0", - "json-schema": "0.4.0", - "verror": "1.10.0" - } - }, "node_modules/just-performance": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/just-performance/-/just-performance-4.3.0.tgz", @@ -13551,24 +10923,14 @@ "node": ">=0.10.0" } }, - "node_modules/kleur": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz", - "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - } - }, "node_modules/knex": { - "version": "2.4.2", - "resolved": "https://registry.npmjs.org/knex/-/knex-2.4.2.tgz", - "integrity": "sha512-tMI1M7a+xwHhPxjbl/H9K1kHX+VncEYcvCx5K00M16bWvpYPKAZd6QrCu68PtHAdIZNQPWZn0GVhqVBEthGWCg==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/knex/-/knex-3.1.0.tgz", + "integrity": "sha512-GLoII6hR0c4ti243gMs5/1Rb3B+AjwMOfjYm97pu0FOQa7JH56hgBxYf5WK2525ceSbBY1cjeZ9yk99GPMB6Kw==", "license": "MIT", "dependencies": { "colorette": "2.0.19", - "commander": "^9.1.0", + "commander": "^10.0.0", "debug": "4.3.4", "escalade": "^3.1.1", "esm": "^3.2.25", @@ -13576,7 +10938,7 @@ "getopts": "2.3.0", "interpret": "^2.2.0", "lodash": "^4.17.21", - "pg-connection-string": "2.5.0", + "pg-connection-string": "2.6.2", "rechoir": "^0.8.0", "resolve-from": "^5.0.0", "tarn": "^3.0.2", @@ -13586,7 +10948,7 @@ "knex": "bin/cli.js" }, "engines": { - "node": ">=12" + "node": ">=16" }, "peerDependenciesMeta": { "better-sqlite3": { @@ -13612,21 +10974,6 @@ } } }, - "node_modules/knex/node_modules/colorette": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.19.tgz", - "integrity": "sha512-3tlv/dIP7FWvj3BsbHrGLJ6l/oKh1O3TcgBqMn+yyCagOxc23fyzDS6HypQbgxWbkpDnf52p1LuR4eWDQ/K9WQ==", - "license": "MIT" - }, - "node_modules/knex/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", - "license": "MIT", - "engines": { - "node": "^12.20.0 || >=14" - } - }, "node_modules/knex/node_modules/debug": { "version": "4.3.4", "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", @@ -13651,9 +10998,9 @@ "license": "MIT" }, "node_modules/knex/node_modules/pg-connection-string": { - "version": "2.5.0", - "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", - "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==", + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.6.2.tgz", + "integrity": "sha512-ch6OwaeaPYcova4kKZ15sbJ2hKb/VP48ZD2gE7i1J+L4MspCtBMAx8nMgz7bksc7IojCIIWuEhHibSMFH8m8oA==", "license": "MIT" }, "node_modules/knex/node_modules/resolve-from": { @@ -13672,24 +11019,66 @@ "dev": true, "license": "MIT" }, - "node_modules/lazy-ass": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/lazy-ass/-/lazy-ass-1.6.0.tgz", - "integrity": "sha512-cc8oEVoctTvsFZ/Oje/kGnHbpWHYBe8IAJe4C0QNc3t8uM/0Y8+erSz/7Y1ALuXTEZTMvxXwO6YbX1ey3ujiZw==", + "node_modules/kolorist": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/kolorist/-/kolorist-1.8.0.tgz", + "integrity": "sha512-Y+60/zizpJ3HRH8DCss+q95yr6145JXZo46OTpFvDZWLfRCE4qChOyk1b26nMaNpfHHgxagk9dXT5OP0Tfe+dQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/lazystream/-/lazystream-1.0.1.tgz", + "integrity": "sha512-b94GiNHQNy6JNTrt5w6zNyffMrNkXZb3KTkCZJb2V1xaEGCk093vkZ2jk3tpaeP33/OiXC+WvK9AxUebnf5nbw==", "dev": true, "license": "MIT", + "dependencies": { + "readable-stream": "^2.0.5" + }, "engines": { - "node": "> 0.8" + "node": ">= 0.6.3" } }, - "node_modules/leven": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz", - "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==", + "node_modules/lazystream/node_modules/isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==", + "dev": true, + "license": "MIT" + }, + "node_modules/lazystream/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==", + "dev": true, + "license": "MIT", + "dependencies": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "node_modules/lazystream/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==", "dev": true, "license": "MIT", + "dependencies": { + "safe-buffer": "~5.1.0" + } + }, + "node_modules/leven": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/leven/-/leven-2.1.0.tgz", + "integrity": "sha512-nvVPLpIHUxCUoRLrFqTgSxXJ614d8AgQoWl7zPe/2VadE8+1dpU3LBhowRuBAcuwruWtOdD8oYC9jDNJjXDPyA==", + "license": "MIT", "engines": { - "node": ">=6" + "node": ">=0.10.0" } }, "node_modules/levn": { @@ -13723,9 +11112,9 @@ "license": "MIT" }, "node_modules/liquidjs": { - "version": "10.19.0", - "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.19.0.tgz", - "integrity": "sha512-dNINmbNJ/bp3B8n25BtZQV/GbrmFf0o2InGdMdfQXa+LxfzTFXOkUnBsOLZUb82sLzxaiWv5Jc381Kn4zHjTsQ==", + "version": "10.18.0", + "resolved": "https://registry.npmjs.org/liquidjs/-/liquidjs-10.18.0.tgz", + "integrity": "sha512-gCJPmpmZ3oi2rMMHo/c+bW1LaRF+ZAKYTWQmKXPp0uK9EkWMFRmgbk3+Io4LSJGAOnpCZSgHJbNzcygx3kfAAQ==", "license": "MIT", "dependencies": { "commander": "^10.0.0" @@ -13742,54 +11131,20 @@ "url": "https://opencollective.com/liquidjs" } }, - "node_modules/liquidjs/node_modules/commander": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz", - "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==", - "license": "MIT", - "engines": { - "node": ">=14" - } - }, - "node_modules/listr2": { - "version": "3.14.0", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-3.14.0.tgz", - "integrity": "sha512-TyWI8G99GX9GjE54cJ+RrNMcIFBfwMPxc3XTFiAYGN4s10hWROGtOg7+O6u6LE3mNkyld7RSLE6nrKBvTfcs3g==", - "dev": true, - "license": "MIT", - "dependencies": { - "cli-truncate": "^2.1.0", - "colorette": "^2.0.16", - "log-update": "^4.0.0", - "p-map": "^4.0.0", - "rfdc": "^1.3.0", - "rxjs": "^7.5.1", - "through": "^2.3.8", - "wrap-ansi": "^7.0.0" - }, - "engines": { - "node": ">=10.0.0" - }, - "peerDependencies": { - "enquirer": ">= 2.3.0 < 3" - }, - "peerDependenciesMeta": { - "enquirer": { - "optional": true - } - } - }, "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==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", + "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", "dev": true, "license": "MIT", "dependencies": { - "p-locate": "^4.1.0" + "p-locate": "^5.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/lodash": { @@ -13804,13 +11159,6 @@ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==", "license": "MIT" }, - "node_modules/lodash.debounce": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz", - "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==", - "dev": true, - "license": "MIT" - }, "node_modules/lodash.get": { "version": "4.4.2", "resolved": "https://registry.npmjs.org/lodash.get/-/lodash.get-4.4.2.tgz", @@ -13873,75 +11221,6 @@ "dev": true, "license": "MIT" }, - "node_modules/log-symbols": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz", - "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==", - "dev": true, - "license": "MIT", - "dependencies": { - "chalk": "^4.1.0", - "is-unicode-supported": "^0.1.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-4.0.0.tgz", - "integrity": "sha512-9fkkDevMefjg0mmzWFBW8YkFP91OrizzkW3diF7CpG+S2EYdy4+TVfGwz1zeF8x7hCx1ovSPTOE9Ngib74qqUg==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-escapes": "^4.3.0", - "cli-cursor": "^3.1.0", - "slice-ansi": "^4.0.0", - "wrap-ansi": "^6.2.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/log-update/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, - "node_modules/log-update/node_modules/wrap-ansi": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", - "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "string-width": "^4.1.0", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/long": { "version": "5.2.3", "resolved": "https://registry.npmjs.org/long/-/long-5.2.3.tgz", @@ -13961,19 +11240,36 @@ } }, "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, + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", + "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", "license": "ISC", "dependencies": { - "yallist": "^3.0.2" + "yallist": "^4.0.0" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/lru.min": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/lru.min/-/lru.min-1.1.1.tgz", + "integrity": "sha512-FbAj6lXil6t8z4z3j0E5mfRlPzxkySotzUHwRXjlpRh10vc6AI6WN62ehZj82VG7M20rqogJ0GLwar2Xa05a8Q==", + "license": "MIT", + "engines": { + "bun": ">=1.0.0", + "deno": ">=1.30.0", + "node": ">=8.0.0" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/wellwelwel" } }, "node_modules/magic-string": { - "version": "0.30.17", - "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.17.tgz", - "integrity": "sha512-sNPKHvyjVf7gyjwS4xGTaW/mCnF8wnjtifKBEhxfZ7E/S8tQ0rssrwGNn6q8JH/ohItJfSQp9mBtQYuTlH5QnA==", + "version": "0.30.12", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.12.tgz", + "integrity": "sha512-Ea8I3sQMVXr8JhN4z+H/d8zwo+tYDgHE9+5G4Wnrwhs0gaK9fXTKx0Tw5Xwsd/bCPTTZNRAdpyzvoeORe9LYpw==", "dev": true, "license": "MIT", "dependencies": { @@ -14042,6 +11338,19 @@ "node": ">= 6" } }, + "node_modules/make-fetch-happen/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "optional": true, + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/make-fetch-happen/node_modules/http-proxy-agent": { "version": "4.0.1", "resolved": "https://registry.npmjs.org/http-proxy-agent/-/http-proxy-agent-4.0.1.tgz", @@ -14057,36 +11366,6 @@ "node": ">= 6" } }, - "node_modules/make-fetch-happen/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "optional": true, - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/make-fetch-happen/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC", - "optional": 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, - "license": "BSD-3-Clause", - "dependencies": { - "tmpl": "1.0.5" - } - }, "node_modules/map-obj": { "version": "4.3.0", "resolved": "https://registry.npmjs.org/map-obj/-/map-obj-4.3.0.tgz", @@ -14101,25 +11380,15 @@ } }, "node_modules/marked": { - "version": "4.2.12", - "resolved": "https://registry.npmjs.org/marked/-/marked-4.2.12.tgz", - "integrity": "sha512-yr8hSKa3Fv4D3jdZmtMMPghgVt6TWbk86WQaWhDloQjRSQhMMYCAro7jP7VDJrjjdV8pxVxMssXS8B8Y5DZ5aw==", - "dev": true, + "version": "14.1.3", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.1.3.tgz", + "integrity": "sha512-ZibJqTULGlt9g5k4VMARAktMAjXoVnnr+Y3aCqW1oDftcV4BA3UmrBifzXoZyenHRk75csiPu9iwsTj4VNBT0g==", "license": "MIT", "bin": { "marked": "bin/marked.js" }, "engines": { - "node": ">= 12" - } - }, - "node_modules/math-intrinsics": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", - "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", - "license": "MIT", - "engines": { - "node": ">= 0.4" + "node": ">= 18" } }, "node_modules/mathml-tag-names": { @@ -14295,13 +11564,16 @@ } }, "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==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-4.0.0.tgz", + "integrity": "sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/mimic-response": { @@ -14324,25 +11596,25 @@ } }, "node_modules/minimatch": { - "version": "3.1.2", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz", - "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==", + "version": "9.0.3", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.3.tgz", + "integrity": "sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg==", "license": "ISC", "dependencies": { - "brace-expansion": "^1.1.7" + "brace-expansion": "^2.0.1" }, "engines": { - "node": "*" + "node": ">=16 || 14 >=14.17" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/minimist": { - "version": "1.2.8", - "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", - "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/ljharb" - } + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.6.tgz", + "integrity": "sha512-Jsjnk4bw3YJqYzbdyBiNsPWHPfO++UGG749Cxs6peCu5Xg4nrena6OVxOYxrQTqww0Jmwt+Ref8rggumkTLz9Q==", + "license": "MIT" }, "node_modules/minimist-options": { "version": "4.1.0", @@ -14441,12 +11713,6 @@ "node": ">=8" } }, - "node_modules/minipass/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/minizlib": { "version": "2.1.2", "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-2.1.2.tgz", @@ -14460,11 +11726,11 @@ "node": ">= 8" } }, - "node_modules/minizlib/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" + "node_modules/mitt": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz", + "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==", + "license": "MIT" }, "node_modules/mkdirp": { "version": "1.0.4", @@ -14478,6 +11744,13 @@ "node": ">=10" } }, + "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==", + "dev": true, + "license": "MIT" + }, "node_modules/mongodb": { "version": "4.17.2", "resolved": "https://registry.npmjs.org/mongodb/-/mongodb-4.17.2.tgz", @@ -14590,18 +11863,6 @@ "process-nextick-args": "^2.0.1" } }, - "node_modules/mqtt/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, "node_modules/mqtt/node_modules/mqtt-packet": { "version": "6.10.0", "resolved": "https://registry.npmjs.org/mqtt-packet/-/mqtt-packet-6.10.0.tgz", @@ -14634,11 +11895,15 @@ } } }, - "node_modules/mqtt/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" + "node_modules/mrmime": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.0.tgz", + "integrity": "sha512-eu38+hdgojoyq63s+yTpN4XMBdt5l8HhMhc4VKLO9KM5caLIBvUm4thi7fFaxyTmCKeNnXZ5pAlBwCUnhA09uw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=10" + } }, "node_modules/ms": { "version": "2.1.3", @@ -14647,45 +11912,46 @@ "license": "MIT" }, "node_modules/mssql": { - "version": "8.1.4", - "resolved": "https://registry.npmjs.org/mssql/-/mssql-8.1.4.tgz", - "integrity": "sha512-nqkYYehETWVvFLB9zAGJV2kegOsdtLjUnkHA52aFhlE0ZIoOXC3BL8pLERwFicFypM4i3DX1hYeuM726EEIxjQ==", + "version": "11.0.1", + "resolved": "https://registry.npmjs.org/mssql/-/mssql-11.0.1.tgz", + "integrity": "sha512-KlGNsugoT90enKlR8/G36H0kTxPthDhmtNUCwEHvgRza5Cjpjoj+P2X6eMpFUDN7pFrJZsKadL4x990G8RBE1w==", "license": "MIT", "dependencies": { - "@tediousjs/connection-string": "^0.3.0", - "commander": "^9.1.0", + "@tediousjs/connection-string": "^0.5.0", + "commander": "^11.0.0", "debug": "^4.3.3", "rfdc": "^1.3.0", "tarn": "^3.0.2", - "tedious": "^14.0.0" + "tedious": "^18.2.1" }, "bin": { "mssql": "bin/mssql" }, "engines": { - "node": ">=10" + "node": ">=18" } }, "node_modules/mssql/node_modules/commander": { - "version": "9.5.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", - "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "license": "MIT", "engines": { - "node": "^12.20.0 || >=14" + "node": ">=16" } }, "node_modules/mysql2": { - "version": "3.9.9", - "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.9.9.tgz", - "integrity": "sha512-Qtb2RUxwWMFkWXqF7Rd/7ySkupbQnNY7O0zQuQYgPcuJZ06M36JG3HIDEh/pEeq7LImcvA6O3lOVQ9XQK+HEZg==", + "version": "3.11.3", + "resolved": "https://registry.npmjs.org/mysql2/-/mysql2-3.11.3.tgz", + "integrity": "sha512-Qpu2ADfbKzyLdwC/5d4W7+5Yz7yBzCU05YWt5npWzACST37wJsB23wgOSo00qi043urkiRwXtEvJc9UnuLX/MQ==", "license": "MIT", "dependencies": { + "aws-ssl-profiles": "^1.1.1", "denque": "^2.1.0", "generate-function": "^2.3.1", "iconv-lite": "^0.6.3", "long": "^5.2.1", - "lru-cache": "^8.0.0", + "lru.min": "^1.0.0", "named-placeholders": "^1.1.3", "seq-queue": "^0.0.5", "sqlstring": "^2.3.2" @@ -14694,15 +11960,6 @@ "node": ">= 8.0" } }, - "node_modules/mysql2/node_modules/lru-cache": { - "version": "8.0.5", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-8.0.5.tgz", - "integrity": "sha512-MhWWlVnuab1RG5/zMRRcVGXZLCXrZTgfwMikgzCegsPnG62yDQo5JnqKkrK4jO5iKqDAZGItAqN5CtKBCBWRUA==", - "license": "ISC", - "engines": { - "node": ">=16.14" - } - }, "node_modules/named-placeholders": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/named-placeholders/-/named-placeholders-1.1.3.tgz", @@ -14733,9 +11990,9 @@ "optional": true }, "node_modules/nanoid": { - "version": "3.3.8", - "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.8.tgz", - "integrity": "sha512-WNLf5Sd8oZxOm+TzppcYk8gVOgP+l58xNy58D0nbUnOxOWRWvlcCV4kUF7ltmI6PsrLl/BgKEyS4mqsGChFN0w==", + "version": "3.3.7", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", + "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==", "funding": [ { "type": "github", @@ -14764,19 +12021,23 @@ "license": "MIT" }, "node_modules/negotiator": { - "version": "0.6.4", - "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz", - "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==", + "version": "0.6.3", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz", + "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==", "license": "MIT", "engines": { "node": ">= 0.6" } }, - "node_modules/node-abort-controller": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", - "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==", - "license": "MIT" + "node_modules/net-snmp": { + "version": "3.15.1", + "resolved": "https://registry.npmjs.org/net-snmp/-/net-snmp-3.15.1.tgz", + "integrity": "sha512-o6BV8iti9qhla2mLYhDoucYY/vBl7GZbyvEXgIxl3fgwald9R0RJdUFEnOohIFP6UUVONVazD1VcTuuSctd7tQ==", + "license": "MIT", + "dependencies": { + "asn1-ber": "^1.2.1", + "smart-buffer": "^4.1.0" + } }, "node_modules/node-addon-api": { "version": "4.3.0", @@ -14913,13 +12174,6 @@ "node": "^12.13.0 || ^14.15.0 || >=16.0.0" } }, - "node_modules/node-int64": { - "version": "0.4.0", - "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz", - "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==", - "dev": true, - "license": "MIT" - }, "node_modules/node-radius-client": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/node-radius-client/-/node-radius-client-1.0.0.tgz", @@ -14938,9 +12192,9 @@ "license": "MIT" }, "node_modules/node-releases": { - "version": "2.0.19", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.19.tgz", - "integrity": "sha512-xxOWJsBKtzAq7DY0J+DTzuz58K8e7sJbdgwkbMWQe8UYB6ekmsQ45q0M/tJDsGaZmbC+l7n57UV8Hl5tHxO9uw==", + "version": "2.0.18", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz", + "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==", "dev": true, "license": "MIT" }, @@ -14964,9 +12218,9 @@ } }, "node_modules/nodemailer": { - "version": "6.9.16", - "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.16.tgz", - "integrity": "sha512-psAuZdTIRN08HKVd/E8ObdV6NO7NTBY3KsC30F7M4H1OnmLCUNaS56FpYxyb26zWLSyYF9Ozch9KYHhHegsiOQ==", + "version": "6.9.15", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-6.9.15.tgz", + "integrity": "sha512-AHf04ySLC6CIfuRtRiEYtGEXgRfa6INgWGluDhnxTZhHSKvrBu7lc1VVchQ0d8nPc4cFaZoPq8vkyNoZr0TpGQ==", "license": "MIT-0", "engines": { "node": ">=6.0.0" @@ -15056,16 +12310,32 @@ } }, "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==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-5.3.0.tgz", + "integrity": "sha512-ppwTtiJZq0O/ai0z7yfudtBpWIoxM8yE6nHi1X47eFR2EWORqfbu6CnPlNsjeN683eT0qG6H/Pyf9fCcvjnnnQ==", "dev": true, "license": "MIT", "dependencies": { - "path-key": "^3.0.0" + "path-key": "^4.0.0" }, "engines": { - "node": ">=8" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/npm-run-path/node_modules/path-key": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-4.0.0.tgz", + "integrity": "sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/npmlog": { @@ -15122,9 +12392,9 @@ } }, "node_modules/object-inspect": { - "version": "1.13.3", - "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz", - "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==", + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.2.tgz", + "integrity": "sha512-IRZSRuzJiynemAXPYtPe5BoI/RESNYR7TYm50MC5Mqbd3Jmw5y790sErYw3V6SryFJD64b74qQQs9wn5Bg/k3g==", "license": "MIT", "engines": { "node": ">= 0.4" @@ -15137,22 +12407,22 @@ "version": "1.1.1", "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz", "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/object.assign": { - "version": "4.1.7", - "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz", - "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==", + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz", + "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bind": "^1.0.5", "define-properties": "^1.2.1", - "es-object-atoms": "^1.0.0", - "has-symbols": "^1.1.0", + "has-symbols": "^1.0.3", "object-keys": "^1.1.1" }, "engines": { @@ -15202,16 +12472,16 @@ } }, "node_modules/onetime": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz", - "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-6.0.0.tgz", + "integrity": "sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ==", "dev": true, "license": "MIT", "dependencies": { - "mimic-fn": "^2.1.0" + "mimic-fn": "^4.0.0" }, "engines": { - "node": ">=6" + "node": ">=12" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -15235,9 +12505,9 @@ } }, "node_modules/openid-client": { - "version": "5.7.1", - "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.1.tgz", - "integrity": "sha512-jDBPgSVfTnkIh71Hg9pRvtJc6wTwqjRkN88+gCFtYWrlP4Yx2Dsrow8uPi3qLr/aeymPF3o2+dS+wOpglK04ew==", + "version": "5.7.0", + "resolved": "https://registry.npmjs.org/openid-client/-/openid-client-5.7.0.tgz", + "integrity": "sha512-4GCCGZt1i2kTHpwvaC/sCpTpQqDnBzDzuJcJMbH+y1Q5qI8U8RBvoSh28svarXszZHR5BAMXbJPX1PGPRE3VOA==", "license": "MIT", "dependencies": { "jose": "^4.15.9", @@ -15249,24 +12519,6 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/openid-client/node_modules/lru-cache": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz", - "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/openid-client/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/optionator": { "version": "0.9.4", "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz", @@ -15285,13 +12537,6 @@ "node": ">= 0.8.0" } }, - "node_modules/ospath": { - "version": "1.2.2", - "resolved": "https://registry.npmjs.org/ospath/-/ospath-1.2.2.tgz", - "integrity": "sha512-o6E5qJV5zkAbIDNhGSIlyOhScKXgQrSRMilfph0clDfM0nEnBOlKlH4sWDmG95BW/CvwNz0vmm7dJVtU2KlMiA==", - "dev": true, - "license": "MIT" - }, "node_modules/p-cancelable": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/p-cancelable/-/p-cancelable-3.0.0.tgz", @@ -15318,29 +12563,16 @@ } }, "node_modules/p-locate": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", - "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^2.2.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/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==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", + "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", "dev": true, "license": "MIT", "dependencies": { - "p-try": "^2.0.0" + "p-limit": "^3.0.2" }, "engines": { - "node": ">=6" + "node": ">=10" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -15350,8 +12582,8 @@ "version": "4.0.0", "resolved": "https://registry.npmjs.org/p-map/-/p-map-4.0.0.tgz", "integrity": "sha512-/bjOqmgETBYB5BoEeGVea8dmvHb2m9GLy1E9W43yeyfP6QQCZGFNa+XRceJEuDB6zqr+gKpIAmlLebMpykw/MQ==", - "devOptional": true, "license": "MIT", + "optional": true, "dependencies": { "aggregate-error": "^3.0.0" }, @@ -15372,6 +12604,13 @@ "node": ">=6" } }, + "node_modules/package-json-from-dist": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz", + "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==", + "dev": true, + "license": "BlueOak-1.0.0" + }, "node_modules/parent-module": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz", @@ -15405,9 +12644,9 @@ } }, "node_modules/parse5": { - "version": "7.2.1", - "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz", - "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==", + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.0.tgz", + "integrity": "sha512-ZkDsAOcxsUMZ4Lz5fVciOehNcJ+Gb8gTzcA4yl3wnc273BAybYWrQ+Ks/OjCjSEpjvQkDSeZbybK9qj2VHHdGA==", "license": "MIT", "dependencies": { "entities": "^4.5.0" @@ -15429,6 +12668,18 @@ "url": "https://github.com/inikulin/parse5?sponsor=1" } }, + "node_modules/parse5-parser-stream": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz", + "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==", + "license": "MIT", + "dependencies": { + "parse5": "^7.0.0" + }, + "funding": { + "url": "https://github.com/inikulin/parse5?sponsor=1" + } + }, "node_modules/parseurl": { "version": "1.3.3", "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", @@ -15515,9 +12766,9 @@ } }, "node_modules/path-to-regexp": { - "version": "0.1.12", - "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz", - "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==", + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.10.tgz", + "integrity": "sha512-7lf7qcQidTku0Gu3YDPc8DJ1q7OOucfa/BSsIwjuh56VU7katFvuM8hULfkwB3Fns/rsVF7PwPKVw1sl5KQS9w==", "license": "MIT" }, "node_modules/path-type": { @@ -15530,17 +12781,17 @@ "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/pathe": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-1.1.2.tgz", + "integrity": "sha512-whLdWMYL2TwI08hn8/ZqAbrVemu0LNaNNJZX73O6qaIdCTfXutsLhMkjdENX0qhsQ9uIimo4/aQOmXkoon2nDQ==", "dev": true, "license": "MIT" }, - "node_modules/performance-now": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", - "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==", + "node_modules/perfect-debounce": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-1.0.0.tgz", + "integrity": "sha512-xCy9V055GLEqoFaHoC1SoLIaLmWctgCUaBaWxDZ7/Zx4CTyX7cJQLJOok/orfjZAh9kEYpjJa4d0KcJmCbctZA==", "dev": true, "license": "MIT" }, @@ -15656,43 +12907,10 @@ "dev": true, "license": "MIT", "engines": { - "node": ">=8.6" - }, - "funding": { - "url": "https://github.com/sponsors/jonschlinkert" - } - }, - "node_modules/pify": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", - "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=0.10.0" - } - }, - "node_modules/pirates": { - "version": "4.0.6", - "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz", - "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">= 6" - } - }, - "node_modules/pkg-dir": { - "version": "4.2.0", - "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz", - "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "find-up": "^4.0.0" - }, - "engines": { - "node": ">=8" + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" } }, "node_modules/pkginfo": { @@ -15704,10 +12922,29 @@ "node": ">= 0.4.0" } }, + "node_modules/playwright": { + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright/-/playwright-1.39.0.tgz", + "integrity": "sha512-naE5QT11uC/Oiq0BwZ50gDmy8c8WLPRTEWuSSFVG2egBka/1qMoSqYQcROMT9zLwJ86oPofcTH2jBY/5wWOgIw==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "playwright-core": "1.39.0" + }, + "bin": { + "playwright": "cli.js" + }, + "engines": { + "node": ">=16" + }, + "optionalDependencies": { + "fsevents": "2.3.2" + } + }, "node_modules/playwright-core": { - "version": "1.35.1", - "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.35.1.tgz", - "integrity": "sha512-pNXb6CQ7OqmGDRspEjlxE49w+4YtR6a3X6mT1hZXeJHWmsEz7SunmvZeiG/+y1yyMZdHnnn73WKYdtV1er0Xyg==", + "version": "1.39.0", + "resolved": "https://registry.npmjs.org/playwright-core/-/playwright-core-1.39.0.tgz", + "integrity": "sha512-+k4pdZgs1qiM+OUkSjx96YiKsXsmb59evFoqv8SKO067qBA+Z2s/dCzJij/ZhdQcs2zlTAgRKfeiiLm8PQ2qvw==", "license": "Apache-2.0", "bin": { "playwright-core": "cli.js" @@ -15730,15 +12967,16 @@ "version": "1.0.0", "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz", "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==", + "dev": true, "license": "MIT", "engines": { "node": ">= 0.4" } }, "node_modules/postcss": { - "version": "8.4.49", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz", - "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==", + "version": "8.4.47", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", + "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==", "dev": true, "funding": [ { @@ -15757,7 +12995,7 @@ "license": "MIT", "dependencies": { "nanoid": "^3.3.7", - "picocolors": "^1.1.1", + "picocolors": "^1.1.0", "source-map-js": "^1.2.1" }, "engines": { @@ -15780,12 +13018,25 @@ "node": "^12 || >=14" } }, - "node_modules/postcss-html/node_modules/js-tokens": { - "version": "8.0.3", - "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-8.0.3.tgz", - "integrity": "sha512-UfJMcSJc+SEXEl9lH/VLHSZbThQyLpw1vLO1Lb+j4RWDvG3N2f7yj3PVQA3cmkTBNldJ9eFnM+xEXxHIXrYiJw==", + "node_modules/postcss-html/node_modules/htmlparser2": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-8.0.2.tgz", + "integrity": "sha512-GYdjWKDkbRLkZ5geuHs5NY1puJ+PXwP7+fHPRz06Eirsb9ugf6d8kkXav6ADhcODhFFPMIXyxkxSuMf3D6NCFA==", "dev": true, - "license": "MIT" + "funding": [ + "https://github.com/fb55/htmlparser2?sponsor=1", + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ], + "license": "MIT", + "dependencies": { + "domelementtype": "^2.3.0", + "domhandler": "^5.0.3", + "domutils": "^3.0.1", + "entities": "^4.4.0" + } }, "node_modules/postcss-resolve-nested-selector": { "version": "0.1.6", @@ -15924,47 +13175,6 @@ "node": ">= 0.8.0" } }, - "node_modules/pretty-bytes": { - "version": "5.6.0", - "resolved": "https://registry.npmjs.org/pretty-bytes/-/pretty-bytes-5.6.0.tgz", - "integrity": "sha512-FFw039TmrBqFK8ma/7OL3sDz/VytdtJr044/QUJtH0wK9lb9jLq9tJyIxUwtQJHwar2BqtiA4iCWSwo9JLkzFg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=6" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/pretty-format": { - "version": "29.7.0", - "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz", - "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "@jest/schemas": "^29.6.3", - "ansi-styles": "^5.0.0", - "react-is": "^18.0.0" - }, - "engines": { - "node": "^14.15.0 || ^16.10.0 || >=18.0.0" - } - }, - "node_modules/pretty-format/node_modules/ansi-styles": { - "version": "5.2.0", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz", - "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/ansi-styles?sponsor=1" - } - }, "node_modules/prismjs": { "version": "1.29.0", "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.29.0.tgz", @@ -15979,7 +13189,6 @@ "version": "0.11.10", "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", "integrity": "sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==", - "dev": true, "license": "MIT", "engines": { "node": ">= 0.6.0" @@ -16059,18 +13268,33 @@ "node": ">=8" } }, - "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==", + "node_modules/proper-lockfile": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/proper-lockfile/-/proper-lockfile-4.1.2.tgz", + "integrity": "sha512-TjNPblN4BwAWMXU8s9AEz4JmQxnD1NNL7bNOY/AKUzyamc379FWASUhc/K1pL2noVb+XmZKLL68cjzLsiOAMaA==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.4", + "retry": "^0.12.0", + "signal-exit": "^3.0.2" + } + }, + "node_modules/properties-reader": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/properties-reader/-/properties-reader-2.3.0.tgz", + "integrity": "sha512-z597WicA7nDZxK12kZqHr2TcvwNU1GCfA5UwfDY/HDp3hXPoPlb5rlEx9bwGTiJnc0OqbBTkU975jDToth8Gxw==", "dev": true, "license": "MIT", "dependencies": { - "kleur": "^3.0.3", - "sisteransi": "^1.0.5" + "mkdirp": "^1.0.4" }, "engines": { - "node": ">= 6" + "node": ">=14" + }, + "funding": { + "type": "github", + "url": "https://github.com/steveukx/properties?sponsor=1" } }, "node_modules/protobufjs": { @@ -16116,6 +13340,12 @@ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==", "license": "MIT" }, + "node_modules/psl": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.9.0.tgz", + "integrity": "sha512-E/ZsdU4HLs/68gYzgGTkMicWTLPdAftJLfJFlLUAAKZGkStNU72sZjT66SnMDVOfOWY/YAoiD7Jxa9iHvngcag==", + "license": "MIT" + }, "node_modules/pump": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.2.tgz", @@ -16135,23 +13365,6 @@ "node": ">=6" } }, - "node_modules/pure-rand": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz", - "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==", - "dev": true, - "funding": [ - { - "type": "individual", - "url": "https://github.com/sponsors/dubzzz" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fast-check" - } - ], - "license": "MIT" - }, "node_modules/qlobber": { "version": "5.0.3", "resolved": "https://registry.npmjs.org/qlobber/-/qlobber-5.0.3.tgz", @@ -16180,6 +13393,16 @@ "node": ">=10.13.0" } }, + "node_modules/qrcode/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, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, "node_modules/qrcode/node_modules/cliui": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz", @@ -16202,6 +13425,62 @@ "node": ">=0.10.0" } }, + "node_modules/qrcode/node_modules/find-up": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz", + "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==", + "dev": true, + "license": "MIT", + "dependencies": { + "locate-path": "^5.0.0", + "path-exists": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/locate-path": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz", + "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-locate": "^4.1.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/qrcode/node_modules/p-limit": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", + "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-try": "^2.0.0" + }, + "engines": { + "node": ">=6" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/qrcode/node_modules/p-locate": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz", + "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==", + "dev": true, + "license": "MIT", + "dependencies": { + "p-limit": "^2.2.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/qrcode/node_modules/wrap-ansi": { "version": "6.2.0", "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz", @@ -16276,6 +13555,12 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/querystringify": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz", + "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==", + "license": "MIT" + }, "node_modules/queue-microtask": { "version": "1.2.3", "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz", @@ -16297,6 +13582,13 @@ ], "license": "MIT" }, + "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==", + "dev": true, + "license": "MIT" + }, "node_modules/quick-lru": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz", @@ -16341,6 +13633,15 @@ "node": ">= 0.8" } }, + "node_modules/raw-body/node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "license": "MIT", + "engines": { + "node": ">= 0.8" + } + }, "node_modules/raw-body/node_modules/iconv-lite": { "version": "0.4.24", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", @@ -16353,13 +13654,6 @@ "node": ">=0.10.0" } }, - "node_modules/react-is": { - "version": "18.3.1", - "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz", - "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg==", - "dev": true, - "license": "MIT" - }, "node_modules/read-pkg": { "version": "6.0.0", "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-6.0.0.tgz", @@ -16397,55 +13691,6 @@ "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/read-pkg-up/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/read-pkg-up/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/read-pkg-up/node_modules/type-fest": { "version": "1.4.0", "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-1.4.0.tgz", @@ -16486,6 +13731,29 @@ "node": ">= 6" } }, + "node_modules/readdir-glob": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/readdir-glob/-/readdir-glob-1.1.3.tgz", + "integrity": "sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==", + "dev": true, + "license": "Apache-2.0", + "dependencies": { + "minimatch": "^5.1.0" + } + }, + "node_modules/readdir-glob/node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dev": true, + "license": "ISC", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, "node_modules/readdirp": { "version": "3.6.0", "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", @@ -16531,13 +13799,30 @@ "integrity": "sha512-wheIYdr4NYML61AjC8MKj/2jrR/kDQri/CIpVoZwldwhnIrD/j9jIU5bJ8yBKuB2VhpFV7Ab6G2XkBjv9r9Zzw==", "license": "MIT" }, - "node_modules/redbean-node/node_modules/brace-expansion": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", - "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", + "node_modules/redbean-node/node_modules/commander": { + "version": "9.5.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-9.5.0.tgz", + "integrity": "sha512-KRs7WVDKg86PWiuAqhDrAQnTXZKraVcCc6vFdL14qrZ/DcWwuRo7VoiYXalXO7S5GKpqYiVEwCbgFDfxNHKJBQ==", + "license": "MIT", + "engines": { + "node": "^12.20.0 || >=14" + } + }, + "node_modules/redbean-node/node_modules/debug": { + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "license": "MIT", "dependencies": { - "balanced-match": "^1.0.0" + "ms": "2.1.2" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } } }, "node_modules/redbean-node/node_modules/glob": { @@ -16562,19 +13847,55 @@ "url": "https://github.com/sponsors/isaacs" } }, - "node_modules/redbean-node/node_modules/minimatch": { - "version": "9.0.5", - "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz", - "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==", - "license": "ISC", + "node_modules/redbean-node/node_modules/knex": { + "version": "2.4.2", + "resolved": "https://registry.npmjs.org/knex/-/knex-2.4.2.tgz", + "integrity": "sha512-tMI1M7a+xwHhPxjbl/H9K1kHX+VncEYcvCx5K00M16bWvpYPKAZd6QrCu68PtHAdIZNQPWZn0GVhqVBEthGWCg==", + "license": "MIT", "dependencies": { - "brace-expansion": "^2.0.1" + "colorette": "2.0.19", + "commander": "^9.1.0", + "debug": "4.3.4", + "escalade": "^3.1.1", + "esm": "^3.2.25", + "get-package-type": "^0.1.0", + "getopts": "2.3.0", + "interpret": "^2.2.0", + "lodash": "^4.17.21", + "pg-connection-string": "2.5.0", + "rechoir": "^0.8.0", + "resolve-from": "^5.0.0", + "tarn": "^3.0.2", + "tildify": "2.0.0" + }, + "bin": { + "knex": "bin/cli.js" }, "engines": { - "node": ">=16 || 14 >=14.17" + "node": ">=12" }, - "funding": { - "url": "https://github.com/sponsors/isaacs" + "peerDependenciesMeta": { + "better-sqlite3": { + "optional": true + }, + "mysql": { + "optional": true + }, + "mysql2": { + "optional": true + }, + "pg": { + "optional": true + }, + "pg-native": { + "optional": true + }, + "sqlite3": { + "optional": true + }, + "tedious": { + "optional": true + } } }, "node_modules/redbean-node/node_modules/minipass": { @@ -16586,6 +13907,27 @@ "node": ">=16 || 14 >=14.17" } }, + "node_modules/redbean-node/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==", + "license": "MIT" + }, + "node_modules/redbean-node/node_modules/pg-connection-string": { + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/pg-connection-string/-/pg-connection-string-2.5.0.tgz", + "integrity": "sha512-r5o/V/ORTA6TmUnyWZR9nCj1klXCO2CEKNRlVuJptZe85QuhFayC7WeMic7ndayT5IRIR0S0xFxFi2ousartlQ==", + "license": "MIT" + }, + "node_modules/redbean-node/node_modules/resolve-from": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", + "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", + "license": "MIT", + "engines": { + "node": ">=8" + } + }, "node_modules/redent": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/redent/-/redent-4.0.0.tgz", @@ -16633,69 +13975,18 @@ "@redis/time-series": "1.0.4" } }, - "node_modules/reflect.getprototypeof": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.9.tgz", - "integrity": "sha512-r0Ay04Snci87djAsI4U+WNRcSw5S4pOH7qFjd/veA5gC7TbqESR3tcj28ia95L/fYUDw11JKP7uqUKUAfVvV5Q==", - "license": "MIT", - "dependencies": { - "call-bind": "^1.0.8", - "define-properties": "^1.2.1", - "dunder-proto": "^1.0.1", - "es-abstract": "^1.23.6", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.6", - "gopd": "^1.2.0", - "which-builtin-type": "^1.2.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/regenerate": { - "version": "1.4.2", - "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz", - "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==", - "dev": true, - "license": "MIT" - }, - "node_modules/regenerate-unicode-properties": { - "version": "10.2.0", - "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz", - "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.2" - }, - "engines": { - "node": ">=4" - } - }, "node_modules/regenerator-runtime": { - "version": "0.13.11", - "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", - "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==", + "version": "0.14.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz", + "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw==", "dev": true, "license": "MIT" }, - "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, - "license": "MIT", - "dependencies": { - "@babel/runtime": "^7.8.4" - } - }, "node_modules/regexp.prototype.flags": { "version": "1.5.3", "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz", "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", @@ -16723,60 +14014,12 @@ "url": "https://github.com/sponsors/mysticatea" } }, - "node_modules/regexpu-core": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.2.0.tgz", - "integrity": "sha512-H66BPQMrv+V16t8xtmq+UC0CBpiTBA60V8ibS1QVReIp8T1z8hwFxqcGzm9K6lgsN7sB5edVH8a+ze6Fqm4weA==", - "dev": true, - "license": "MIT", - "dependencies": { - "regenerate": "^1.4.2", - "regenerate-unicode-properties": "^10.2.0", - "regjsgen": "^0.8.0", - "regjsparser": "^0.12.0", - "unicode-match-property-ecmascript": "^2.0.0", - "unicode-match-property-value-ecmascript": "^2.1.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/regjsgen": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz", - "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==", - "dev": true, - "license": "MIT" - }, - "node_modules/regjsparser": { - "version": "0.12.0", - "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.12.0.tgz", - "integrity": "sha512-cnE+y8bz4NhMjISKbgeVJtqNbtf5QpjZP+Bslo+UqkIt9QPnX9q095eiRRASJG1/tz6dlNr6Z5NsBiWYokp6EQ==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "jsesc": "~3.0.2" - }, - "bin": { - "regjsparser": "bin/parser" - } - }, "node_modules/reinterval": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/reinterval/-/reinterval-1.1.0.tgz", "integrity": "sha512-QIRet3SYrGp0HUHO88jVskiG6seqUGC5iAG7AwI/BV4ypGcuqk9Du6YQBUOUqm9c8pw1eyLoIaONifRua1lsEQ==", "license": "MIT" }, - "node_modules/request-progress": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/request-progress/-/request-progress-3.0.0.tgz", - "integrity": "sha512-MnWzEHHaxHO2iWiQuHrUPBi/1WeBf5PkxQqNyNvLl9VAYSdXkP8tQ3pBSeCPD+yw0v0Aq1zosWLz0BdeXpWwZg==", - "dev": true, - "license": "MIT", - "dependencies": { - "throttleit": "^1.0.0" - } - }, "node_modules/require-directory": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", @@ -16803,22 +14046,25 @@ "dev": true, "license": "ISC" }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "license": "MIT" + }, "node_modules/resolve": { - "version": "1.22.10", - "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.10.tgz", - "integrity": "sha512-NPRy+/ncIMeDlTAsuqwKIiferiawhefFJtkNSW0qZJEqMEb+qBt/77B/jGeeek+F0uOeN05CDa6HXbbIgtVX4w==", + "version": "1.22.8", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz", + "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==", "license": "MIT", "dependencies": { - "is-core-module": "^2.16.0", + "is-core-module": "^2.13.0", "path-parse": "^1.0.7", "supports-preserve-symlinks-flag": "^1.0.0" }, "bin": { "resolve": "bin/resolve" }, - "engines": { - "node": ">= 0.4" - }, "funding": { "url": "https://github.com/sponsors/ljharb" } @@ -16829,29 +14075,6 @@ "integrity": "sha512-0a1F4l73/ZFZOakJnQ3FvkJ2+gSTQWz/r2KE5OdDY0TxPm5h4GkqkWWfM47T7HsbnOtcJVEF4epCVy6u7Q3K+g==", "license": "MIT" }, - "node_modules/resolve-cwd": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz", - "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==", - "dev": true, - "license": "MIT", - "dependencies": { - "resolve-from": "^5.0.0" - }, - "engines": { - "node": ">=8" - } - }, - "node_modules/resolve-cwd/node_modules/resolve-from": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz", - "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/resolve-from": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz", @@ -16862,16 +14085,6 @@ "node": ">=4" } }, - "node_modules/resolve.exports": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", - "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=10" - } - }, "node_modules/responselike": { "version": "2.0.1", "resolved": "https://registry.npmjs.org/responselike/-/responselike-2.0.1.tgz", @@ -16893,20 +14106,6 @@ "node": ">=8" } }, - "node_modules/restore-cursor": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz", - "integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^5.1.0", - "signal-exit": "^3.0.2" - }, - "engines": { - "node": ">=8" - } - }, "node_modules/retimer": { "version": "3.0.0", "resolved": "https://registry.npmjs.org/retimer/-/retimer-3.0.0.tgz", @@ -16918,8 +14117,8 @@ "version": "0.12.0", "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz", "integrity": "sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==", + "devOptional": true, "license": "MIT", - "optional": true, "engines": { "node": ">= 4" } @@ -16958,9 +14157,9 @@ } }, "node_modules/rollup": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.28.1.tgz", - "integrity": "sha512-61fXYl/qNVinKmGSTHAZ6Yy8I3YIJC/r2m9feHo6SwVAVcLT5MPwOUFe7EuURA/4m0NR8lXG4BBXuo/IZEsjMg==", + "version": "4.24.0", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.24.0.tgz", + "integrity": "sha512-DOmrlGSXNk1DM0ljiQA+i+o0rSLhtii1je5wgk60j49d1jHT5YYttBv1iWOnYSTG+fZZESUOSNiAl89SIet+Cg==", "dev": true, "license": "MIT", "dependencies": { @@ -16974,25 +14173,22 @@ "npm": ">=8.0.0" }, "optionalDependencies": { - "@rollup/rollup-android-arm-eabi": "4.28.1", - "@rollup/rollup-android-arm64": "4.28.1", - "@rollup/rollup-darwin-arm64": "4.28.1", - "@rollup/rollup-darwin-x64": "4.28.1", - "@rollup/rollup-freebsd-arm64": "4.28.1", - "@rollup/rollup-freebsd-x64": "4.28.1", - "@rollup/rollup-linux-arm-gnueabihf": "4.28.1", - "@rollup/rollup-linux-arm-musleabihf": "4.28.1", - "@rollup/rollup-linux-arm64-gnu": "4.28.1", - "@rollup/rollup-linux-arm64-musl": "4.28.1", - "@rollup/rollup-linux-loongarch64-gnu": "4.28.1", - "@rollup/rollup-linux-powerpc64le-gnu": "4.28.1", - "@rollup/rollup-linux-riscv64-gnu": "4.28.1", - "@rollup/rollup-linux-s390x-gnu": "4.28.1", - "@rollup/rollup-linux-x64-gnu": "4.28.1", - "@rollup/rollup-linux-x64-musl": "4.28.1", - "@rollup/rollup-win32-arm64-msvc": "4.28.1", - "@rollup/rollup-win32-ia32-msvc": "4.28.1", - "@rollup/rollup-win32-x64-msvc": "4.28.1", + "@rollup/rollup-android-arm-eabi": "4.24.0", + "@rollup/rollup-android-arm64": "4.24.0", + "@rollup/rollup-darwin-arm64": "4.24.0", + "@rollup/rollup-darwin-x64": "4.24.0", + "@rollup/rollup-linux-arm-gnueabihf": "4.24.0", + "@rollup/rollup-linux-arm-musleabihf": "4.24.0", + "@rollup/rollup-linux-arm64-gnu": "4.24.0", + "@rollup/rollup-linux-arm64-musl": "4.24.0", + "@rollup/rollup-linux-powerpc64le-gnu": "4.24.0", + "@rollup/rollup-linux-riscv64-gnu": "4.24.0", + "@rollup/rollup-linux-s390x-gnu": "4.24.0", + "@rollup/rollup-linux-x64-gnu": "4.24.0", + "@rollup/rollup-linux-x64-musl": "4.24.0", + "@rollup/rollup-win32-arm64-msvc": "4.24.0", + "@rollup/rollup-win32-ia32-msvc": "4.24.0", + "@rollup/rollup-win32-x64-msvc": "4.24.0", "fsevents": "~2.3.2" } }, @@ -17023,16 +14219,6 @@ } } }, - "node_modules/rollup-plugin-visualizer/node_modules/source-map": { - "version": "0.7.4", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", - "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", - "dev": true, - "license": "BSD-3-Clause", - "engines": { - "node": ">= 8" - } - }, "node_modules/rtlcss": { "version": "3.5.0", "resolved": "https://registry.npmjs.org/rtlcss/-/rtlcss-3.5.0.tgz", @@ -17049,50 +14235,14 @@ "rtlcss": "bin/rtlcss.js" } }, - "node_modules/rtlcss/node_modules/find-up": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz", - "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==", - "dev": true, - "license": "MIT", - "dependencies": { - "locate-path": "^6.0.0", - "path-exists": "^4.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/rtlcss/node_modules/locate-path": { - "version": "6.0.0", - "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz", - "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==", - "dev": true, - "license": "MIT", - "dependencies": { - "p-locate": "^5.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/rtlcss/node_modules/p-locate": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz", - "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==", + "node_modules/run-applescript": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz", + "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==", "dev": true, "license": "MIT", - "dependencies": { - "p-limit": "^3.0.2" - }, "engines": { - "node": ">=10" + "node": ">=18" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -17133,53 +14283,40 @@ } }, "node_modules/safe-array-concat": { - "version": "1.1.3", - "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz", - "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==", + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz", + "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "get-intrinsic": "^1.2.6", - "has-symbols": "^1.1.0", - "isarray": "^2.0.5" - }, - "engines": { - "node": ">=0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/safe-buffer": { - "version": "5.2.1", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", - "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/feross" - }, - { - "type": "patreon", - "url": "https://www.patreon.com/feross" - }, - { - "type": "consulting", - "url": "https://feross.org/support" - } - ], + "call-bind": "^1.0.7", + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "isarray": "^2.0.5" + }, + "engines": { + "node": ">=0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", "license": "MIT" }, "node_modules/safe-regex-test": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz", - "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==", + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz", + "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", + "call-bind": "^1.0.6", "es-errors": "^1.3.0", - "is-regex": "^1.2.1" + "is-regex": "^1.1.4" }, "engines": { "node": ">= 0.4" @@ -17211,9 +14348,9 @@ } }, "node_modules/sax": { - "version": "1.2.4", - "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", - "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz", + "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==", "license": "ISC" }, "node_modules/sb-promise-queue": { @@ -17252,6 +14389,15 @@ "seek-table": "bin/seek-bzip-table" } }, + "node_modules/seek-bzip/node_modules/commander": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz", + "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==", + "license": "MIT", + "engines": { + "node": ">= 6" + } + }, "node_modules/semver": { "version": "7.5.4", "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.4.tgz", @@ -17267,24 +14413,6 @@ "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==", - "license": "ISC", - "dependencies": { - "yallist": "^4.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/semver/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/send": { "version": "0.19.0", "resolved": "https://registry.npmjs.org/send/-/send-0.19.0.tgz", @@ -17380,6 +14508,7 @@ "version": "2.0.2", "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz", "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==", + "dev": true, "license": "MIT", "dependencies": { "define-data-property": "^1.1.4", @@ -17426,82 +14555,25 @@ "license": "MIT" }, "node_modules/shell-quote": { - "version": "1.8.2", - "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.2.tgz", - "integrity": "sha512-AzqKpGKjrj7EM6rKVQEPpB288oCfnrEIuyoT9cyF4nmGa7V8Zk6f7RRqYisX8X9m+Q7bd632aZW4ky7EhbQztA==", + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz", + "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==", "dev": true, "license": "MIT", - "engines": { - "node": ">= 0.4" - }, "funding": { "url": "https://github.com/sponsors/ljharb" } }, "node_modules/side-channel": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", - "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3", - "side-channel-list": "^1.0.0", - "side-channel-map": "^1.0.1", - "side-channel-weakmap": "^1.0.2" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-list": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", - "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", - "license": "MIT", - "dependencies": { - "es-errors": "^1.3.0", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-map": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", - "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/side-channel-weakmap": { - "version": "1.0.2", - "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", - "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz", + "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==", "license": "MIT", "dependencies": { - "call-bound": "^1.0.2", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "get-intrinsic": "^1.2.5", - "object-inspect": "^1.13.3", - "side-channel-map": "^1.0.1" + "get-intrinsic": "^1.2.4", + "object-inspect": "^1.13.1" }, "engines": { "node": ">= 0.4" @@ -17516,12 +14588,20 @@ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", "license": "ISC" }, - "node_modules/sisteransi": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz", - "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==", + "node_modules/sirv": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.0.tgz", + "integrity": "sha512-BPwJGUeDaDCHihkORDchNyyTvWFhcusy1XMmhEVTQTwGeybFbp8YEmB+njbPnth1FibULBSBVwCQni25XlCUDg==", "dev": true, - "license": "MIT" + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } }, "node_modules/slash": { "version": "3.0.0", @@ -17534,9 +14614,9 @@ } }, "node_modules/slice-ansi": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-3.0.0.tgz", - "integrity": "sha512-pSyv7bSTC7ig9Dcgbw9AuRNUb5k5V6oDudjZoMBSr13qpLBG7tB+zgCkARjq7xIUgdz5P1Qe8u+rSGdouOOIyQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", + "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", "dev": true, "license": "MIT", "dependencies": { @@ -17545,7 +14625,10 @@ "is-fullwidth-code-point": "^3.0.0" }, "engines": { - "node": ">=8" + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/slice-ansi?sponsor=1" } }, "node_modules/smart-buffer": { @@ -17586,23 +14669,6 @@ "ws": "~8.17.1" } }, - "node_modules/socket.io-adapter/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/socket.io-adapter/node_modules/ws": { "version": "8.17.1", "resolved": "https://registry.npmjs.org/ws/-/ws-8.17.1.tgz", @@ -17639,23 +14705,6 @@ "node": ">=10.0.0" } }, - "node_modules/socket.io-client/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/socket.io-parser": { "version": "4.2.4", "resolved": "https://registry.npmjs.org/socket.io-parser/-/socket.io-parser-4.2.4.tgz", @@ -17669,40 +14718,6 @@ "node": ">=10.0.0" } }, - "node_modules/socket.io-parser/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, - "node_modules/socket.io/node_modules/debug": { - "version": "4.3.7", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz", - "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==", - "license": "MIT", - "dependencies": { - "ms": "^2.1.3" - }, - "engines": { - "node": ">=6.0" - }, - "peerDependenciesMeta": { - "supports-color": { - "optional": true - } - } - }, "node_modules/socks": { "version": "2.8.3", "resolved": "https://registry.npmjs.org/socks/-/socks-2.8.3.tgz", @@ -17731,6 +14746,18 @@ "node": ">= 10" } }, + "node_modules/socks-proxy-agent/node_modules/agent-base": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-6.0.2.tgz", + "integrity": "sha512-RZNwNclF7+MS/8bDg70amg32dyeZGZxiDuQmZxKLAlQjr3jGyLx+4Kkk58UO7D2QdgFIQCovuSuZESne6RG6XQ==", + "license": "MIT", + "dependencies": { + "debug": "4" + }, + "engines": { + "node": ">= 6.0.0" + } + }, "node_modules/sortablejs": { "version": "1.14.0", "resolved": "https://registry.npmjs.org/sortablejs/-/sortablejs-1.14.0.tgz", @@ -17739,13 +14766,13 @@ "license": "MIT" }, "node_modules/source-map": { - "version": "0.6.1", - "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", - "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "version": "0.7.4", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz", + "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==", "dev": true, "license": "BSD-3-Clause", "engines": { - "node": ">=0.10.0" + "node": ">= 8" } }, "node_modules/source-map-js": { @@ -17759,9 +14786,9 @@ } }, "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==", + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", "dev": true, "license": "MIT", "dependencies": { @@ -17769,6 +14796,16 @@ "source-map": "^0.6.0" } }, + "node_modules/source-map-support/node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/sparse-bitfield": { "version": "3.0.3", "resolved": "https://registry.npmjs.org/sparse-bitfield/-/sparse-bitfield-3.0.3.tgz", @@ -17821,6 +14858,23 @@ "dev": true, "license": "CC0-1.0" }, + "node_modules/speakingurl": { + "version": "14.0.1", + "resolved": "https://registry.npmjs.org/speakingurl/-/speakingurl-14.0.1.tgz", + "integrity": "sha512-1POYv7uv2gXoyGFpBCmpDVSNV74IfsWlDW216UPjbWufNf+bSU6GdbDsxdcxtfwb4xlI3yxzOTKClUosxARYrQ==", + "dev": true, + "license": "BSD-3-Clause", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/split-ca": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/split-ca/-/split-ca-1.0.1.tgz", + "integrity": "sha512-Q5thBSxp5t8WPTTJQS59LrGqOZqOsrhDGDVm8azCqIBjSBd7nd9o2PM+mDulQQkh8h//4U6hFZnc/mul8t5pWQ==", + "dev": true, + "license": "ISC" + }, "node_modules/split2": { "version": "3.2.2", "resolved": "https://registry.npmjs.org/split2/-/split2-3.2.2.tgz", @@ -17845,6 +14899,28 @@ "node": ">= 0.6" } }, + "node_modules/ssh-remote-port-forward": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/ssh-remote-port-forward/-/ssh-remote-port-forward-1.0.4.tgz", + "integrity": "sha512-x0LV1eVDwjf1gmG7TTnfqIzf+3VPRz7vrNIjX6oYLbeCrf/PeVY6hkT68Mg+q02qXxQhrLjB0jfgvhevoCRmLQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/ssh2": "^0.5.48", + "ssh2": "^1.4.0" + } + }, + "node_modules/ssh-remote-port-forward/node_modules/@types/ssh2": { + "version": "0.5.52", + "resolved": "https://registry.npmjs.org/@types/ssh2/-/ssh2-0.5.52.tgz", + "integrity": "sha512-lbLLlXxdCZOSJMCInKH2+9V/77ET2J6NPQHpFI0kda61Dd1KglJs+fPQBchizmzYSOJBgdTajhPqBO1xxLywvg==", + "dev": true, + "license": "MIT", + "dependencies": { + "@types/node": "*", + "@types/ssh2-streams": "*" + } + }, "node_modules/ssh2": { "version": "1.16.0", "resolved": "https://registry.npmjs.org/ssh2/-/ssh2-1.16.0.tgz", @@ -17863,39 +14939,6 @@ "nan": "^2.20.0" } }, - "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==", - "dev": true, - "license": "MIT", - "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/sshpk/node_modules/jsbn": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", - "integrity": "sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==", - "dev": true, - "license": "MIT" - }, "node_modules/ssri": { "version": "8.0.1", "resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz", @@ -17904,32 +14947,9 @@ "optional": true, "dependencies": { "minipass": "^3.1.1" - }, - "engines": { - "node": ">= 8" - } - }, - "node_modules/stack-utils": { - "version": "2.0.6", - "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz", - "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "escape-string-regexp": "^2.0.0" - }, - "engines": { - "node": ">=10" - } - }, - "node_modules/stack-utils/node_modules/escape-string-regexp": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz", - "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==", - "dev": true, - "license": "MIT", + }, "engines": { - "node": ">=8" + "node": ">= 8" } }, "node_modules/statuses": { @@ -17957,6 +14977,21 @@ "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==", "license": "MIT" }, + "node_modules/streamx": { + "version": "2.20.1", + "resolved": "https://registry.npmjs.org/streamx/-/streamx-2.20.1.tgz", + "integrity": "sha512-uTa0mU6WUC65iUvzKH4X9hEdvSW7rbPxPtwfWiLMSj3qTdQbAiUboZTxauKfpFuGIGa1C2BYijZ7wgdUXICJhA==", + "dev": true, + "license": "MIT", + "dependencies": { + "fast-fifo": "^1.3.2", + "queue-tick": "^1.0.1", + "text-decoder": "^1.1.0" + }, + "optionalDependencies": { + "bare-events": "^2.2.0" + } + }, "node_modules/string_decoder": { "version": "1.3.0", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz", @@ -17966,19 +15001,25 @@ "safe-buffer": "~5.2.0" } }, - "node_modules/string-length": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz", - "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "char-regex": "^1.0.2", - "strip-ansi": "^6.0.0" - }, - "engines": { - "node": ">=10" - } + "node_modules/string_decoder/node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT" }, "node_modules/string-to-stream": { "version": "1.1.1", @@ -18011,12 +15052,6 @@ "util-deprecate": "~1.0.1" } }, - "node_modules/string-to-stream/node_modules/safe-buffer": { - "version": "5.1.2", - "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", - "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==", - "license": "MIT" - }, "node_modules/string-to-stream/node_modules/string_decoder": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", @@ -18055,19 +15090,21 @@ "node": ">=8" } }, - "node_modules/string.prototype.trim": { - "version": "1.2.10", - "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz", - "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==", + "node_modules/string.prototype.replaceall": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/string.prototype.replaceall/-/string.prototype.replaceall-1.0.10.tgz", + "integrity": "sha512-PKLapcZUZmXUdfIM6rTTTMYOxaj4JiQrgl0SKEeCFug1CdMAuJq8hVZd4eek9yMXAW4ldGUq+TiZRtjLJRU96g==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", - "define-data-property": "^1.1.4", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", - "es-abstract": "^1.23.5", + "es-abstract": "^1.23.2", + "es-errors": "^1.3.0", "es-object-atoms": "^1.0.0", - "has-property-descriptors": "^1.0.2" + "get-intrinsic": "^1.2.4", + "has-symbols": "^1.0.3", + "is-regex": "^1.1.4" }, "engines": { "node": ">= 0.4" @@ -18076,15 +15113,16 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/string.prototype.trimend": { - "version": "1.0.9", - "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz", - "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==", + "node_modules/string.prototype.trim": { + "version": "1.2.9", + "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz", + "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", - "call-bound": "^1.0.2", + "call-bind": "^1.0.7", "define-properties": "^1.2.1", + "es-abstract": "^1.23.0", "es-object-atoms": "^1.0.0" }, "engines": { @@ -18094,10 +15132,26 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/string.prototype.trimend": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz", + "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "call-bind": "^1.0.7", + "define-properties": "^1.2.1", + "es-object-atoms": "^1.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, "node_modules/string.prototype.trimstart": { "version": "1.0.8", "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz", "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", @@ -18136,24 +15190,17 @@ "node": ">=8" } }, - "node_modules/strip-bom": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz", - "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/strip-final-newline": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", - "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-3.0.0.tgz", + "integrity": "sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw==", "dev": true, "license": "MIT", "engines": { - "node": ">=6" + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/strip-indent": { @@ -18311,31 +15358,17 @@ "node": ">=8" } }, - "node_modules/stylelint/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, - "node_modules/stylelint/node_modules/write-file-atomic": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", - "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", + "node_modules/superjson": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/superjson/-/superjson-2.2.1.tgz", + "integrity": "sha512-8iGv75BYOa0xRJHK5vRLEjE2H/i4lulTjzpUXic3Eg8akftYjkmQDa8JARQ42rlczXyFR3IeRoeFCc7RxHsYZA==", "dev": true, - "license": "ISC", + "license": "MIT", "dependencies": { - "imurmurhash": "^0.1.4", - "signal-exit": "^4.0.1" + "copy-anything": "^3.0.2" }, "engines": { - "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + "node": ">=16" } }, "node_modules/supports-color": { @@ -18402,17 +15435,10 @@ "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==", "dev": true }, - "node_modules/systemjs": { - "version": "6.15.1", - "resolved": "https://registry.npmjs.org/systemjs/-/systemjs-6.15.1.tgz", - "integrity": "sha512-Nk8c4lXvMB98MtbmjX7JwJRgJOL8fluecYCfCeYBznwmpOs8Bf15hLM6z4z71EDAhQVrQrI+wt1aLWSXZq+hXA==", - "dev": true, - "license": "MIT" - }, "node_modules/table": { - "version": "6.9.0", - "resolved": "https://registry.npmjs.org/table/-/table-6.9.0.tgz", - "integrity": "sha512-9kY+CygyYM6j02t5YFHbNz2FN5QmYGv9zAjVp4lCDjlCw7amdckXlEt/bjMhUIfj4ThGRE4gCUH5+yGnNuPo5A==", + "version": "6.8.2", + "resolved": "https://registry.npmjs.org/table/-/table-6.8.2.tgz", + "integrity": "sha512-w2sfv80nrAh2VCbqR5AK27wswXhqcck2AhfnNW76beQXskGZ1V12GwS//yYVa3d3fcvAip2OUnbDAjW2k3v9fA==", "dev": true, "license": "BSD-3-Clause", "dependencies": { @@ -18450,24 +15476,6 @@ "dev": true, "license": "MIT" }, - "node_modules/table/node_modules/slice-ansi": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-4.0.0.tgz", - "integrity": "sha512-qMCMfhY040cVHT43K9BFygqYbUPFZKHOg7K73mtTWJRb8pyP3fzf4Ixd5SzdEJQ6MRUg/WBnOLxghZtKKurENQ==", - "dev": true, - "license": "MIT", - "dependencies": { - "ansi-styles": "^4.0.0", - "astral-regex": "^2.0.0", - "is-fullwidth-code-point": "^3.0.0" - }, - "engines": { - "node": ">=10" - }, - "funding": { - "url": "https://github.com/chalk/slice-ansi?sponsor=1" - } - }, "node_modules/tar": { "version": "6.2.1", "resolved": "https://registry.npmjs.org/tar/-/tar-6.2.1.tgz", @@ -18485,6 +15493,33 @@ "node": ">=10" } }, + "node_modules/tar-fs": { + "version": "3.0.6", + "resolved": "https://registry.npmjs.org/tar-fs/-/tar-fs-3.0.6.tgz", + "integrity": "sha512-iokBDQQkUyeXhgPYaZxmczGPhnhXZ0CmrqI+MOb/WFGS9DW5wnfrLgtjUJBvz50vQ3qfRwJ62QVoCFu8mPVu5w==", + "dev": true, + "license": "MIT", + "dependencies": { + "pump": "^3.0.0", + "tar-stream": "^3.1.5" + }, + "optionalDependencies": { + "bare-fs": "^2.1.1", + "bare-path": "^2.1.0" + } + }, + "node_modules/tar-stream": { + "version": "3.1.7", + "resolved": "https://registry.npmjs.org/tar-stream/-/tar-stream-3.1.7.tgz", + "integrity": "sha512-qJj60CXt7IU1Ffyc3NJMjh6EkuCFej46zUqJ4J7pqYlThyd9bO0XBTmcOIhSzZJVWfsLks0+nle/j538YAW9RQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "b4a": "^1.6.4", + "fast-fifo": "^1.2.0", + "streamx": "^2.15.0" + } + }, "node_modules/tar/node_modules/minipass": { "version": "5.0.0", "resolved": "https://registry.npmjs.org/minipass/-/minipass-5.0.0.tgz", @@ -18494,12 +15529,6 @@ "node": ">=8" } }, - "node_modules/tar/node_modules/yallist": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", - "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", - "license": "ISC" - }, "node_modules/tarn": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/tarn/-/tarn-3.0.2.tgz", @@ -18525,38 +15554,36 @@ } }, "node_modules/tedious": { - "version": "14.7.0", - "resolved": "https://registry.npmjs.org/tedious/-/tedious-14.7.0.tgz", - "integrity": "sha512-d3qlmZcvZyt7akyPHiOdR+knfzObWZH3mW+gouQTSb7YTSwtpHuYHcvsQabfbY7oOvgbs51xRb7CwOahWK/t9w==", + "version": "18.6.1", + "resolved": "https://registry.npmjs.org/tedious/-/tedious-18.6.1.tgz", + "integrity": "sha512-9AvErXXQTd6l7TDd5EmM+nxbOGyhnmdbp/8c3pw+tjaiSXW9usME90ET/CRG1LN1Y9tPMtz/p83z4Q97B4DDpw==", "license": "MIT", "dependencies": { - "@azure/identity": "^2.0.4", + "@azure/core-auth": "^1.7.2", + "@azure/identity": "^4.2.1", "@azure/keyvault-keys": "^4.4.0", - "@js-joda/core": "^5.2.0", - "@types/es-aggregate-error": "^1.0.2", - "bl": "^5.0.0", - "es-aggregate-error": "^1.0.8", + "@js-joda/core": "^5.6.1", + "@types/node": ">=18", + "bl": "^6.0.11", "iconv-lite": "^0.6.3", "js-md4": "^0.3.2", - "jsbi": "^4.3.0", "native-duplexpair": "^1.0.0", - "node-abort-controller": "^3.0.1", - "punycode": "^2.1.0", - "sprintf-js": "^1.1.2" + "sprintf-js": "^1.1.3" }, "engines": { - "node": ">=12.3.0" + "node": ">=18" } }, "node_modules/tedious/node_modules/bl": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/bl/-/bl-5.1.0.tgz", - "integrity": "sha512-tv1ZJHLfTDnXE6tMHv73YgSJaWR2AFuPwMntBe7XL/GBFHnT0CLnsHMogfk5+GzCDC5ZWarSCYaIGATZt9dNsQ==", + "version": "6.0.16", + "resolved": "https://registry.npmjs.org/bl/-/bl-6.0.16.tgz", + "integrity": "sha512-V/kz+z2Mx5/6qDfRCilmrukUXcXuCoXKg3/3hDvzKKoSUx8CJKudfIoT29XZc3UE9xBvxs5qictiHdprwtteEg==", "license": "MIT", "dependencies": { + "@types/readable-stream": "^4.0.0", "buffer": "^6.0.3", "inherits": "^2.0.4", - "readable-stream": "^3.4.0" + "readable-stream": "^4.2.0" } }, "node_modules/tedious/node_modules/buffer": { @@ -18583,6 +15610,22 @@ "ieee754": "^1.2.1" } }, + "node_modules/tedious/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, "node_modules/terser": { "version": "5.15.1", "resolved": "https://registry.npmjs.org/terser/-/terser-5.15.1.tgz", @@ -18609,32 +15652,97 @@ "dev": true, "license": "MIT" }, - "node_modules/terser/node_modules/source-map-support": { - "version": "0.5.21", - "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", - "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "node_modules/test": { + "version": "3.3.0", + "resolved": "https://registry.npmjs.org/test/-/test-3.3.0.tgz", + "integrity": "sha512-JKlEohxDIJRjwBH/+BrTcAPHljBALrAHw3Zs99RqZlaC605f6BggqXhxkdqZThbSHgaYPwpNJlf9bTSWkb/1rA==", "dev": true, "license": "MIT", "dependencies": { - "buffer-from": "^1.0.0", - "source-map": "^0.6.0" + "minimist": "^1.2.6", + "readable-stream": "^4.3.0", + "string.prototype.replaceall": "^1.0.6" + }, + "bin": { + "node--test": "bin/node--test.js", + "node--test-name-pattern": "bin/node--test-name-pattern.js", + "node--test-only": "bin/node--test-only.js", + "test": "bin/node-core-test.js" } }, - "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==", + "node_modules/test/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", "dev": true, - "license": "ISC", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", "dependencies": { - "@istanbuljs/schema": "^0.1.2", - "glob": "^7.1.4", - "minimatch": "^3.0.4" + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/test/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" }, "engines": { - "node": ">=8" + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } + }, + "node_modules/testcontainers": { + "version": "10.13.2", + "resolved": "https://registry.npmjs.org/testcontainers/-/testcontainers-10.13.2.tgz", + "integrity": "sha512-LfEll+AG/1Ks3n4+IA5lpyBHLiYh/hSfI4+ERa6urwfQscbDU+M2iW1qPQrHQi+xJXQRYy4whyK1IEHdmxWa3Q==", + "dev": true, + "license": "MIT", + "dependencies": { + "@balena/dockerignore": "^1.0.2", + "@types/dockerode": "^3.3.29", + "archiver": "^7.0.1", + "async-lock": "^1.4.1", + "byline": "^5.0.0", + "debug": "^4.3.5", + "docker-compose": "^0.24.8", + "dockerode": "^3.3.5", + "get-port": "^5.1.1", + "proper-lockfile": "^4.1.2", + "properties-reader": "^2.3.0", + "ssh-remote-port-forward": "^1.0.4", + "tar-fs": "^3.0.6", + "tmp": "^0.2.3", + "undici": "^5.28.4" } }, + "node_modules/text-decoder": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/text-decoder/-/text-decoder-1.2.1.tgz", + "integrity": "sha512-x9v3H/lTKIJKQQe7RPQkLfKAnc9lUTkWDypIQgTzPJAq+5/GCDHonmshfvlsNSj58yyshbIJJDLmU15qNERrXQ==", + "dev": true, + "license": "Apache-2.0" + }, "node_modules/text-table": { "version": "0.2.0", "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", @@ -18650,23 +15758,6 @@ "node": ">=0.2.6" } }, - "node_modules/throttleit": { - "version": "1.0.1", - "resolved": "https://registry.npmjs.org/throttleit/-/throttleit-1.0.1.tgz", - "integrity": "sha512-vDZpf9Chs9mAdfY046mcPt8fg5QSZr37hEH4TXYBnDF+izxgrbRGUAAaBvIk/fJm9aOFCGFd1EsNg5AZCbnQCQ==", - "dev": true, - "license": "MIT", - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/through": { - "version": "2.3.8", - "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz", - "integrity": "sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==", - "dev": true, - "license": "MIT" - }, "node_modules/tildify": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/tildify/-/tildify-2.0.0.tgz", @@ -18676,33 +15767,6 @@ "node": ">=8" } }, - "node_modules/timezones-list": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/timezones-list/-/timezones-list-3.0.3.tgz", - "integrity": "sha512-C+Vdvvj2c1xB6pu81pOX8geo6mrk/QsudFVlTVQET7QQwu8WAIyhDNeCrK5grU7EMzmbKLWqz7uU6dN8fvQvPQ==", - "dev": true, - "license": "MIT" - }, - "node_modules/tldts": { - "version": "6.1.69", - "resolved": "https://registry.npmjs.org/tldts/-/tldts-6.1.69.tgz", - "integrity": "sha512-Oh/CqRQ1NXNY7cy9NkTPUauOWiTro0jEYZTioGbOmcQh6EC45oribyIMJp0OJO3677r13tO6SKdWoGZUx2BDFw==", - "dev": true, - "license": "MIT", - "dependencies": { - "tldts-core": "^6.1.69" - }, - "bin": { - "tldts": "bin/cli.js" - } - }, - "node_modules/tldts-core": { - "version": "6.1.69", - "resolved": "https://registry.npmjs.org/tldts-core/-/tldts-core-6.1.69.tgz", - "integrity": "sha512-nygxy9n2PBUFQUtAXAc122gGo+04/j5qr5TGQFZTHafTKYvmARVXt2cA5rgero2/dnXUfkdPtiJoKmrd3T+wdA==", - "dev": true, - "license": "MIT" - }, "node_modules/tmp": { "version": "0.2.3", "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.3.tgz", @@ -18713,13 +15777,6 @@ "node": ">=14.14" } }, - "node_modules/tmpl": { - "version": "1.0.5", - "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz", - "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==", - "dev": true, - "license": "BSD-3-Clause" - }, "node_modules/to-regex-range": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz", @@ -18752,17 +15809,29 @@ "hoek": "6.x.x" } }, - "node_modules/tough-cookie": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-5.0.0.tgz", - "integrity": "sha512-FRKsF7cz96xIIeMZ82ehjC3xW2E+O2+v11udrDYewUbszngYhsGa8z6YUMMzO9QJZzzyd0nGGXnML/TReX6W8Q==", + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, + "license": "MIT", + "engines": { + "node": ">=6" + } + }, + "node_modules/tough-cookie": { + "version": "4.1.4", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-4.1.4.tgz", + "integrity": "sha512-Loo5UUvLD9ScZ6jh8beX1T6sO1w2/MpCRpEP7V280GKMVUQ0Jzar2U3UJPsrdbziLEMMhu3Ujnq//rhiFuIeag==", "license": "BSD-3-Clause", "dependencies": { - "tldts": "^6.1.32" + "psl": "^1.1.33", + "punycode": "^2.1.1", + "universalify": "^0.2.0", + "url-parse": "^1.5.3" }, "engines": { - "node": ">=16" + "node": ">=6" } }, "node_modules/tr46": { @@ -18811,10 +15880,23 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/ts-api-utils": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.3.0.tgz", + "integrity": "sha512-UQMIo7pb8WRomKR1/+MFVLTroIvDVtMX3K6OUir8ynLyzB8Jeriont2bTAtmNPa1ekAgN7YPDyf6V+ygrdU+eQ==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=16" + }, + "peerDependencies": { + "typescript": ">=4.2.0" + } + }, "node_modules/tslib": { - "version": "2.8.1", - "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz", - "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==", + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.0.tgz", + "integrity": "sha512-jWVzBLplnCmoaTr13V9dYbiQ99wvZRd0vNWaDRg+aVYRcjDF3nDksxFDE/+fkXnKhpnUUkmx5pK/v8mCtLVqZA==", "license": "0BSD" }, "node_modules/tunnel": { @@ -18827,19 +15909,6 @@ "node": ">=0.6.11 <=0.7.0 || >=0.7.3" } }, - "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==", - "dev": true, - "license": "Apache-2.0", - "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", @@ -18860,20 +15929,10 @@ "node": ">= 0.8.0" } }, - "node_modules/type-detect": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz", - "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/type-fest": { - "version": "0.21.3", - "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz", - "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==", + "version": "0.20.2", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.20.2.tgz", + "integrity": "sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ==", "dev": true, "license": "(MIT OR CC0-1.0)", "engines": { @@ -18897,30 +15956,32 @@ } }, "node_modules/typed-array-buffer": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz", - "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz", + "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", + "call-bind": "^1.0.7", "es-errors": "^1.3.0", - "is-typed-array": "^1.1.14" + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" } }, "node_modules/typed-array-byte-length": { - "version": "1.0.3", - "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz", - "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==", + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz", + "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==", + "dev": true, "license": "MIT", "dependencies": { - "call-bind": "^1.0.8", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.14" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -18930,18 +15991,18 @@ } }, "node_modules/typed-array-byte-offset": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz", - "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz", + "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==", + "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "gopd": "^1.2.0", - "has-proto": "^1.2.0", - "is-typed-array": "^1.1.15", - "reflect.getprototypeof": "^1.0.9" + "gopd": "^1.0.1", + "has-proto": "^1.0.3", + "is-typed-array": "^1.1.13" }, "engines": { "node": ">= 0.4" @@ -18951,17 +16012,18 @@ } }, "node_modules/typed-array-length": { - "version": "1.0.7", - "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz", - "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==", + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz", + "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==", + "dev": true, "license": "MIT", "dependencies": { "call-bind": "^1.0.7", "for-each": "^0.3.3", "gopd": "^1.0.1", + "has-proto": "^1.0.3", "is-typed-array": "^1.1.13", - "possible-typed-array-names": "^1.0.0", - "reflect.getprototypeof": "^1.0.6" + "possible-typed-array-names": "^1.0.0" }, "engines": { "node": ">= 0.4" @@ -18991,18 +16053,16 @@ } }, "node_modules/unbox-primitive": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz", - "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==", + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz", + "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==", + "dev": true, "license": "MIT", "dependencies": { - "call-bound": "^1.0.3", + "call-bind": "^1.0.2", "has-bigints": "^1.0.2", - "has-symbols": "^1.1.0", - "which-boxed-primitive": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" + "has-symbols": "^1.0.3", + "which-boxed-primitive": "^1.0.2" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -19028,55 +16088,11 @@ } }, "node_modules/undici-types": { - "version": "6.20.0", - "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz", - "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg==", + "version": "6.19.8", + "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.19.8.tgz", + "integrity": "sha512-ve2KP6f/JnbPBFyobGHuerC9g1FYGn/F8n1LWTwNxCEzd6IfqTwUQcNXgEtmmQ6DlRrC1hrSrBnCZPokRrDHjw==", "license": "MIT" }, - "node_modules/unicode-canonical-property-names-ecmascript": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz", - "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-ecmascript": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz", - "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==", - "dev": true, - "license": "MIT", - "dependencies": { - "unicode-canonical-property-names-ecmascript": "^2.0.0", - "unicode-property-aliases-ecmascript": "^2.0.0" - }, - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-match-property-value-ecmascript": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz", - "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, - "node_modules/unicode-property-aliases-ecmascript": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz", - "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=4" - } - }, "node_modules/unique-filename": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz", @@ -19105,13 +16121,12 @@ "license": "ISC" }, "node_modules/universalify": { - "version": "2.0.1", - "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", - "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", - "dev": true, + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.2.0.tgz", + "integrity": "sha512-CJ1QgKmNg3CwvAv/kOFmtnEN05f0D/cn9QntgNOQlQF9dgvVTHj3t+8JPdjqawCHk7V/KA+fbUqzZ9XWhcqPUg==", "license": "MIT", "engines": { - "node": ">= 10.0.0" + "node": ">= 4.0.0" } }, "node_modules/unpipe": { @@ -19123,16 +16138,6 @@ "node": ">= 0.8" } }, - "node_modules/untildify": { - "version": "4.0.0", - "resolved": "https://registry.npmjs.org/untildify/-/untildify-4.0.0.tgz", - "integrity": "sha512-KK8xQ1mkzZeg9inewmFVDNkg3l5LUhoq9kN6iWYB/CC9YMG8HA+c1Q8HwDe6dEX7kErrEVNVBO3fWsVq5iDgtw==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=8" - } - }, "node_modules/update-browserslist-db": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz", @@ -19174,6 +16179,16 @@ "punycode": "^2.1.0" } }, + "node_modules/url-parse": { + "version": "1.5.10", + "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz", + "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==", + "license": "MIT", + "dependencies": { + "querystringify": "^2.1.1", + "requires-port": "^1.0.0" + } + }, "node_modules/util-deprecate": { "version": "1.0.2", "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", @@ -19224,21 +16239,6 @@ "dev": true, "license": "MIT" }, - "node_modules/v8-to-istanbul": { - "version": "9.3.0", - "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz", - "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==", - "dev": true, - "license": "ISC", - "dependencies": { - "@jridgewell/trace-mapping": "^0.3.12", - "@types/istanbul-lib-coverage": "^2.0.1", - "convert-source-map": "^2.0.0" - }, - "engines": { - "node": ">=10.12.0" - } - }, "node_modules/validate-npm-package-license": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", @@ -19265,21 +16265,6 @@ "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==", - "dev": true, - "engines": [ - "node >=0.6.0" - ], - "license": "MIT", - "dependencies": { - "assert-plus": "^1.0.0", - "core-util-is": "1.0.2", - "extsprintf": "^1.2.0" - } - }, "node_modules/vite": { "version": "5.2.14", "resolved": "https://registry.npmjs.org/vite/-/vite-5.2.14.tgz", @@ -19295,89 +16280,265 @@ "vite": "bin/vite.js" }, "engines": { - "node": "^18.0.0 || >=20.0.0" - }, - "funding": { - "url": "https://github.com/vitejs/vite?sponsor=1" - }, - "optionalDependencies": { - "fsevents": "~2.3.3" + "node": "^18.0.0 || >=20.0.0" + }, + "funding": { + "url": "https://github.com/vitejs/vite?sponsor=1" + }, + "optionalDependencies": { + "fsevents": "~2.3.3" + }, + "peerDependencies": { + "@types/node": "^18.0.0 || >=20.0.0", + "less": "*", + "lightningcss": "^1.21.0", + "sass": "*", + "stylus": "*", + "sugarss": "*", + "terser": "^5.4.0" + }, + "peerDependenciesMeta": { + "@types/node": { + "optional": true + }, + "less": { + "optional": true + }, + "lightningcss": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "terser": { + "optional": true + } + } + }, + "node_modules/vite-hot-client": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/vite-hot-client/-/vite-hot-client-0.2.3.tgz", + "integrity": "sha512-rOGAV7rUlUHX89fP2p2v0A2WWvV3QMX2UYq0fRqsWSvFvev4atHWqjwGoKaZT1VTKyLGk533ecu3eyd0o59CAg==", + "dev": true, + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^2.6.0 || ^3.0.0 || ^4.0.0 || ^5.0.0-0" + } + }, + "node_modules/vite-plugin-compression": { + "version": "0.5.1", + "resolved": "https://registry.npmjs.org/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz", + "integrity": "sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==", + "dev": true, + "license": "MIT", + "dependencies": { + "chalk": "^4.1.2", + "debug": "^4.3.3", + "fs-extra": "^10.0.0" + }, + "peerDependencies": { + "vite": ">=2.0.0" + } + }, + "node_modules/vite-plugin-inspect": { + "version": "0.8.7", + "resolved": "https://registry.npmjs.org/vite-plugin-inspect/-/vite-plugin-inspect-0.8.7.tgz", + "integrity": "sha512-/XXou3MVc13A5O9/2Nd6xczjrUwt7ZyI9h8pTnUMkr5SshLcb0PJUOVq2V+XVkdeU4njsqAtmK87THZuO2coGA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@antfu/utils": "^0.7.10", + "@rollup/pluginutils": "^5.1.0", + "debug": "^4.3.6", + "error-stack-parser-es": "^0.1.5", + "fs-extra": "^11.2.0", + "open": "^10.1.0", + "perfect-debounce": "^1.0.0", + "picocolors": "^1.0.1", + "sirv": "^2.0.4" + }, + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/antfu" + }, + "peerDependencies": { + "vite": "^3.1.0 || ^4.0.0 || ^5.0.0-0" + }, + "peerDependenciesMeta": { + "@nuxt/kit": { + "optional": true + } + } + }, + "node_modules/vite-plugin-inspect/node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vite-plugin-inspect/node_modules/fs-extra": { + "version": "11.2.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz", + "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==", + "dev": true, + "license": "MIT", + "dependencies": { + "graceful-fs": "^4.2.0", + "jsonfile": "^6.0.1", + "universalify": "^2.0.0" + }, + "engines": { + "node": ">=14.14" + } + }, + "node_modules/vite-plugin-inspect/node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "license": "MIT", + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vite-plugin-inspect/node_modules/open": { + "version": "10.1.0", + "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz", + "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==", + "dev": true, + "license": "MIT", + "dependencies": { + "default-browser": "^5.2.1", + "define-lazy-prop": "^3.0.0", + "is-inside-container": "^1.0.0", + "is-wsl": "^3.1.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/vite-plugin-inspect/node_modules/sirv": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz", + "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==", + "dev": true, + "license": "MIT", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">= 10" + } + }, + "node_modules/vite-plugin-inspect/node_modules/universalify": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz", + "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==", + "dev": true, + "license": "MIT", + "engines": { + "node": ">= 10.0.0" + } + }, + "node_modules/vite-plugin-vue-devtools": { + "version": "7.5.4", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-devtools/-/vite-plugin-vue-devtools-7.5.4.tgz", + "integrity": "sha512-6yTcGrF+YdplDhNiNCkwj23BQDHA/jp06FR4Bo3rui1GW+8VdFcc26au2gtynPwRDNJXNueTxiVtVb6dq+lNZA==", + "dev": true, + "license": "MIT", + "dependencies": { + "@vue/devtools-core": "^7.5.4", + "@vue/devtools-kit": "^7.5.4", + "@vue/devtools-shared": "^7.5.4", + "execa": "^8.0.1", + "sirv": "^3.0.0", + "vite-plugin-inspect": "^0.8.7", + "vite-plugin-vue-inspector": "^5.2.0" + }, + "engines": { + "node": ">=v14.21.3" }, "peerDependencies": { - "@types/node": "^18.0.0 || >=20.0.0", - "less": "*", - "lightningcss": "^1.21.0", - "sass": "*", - "stylus": "*", - "sugarss": "*", - "terser": "^5.4.0" - }, - "peerDependenciesMeta": { - "@types/node": { - "optional": true - }, - "less": { - "optional": true - }, - "lightningcss": { - "optional": true - }, - "sass": { - "optional": true - }, - "stylus": { - "optional": true - }, - "sugarss": { - "optional": true - }, - "terser": { - "optional": true - } + "vite": "^3.1.0 || ^4.0.0-0 || ^5.0.0-0" } }, - "node_modules/vite-plugin-compression": { - "version": "0.5.1", - "resolved": "https://registry.npmjs.org/vite-plugin-compression/-/vite-plugin-compression-0.5.1.tgz", - "integrity": "sha512-5QJKBDc+gNYVqL/skgFAP81Yuzo9R+EAf19d+EtsMF/i8kFUpNi3J/H01QD3Oo8zBQn+NzoCIFkpPLynoOzaJg==", + "node_modules/vite-plugin-vue-inspector": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/vite-plugin-vue-inspector/-/vite-plugin-vue-inspector-5.2.0.tgz", + "integrity": "sha512-wWxyb9XAtaIvV/Lr7cqB1HIzmHZFVUJsTNm3yAxkS87dgh/Ky4qr2wDEWNxF23fdhVa3jQ8MZREpr4XyiuaRqA==", "dev": true, "license": "MIT", "dependencies": { - "chalk": "^4.1.2", - "debug": "^4.3.3", - "fs-extra": "^10.0.0" + "@babel/core": "^7.23.0", + "@babel/plugin-proposal-decorators": "^7.23.0", + "@babel/plugin-syntax-import-attributes": "^7.22.5", + "@babel/plugin-syntax-import-meta": "^7.10.4", + "@babel/plugin-transform-typescript": "^7.22.15", + "@vue/babel-plugin-jsx": "^1.1.5", + "@vue/compiler-dom": "^3.3.4", + "kolorist": "^1.8.0", + "magic-string": "^0.30.4" }, "peerDependencies": { - "vite": ">=2.0.0" + "vite": "^3.0.0-0 || ^4.0.0-0 || ^5.0.0-0" } }, - "node_modules/vite-plugin-compression/node_modules/fs-extra": { - "version": "10.1.0", - "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.1.0.tgz", - "integrity": "sha512-oRXApq54ETRj4eMiFzGnHWGy+zo5raudjuxN0b8H7s/RU2oW0Wvsx9O0ACRN/kRq9E8Vu/ReskGB5o3ji+FzHQ==", + "node_modules/vite/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, "license": "MIT", - "dependencies": { - "graceful-fs": "^4.2.0", - "jsonfile": "^6.0.1", - "universalify": "^2.0.0" - }, + "optional": true, + "os": [ + "darwin" + ], "engines": { - "node": ">=12" + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" } }, "node_modules/vue": { - "version": "3.3.13", - "resolved": "https://registry.npmjs.org/vue/-/vue-3.3.13.tgz", - "integrity": "sha512-LDnUpQvDgsfc0u/YgtAgTMXJlJQqjkxW1PVcOnJA5cshPleULDjHi7U45pl2VJYazSSvLH8UKcid/kzH8I0a0Q==", + "version": "3.4.38", + "resolved": "https://registry.npmjs.org/vue/-/vue-3.4.38.tgz", + "integrity": "sha512-f0ZgN+mZ5KFgVv9wz0f4OgVKukoXtS3nwET4c2vLBGQR50aI8G0cqbFtLlX9Yiyg3LFGBitruPHt2PxwTduJEw==", "dev": true, "license": "MIT", "dependencies": { - "@vue/compiler-dom": "3.3.13", - "@vue/compiler-sfc": "3.3.13", - "@vue/runtime-dom": "3.3.13", - "@vue/server-renderer": "3.3.13", - "@vue/shared": "3.3.13" + "@vue/compiler-dom": "3.4.38", + "@vue/compiler-sfc": "3.4.38", + "@vue/runtime-dom": "3.4.38", + "@vue/server-renderer": "3.4.38", + "@vue/shared": "3.4.38" }, "peerDependencies": { "typescript": "*" @@ -19471,46 +16632,6 @@ "eslint": ">=6.0.0" } }, - "node_modules/vue-eslint-parser/node_modules/eslint-scope": { - "version": "7.2.2", - "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-7.2.2.tgz", - "integrity": "sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg==", - "dev": true, - "license": "BSD-2-Clause", - "dependencies": { - "esrecurse": "^4.3.0", - "estraverse": "^5.2.0" - }, - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": { - "version": "3.4.3", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz", - "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==", - "dev": true, - "license": "Apache-2.0", - "engines": { - "node": "^12.22.0 || ^14.17.0 || >=16.0.0" - }, - "funding": { - "url": "https://opencollective.com/eslint" - } - }, - "node_modules/vue-eslint-parser/node_modules/estraverse": { - "version": "5.3.0", - "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz", - "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==", - "dev": true, - "license": "BSD-2-Clause", - "engines": { - "node": ">=4.0" - } - }, "node_modules/vue-i18n": { "version": "9.2.2", "resolved": "https://registry.npmjs.org/vue-i18n/-/vue-i18n-9.2.2.tgz", @@ -19586,13 +16707,13 @@ } }, "node_modules/vue-router": { - "version": "4.0.16", - "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.0.16.tgz", - "integrity": "sha512-JcO7cb8QJLBWE+DfxGUL3xUDOae/8nhM1KVdnudadTAORbuxIC/xAydC5Zr/VLHUDQi1ppuTF5/rjBGzgzrJNA==", + "version": "4.2.5", + "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-4.2.5.tgz", + "integrity": "sha512-DIUpKcyg4+PTQKfFPX88UWhlagBEBEfJ5A8XDXRJLUnZOvcpMF8o/dnL90vpVkGaPbjvXazV/rC1qBKrZlFugw==", "dev": true, "license": "MIT", "dependencies": { - "@vue/devtools-api": "^6.0.0" + "@vue/devtools-api": "^6.5.0" }, "funding": { "url": "https://github.com/sponsors/posva" @@ -19645,9 +16766,9 @@ } }, "node_modules/wait-on/node_modules/axios": { - "version": "1.7.9", - "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.9.tgz", - "integrity": "sha512-LhLcE7Hbiryz8oMDdDptSrWowmB4Bl6RCt6sIJKpRB4XtVf0iEgewX3au/pJqm+Py1kCASkb/FFKjxQaLtxJvw==", + "version": "1.7.7", + "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz", + "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==", "dev": true, "license": "MIT", "dependencies": { @@ -19670,14 +16791,14 @@ "@sideway/pinpoint": "^2.0.0" } }, - "node_modules/walker": { - "version": "1.0.8", - "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz", - "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==", + "node_modules/wait-on/node_modules/minimist": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz", + "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==", "dev": true, - "license": "Apache-2.0", - "dependencies": { - "makeerror": "1.0.12" + "license": "MIT", + "funding": { + "url": "https://github.com/sponsors/ljharb" } }, "node_modules/webidl-conversions": { @@ -19689,6 +16810,27 @@ "node": ">=12" } }, + "node_modules/whatwg-encoding": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz", + "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==", + "license": "MIT", + "dependencies": { + "iconv-lite": "0.6.3" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/whatwg-mimetype": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz", + "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==", + "license": "MIT", + "engines": { + "node": ">=18" + } + }, "node_modules/whatwg-url": { "version": "12.0.1", "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-12.0.1.tgz", @@ -19719,64 +16861,17 @@ } }, "node_modules/which-boxed-primitive": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz", - "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==", - "license": "MIT", - "dependencies": { - "is-bigint": "^1.1.0", - "is-boolean-object": "^1.2.1", - "is-number-object": "^1.1.1", - "is-string": "^1.1.1", - "is-symbol": "^1.1.1" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-builtin-type": { - "version": "1.2.1", - "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz", - "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==", - "license": "MIT", - "dependencies": { - "call-bound": "^1.0.2", - "function.prototype.name": "^1.1.6", - "has-tostringtag": "^1.0.2", - "is-async-function": "^2.0.0", - "is-date-object": "^1.1.0", - "is-finalizationregistry": "^1.1.0", - "is-generator-function": "^1.0.10", - "is-regex": "^1.2.1", - "is-weakref": "^1.0.2", - "isarray": "^2.0.5", - "which-boxed-primitive": "^1.1.0", - "which-collection": "^1.0.2", - "which-typed-array": "^1.1.16" - }, - "engines": { - "node": ">= 0.4" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, - "node_modules/which-collection": { "version": "1.0.2", - "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz", - "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==", + "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz", + "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==", + "dev": true, "license": "MIT", "dependencies": { - "is-map": "^2.0.3", - "is-set": "^2.0.3", - "is-weakmap": "^2.0.2", - "is-weakset": "^2.0.3" - }, - "engines": { - "node": ">= 0.4" + "is-bigint": "^1.0.1", + "is-boolean-object": "^1.1.0", + "is-number-object": "^1.0.4", + "is-string": "^1.0.5", + "is-symbol": "^1.0.3" }, "funding": { "url": "https://github.com/sponsors/ljharb" @@ -19790,16 +16885,16 @@ "license": "ISC" }, "node_modules/which-typed-array": { - "version": "1.1.18", - "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.18.tgz", - "integrity": "sha512-qEcY+KJYlWyLH9vNbsr6/5j59AXk5ni5aakf8ldzBvGde6Iz4sxZGkJyWSAueTG7QhOvNRYb1lDdFmL5Td0QKA==", + "version": "1.1.15", + "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz", + "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==", + "dev": true, "license": "MIT", "dependencies": { "available-typed-arrays": "^1.0.7", - "call-bind": "^1.0.8", - "call-bound": "^1.0.3", + "call-bind": "^1.0.7", "for-each": "^0.3.3", - "gopd": "^1.2.0", + "gopd": "^1.0.1", "has-tostringtag": "^1.0.2" }, "engines": { @@ -19870,17 +16965,30 @@ "license": "ISC" }, "node_modules/write-file-atomic": { - "version": "4.0.2", - "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz", - "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==", + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-5.0.1.tgz", + "integrity": "sha512-+QU2zd6OTD8XWIJCbffaiQeH9U73qIqafo1x6V1snCWYGJf6cVE0cDR4D8xRzcEnfI21IFrUPzPGtcPf8AC+Rw==", "dev": true, "license": "ISC", "dependencies": { "imurmurhash": "^0.1.4", - "signal-exit": "^3.0.7" + "signal-exit": "^4.0.1" }, "engines": { - "node": "^12.13.0 || ^14.15.0 || >=16.0.0" + "node": "^14.17.0 || ^16.13.0 || >=18.0.0" + } + }, + "node_modules/write-file-atomic/node_modules/signal-exit": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", + "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", + "dev": true, + "license": "ISC", + "engines": { + "node": ">=14" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" } }, "node_modules/ws": { @@ -19904,6 +17012,18 @@ } } }, + "node_modules/xml-js": { + "version": "1.6.11", + "resolved": "https://registry.npmjs.org/xml-js/-/xml-js-1.6.11.tgz", + "integrity": "sha512-7rVi2KMfwfWFl+GpPg6m80IVMWXLRjO+PxTq7V2CDhoGak0wzYzFgUY2m4XJ47OGdXd8eLE8EmwfAmdjw7lC1g==", + "license": "MIT", + "dependencies": { + "sax": "^1.2.4" + }, + "bin": { + "xml-js": "bin/cli.js" + } + }, "node_modules/xmlbuilder": { "version": "8.2.2", "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-8.2.2.tgz", @@ -19935,6 +17055,12 @@ "npm": ">=1.0.0" } }, + "node_modules/xmlrpc/node_modules/sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==", + "license": "ISC" + }, "node_modules/xtend": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz", @@ -19954,12 +17080,24 @@ } }, "node_modules/yallist": { - "version": "3.1.1", - "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz", - "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==", - "dev": true, + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz", + "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==", "license": "ISC" }, + "node_modules/yaml": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz", + "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==", + "dev": true, + "license": "ISC", + "bin": { + "yaml": "bin.mjs" + }, + "engines": { + "node": ">= 14" + } + }, "node_modules/yargs": { "version": "17.7.2", "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz", @@ -19997,17 +17135,6 @@ "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==", - "dev": true, - "license": "MIT", - "dependencies": { - "buffer-crc32": "~0.2.3", - "fd-slicer": "~1.1.0" - } - }, "node_modules/yocto-queue": { "version": "0.1.0", "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz", @@ -20020,6 +17147,63 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zip-stream": { + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/zip-stream/-/zip-stream-6.0.1.tgz", + "integrity": "sha512-zK7YHHz4ZXpW89AHXUPbQVGKI7uvkd3hzusTdotCg1UxyaVtg0zFJSTfW/Dq5f7OBBVnq6cZIaC8Ti4hb6dtCA==", + "dev": true, + "license": "MIT", + "dependencies": { + "archiver-utils": "^5.0.0", + "compress-commons": "^6.0.2", + "readable-stream": "^4.0.0" + }, + "engines": { + "node": ">= 14" + } + }, + "node_modules/zip-stream/node_modules/buffer": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/buffer/-/buffer-6.0.3.tgz", + "integrity": "sha512-FTiCpNxtwiZZHEZbcbTIcZjERVICn9yq/pDFkTl95/AxzD1naBctN7YO68riM/gLSDY7sdrMby8hofADYuuqOA==", + "dev": true, + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ], + "license": "MIT", + "dependencies": { + "base64-js": "^1.3.1", + "ieee754": "^1.2.1" + } + }, + "node_modules/zip-stream/node_modules/readable-stream": { + "version": "4.5.2", + "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-4.5.2.tgz", + "integrity": "sha512-yjavECdqeZ3GLXNgRXgeQEdz9fvDDkNKyHnbHRFtOr7/LcfgBcmct7t/ET+HaCTqfh06OzoAxrkN/IfjJBVe+g==", + "dev": true, + "license": "MIT", + "dependencies": { + "abort-controller": "^3.0.0", + "buffer": "^6.0.3", + "events": "^3.3.0", + "process": "^0.11.10", + "string_decoder": "^1.3.0" + }, + "engines": { + "node": "^12.22.0 || ^14.17.0 || >=16.0.0" + } } } } diff --git a/package.json b/package.json index 2ef1dc14e7..4f8eef138f 100644 --- a/package.json +++ b/package.json @@ -1,17 +1,15 @@ { "name": "uptime-kuma", - "version": "1.23.16", + "version": "2.0.0-beta.0", "license": "MIT", "repository": { "type": "git", "url": "https://github.com/louislam/uptime-kuma.git" }, "engines": { - "node": "14 || 16 || 18 || >= 20.4.0" + "node": "18 || >= 20.4.0" }, "scripts": { - "install-legacy": "npm install", - "update-legacy": "npm update", "lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .", "lint:js-prod": "npm run lint:js -- --max-warnings 0", "lint-fix:js": "eslint --ext \".js,.vue\" --fix --ignore-path .gitignore .", @@ -24,85 +22,78 @@ "start-frontend-devcontainer": "cross-env NODE_ENV=development DEVCONTAINER=1 vite --host --config ./config/vite.config.js", "start": "npm run start-server", "start-server": "node server/server.js", - "start-server-dev": "cross-env NODE_ENV=development node server/server.js --data-dir=./data/v1/", + "start-server-dev": "cross-env NODE_ENV=development node server/server.js", + "start-server-dev:watch": "cross-env NODE_ENV=development node --watch server/server.js", "build": "vite build --config ./config/vite.config.js", - "test": "node test/prepare-test-server.js && npm run jest-backend", + "test": "npm run test-backend && npm run test-e2e", "test-with-build": "npm run build && npm test", - "jest-backend": "cross-env TEST_BACKEND=1 jest --runInBand --detectOpenHandles --forceExit --config=./config/jest-backend.config.js", + "test-backend": "cross-env TEST_BACKEND=1 node --test test/backend-test", + "test-e2e": "playwright test --config ./config/playwright.config.js", + "test-e2e-ui": "playwright test --config ./config/playwright.config.js --ui --ui-port=51063", + "playwright-codegen": "playwright codegen localhost:3000 --save-storage=./private/e2e-auth.json", + "playwright-show-report": "playwright show-report ./private/playwright-report", "tsc": "tsc", "vite-preview-dist": "vite preview --host --config ./config/vite.config.js", - "build-docker": "npm run build && npm run build-docker-debian && npm run build-docker-alpine", - "build-docker-alpine-base": "docker buildx build -f docker/alpine-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-alpine . --push", - "build-docker-debian-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base-debian . --push", + "build-docker-base": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base2 --target base2 . --push", + "build-docker-base-slim": "docker buildx build -f docker/debian-base.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:base2-slim --target base2-slim . --push", "build-docker-builder-go": "docker buildx build -f docker/builder-go.dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:builder-go . --push", - "build-docker-alpine": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:alpine -t louislam/uptime-kuma:1-alpine -t louislam/uptime-kuma:$VERSION-alpine --target release . --push", - "build-docker-debian": "node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma -t louislam/uptime-kuma:1 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:debian -t louislam/uptime-kuma:1-debian -t louislam/uptime-kuma:$VERSION-debian --target release . --push", - "build-docker-nightly": "node ./extra/test-docker.js && npm run build && docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly --target nightly . --push", - "build-docker-nightly-alpine": "docker buildx build -f docker/dockerfile-alpine --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:nightly-alpine --target nightly . --push", - "build-docker-nightly-amd64": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:nightly-amd64 --target nightly . --push --progress plain", - "build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test --target pr-test . --push", - "upload-artifacts": "docker buildx build -f docker/dockerfile --platform linux/amd64 -t louislam/uptime-kuma:upload-artifact --build-arg VERSION --build-arg GITHUB_TOKEN --target upload-artifact . --progress plain", - "setup": "git checkout 1.23.16 && npm ci --production && npm run download-dist", + "build-docker-nightly-local": "npm run build && docker build -f docker/dockerfile -t louislam/uptime-kuma:nightly2 --target nightly .", + "build-docker-pr-test": "docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64 -t louislam/uptime-kuma:pr-test2 --target pr-test2 . --push", + "upload-artifacts": "node extra/release/upload-artifacts.mjs", + "upload-artifacts-beta": "node extra/release/upload-artifacts-beta.mjs", + "setup": "git checkout 1.23.15 && npm ci --production && npm run download-dist", "download-dist": "node extra/download-dist.js", "mark-as-nightly": "node extra/mark-as-nightly.js", "reset-password": "node extra/reset-password.js", "remove-2fa": "node extra/remove-2fa.js", - "compile-install-script": "@powershell -NoProfile -ExecutionPolicy Unrestricted -Command ./extra/compile-install-script.ps1", - "test-install-script-rockylinux": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/rockylinux.dockerfile .", - "test-install-script-centos7": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/centos7.dockerfile .", - "test-install-script-alpine3": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/alpine3.dockerfile .", - "test-install-script-debian": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/debian.dockerfile .", - "test-install-script-debian-buster": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/debian-buster.dockerfile .", - "test-install-script-ubuntu": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/ubuntu.dockerfile .", - "test-install-script-ubuntu1804": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/ubuntu1804.dockerfile .", - "test-install-script-ubuntu1604": "npm run compile-install-script && docker build --progress plain -f test/test_install_script/ubuntu1604.dockerfile .", "simple-dns-server": "node extra/simple-dns-server.js", "simple-mqtt-server": "node extra/simple-mqtt-server.js", "simple-mongo": "docker run --rm -p 27017:27017 mongo", "simple-postgres": "docker run --rm -p 5432:5432 -e POSTGRES_PASSWORD=postgres postgres", "simple-mariadb": "docker run --rm -p 3306:3306 -e MYSQL_ROOT_PASSWORD=mariadb# mariadb", "update-language-files": "cd extra/update-language-files && node index.js && cross-env-shell eslint ../../src/languages/$npm_config_language.js --fix", - "ncu-patch": "npm-check-updates -u -t patch", - "release-final": "node ./extra/test-docker.js && node extra/update-version.js && npm run build-docker && node ./extra/press-any-key.js && npm run upload-artifacts && node ./extra/update-wiki-version.js", - "release-beta": "node ./extra/test-docker.js && node extra/beta/update-version.js && npm run build && node ./extra/env2arg.js docker buildx build -f docker/dockerfile --platform linux/amd64,linux/arm64,linux/arm/v7 -t louislam/uptime-kuma:$VERSION -t louislam/uptime-kuma:beta . --target release --push && node ./extra/press-any-key.js && npm run upload-artifacts", + "release-final": "node ./extra/release/final.mjs", + "release-beta": "node ./extra/release/beta.mjs", + "release-nightly": "node ./extra/release/nightly.mjs", "git-remove-tag": "git tag -d", "build-dist-and-restart": "npm run build && npm run start-server-dev", "start-pr-test": "node extra/checkout-pr.js && npm install && npm run dev", - "cy:test": "node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/ --e2e", - "cy:run": "npx cypress run --browser chrome --headless --config-file ./config/cypress.config.js", - "cy:run:unit": "npx cypress run --browser chrome --headless --config-file ./config/cypress.frontend.config.js", - "cypress-open": "concurrently -k -r \"node test/prepare-test-server.js && node server/server.js --port=3002 --data-dir=./data/test/\" \"cypress open --config-file ./config/cypress.config.js\"", "build-healthcheck-armv7": "cross-env GOOS=linux GOARCH=arm GOARM=7 go build -x -o ./extra/healthcheck-armv7 ./extra/healthcheck.go", "deploy-demo-server": "node extra/deploy-demo-server.js", "sort-contributors": "node extra/sort-contributors.js", - "start-server-node14-win": "private\\node14\\node.exe server/server.js" + "quick-run-nightly": "docker run --rm --env NODE_ENV=development -p 3001:3001 louislam/uptime-kuma:nightly2", + "start-dev-container": "cd docker && docker-compose -f docker-compose-dev.yml up --force-recreate", + "rebase-pr-to-1.23.X": "node extra/rebase-pr.js 1.23.X", + "reset-migrate-aggregate-table-state": "node extra/reset-migrate-aggregate-table-state.js" }, "dependencies": { "@grpc/grpc-js": "~1.8.22", "@louislam/ping": "~0.4.4-mod.1", "@louislam/sqlite3": "15.1.6", + "@vvo/tzdb": "^6.125.0", "args-parser": "~1.3.0", "axios": "~0.28.1", - "axios-ntlm": "1.3.0", "badge-maker": "~3.3.1", "bcryptjs": "~2.4.3", - "cacheable-lookup": "~6.0.4", "chardet": "~1.4.0", "check-password-strength": "^2.0.5", - "cheerio": "1.0.0-rc.12", + "cheerio": "~1.0.0-rc.12", "chroma-js": "~2.4.2", "command-exists": "~1.2.9", "compare-versions": "~3.6.0", "compression": "~1.7.4", - "croner": "~6.0.5", + "croner": "~8.1.0", "dayjs": "~1.11.5", + "dev-null": "^0.1.1", "dotenv": "~16.0.3", "express": "~4.21.0", "express-basic-auth": "~1.2.1", "express-static-gzip": "~2.1.7", + "feed": "^4.2.2", "form-data": "~4.0.0", "gamedig": "^4.2.0", "html-escaper": "^3.0.3", + "http-cookie-agent": "~5.0.4", "http-graceful-shutdown": "~3.1.7", "http-proxy-agent": "~5.0.0", "https-proxy-agent": "~5.0.1", @@ -113,13 +104,17 @@ "jsonwebtoken": "~9.0.0", "jwt-decode": "~3.1.2", "kafkajs": "^2.2.4", + "knex": "~3.1.0", "limiter": "~2.1.0", "liquidjs": "^10.7.0", + "marked": "^14.0.0", + "mitt": "~3.0.1", "mongodb": "~4.17.1", "mqtt": "~4.3.7", - "mssql": "~8.1.4", - "mysql2": "~3.9.6", + "mssql": "~11.0.0", + "mysql2": "~3.11.3", "nanoid": "~3.3.4", + "net-snmp": "^3.11.2", "node-cloudflared-tunnel": "~1.0.9", "node-radius-client": "~1.0.0", "nodemailer": "~6.9.13", @@ -129,7 +124,7 @@ "password-hash": "~1.2.2", "pg": "~8.11.3", "pg-connection-string": "~2.6.2", - "playwright-core": "~1.35.1", + "playwright-core": "~1.39.0", "prom-client": "~13.2.0", "prometheus-api-metrics": "~3.2.1", "promisify-child-process": "~4.1.2", @@ -144,21 +139,25 @@ "tar": "~6.2.1", "tcp-ping": "~0.1.1", "thirty-two": "~1.0.2", + "tough-cookie": "~4.1.3", "ws": "^8.13.0" }, "devDependencies": { "@actions/github": "~5.1.1", - "@babel/eslint-parser": "^7.22.7", - "@babel/preset-env": "^7.15.8", "@fortawesome/fontawesome-svg-core": "~1.2.36", "@fortawesome/free-regular-svg-icons": "~5.15.4", "@fortawesome/free-solid-svg-icons": "~5.15.4", "@fortawesome/vue-fontawesome": "~3.0.0-5", + "@playwright/test": "~1.39.0", "@popperjs/core": "~2.10.2", + "@testcontainers/hivemq": "^10.13.1", + "@testcontainers/rabbitmq": "^10.13.2", "@types/bootstrap": "~5.1.9", - "@vitejs/plugin-legacy": "~4.1.0", - "@vitejs/plugin-vue": "~4.2.3", - "@vue/compiler-sfc": "~3.3.4", + "@types/node": "^20.8.6", + "@typescript-eslint/eslint-plugin": "^6.7.5", + "@typescript-eslint/parser": "^6.7.5", + "@vitejs/plugin-vue": "~5.0.1", + "@vue/compiler-sfc": "~3.4.2", "@vuepic/vue-datepicker": "~3.4.8", "aedes": "^0.46.3", "bootstrap": "5.1.3", @@ -168,15 +167,14 @@ "core-js": "~3.26.1", "cronstrue": "~2.24.0", "cross-env": "~7.0.3", - "cypress": "^13.2.0", "delay": "^5.0.0", "dns2": "~2.0.1", "dompurify": "~3.1.7", "eslint": "~8.14.0", + "eslint-plugin-jsdoc": "~46.4.6", "eslint-plugin-vue": "~8.7.1", "favico.js": "~0.3.10", - "jest": "~29.6.1", - "marked": "~4.2.5", + "get-port-please": "^3.1.1", "node-ssh": "~13.1.0", "postcss-html": "~1.5.0", "postcss-rtlcss": "~3.7.2", @@ -188,12 +186,14 @@ "stylelint": "^15.10.1", "stylelint-config-standard": "~25.0.0", "terser": "~5.15.0", - "timezones-list": "~3.0.1", + "test": "~3.3.0", + "testcontainers": "^10.13.1", "typescript": "~4.4.4", "v-pagination-3": "~0.1.7", "vite": "~5.2.8", "vite-plugin-compression": "^0.5.1", - "vue": "~3.3.4", + "vite-plugin-vue-devtools": "^7.0.15", + "vue": "~3.4.2", "vue-chartjs": "~5.2.0", "vue-confirm-dialog": "~1.0.2", "vue-contenteditable": "~3.0.4", @@ -202,7 +202,7 @@ "vue-multiselect": "~3.0.0-alpha.2", "vue-prism-editor": "~2.0.0-alpha.2", "vue-qrcode": "~1.0.0", - "vue-router": "~4.0.14", + "vue-router": "~4.2.5", "vue-toastification": "~2.0.0-rc.5", "vuedraggable": "~4.1.0", "wait-on": "^7.2.0", diff --git a/server/auth.js b/server/auth.js index 1ea8b45f92..597cf3d753 100644 --- a/server/auth.js +++ b/server/auth.js @@ -9,9 +9,9 @@ const dayjs = require("dayjs"); /** * Login to web app - * @param {string} username - * @param {string} password - * @returns {Promise<(Bean|null)>} + * @param {string} username Username to login with + * @param {string} password Password to login with + * @returns {Promise<(Bean|null)>} User or null if login failed */ exports.login = async function (username, password) { if (typeof username !== "string" || typeof password !== "string") { @@ -39,6 +39,7 @@ exports.login = async function (username, password) { /** * Validate a provided API key * @param {string} key API key to verify + * @returns {boolean} API is ok? */ async function verifyAPIKey(key) { if (typeof key !== "string") { @@ -73,9 +74,10 @@ async function verifyAPIKey(key) { /** * Custom authorizer for express-basic-auth - * @param {string} username - * @param {string} password - * @param {authCallback} callback + * @param {string} username Username to login with + * @param {string} password Password to login with + * @param {authCallback} callback Callback to handle login result + * @returns {void} */ function apiAuthorizer(username, password, callback) { // API Rate Limit @@ -99,9 +101,10 @@ function apiAuthorizer(username, password, callback) { /** * Custom authorizer for express-basic-auth - * @param {string} username - * @param {string} password - * @param {authCallback} callback + * @param {string} username Username to login with + * @param {string} password Password to login with + * @param {authCallback} callback Callback to handle login result + * @returns {void} */ function userAuthorizer(username, password, callback) { // Login Rate Limit @@ -126,7 +129,8 @@ function userAuthorizer(username, password, callback) { * Use basic auth if auth is not disabled * @param {express.Request} req Express request object * @param {express.Response} res Express response object - * @param {express.NextFunction} next + * @param {express.NextFunction} next Next handler in chain + * @returns {Promise} */ exports.basicAuth = async function (req, res, next) { const middleware = basicAuth({ @@ -148,7 +152,8 @@ exports.basicAuth = async function (req, res, next) { * Use use API Key if API keys enabled, else use basic auth * @param {express.Request} req Express request object * @param {express.Response} res Express response object - * @param {express.NextFunction} next + * @param {express.NextFunction} next Next handler in chain + * @returns {Promise} */ exports.apiAuth = async function (req, res, next) { if (!await Settings.get("disableAuth")) { diff --git a/server/cacheable-dns-http-agent.js b/server/cacheable-dns-http-agent.js deleted file mode 100644 index cc067f72b2..0000000000 --- a/server/cacheable-dns-http-agent.js +++ /dev/null @@ -1,86 +0,0 @@ -const https = require("https"); -const http = require("http"); -const CacheableLookup = require("cacheable-lookup"); -const { Settings } = require("./settings"); -const { log } = require("../src/util"); - -class CacheableDnsHttpAgent { - - static cacheable = new CacheableLookup(); - - static httpAgentList = {}; - static httpsAgentList = {}; - - static enable = false; - - /** - * Register/Disable cacheable to global agents - */ - static async update() { - log.debug("CacheableDnsHttpAgent", "update"); - let isEnable = await Settings.get("dnsCache"); - - if (isEnable !== this.enable) { - log.debug("CacheableDnsHttpAgent", "value changed"); - - if (isEnable) { - log.debug("CacheableDnsHttpAgent", "enable"); - this.cacheable.install(http.globalAgent); - this.cacheable.install(https.globalAgent); - } else { - log.debug("CacheableDnsHttpAgent", "disable"); - this.cacheable.uninstall(http.globalAgent); - this.cacheable.uninstall(https.globalAgent); - } - } - - this.enable = isEnable; - } - - /** - * Attach cacheable to HTTP agent - * @param {http.Agent} agent Agent to install - */ - static install(agent) { - this.cacheable.install(agent); - } - - /** - * @var {https.AgentOptions} agentOptions - * @return {https.Agent} - */ - static getHttpsAgent(agentOptions) { - if (!this.enable) { - return new https.Agent(agentOptions); - } - - let key = JSON.stringify(agentOptions); - if (!(key in this.httpsAgentList)) { - this.httpsAgentList[key] = new https.Agent(agentOptions); - this.cacheable.install(this.httpsAgentList[key]); - } - return this.httpsAgentList[key]; - } - - /** - * @var {http.AgentOptions} agentOptions - * @return {https.Agents} - */ - static getHttpAgent(agentOptions) { - if (!this.enable) { - return new http.Agent(agentOptions); - } - - let key = JSON.stringify(agentOptions); - if (!(key in this.httpAgentList)) { - this.httpAgentList[key] = new http.Agent(agentOptions); - this.cacheable.install(this.httpAgentList[key]); - } - return this.httpAgentList[key]; - } - -} - -module.exports = { - CacheableDnsHttpAgent, -}; diff --git a/server/client.js b/server/client.js index 7891dd166f..72f0a4e8e2 100644 --- a/server/client.js +++ b/server/client.js @@ -8,11 +8,12 @@ const server = UptimeKumaServer.getInstance(); const io = server.io; const { setting } = require("./util-server"); const checkVersion = require("./check-version"); +const Database = require("./database"); /** * Send list of notification providers to client * @param {Socket} socket Socket.io socket instance - * @returns {Promise} + * @returns {Promise} List of notifications */ async function sendNotificationList(socket) { const timeLogger = new TimeLogger(); @@ -40,13 +41,11 @@ async function sendNotificationList(socket) { * Send Heartbeat History list to socket * @param {Socket} socket Socket.io instance * @param {number} monitorID ID of monitor to send heartbeat history - * @param {boolean} [toUser=false] True = send to all browsers with the same user id, False = send to the current browser only - * @param {boolean} [overwrite=false] Overwrite client-side's heartbeat list + * @param {boolean} toUser True = send to all browsers with the same user id, False = send to the current browser only + * @param {boolean} overwrite Overwrite client-side's heartbeat list * @returns {Promise} */ async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite = false) { - const timeLogger = new TimeLogger(); - let list = await R.getAll(` SELECT * FROM heartbeat WHERE monitor_id = ? @@ -63,16 +62,14 @@ async function sendHeartbeatList(socket, monitorID, toUser = false, overwrite = } else { socket.emit("heartbeatList", monitorID, result, overwrite); } - - timeLogger.print(`[Monitor: ${monitorID}] sendHeartbeatList`); } /** * Important Heart beat list (aka event list) * @param {Socket} socket Socket.io instance * @param {number} monitorID ID of monitor to send heartbeat history - * @param {boolean} [toUser=false] True = send to all browsers with the same user id, False = send to the current browser only - * @param {boolean} [overwrite=false] Overwrite client-side's heartbeat list + * @param {boolean} toUser True = send to all browsers with the same user id, False = send to the current browser only + * @param {boolean} overwrite Overwrite client-side's heartbeat list * @returns {Promise} */ async function sendImportantHeartbeatList(socket, monitorID, toUser = false, overwrite = false) { @@ -100,7 +97,7 @@ async function sendImportantHeartbeatList(socket, monitorID, toUser = false, ove /** * Emit proxy list to client * @param {Socket} socket Socket.io socket instance - * @return {Promise} + * @returns {Promise} List of proxies */ async function sendProxyList(socket) { const timeLogger = new TimeLogger(); @@ -141,24 +138,27 @@ async function sendAPIKeyList(socket) { /** * Emits the version information to the client. * @param {Socket} socket Socket.io socket instance - * @param {boolean} hideVersion + * @param {boolean} hideVersion Should we hide the version information in the response? * @returns {Promise} */ async function sendInfo(socket, hideVersion = false) { let version; let latestVersion; let isContainer; + let dbType; if (!hideVersion) { version = checkVersion.version; latestVersion = checkVersion.latestVersion; isContainer = (process.env.UPTIME_KUMA_IS_CONTAINER === "1"); + dbType = Database.dbConfig.type; } socket.emit("info", { version, latestVersion, isContainer, + dbType, primaryBaseURL: await setting("primaryBaseURL"), serverTimezone: await server.getTimezone(), serverTimezoneOffset: server.getTimezoneOffset(), @@ -168,7 +168,7 @@ async function sendInfo(socket, hideVersion = false) { /** * Send list of docker hosts to client * @param {Socket} socket Socket.io socket instance - * @returns {Promise} + * @returns {Promise} List of docker hosts */ async function sendDockerHostList(socket) { const timeLogger = new TimeLogger(); @@ -189,6 +189,56 @@ async function sendDockerHostList(socket) { return list; } +/** + * Send list of docker hosts to client + * @param {Socket} socket Socket.io socket instance + * @returns {Promise} List of docker hosts + */ +async function sendRemoteBrowserList(socket) { + const timeLogger = new TimeLogger(); + + let result = []; + let list = await R.find("remote_browser", " user_id = ? ", [ + socket.userID, + ]); + + for (let bean of list) { + result.push(bean.toJSON()); + } + + io.to(socket.userID).emit("remoteBrowserList", result); + + timeLogger.print("Send Remote Browser List"); + + return list; +} + +/** + * Send list of monitor types to client + * @param {Socket} socket Socket.io socket instance + * @returns {Promise} + */ +async function sendMonitorTypeList(socket) { + const result = Object.entries(UptimeKumaServer.monitorTypeList).map(([ key, type ]) => { + return [ key, { + supportsConditions: type.supportsConditions, + conditionVariables: type.conditionVariables.map(v => { + return { + id: v.id, + operators: v.operators.map(o => { + return { + id: o.id, + caption: o.caption, + }; + }), + }; + }), + }]; + }); + + io.to(socket.userID).emit("monitorTypeList", Object.fromEntries(result)); +} + module.exports = { sendNotificationList, sendImportantHeartbeatList, @@ -196,5 +246,7 @@ module.exports = { sendProxyList, sendAPIKeyList, sendInfo, - sendDockerHostList + sendDockerHostList, + sendRemoteBrowserList, + sendMonitorTypeList, }; diff --git a/server/config.js b/server/config.js index 635c37e7fb..515b90465f 100644 --- a/server/config.js +++ b/server/config.js @@ -19,6 +19,10 @@ const sslKeyPassphrase = args["ssl-key-passphrase"] || process.env.UPTIME_KUMA_S const isSSL = sslKey && sslCert; +/** + * Get the local WebSocket URL + * @returns {string} The local WebSocket URL + */ function getLocalWebSocketURL() { const protocol = isSSL ? "wss" : "ws"; const host = hostname || "localhost"; diff --git a/server/database.js b/server/database.js index d31423c774..3b7646de8c 100644 --- a/server/database.js +++ b/server/database.js @@ -4,28 +4,53 @@ const { setSetting, setting } = require("./util-server"); const { log, sleep } = require("../src/util"); const knex = require("knex"); const path = require("path"); +const { EmbeddedMariaDB } = require("./embedded-mariadb"); +const mysql = require("mysql2/promise"); +const { Settings } = require("./settings"); +const { UptimeCalculator } = require("./uptime-calculator"); +const dayjs = require("dayjs"); +const { SimpleMigrationServer } = require("./utils/simple-migration-server"); +const KumaColumnCompiler = require("./utils/knex/lib/dialects/mysql2/schema/mysql2-columncompiler"); /** * Database & App Data Folder */ class Database { + /** + * Boostrap database for SQLite + * @type {string} + */ static templatePath = "./db/kuma.db"; /** * Data Dir (Default: ./data) + * @type {string} */ static dataDir; /** * User Upload Dir (Default: ./data/upload) + * @type {string} */ static uploadDir; + /** + * Chrome Screenshot Dir (Default: ./data/screenshots) + * @type {string} + */ static screenshotDir; - static path; + /** + * SQLite file path (Default: ./data/kuma.db) + * @type {string} + */ + static sqlitePath; + /** + * For storing Docker TLS certs (Default: ./data/docker-tls) + * @type {string} + */ static dockerTLSDir; /** @@ -34,11 +59,13 @@ class Database { static patched = false; /** + * SQLite only * Add patch filename in key * Values: * true: Add it regardless of order * false: Do nothing * { parents: []}: Need parents before add it + * @deprecated */ static patchList = { "patch-setting-value-type.sql": true, @@ -84,7 +111,7 @@ class Database { "patch-notification-config.sql": true, "patch-fix-kafka-producer-booleans.sql": true, "patch-timeout.sql": true, - "patch-monitor-tls-info-add-fk.sql": true, + "patch-monitor-tls-info-add-fk.sql": true, // The last file so far converted to a knex migration file }; /** @@ -95,15 +122,20 @@ class Database { static noReject = true; + static dbConfig = {}; + + static knexMigrationsPath = "./db/knex_migrations"; + /** - * Initialize the database - * @param {Object} args Arguments to initialize DB with + * Initialize the data directory + * @param {object} args Arguments to initialize DB with + * @returns {void} */ - static init(args) { + static initDataDir(args) { // Data Directory (must be end with "/") Database.dataDir = process.env.DATA_DIR || args["data-dir"] || "./data/"; - Database.path = path.join(Database.dataDir, "kuma.db"); + Database.sqlitePath = path.join(Database.dataDir, "kuma.db"); if (! fs.existsSync(Database.dataDir)) { fs.mkdirSync(Database.dataDir, { recursive: true }); } @@ -125,39 +157,172 @@ class Database { fs.mkdirSync(Database.dockerTLSDir, { recursive: true }); } - log.info("db", `Data Dir: ${Database.dataDir}`); + log.info("server", `Data Dir: ${Database.dataDir}`); + } + + /** + * Read the database config + * @throws {Error} If the config is invalid + * @typedef {string|undefined} envString + * @returns {{type: "sqlite"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString}} Database config + */ + static readDBConfig() { + let dbConfig; + + let dbConfigString = fs.readFileSync(path.join(Database.dataDir, "db-config.json")).toString("utf-8"); + dbConfig = JSON.parse(dbConfigString); + + if (typeof dbConfig !== "object") { + throw new Error("Invalid db-config.json, it must be an object"); + } + + if (typeof dbConfig.type !== "string") { + throw new Error("Invalid db-config.json, type must be a string"); + } + return dbConfig; + } + + /** + * @typedef {string|undefined} envString + * @param {{type: "sqlite"} | {type:envString, hostname:envString, port:envString, database:envString, username:envString, password:envString}} dbConfig the database configuration that should be written + * @returns {void} + */ + static writeDBConfig(dbConfig) { + fs.writeFileSync(path.join(Database.dataDir, "db-config.json"), JSON.stringify(dbConfig, null, 4)); } /** * Connect to the database - * @param {boolean} [testMode=false] Should the connection be - * started in test mode? - * @param {boolean} [autoloadModels=true] Should models be - * automatically loaded? - * @param {boolean} [noLog=false] Should logs not be output? + * @param {boolean} testMode Should the connection be started in test mode? + * @param {boolean} autoloadModels Should models be automatically loaded? + * @param {boolean} noLog Should logs not be output? * @returns {Promise} */ static async connect(testMode = false, autoloadModels = true, noLog = false) { + // Patch "mysql2" knex client + // Workaround: Tried extending the ColumnCompiler class, but it didn't work for unknown reasons, so I override the function via prototype + const { getDialectByNameOrAlias } = require("knex/lib/dialects"); + const mysql2 = getDialectByNameOrAlias("mysql2"); + mysql2.prototype.columnCompiler = function () { + return new KumaColumnCompiler(this, ...arguments); + }; + const acquireConnectionTimeout = 120 * 1000; + let dbConfig; + try { + dbConfig = this.readDBConfig(); + Database.dbConfig = dbConfig; + } catch (err) { + log.warn("db", err.message); + dbConfig = { + type: "sqlite", + }; + } + + let config = {}; - const Dialect = require("knex/lib/dialects/sqlite3/index.js"); - Dialect.prototype._driver = () => require("@louislam/sqlite3"); - - const knexInstance = knex({ - client: Dialect, - connection: { - filename: Database.path, - acquireConnectionTimeout: acquireConnectionTimeout, - }, - useNullAsDefault: true, - pool: { - min: 1, - max: 1, - idleTimeoutMillis: 120 * 1000, - propagateCreateError: false, - acquireTimeoutMillis: acquireConnectionTimeout, + let mariadbPoolConfig = { + min: 0, + max: 10, + idleTimeoutMillis: 30000, + }; + + log.info("db", `Database Type: ${dbConfig.type}`); + + if (dbConfig.type === "sqlite") { + + if (! fs.existsSync(Database.sqlitePath)) { + log.info("server", "Copying Database"); + fs.copyFileSync(Database.templatePath, Database.sqlitePath); } - }); + + const Dialect = require("knex/lib/dialects/sqlite3/index.js"); + Dialect.prototype._driver = () => require("@louislam/sqlite3"); + + config = { + client: Dialect, + connection: { + filename: Database.sqlitePath, + acquireConnectionTimeout: acquireConnectionTimeout, + }, + useNullAsDefault: true, + pool: { + min: 1, + max: 1, + idleTimeoutMillis: 120 * 1000, + propagateCreateError: false, + acquireTimeoutMillis: acquireConnectionTimeout, + } + }; + } else if (dbConfig.type === "mariadb") { + if (!/^\w+$/.test(dbConfig.dbName)) { + throw Error("Invalid database name. A database name can only consist of letters, numbers and underscores"); + } + + const connection = await mysql.createConnection({ + host: dbConfig.hostname, + port: dbConfig.port, + user: dbConfig.username, + password: dbConfig.password, + }); + + await connection.execute("CREATE DATABASE IF NOT EXISTS " + dbConfig.dbName + " CHARACTER SET utf8mb4"); + connection.end(); + + config = { + client: "mysql2", + connection: { + host: dbConfig.hostname, + port: dbConfig.port, + user: dbConfig.username, + password: dbConfig.password, + database: dbConfig.dbName, + timezone: "Z", + typeCast: function (field, next) { + if (field.type === "DATETIME") { + // Do not perform timezone conversion + return field.string(); + } + return next(); + }, + }, + pool: mariadbPoolConfig, + }; + } else if (dbConfig.type === "embedded-mariadb") { + let embeddedMariaDB = EmbeddedMariaDB.getInstance(); + await embeddedMariaDB.start(); + log.info("mariadb", "Embedded MariaDB started"); + config = { + client: "mysql2", + connection: { + socketPath: embeddedMariaDB.socketPath, + user: embeddedMariaDB.username, + database: "kuma", + timezone: "Z", + typeCast: function (field, next) { + if (field.type === "DATETIME") { + // Do not perform timezone conversion + return field.string(); + } + return next(); + }, + }, + pool: mariadbPoolConfig, + }; + } else { + throw new Error("Unknown Database type: " + dbConfig.type); + } + + // Set to utf8mb4 for MariaDB + if (dbConfig.type.endsWith("mariadb")) { + config.pool = { + afterCreate(conn, done) { + conn.query("SET CHARACTER SET utf8mb4;", (err) => done(err, conn)); + }, + }; + } + + const knexInstance = knex(config); R.setup(knexInstance); @@ -172,6 +337,19 @@ class Database { await R.autoloadModels("./server/model"); } + if (dbConfig.type === "sqlite") { + await this.initSQLite(testMode, noLog); + } else if (dbConfig.type.endsWith("mariadb")) { + await this.initMariaDB(); + } + } + + /** + @param {boolean} testMode Should the connection be started in test mode? + @param {boolean} noLog Should logs not be output? + @returns {Promise} + */ + static async initSQLite(testMode, noLog) { await R.exec("PRAGMA foreign_keys = ON"); if (testMode) { // Change to MEMORY @@ -189,35 +367,110 @@ class Database { await R.exec("PRAGMA synchronous = NORMAL"); if (!noLog) { - log.info("db", "SQLite config:"); - log.info("db", await R.getAll("PRAGMA journal_mode")); - log.info("db", await R.getAll("PRAGMA cache_size")); - log.info("db", "SQLite Version: " + await R.getCell("SELECT sqlite_version()")); + log.debug("db", "SQLite config:"); + log.debug("db", await R.getAll("PRAGMA journal_mode")); + log.debug("db", await R.getAll("PRAGMA cache_size")); + log.debug("db", "SQLite Version: " + await R.getCell("SELECT sqlite_version()")); + } + } + + /** + * Initialize MariaDB + * @returns {Promise} + */ + static async initMariaDB() { + log.debug("db", "Checking if MariaDB database exists..."); + + let hasTable = await R.hasTable("docker_host"); + if (!hasTable) { + const { createTables } = require("../db/knex_init_db"); + await createTables(); + } else { + log.debug("db", "MariaDB database already exists"); + } + } + + /** + * Patch the database + * @param {number} port Start the migration server for aggregate tables on this port if provided + * @param {string} hostname Start the migration server for aggregate tables on this hostname if provided + * @returns {Promise} + */ + static async patch(port = undefined, hostname = undefined) { + // Still need to keep this for old versions of Uptime Kuma + if (Database.dbConfig.type === "sqlite") { + await this.patchSqlite(); + } + + // Using knex migrations + // https://knexjs.org/guide/migrations.html + // https://gist.github.com/NigelEarle/70db130cc040cc2868555b29a0278261 + try { + // Disable foreign key check for SQLite + // Known issue of knex: https://github.com/drizzle-team/drizzle-orm/issues/1813 + if (Database.dbConfig.type === "sqlite") { + await R.exec("PRAGMA foreign_keys = OFF"); + } + + await R.knex.migrate.latest({ + directory: Database.knexMigrationsPath, + }); + + // Enable foreign key check for SQLite + if (Database.dbConfig.type === "sqlite") { + await R.exec("PRAGMA foreign_keys = ON"); + } + + await this.migrateAggregateTable(port, hostname); + + } catch (e) { + // Allow missing patch files for downgrade or testing pr. + if (e.message.includes("the following files are missing:")) { + log.warn("db", e.message); + log.warn("db", "Database migration failed, you may be downgrading Uptime Kuma."); + } else { + log.error("db", "Database migration failed"); + throw e; + } } } - /** Patch the database */ - static async patch() { + /** + * TODO + * @returns {Promise} + */ + static async rollbackLatestPatch() { + + } + + /** + * Patch the database for SQLite + * @returns {Promise} + * @deprecated + */ + static async patchSqlite() { let version = parseInt(await setting("database_version")); if (! version) { version = 0; } - log.info("db", "Your database version: " + version); - log.info("db", "Latest database version: " + this.latestVersion); + if (version !== this.latestVersion) { + log.info("db", "Your database version: " + version); + log.info("db", "Latest database version: " + this.latestVersion); + } if (version === this.latestVersion) { - log.info("db", "Database patch not needed"); + log.debug("db", "Database patch not needed"); } else if (version > this.latestVersion) { - log.info("db", "Warning: Database version is newer than expected"); + log.warn("db", "Warning: Database version is newer than expected"); } else { log.info("db", "Database patch is needed"); // Try catch anything here try { for (let i = version + 1; i <= this.latestVersion; i++) { - const sqlFile = `./db/patch${i}.sql`; + const sqlFile = `./db/old_migrations/patch${i}.sql`; log.info("db", `Patching ${sqlFile}`); await Database.importSQLFile(sqlFile); log.info("db", `Patched ${sqlFile}`); @@ -234,18 +487,19 @@ class Database { } } - await this.patch2(); + await this.patchSqlite2(); await this.migrateNewStatusPage(); } /** * Patch DB using new process * Call it from patch() only + * @deprecated * @private * @returns {Promise} */ - static async patch2() { - log.info("db", "Database Patch 2.0 Process"); + static async patchSqlite2() { + log.debug("db", "Database Patch 2.0 Process"); let databasePatchedFiles = await setting("databasePatchedFiles"); if (! databasePatchedFiles) { @@ -278,6 +532,7 @@ class Database { } /** + * SQlite only * Migrate status page value in setting to "status_page" table * @returns {Promise} */ @@ -349,8 +604,8 @@ class Database { * Patch database using new patching process * Used it patch2() only * @private - * @param sqlFilename - * @param databasePatchedFiles + * @param {string} sqlFilename Name of SQL file to load + * @param {object} databasePatchedFiles Patch status of database files * @returns {Promise} */ static async patch2Recursion(sqlFilename, databasePatchedFiles) { @@ -374,7 +629,7 @@ class Database { log.info("db", sqlFilename + " is patching"); this.patched = true; - await this.importSQLFile("./db/" + sqlFilename); + await this.importSQLFile("./db/old_migrations/" + sqlFilename); databasePatchedFiles[sqlFilename] = true; log.info("db", sqlFilename + " was patched successfully"); @@ -385,7 +640,7 @@ class Database { /** * Load an SQL file and execute it - * @param filename Filename of SQL file to import + * @param {string} filename Filename of SQL file to import * @returns {Promise} */ static async importSQLFile(filename) { @@ -417,14 +672,6 @@ class Database { } } - /** - * Aquire a direct connection to database - * @returns {any} - */ - static getBetterSQLite3Database() { - return R.knex.client.acquireConnection(); - } - /** * Special handle, because tarn.js throw a promise reject that cannot be caught * @returns {Promise} @@ -438,7 +685,9 @@ class Database { log.info("db", "Closing the database"); // Flush WAL to main database - await R.exec("PRAGMA wal_checkpoint(TRUNCATE)"); + if (Database.dbConfig.type === "sqlite") { + await R.exec("PRAGMA wal_checkpoint(TRUNCATE)"); + } while (true) { Database.noReject = true; @@ -451,17 +700,23 @@ class Database { log.info("db", "Waiting to close the database"); } } - log.info("db", "SQLite closed"); + log.info("db", "Database closed"); process.removeListener("unhandledRejection", listener); } - /** Get the size of the database */ + /** + * Get the size of the database (SQLite only) + * @returns {number} Size of database + */ static getSize() { - log.debug("db", "Database.getSize()"); - let stats = fs.statSync(Database.path); - log.debug("db", stats); - return stats.size; + if (Database.dbConfig.type === "sqlite") { + log.debug("db", "Database.getSize()"); + let stats = fs.statSync(Database.sqlitePath); + log.debug("db", stats); + return stats.size; + } + return 0; } /** @@ -469,8 +724,189 @@ class Database { * @returns {Promise} */ static async shrink() { - await R.exec("VACUUM"); + if (Database.dbConfig.type === "sqlite") { + await R.exec("VACUUM"); + } + } + + /** + * @returns {string} Get the SQL for the current time plus a number of hours + */ + static sqlHourOffset() { + if (Database.dbConfig.type === "sqlite") { + return "DATETIME('now', ? || ' hours')"; + } else { + return "DATE_ADD(NOW(), INTERVAL ? HOUR)"; + } + } + + /** + * Migrate the old data in the heartbeat table to the new format (stat_daily, stat_hourly, stat_minutely) + * It should be run once while upgrading V1 to V2 + * + * Normally, it should be in transaction, but UptimeCalculator wasn't designed to be in transaction before that. + * I don't want to heavily modify the UptimeCalculator, so it is not in transaction. + * Run `npm run reset-migrate-aggregate-table-state` to reset, in case the migration is interrupted. + * @param {number} port Start the migration server on this port if provided + * @param {string} hostname Start the migration server on this hostname if provided + * @returns {Promise} + */ + static async migrateAggregateTable(port, hostname = undefined) { + log.debug("db", "Enter Migrate Aggregate Table function"); + + // Add a setting for 2.0.0-dev users to skip this migration + if (process.env.SET_MIGRATE_AGGREGATE_TABLE_TO_TRUE === "1") { + log.warn("db", "SET_MIGRATE_AGGREGATE_TABLE_TO_TRUE is set to 1, skipping aggregate table migration forever (for 2.0.0-dev users)"); + await Settings.set("migrateAggregateTableState", "migrated"); + } + + let migrateState = await Settings.get("migrateAggregateTableState"); + + // Skip if already migrated + // If it is migrating, it possibly means the migration was interrupted, or the migration is in progress + if (migrateState === "migrated") { + log.debug("db", "Migrated aggregate table already, skip"); + return; + } else if (migrateState === "migrating") { + log.warn("db", "Aggregate table migration is already in progress, or it was interrupted"); + throw new Error("Aggregate table migration is already in progress"); + } + + /** + * Start migration server for displaying the migration status + * @type {SimpleMigrationServer} + */ + let migrationServer; + let msg; + + if (port) { + migrationServer = new SimpleMigrationServer(); + await migrationServer.start(port, hostname); + } + + log.info("db", "Migrating Aggregate Table"); + + log.info("db", "Getting list of unique monitors"); + + // Get a list of unique monitors from the heartbeat table, using raw sql + let monitors = await R.getAll(` + SELECT DISTINCT monitor_id + FROM heartbeat + ORDER BY monitor_id ASC + `); + + // Stop if stat_* tables are not empty + for (let table of [ "stat_minutely", "stat_hourly", "stat_daily" ]) { + let countResult = await R.getRow(`SELECT COUNT(*) AS count FROM ${table}`); + let count = countResult.count; + if (count > 0) { + log.warn("db", `Aggregate table ${table} is not empty, migration will not be started (Maybe you were using 2.0.0-dev?)`); + await migrationServer?.stop(); + return; + } + } + + await Settings.set("migrateAggregateTableState", "migrating"); + + let progressPercent = 0; + let part = 100 / monitors.length; + let i = 1; + for (let monitor of monitors) { + // Get a list of unique dates from the heartbeat table, using raw sql + let dates = await R.getAll(` + SELECT DISTINCT DATE(time) AS date + FROM heartbeat + WHERE monitor_id = ? + ORDER BY date ASC + `, [ + monitor.monitor_id + ]); + + for (let date of dates) { + // New Uptime Calculator + let calculator = new UptimeCalculator(); + calculator.monitorID = monitor.monitor_id; + calculator.setMigrationMode(true); + + // Get all the heartbeats for this monitor and date + let heartbeats = await R.getAll(` + SELECT status, ping, time + FROM heartbeat + WHERE monitor_id = ? + AND DATE(time) = ? + ORDER BY time ASC + `, [ monitor.monitor_id, date.date ]); + + if (heartbeats.length > 0) { + msg = `[DON'T STOP] Migrating monitor data ${monitor.monitor_id} - ${date.date} [${progressPercent.toFixed(2)}%][${i}/${monitors.length}]`; + log.info("db", msg); + migrationServer?.update(msg); + } + + for (let heartbeat of heartbeats) { + await calculator.update(heartbeat.status, parseFloat(heartbeat.ping), dayjs(heartbeat.time)); + } + + progressPercent += (Math.round(part / dates.length * 100) / 100); + + // Lazy to fix the floating point issue, it is acceptable since it is just a progress bar + if (progressPercent > 100) { + progressPercent = 100; + } + } + + i++; + } + + msg = "Clearing non-important heartbeats"; + log.info("db", msg); + migrationServer?.update(msg); + + await Database.clearHeartbeatData(true); + await Settings.set("migrateAggregateTableState", "migrated"); + await migrationServer?.stop(); + + if (monitors.length > 0) { + log.info("db", "Aggregate Table Migration Completed"); + } else { + log.info("db", "No data to migrate"); + } + } + + /** + * Remove all non-important heartbeats from heartbeat table, keep last 24-hour or {KEEP_LAST_ROWS} rows for each monitor + * @param {boolean} detailedLog Log detailed information + * @returns {Promise} + */ + static async clearHeartbeatData(detailedLog = false) { + let monitors = await R.getAll("SELECT id FROM monitor"); + const sqlHourOffset = Database.sqlHourOffset(); + + for (let monitor of monitors) { + if (detailedLog) { + log.info("db", "Deleting non-important heartbeats for monitor " + monitor.id); + } + await R.exec(` + DELETE FROM heartbeat + WHERE monitor_id = ? + AND important = 0 + AND time < ${sqlHourOffset} + AND id NOT IN ( + SELECT id + FROM heartbeat + WHERE monitor_id = ? + ORDER BY time DESC + LIMIT ? + ) + `, [ + monitor.id, + -24, + monitor.id, + 100, + ]); + } } + } module.exports = Database; diff --git a/server/docker.js b/server/docker.js index 56f325828f..ee6051dfae 100644 --- a/server/docker.js +++ b/server/docker.js @@ -1,10 +1,10 @@ const axios = require("axios"); const { R } = require("redbean-node"); -const version = require("../package.json").version; const https = require("https"); const fs = require("fs"); const path = require("path"); const Database = require("./database"); +const { axiosAbortSignal } = require("./util-server"); class DockerHost { @@ -14,10 +14,10 @@ class DockerHost { /** * Save a docker host - * @param {Object} dockerHost Docker host to save + * @param {object} dockerHost Docker host to save * @param {?number} dockerHostID ID of the docker host to update * @param {number} userID ID of the user who adds the docker host - * @returns {Promise} + * @returns {Promise} Updated docker host */ static async save(dockerHost, dockerHostID, userID) { let bean; @@ -64,16 +64,17 @@ class DockerHost { /** * Fetches the amount of containers on the Docker host - * @param {Object} dockerHost Docker host to check for - * @returns {number} Total amount of containers on the host + * @param {object} dockerHost Docker host to check for + * @returns {Promise} Total amount of containers on the host */ static async testDockerHost(dockerHost) { const options = { url: "/containers/json?all=true", + timeout: 5000, headers: { "Accept": "*/*", - "User-Agent": "Uptime-Kuma/" + version }, + signal: axiosAbortSignal(6000), }; if (dockerHost.dockerType === "socket") { @@ -83,31 +84,40 @@ class DockerHost { options.httpsAgent = new https.Agent(DockerHost.getHttpsAgentOptions(dockerHost.dockerType, options.baseURL)); } - let res = await axios.request(options); + try { + let res = await axios.request(options); - if (Array.isArray(res.data)) { + if (Array.isArray(res.data)) { - if (res.data.length > 1) { + if (res.data.length > 1) { + + if ("ImageID" in res.data[0]) { + return res.data.length; + } else { + throw new Error("Invalid Docker response, is it Docker really a daemon?"); + } - if ("ImageID" in res.data[0]) { - return res.data.length; } else { - throw new Error("Invalid Docker response, is it Docker really a daemon?"); + return res.data.length; } } else { - return res.data.length; + throw new Error("Invalid Docker response, is it Docker really a daemon?"); + } + } catch (e) { + if (e.code === "ECONNABORTED" || e.name === "CanceledError") { + throw new Error("Connection to Docker daemon timed out."); + } else { + throw e; } - - } else { - throw new Error("Invalid Docker response, is it Docker really a daemon?"); } - } /** * Since axios 0.27.X, it does not accept `tcp://` protocol. * Change it to `http://` on the fly in order to fix it. (https://github.com/louislam/uptime-kuma/issues/2165) + * @param {any} url URL to fix + * @returns {any} URL with tcp:// replaced by http:// */ static patchDockerURL(url) { if (typeof url === "string") { @@ -129,11 +139,10 @@ class DockerHost { * 'data/docker-tls/example.com/' would be searched for certificate files), * then 'ca.pem', 'key.pem' and 'cert.pem' files are included in the agent options. * File names can also be overridden via 'DOCKER_TLS_FILE_NAME_(CA|KEY|CERT)'. - * - * @param {String} dockerType i.e. "tcp" or "socket" - * @param {String} url The docker host URL rewritten to https:// - * @return {Object} - * */ + * @param {string} dockerType i.e. "tcp" or "socket" + * @param {string} url The docker host URL rewritten to https:// + * @returns {object} HTTP agent options + */ static getHttpsAgentOptions(dockerType, url) { let baseOptions = { maxCachedSessions: 0, diff --git a/server/embedded-mariadb.js b/server/embedded-mariadb.js new file mode 100644 index 0000000000..7c9630dd79 --- /dev/null +++ b/server/embedded-mariadb.js @@ -0,0 +1,219 @@ +const { log } = require("../src/util"); +const childProcess = require("child_process"); +const fs = require("fs"); +const mysql = require("mysql2"); + +/** + * It is only used inside the docker container + */ +class EmbeddedMariaDB { + + static instance = null; + + exec = "mariadbd"; + + mariadbDataDir = "/app/data/mariadb"; + + runDir = "/app/data/run"; + + socketPath = this.runDir + "/mariadb.sock"; + + /** + * The username to connect to the MariaDB + * @type {string} + */ + username = null; + + /** + * @type {ChildProcessWithoutNullStreams} + * @private + */ + childProcess = null; + running = false; + + started = false; + + /** + * @returns {EmbeddedMariaDB} The singleton instance + */ + static getInstance() { + if (!EmbeddedMariaDB.instance) { + EmbeddedMariaDB.instance = new EmbeddedMariaDB(); + } + return EmbeddedMariaDB.instance; + } + + /** + * @returns {boolean} If the singleton instance is created + */ + static hasInstance() { + return !!EmbeddedMariaDB.instance; + } + + /** + * Start the embedded MariaDB + * @throws {Error} If the current user is not "node" or "root" + * @returns {Promise|void} A promise that resolves when the MariaDB is started or void if it is already started + */ + start() { + // Check if the current user is "node" or "root" + this.username = require("os").userInfo().username; + if (this.username !== "node" && this.username !== "root") { + throw new Error("Embedded Mariadb supports only 'node' or 'root' user, but the current user is: " + this.username); + } + + this.initDB(); + + this.startChildProcess(); + + return new Promise((resolve) => { + let interval = setInterval(() => { + if (this.started) { + clearInterval(interval); + resolve(); + } else { + log.info("mariadb", "Waiting for Embedded MariaDB to start..."); + } + }, 1000); + }); + } + + /** + * Start the child process + * @returns {void} + */ + startChildProcess() { + if (this.childProcess) { + log.info("mariadb", "Already started"); + return; + } + + this.running = true; + log.info("mariadb", "Starting Embedded MariaDB"); + this.childProcess = childProcess.spawn(this.exec, [ + "--user=node", + "--datadir=" + this.mariadbDataDir, + `--socket=${this.socketPath}`, + `--pid-file=${this.runDir}/mysqld.pid`, + // Don't add the following option, the mariadb will not report message to the console, which affects initDBAfterStarted() + // "--log-error=" + `${this.mariadbDataDir}/mariadb-error.log`, + ]); + + this.childProcess.on("close", (code) => { + this.running = false; + this.childProcess = null; + this.started = false; + log.info("mariadb", "Stopped Embedded MariaDB: " + code); + + if (code !== 0) { + log.error("mariadb", "Try to restart Embedded MariaDB as it is not stopped by user"); + this.startChildProcess(); + } + }); + + this.childProcess.on("error", (err) => { + if (err.code === "ENOENT") { + log.error("mariadb", `Embedded MariaDB: ${this.exec} is not found`); + } else { + log.error("mariadb", err); + } + }); + + let handler = (data) => { + log.info("mariadb", data.toString("utf-8")); + if (data.toString("utf-8").includes("ready for connections")) { + this.initDBAfterStarted(); + } + }; + + this.childProcess.stdout.on("data", handler); + this.childProcess.stderr.on("data", handler); + } + + /** + * Stop all the child processes + * @returns {void} + */ + stop() { + if (this.childProcess) { + this.childProcess.kill("SIGINT"); + this.childProcess = null; + } + } + + /** + * Install MariaDB if it is not installed and make sure the `runDir` directory exists + * @returns {void} + */ + initDB() { + if (!fs.existsSync(this.mariadbDataDir)) { + log.info("mariadb", `Embedded MariaDB: ${this.mariadbDataDir} is not found, create one now.`); + fs.mkdirSync(this.mariadbDataDir, { + recursive: true, + }); + + let result = childProcess.spawnSync("mariadb-install-db", [ + "--user=node", + "--auth-root-socket-user=node", + "--datadir=" + this.mariadbDataDir, + "--auth-root-authentication-method=socket", + ]); + + if (result.status !== 0) { + let error = result.stderr.toString("utf-8"); + log.error("mariadb", error); + return; + } else { + log.info("mariadb", "Embedded MariaDB: mysql_install_db done:" + result.stdout.toString("utf-8")); + } + } + + // Check the owner of the mariadb directory, and change it if necessary + let stat = fs.statSync(this.mariadbDataDir); + if (stat.uid !== 1000 || stat.gid !== 1000) { + fs.chownSync(this.mariadbDataDir, 1000, 1000); + } + + // Check the permission of the mariadb directory, and change it if it is not 755 + if (stat.mode !== 0o755) { + fs.chmodSync(this.mariadbDataDir, 0o755); + } + + if (!fs.existsSync(this.runDir)) { + log.info("mariadb", `Embedded MariaDB: ${this.runDir} is not found, create one now.`); + fs.mkdirSync(this.runDir, { + recursive: true, + }); + } + + stat = fs.statSync(this.runDir); + if (stat.uid !== 1000 || stat.gid !== 1000) { + fs.chownSync(this.runDir, 1000, 1000); + } + if (stat.mode !== 0o755) { + fs.chmodSync(this.runDir, 0o755); + } + } + + /** + * Initialise the "kuma" database in mariadb if it does not exist + * @returns {Promise} + */ + async initDBAfterStarted() { + const connection = mysql.createConnection({ + socketPath: this.socketPath, + user: this.username, + }); + + let result = await connection.execute("CREATE DATABASE IF NOT EXISTS `kuma`"); + log.debug("mariadb", "CREATE DATABASE: " + JSON.stringify(result)); + + log.info("mariadb", "Embedded MariaDB is ready for connections"); + this.started = true; + } + +} + +module.exports = { + EmbeddedMariaDB, +}; diff --git a/server/google-analytics.js b/server/google-analytics.js index 3e8e645f47..57ae7b754e 100644 --- a/server/google-analytics.js +++ b/server/google-analytics.js @@ -4,8 +4,8 @@ const { escape } = require("html-escaper"); /** * Returns a string that represents the javascript that is required to insert the Google Analytics scripts * into a webpage. - * @param tagId Google UA/G/AW/DC Property ID to use with the Google Analytics script. - * @returns {string} + * @param {string} tagId Google UA/G/AW/DC Property ID to use with the Google Analytics script. + * @returns {string} HTML script tags to inject into page */ function getGoogleAnalyticsScript(tagId) { let escapedTagIdJS = jsesc(tagId, { isScriptContext: true }); diff --git a/server/image-data-uri.js b/server/image-data-uri.js index eaf651f01f..77dd23307b 100644 --- a/server/image-data-uri.js +++ b/server/image-data-uri.js @@ -10,7 +10,7 @@ let ImageDataURI = (() => { /** * Decode the data:image/ URI * @param {string} dataURI data:image/ URI to decode - * @returns {?Object} An object with properties "imageType" and "dataBase64". + * @returns {?object} An object with properties "imageType" and "dataBase64". * The former is the image type, e.g., "png", and the latter is a base64 * encoded string of the image's binary data. If it fails to parse, returns * null instead of an object. @@ -52,8 +52,8 @@ let ImageDataURI = (() => { /** * Write data URI to file * @param {string} dataURI data:image/ URI - * @param {string} [filePath] Path to write file to - * @returns {Promise} + * @param {string} filePath Path to write file to + * @returns {Promise} Write file error */ function outputFile(dataURI, filePath) { filePath = filePath || "./"; diff --git a/server/jobs.js b/server/jobs.js index a17bd8c9b9..0838731d05 100644 --- a/server/jobs.js +++ b/server/jobs.js @@ -39,7 +39,10 @@ const initBackgroundJobs = async function () { }; -/** Stop all background jobs if running */ +/** + * Stop all background jobs if running + * @returns {void} + */ const stopBackgroundJobs = function () { for (const job of jobs) { if (job.croner) { diff --git a/server/jobs/clear-old-data.js b/server/jobs/clear-old-data.js index ad8ea1d380..cfd65a8a89 100644 --- a/server/jobs/clear-old-data.js +++ b/server/jobs/clear-old-data.js @@ -1,20 +1,22 @@ const { R } = require("redbean-node"); const { log } = require("../../src/util"); -const { setSetting, setting } = require("../util-server"); +const Database = require("../database"); +const { Settings } = require("../settings"); +const dayjs = require("dayjs"); -const DEFAULT_KEEP_PERIOD = 180; +const DEFAULT_KEEP_PERIOD = 365; /** - * Clears old data from the heartbeat table of the database. - * @return {Promise} A promise that resolves when the data has been cleared. + * Clears old data from the heartbeat table and the stat_daily of the database. + * @returns {Promise} A promise that resolves when the data has been cleared. */ - const clearOldData = async () => { - let period = await setting("keepDataPeriodDays"); + await Database.clearHeartbeatData(); + let period = await Settings.get("keepDataPeriodDays"); // Set Default Period if (period == null) { - await setSetting("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general"); + await Settings.set("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general"); period = DEFAULT_KEEP_PERIOD; } @@ -24,27 +26,38 @@ const clearOldData = async () => { parsedPeriod = parseInt(period); } catch (_) { log.warn("clearOldData", "Failed to parse setting, resetting to default.."); - await setSetting("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general"); + await Settings.set("keepDataPeriodDays", DEFAULT_KEEP_PERIOD, "general"); parsedPeriod = DEFAULT_KEEP_PERIOD; } if (parsedPeriod < 1) { log.info("clearOldData", `Data deletion has been disabled as period is less than 1. Period is ${parsedPeriod} days.`); } else { - log.debug("clearOldData", `Clearing Data older than ${parsedPeriod} days...`); + const sqlHourOffset = Database.sqlHourOffset(); try { - await R.exec( - "DELETE FROM heartbeat WHERE time < DATETIME('now', '-' || ? || ' days') ", - [ parsedPeriod ] - ); + // Heartbeat + await R.exec("DELETE FROM heartbeat WHERE time < " + sqlHourOffset, [ + parsedPeriod * -24, + ]); + + let timestamp = dayjs().subtract(parsedPeriod, "day").utc().startOf("day").unix(); - await R.exec("PRAGMA optimize;"); + // stat_daily + await R.exec("DELETE FROM stat_daily WHERE timestamp < ? ", [ + timestamp, + ]); + + if (Database.dbConfig.type === "sqlite") { + await R.exec("PRAGMA optimize;"); + } } catch (e) { log.error("clearOldData", `Failed to clear old data: ${e.message}`); } } + + log.debug("clearOldData", "Data cleared."); }; module.exports = { diff --git a/server/jobs/incremental-vacuum.js b/server/jobs/incremental-vacuum.js index a452324635..f0fa78a17c 100644 --- a/server/jobs/incremental-vacuum.js +++ b/server/jobs/incremental-vacuum.js @@ -1,13 +1,19 @@ const { R } = require("redbean-node"); const { log } = require("../../src/util"); +const Database = require("../database"); /** * Run incremental_vacuum and checkpoint the WAL. - * @return {Promise} A promise that resolves when the process is finished. + * @returns {Promise} A promise that resolves when the process is finished. */ const incrementalVacuum = async () => { try { + if (Database.dbConfig.type !== "sqlite") { + log.debug("incrementalVacuum", "Skipping incremental_vacuum, not using SQLite."); + return; + } + log.debug("incrementalVacuum", "Running incremental_vacuum and wal_checkpoint(PASSIVE)..."); await R.exec("PRAGMA incremental_vacuum(200)"); await R.exec("PRAGMA wal_checkpoint(PASSIVE)"); diff --git a/server/model/api_key.js b/server/model/api_key.js index 1b27a60f6c..96de98454c 100644 --- a/server/model/api_key.js +++ b/server/model/api_key.js @@ -19,7 +19,7 @@ class APIKey extends BeanModel { /** * Returns an object that ready to parse to JSON - * @returns {Object} + * @returns {object} Object ready to parse */ toJSON() { return { @@ -37,7 +37,7 @@ class APIKey extends BeanModel { /** * Returns an object that ready to parse to JSON with sensitive fields * removed - * @returns {Object} + * @returns {object} Object ready to parse */ toPublicJSON() { return { @@ -53,9 +53,9 @@ class APIKey extends BeanModel { /** * Create a new API Key and store it in the database - * @param {Object} key Object sent by client + * @param {object} key Object sent by client * @param {int} userID ID of socket user - * @returns {Promise} + * @returns {Promise} API key */ static async save(key, userID) { let bean; diff --git a/server/model/docker_host.js b/server/model/docker_host.js index 205982922d..ceb8f4a3d1 100644 --- a/server/model/docker_host.js +++ b/server/model/docker_host.js @@ -3,7 +3,7 @@ const { BeanModel } = require("redbean-node/dist/bean-model"); class DockerHost extends BeanModel { /** * Returns an object that ready to parse to JSON - * @returns {Object} + * @returns {object} Object ready to parse */ toJSON() { return { diff --git a/server/model/group.js b/server/model/group.js index 5b712aceb3..bd2c301899 100644 --- a/server/model/group.js +++ b/server/model/group.js @@ -4,10 +4,12 @@ const { R } = require("redbean-node"); class Group extends BeanModel { /** - * Return an object that ready to parse to JSON for public - * Only show necessary data to public - * @param {boolean} [showTags=false] Should the JSON include monitor tags - * @returns {Object} + * Return an object that ready to parse to JSON for public Only show + * necessary data to public + * @param {boolean} showTags Should the JSON include monitor tags + * @param {boolean} certExpiry Should JSON include info about + * certificate expiry? + * @returns {Promise} Object ready to parse */ async toPublicJSON(showTags = false, certExpiry = false) { let monitorBeanList = await this.getMonitorList(); @@ -27,7 +29,7 @@ class Group extends BeanModel { /** * Get all monitors - * @returns {Bean[]} + * @returns {Promise} List of monitors */ async getMonitorList() { return R.convertToBeans("monitor", await R.getAll(` diff --git a/server/model/heartbeat.js b/server/model/heartbeat.js index b7847f8791..9e972a376d 100644 --- a/server/model/heartbeat.js +++ b/server/model/heartbeat.js @@ -12,7 +12,7 @@ class Heartbeat extends BeanModel { /** * Return an object that ready to parse to JSON for public * Only show necessary data to public - * @returns {Object} + * @returns {object} Object ready to parse */ toPublicJSON() { return { @@ -25,17 +25,18 @@ class Heartbeat extends BeanModel { /** * Return an object that ready to parse to JSON - * @returns {Object} + * @returns {object} Object ready to parse */ toJSON() { return { - monitorID: this.monitor_id, - status: this.status, - time: this.time, - msg: this.msg, - ping: this.ping, - important: this.important, - duration: this.duration, + monitorID: this._monitorId, + status: this._status, + time: this._time, + msg: this._msg, + ping: this._ping, + important: this._important, + duration: this._duration, + retries: this._retries, }; } diff --git a/server/model/incident.js b/server/model/incident.js index f954cc74a9..c47dabb414 100644 --- a/server/model/incident.js +++ b/server/model/incident.js @@ -5,7 +5,7 @@ class Incident extends BeanModel { /** * Return an object that ready to parse to JSON for public * Only show necessary data to public - * @returns {Object} + * @returns {object} Object ready to parse */ toPublicJSON() { return { diff --git a/server/model/maintenance.js b/server/model/maintenance.js index f18eb026d0..7111a18cb5 100644 --- a/server/model/maintenance.js +++ b/server/model/maintenance.js @@ -11,7 +11,7 @@ class Maintenance extends BeanModel { /** * Return an object that ready to parse to JSON for public * Only show necessary data to public - * @returns {Object} + * @returns {Promise} Object ready to parse */ async toPublicJSON() { @@ -98,7 +98,7 @@ class Maintenance extends BeanModel { /** * Return an object that ready to parse to JSON * @param {string} timezone If not specified, the timeRange will be in UTC - * @returns {Object} + * @returns {Promise} Object ready to parse */ async toJSON(timezone = null) { return this.toPublicJSON(timezone); @@ -142,8 +142,8 @@ class Maintenance extends BeanModel { /** * Convert data from socket to bean * @param {Bean} bean Bean to fill in - * @param {Object} obj Data to fill bean with - * @returns {Bean} Filled bean + * @param {object} obj Data to fill bean with + * @returns {Promise} Filled bean */ static async jsonToBean(bean, obj) { if (obj.id) { @@ -188,16 +188,18 @@ class Maintenance extends BeanModel { /** * Throw error if cron is invalid - * @param cron - * @returns {Promise} + * @param {string|Date} cron Pattern or date + * @returns {void} */ - static async validateCron(cron) { + static validateCron(cron) { let job = new Cron(cron, () => {}); job.stop(); } /** * Run the cron + * @param {boolean} throwError Should an error be thrown on failure + * @returns {Promise} */ async run(throwError = false) { if (this.beanMeta.job) { @@ -237,19 +239,7 @@ class Maintenance extends BeanModel { this.beanMeta.status = "under-maintenance"; clearTimeout(this.beanMeta.durationTimeout); - // Check if duration is still in the window. If not, use the duration from the current time to the end of the window - let duration; - - if (customDuration > 0) { - duration = customDuration; - } else if (this.end_date) { - let d = dayjs(this.end_date).diff(dayjs(), "second"); - if (d < this.duration) { - duration = d * 1000; - } - } else { - duration = this.duration * 1000; - } + let duration = this.inferDuration(customDuration); UptimeKumaServer.getInstance().sendMaintenanceListByUserID(this.user_id); @@ -261,9 +251,21 @@ class Maintenance extends BeanModel { }; // Create Cron - this.beanMeta.job = new Cron(this.cron, { - timezone: await this.getTimezone(), - }, startEvent); + if (this.strategy === "recurring-interval") { + // For recurring-interval, Croner needs to have interval and startAt + const startDate = dayjs(this.startDate); + const [ hour, minute ] = this.startTime.split(":"); + const startDateTime = startDate.hour(hour).minute(minute); + this.beanMeta.job = new Cron(this.cron, { + timezone: await this.getTimezone(), + interval: this.interval_day * 24 * 60 * 60, + startAt: startDateTime.toISOString(), + }, startEvent); + } else { + this.beanMeta.job = new Cron(this.cron, { + timezone: await this.getTimezone(), + }, startEvent); + } // Continue if the maintenance is still in the window let runningTimeslot = this.getRunningTimeslot(); @@ -290,6 +292,10 @@ class Maintenance extends BeanModel { } } + /** + * Get timeslots where maintenance is running + * @returns {object|null} Maintenance time slot + */ getRunningTimeslot() { let start = dayjs(this.beanMeta.job.nextRun(dayjs().add(-this.duration, "second").toDate())); let end = start.add(this.duration, "second"); @@ -305,6 +311,28 @@ class Maintenance extends BeanModel { } } + /** + * Calculate the maintenance duration + * @param {number} customDuration - The custom duration in milliseconds. + * @returns {number} The inferred duration in milliseconds. + */ + inferDuration(customDuration) { + // Check if duration is still in the window. If not, use the duration from the current time to the end of the window + if (customDuration > 0) { + return customDuration; + } else if (this.end_date) { + let d = dayjs(this.end_date).diff(dayjs(), "second"); + if (d < this.duration) { + return d * 1000; + } + } + return this.duration * 1000; + } + + /** + * Stop the maintenance + * @returns {void} + */ stop() { if (this.beanMeta.job) { this.beanMeta.job.stop(); @@ -312,10 +340,18 @@ class Maintenance extends BeanModel { } } + /** + * Is this maintenance currently active + * @returns {Promise} The maintenance is active? + */ async isUnderMaintenance() { return (await this.getStatus()) === "under-maintenance"; } + /** + * Get the timezone of the maintenance + * @returns {Promise} timezone + */ async getTimezone() { if (!this.timezone || this.timezone === "SAME_AS_SERVER") { return await UptimeKumaServer.getInstance().getTimezone(); @@ -323,10 +359,18 @@ class Maintenance extends BeanModel { return this.timezone; } + /** + * Get offset for timezone + * @returns {Promise} offset + */ async getTimezoneOffset() { return dayjs.tz(dayjs(), await this.getTimezone()).format("Z"); } + /** + * Get the current status of the maintenance + * @returns {Promise} Current status + */ async getStatus() { if (!this.active) { return "inactive"; @@ -369,10 +413,8 @@ class Maintenance extends BeanModel { } else if (!this.strategy.startsWith("recurring-")) { this.cron = ""; } else if (this.strategy === "recurring-interval") { - let array = this.start_time.split(":"); - let hour = parseInt(array[0]); - let minute = parseInt(array[1]); - this.cron = minute + " " + hour + " */" + this.interval_day + " * *"; + // For intervals, the pattern is calculated in the run function as the interval-option is set + this.cron = "* * * * *"; this.duration = this.calcDuration(); log.debug("maintenance", "Cron: " + this.cron); log.debug("maintenance", "Duration: " + this.duration); diff --git a/server/model/monitor.js b/server/model/monitor.js index 2848a0cb92..3ad8cfafc1 100644 --- a/server/model/monitor.js +++ b/server/model/monitor.js @@ -1,12 +1,11 @@ -const https = require("https"); const dayjs = require("dayjs"); const axios = require("axios"); const { Prometheus } = require("../prometheus"); -const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, TimeLogger, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND, - SQL_DATETIME_FORMAT +const { log, UP, DOWN, PENDING, MAINTENANCE, flipStatus, MAX_INTERVAL_SECOND, MIN_INTERVAL_SECOND, + SQL_DATETIME_FORMAT, evaluateJsonQuery } = require("../../src/util"); -const { tcping, ping, dnsResolve, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, mqttAsync, setSetting, httpNtlm, radius, grpcQuery, - redisPingAsync, mongodbPing, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal +const { tcping, ping, checkCertificate, checkStatusCode, getTotalClientInRoom, setting, mssqlQuery, postgresQuery, mysqlQuery, setSetting, httpNtlm, radius, grpcQuery, + redisPingAsync, kafkaProducerAsync, getOidcTokenClientCredentials, rootCertificatesFingerprints, axiosAbortSignal } = require("../util-server"); const { R } = require("redbean-node"); const { BeanModel } = require("redbean-node/dist/bean-model"); @@ -16,13 +15,15 @@ const { demoMode } = require("../config"); const version = require("../../package.json").version; const apicache = require("../modules/apicache"); const { UptimeKumaServer } = require("../uptime-kuma-server"); -const { CacheableDnsHttpAgent } = require("../cacheable-dns-http-agent"); const { DockerHost } = require("../docker"); -const { UptimeCacheList } = require("../uptime-cache-list"); const Gamedig = require("gamedig"); -const jsonata = require("jsonata"); const jwt = require("jsonwebtoken"); const crypto = require("crypto"); +const { UptimeCalculator } = require("../uptime-calculator"); +const { CookieJar } = require("tough-cookie"); +const { HttpsCookieAgent } = require("http-cookie-agent/http"); +const https = require("https"); +const http = require("http"); const rootCertificates = rootCertificatesFingerprints(); @@ -36,9 +37,12 @@ const rootCertificates = rootCertificatesFingerprints(); class Monitor extends BeanModel { /** - * Return an object that ready to parse to JSON for public - * Only show necessary data to public - * @returns {Object} + * Return an object that ready to parse to JSON for public Only show + * necessary data to public + * @param {boolean} showTags Include tags in JSON + * @param {boolean} certExpiry Include certificate expiry info in + * JSON + * @returns {Promise} Object ready to parse */ async toPublicJSON(showTags = false, certExpiry = false) { let obj = { @@ -67,21 +71,12 @@ class Monitor extends BeanModel { /** * Return an object that ready to parse to JSON - * @returns {Object} + * @param {object} preloadData to prevent n+1 problems, we query the data in a batch outside of this function + * @param {boolean} includeSensitiveData Include sensitive data in + * JSON + * @returns {object} Object ready to parse */ - async toJSON(includeSensitiveData = true) { - - let notificationIDList = {}; - - let list = await R.find("monitor_notification", " monitor_id = ? ", [ - this.id, - ]); - - for (let bean of list) { - notificationIDList[bean.notification_id] = true; - } - - const tags = await this.getTags(); + toJSON(preloadData = {}, includeSensitiveData = true) { let screenshot = null; @@ -89,21 +84,25 @@ class Monitor extends BeanModel { screenshot = "/screenshots/" + jwt.sign(this.id, UptimeKumaServer.getInstance().jwtSecret) + ".png"; } + const path = preloadData.paths.get(this.id) || []; + const pathName = path.join(" / "); + let data = { id: this.id, name: this.name, description: this.description, - pathName: await this.getPathName(), + path, + pathName, parent: this.parent, - childrenIDs: await Monitor.getAllChildrenIDs(this.id), + childrenIDs: preloadData.childrenIDs.get(this.id) || [], url: this.url, method: this.method, hostname: this.hostname, port: this.port, maxretries: this.maxretries, weight: this.weight, - active: await this.isActive(), - forceInactive: !await Monitor.isParentActive(this.id), + active: preloadData.activeStatus.get(this.id), + forceInactive: preloadData.forceInactive.get(this.id), type: this.type, timeout: this.timeout, interval: this.interval, @@ -123,11 +122,12 @@ class Monitor extends BeanModel { docker_container: this.docker_container, docker_host: this.docker_host, proxyId: this.proxy_id, - notificationIDList, - tags: tags, - maintenance: await Monitor.isUnderMaintenance(this.id), + notificationIDList: preloadData.notifications.get(this.id) || {}, + tags: preloadData.tags.get(this.id) || [], + maintenance: preloadData.maintenanceStatus.get(this.id), mqttTopic: this.mqttTopic, mqttSuccessMessage: this.mqttSuccessMessage, + mqttCheckType: this.mqttCheckType, databaseQuery: this.databaseQuery, authMethod: this.authMethod, grpcUrl: this.grpcUrl, @@ -148,6 +148,13 @@ class Monitor extends BeanModel { kafkaProducerAllowAutoTopicCreation: this.getKafkaProducerAllowAutoTopicCreation(), kafkaProducerMessage: this.kafkaProducerMessage, screenshot, + cacheBust: this.getCacheBust(), + remote_browser: this.remote_browser, + snmpOid: this.snmpOid, + jsonPathOperator: this.jsonPathOperator, + snmpVersion: this.snmpVersion, + rabbitmqNodes: JSON.parse(this.rabbitmqNodes), + conditions: JSON.parse(this.conditions), }; if (includeSensitiveData) { @@ -177,6 +184,8 @@ class Monitor extends BeanModel { tlsCert: this.tlsCert, tlsKey: this.tlsKey, kafkaProducerSaslOptions: JSON.parse(this.kafkaProducerSaslOptions), + rabbitmqUsername: this.rabbitmqUsername, + rabbitmqPassword: this.rabbitmqPassword, }; } @@ -184,19 +193,10 @@ class Monitor extends BeanModel { return data; } - /** - * Checks if the monitor is active based on itself and its parents - * @returns {Promise} - */ - async isActive() { - const parentActive = await Monitor.isParentActive(this.id); - - return (this.active === 1) && parentActive; - } - /** * Get all tags applied to this monitor - * @returns {Promise[]>} + * @returns {Promise[]>} List of tags on the + * monitor */ async getTags() { return await R.getAll("SELECT mt.*, tag.name, tag.color FROM monitor_tag mt JOIN tag ON mt.tag_id = tag.id WHERE mt.monitor_id = ? ORDER BY tag.name", [ this.id ]); @@ -205,7 +205,8 @@ class Monitor extends BeanModel { /** * Gets certificate expiry for this monitor * @param {number} monitorID ID of monitor to send - * @returns {Promise>} + * @returns {Promise>} Certificate expiry info for + * monitor */ async getCertExpiry(monitorID) { let tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [ @@ -232,7 +233,7 @@ class Monitor extends BeanModel { * for HTTP "basic" auth, as per RFC-7617 * @param {string|null} user - The username (nullable if not changed by a user) * @param {string|null} pass - The password (nullable if not changed by a user) - * @returns {string} + * @returns {string} Encoded Base64 string */ encodeBase64(user, pass) { return Buffer.from(`${user || ""}:${pass || ""}`).toString("base64"); @@ -240,7 +241,7 @@ class Monitor extends BeanModel { /** * Is the TLS expiry notification enabled? - * @returns {boolean} + * @returns {boolean} Enabled? */ isEnabledExpiryNotification() { return Boolean(this.expiryNotification); @@ -248,7 +249,7 @@ class Monitor extends BeanModel { /** * Parse to boolean - * @returns {boolean} + * @returns {boolean} Should TLS errors be ignored? */ getIgnoreTls() { return Boolean(this.ignoreTls); @@ -256,7 +257,7 @@ class Monitor extends BeanModel { /** * Parse to boolean - * @returns {boolean} + * @returns {boolean} Is the monitor in upside down mode? */ isUpsideDown() { return Boolean(this.upsideDown); @@ -264,7 +265,7 @@ class Monitor extends BeanModel { /** * Parse to boolean - * @returns {boolean} + * @returns {boolean} Invert keyword match? */ isInvertKeyword() { return Boolean(this.invertKeyword); @@ -272,20 +273,32 @@ class Monitor extends BeanModel { /** * Parse to boolean - * @returns {boolean} + * @returns {boolean} Enable TLS for gRPC? */ getGrpcEnableTls() { return Boolean(this.grpcEnableTls); } + /** + * Parse to boolean + * @returns {boolean} if cachebusting is enabled + */ + getCacheBust() { + return Boolean(this.cacheBust); + } + /** * Get accepted status codes - * @returns {Object} + * @returns {object} Accepted status codes */ getAcceptedStatuscodes() { return JSON.parse(this.accepted_statuscodes_json); } + /** + * Get if game dig should only use the port which was provided + * @returns {boolean} gamedig should only use the provided port + */ getGameDigGivenPortOnly() { return Boolean(this.gamedigGivenPortOnly); } @@ -309,8 +322,9 @@ class Monitor extends BeanModel { /** * Start monitor * @param {Server} io Socket server instance + * @returns {Promise} */ - start(io) { + async start(io) { let previousBeat = null; let retries = 0; @@ -339,6 +353,9 @@ class Monitor extends BeanModel { previousBeat = await R.findOne("heartbeat", " monitor_id = ? ORDER BY time DESC", [ this.id, ]); + if (previousBeat) { + retries = previousBeat.retries; + } } const isFirstBeat = !previousBeat; @@ -353,13 +370,6 @@ class Monitor extends BeanModel { bean.status = flipStatus(bean.status); } - // Duration - if (!isFirstBeat) { - bean.duration = dayjs(bean.time).diff(dayjs(previousBeat.time), "second"); - } else { - bean.duration = 0; - } - // Runtime patch timeout if it is 0 // See https://github.com/louislam/uptime-kuma/pull/3961#issuecomment-1804149144 if (!this.timeout || this.timeout <= 0) { @@ -421,9 +431,7 @@ class Monitor extends BeanModel { if (this.auth_method === "oauth2-cc") { try { if (this.oauthAccessToken === undefined || new Date(this.oauthAccessToken.expires_at * 1000) <= new Date()) { - log.debug("monitor", `[${this.name}] The oauth access-token undefined or expired. Requesting a new one`); - this.oauthAccessToken = await getOidcTokenClientCredentials(this.oauth_token_url, this.oauth_client_id, this.oauth_client_secret, this.oauth_scopes, this.oauth_auth_method); - log.debug("monitor", `[${this.name}] Obtained oauth access-token. Expires at ${new Date(this.oauthAccessToken.expires_at * 1000)}`); + this.oauthAccessToken = await this.makeOidcTokenClientCredentialsRequest(); } oauth2AuthHeader = { "Authorization": this.oauthAccessToken.token_type + " " + this.oauthAccessToken.access_token, @@ -452,6 +460,9 @@ class Monitor extends BeanModel { } catch (e) { throw new Error("Your JSON body is invalid. " + e.message); } + } else if (this.httpBodyEncoding === "form") { + bodyValue = this.body; + contentType = "application/x-www-form-urlencoded"; } else if (this.httpBodyEncoding === "xml") { bodyValue = this.body; contentType = "text/xml; charset=utf-8"; @@ -465,7 +476,6 @@ class Monitor extends BeanModel { timeout: this.timeout * 1000, headers: { "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9", - "User-Agent": "Uptime-Kuma/" + version, ...(contentType ? { "Content-Type": contentType } : {}), ...(basicAuthHeader), ...(oauth2AuthHeader), @@ -482,6 +492,14 @@ class Monitor extends BeanModel { options.data = bodyValue; } + if (this.cacheBust) { + const randomFloatString = Math.random().toString(36); + const cacheBust = randomFloatString.substring(2); + options.params = { + uptime_kuma_cachebuster: cacheBust, + }; + } + if (this.proxy_id) { const proxy = await R.load("proxy", this.proxy_id); @@ -497,7 +515,12 @@ class Monitor extends BeanModel { } if (!options.httpsAgent) { - options.httpsAgent = new https.Agent(httpsAgentOptions); + let jar = new CookieJar(); + let httpsCookieAgentOptions = { + ...httpsAgentOptions, + cookies: { jar } + }; + options.httpsAgent = new HttpsCookieAgent(httpsCookieAgentOptions); } if (this.auth_method === "mtls") { @@ -577,25 +600,15 @@ class Monitor extends BeanModel { } else if (this.type === "json-query") { let data = res.data; - // convert data to object - if (typeof data === "string" && res.headers["content-type"] !== "application/json") { - try { - data = JSON.parse(data); - } catch (_) { - // Failed to parse as JSON, just process it as a string - } - } - - let expression = jsonata(this.jsonPath); - - let result = await expression.evaluate(data); + const { status, response } = await evaluateJsonQuery(data, this.jsonPath, this.jsonPathOperator, this.expectedValue); - if (result.toString() === this.expectedValue) { - bean.msg += ", expected value is found"; + if (status) { bean.status = UP; + bean.msg = `JSON query passes (comparing ${response} ${this.jsonPathOperator} ${this.expectedValue})`; } else { - throw new Error(bean.msg + ", but value is not equal to expected value, value was: [" + result + "]"); + throw new Error(`JSON query does not pass (comparing ${response} ${this.jsonPathOperator} ${this.expectedValue})`); } + } } else if (this.type === "port") { @@ -607,46 +620,6 @@ class Monitor extends BeanModel { bean.ping = await ping(this.hostname, this.packetSize); bean.msg = ""; bean.status = UP; - } else if (this.type === "dns") { - let startTime = dayjs().valueOf(); - let dnsMessage = ""; - - let dnsRes = await dnsResolve(this.hostname, this.dns_resolve_server, this.port, this.dns_resolve_type); - bean.ping = dayjs().valueOf() - startTime; - - if (this.dns_resolve_type === "A" || this.dns_resolve_type === "AAAA" || this.dns_resolve_type === "TXT" || this.dns_resolve_type === "PTR") { - dnsMessage += "Records: "; - dnsMessage += dnsRes.join(" | "); - } else if (this.dns_resolve_type === "CNAME") { - dnsMessage += dnsRes[0]; - } else if (this.dns_resolve_type === "CAA") { - dnsMessage += dnsRes[0].issue; - } else if (this.dns_resolve_type === "MX") { - dnsRes.forEach(record => { - dnsMessage += `Hostname: ${record.exchange} - Priority: ${record.priority} | `; - }); - dnsMessage = dnsMessage.slice(0, -2); - } else if (this.dns_resolve_type === "NS") { - dnsMessage += "Servers: "; - dnsMessage += dnsRes.join(" | "); - } else if (this.dns_resolve_type === "SOA") { - dnsMessage += `NS-Name: ${dnsRes.nsname} | Hostmaster: ${dnsRes.hostmaster} | Serial: ${dnsRes.serial} | Refresh: ${dnsRes.refresh} | Retry: ${dnsRes.retry} | Expire: ${dnsRes.expire} | MinTTL: ${dnsRes.minttl}`; - } else if (this.dns_resolve_type === "SRV") { - dnsRes.forEach(record => { - dnsMessage += `Name: ${record.name} | Port: ${record.port} | Priority: ${record.priority} | Weight: ${record.weight} | `; - }); - dnsMessage = dnsMessage.slice(0, -2); - } - - if (this.dnsLastResult !== dnsMessage && dnsMessage !== undefined) { - R.exec("UPDATE `monitor` SET dns_last_result = ? WHERE id = ? ", [ - dnsMessage, - this.id - ]); - } - - bean.msg = dnsMessage; - bean.status = UP; } else if (this.type === "push") { // Type: Push log.debug("monitor", `[${this.name}] Checking monitor at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); const bufferTime = 1000; // 1s buffer to accommodate clock differences @@ -659,6 +632,7 @@ class Monitor extends BeanModel { // If the previous beat was down or pending we use the regular // beatInterval/retryInterval in the setTimeout further below if (previousBeat.status !== (this.isUpsideDown() ? DOWN : UP) || msSinceLastBeat > beatInterval * 1000 + bufferTime) { + bean.duration = Math.round(msSinceLastBeat / 1000); throw new Error("No heartbeat in the time window"); } else { let timeout = beatInterval * 1000 - msSinceLastBeat; @@ -674,6 +648,7 @@ class Monitor extends BeanModel { return; } } else { + bean.duration = beatInterval; throw new Error("No heartbeat in the time window"); } @@ -690,14 +665,13 @@ class Monitor extends BeanModel { timeout: this.timeout * 1000, headers: { "Accept": "*/*", - "User-Agent": "Uptime-Kuma/" + version, }, - httpsAgent: CacheableDnsHttpAgent.getHttpsAgent({ + httpsAgent: new https.Agent({ maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) rejectUnauthorized: !this.getIgnoreTls(), secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT, }), - httpAgent: CacheableDnsHttpAgent.getHttpAgent({ + httpAgent: new http.Agent({ maxCachedSessions: 0, }), maxRedirects: this.maxredirects, @@ -743,14 +717,13 @@ class Monitor extends BeanModel { timeout: this.interval * 1000 * 0.8, headers: { "Accept": "*/*", - "User-Agent": "Uptime-Kuma/" + version, }, - httpsAgent: CacheableDnsHttpAgent.getHttpsAgent({ + httpsAgent: new https.Agent({ maxCachedSessions: 0, // Use Custom agent to disable session reuse (https://github.com/nodejs/node/issues/3940) rejectUnauthorized: !this.getIgnoreTls(), secureOptions: crypto.constants.SSL_OP_LEGACY_SERVER_CONNECT, }), - httpAgent: CacheableDnsHttpAgent.getHttpAgent({ + httpAgent: new http.Agent({ maxCachedSessions: 0, }), }; @@ -765,7 +738,7 @@ class Monitor extends BeanModel { options.socketPath = dockerHost._dockerDaemon; } else if (dockerHost._dockerType === "tcp") { options.baseURL = DockerHost.patchDockerURL(dockerHost._dockerDaemon); - options.httpsAgent = CacheableDnsHttpAgent.getHttpsAgent( + options.httpsAgent = new https.Agent( DockerHost.getHttpsAgentOptions(dockerHost._dockerType, options.baseURL) ); } @@ -784,14 +757,6 @@ class Monitor extends BeanModel { } else { throw Error("Container State is " + res.data.State.Status); } - } else if (this.type === "mqtt") { - bean.msg = await mqttAsync(this.hostname, this.mqttTopic, this.mqttSuccessMessage, { - port: this.port, - username: this.mqttUsername, - password: this.mqttPassword, - interval: this.interval, - }); - bean.status = UP; } else if (this.type === "sqlserver") { let startTime = dayjs().valueOf(); @@ -849,15 +814,6 @@ class Monitor extends BeanModel { bean.msg = await mysqlQuery(this.databaseConnectionString, this.databaseQuery || "SELECT 1", mysqlPassword); bean.status = UP; bean.ping = dayjs().valueOf() - startTime; - } else if (this.type === "mongodb") { - let startTime = dayjs().valueOf(); - - await mongodbPing(this.databaseConnectionString); - - bean.msg = ""; - bean.status = UP; - bean.ping = dayjs().valueOf() - startTime; - } else if (this.type === "radius") { let startTime = dayjs().valueOf(); @@ -888,7 +844,7 @@ class Monitor extends BeanModel { } else if (this.type === "redis") { let startTime = dayjs().valueOf(); - bean.msg = await redisPingAsync(this.databaseConnectionString); + bean.msg = await redisPingAsync(this.databaseConnectionString, !this.ignoreTls); bean.status = UP; bean.ping = dayjs().valueOf() - startTime; @@ -948,9 +904,14 @@ class Monitor extends BeanModel { } else if ((this.maxretries > 0) && (retries < this.maxretries)) { retries++; bean.status = PENDING; + } else { + // Continue counting retries during DOWN + retries++; } } + bean.retries = retries; + log.debug("monitor", `[${this.name}] Check isImportant`); let isImportant = Monitor.isImportantBeat(isFirstBeat, previousBeat?.status, bean.status); @@ -973,7 +934,7 @@ class Monitor extends BeanModel { log.debug("monitor", `[${this.name}] apicache clear`); apicache.clear(); - UptimeKumaServer.getInstance().sendMaintenanceListByUserID(this.user_id); + await UptimeKumaServer.getInstance().sendMaintenanceListByUserID(this.user_id); } else { bean.important = false; @@ -1004,11 +965,17 @@ class Monitor extends BeanModel { log.warn("monitor", `Monitor #${this.id} '${this.name}': Failing: ${bean.msg} | Interval: ${beatInterval} seconds | Type: ${this.type} | Down Count: ${bean.downCount} | Resend Interval: ${this.resendInterval}`); } + // Calculate uptime + let uptimeCalculator = await UptimeCalculator.getUptimeCalculator(this.id); + let endTimeDayjs = await uptimeCalculator.update(bean.status, parseFloat(bean.ping)); + bean.end_time = R.isoDateTimeMillis(endTimeDayjs); + + // Send to frontend log.debug("monitor", `[${this.name}] Send to socket`); - UptimeCacheList.clearCache(this.id); io.to(this.user_id).emit("heartbeat", bean.toJSON()); Monitor.sendStats(io, this.id, this.user_id); + // Store to database log.debug("monitor", `[${this.name}] Store`); await R.store(bean); @@ -1019,14 +986,25 @@ class Monitor extends BeanModel { if (! this.isStop) { log.debug("monitor", `[${this.name}] SetTimeout for next check.`); - this.heartbeatInterval = setTimeout(safeBeat, beatInterval * 1000); + + let intervalRemainingMs = Math.max( + 1, + beatInterval * 1000 - dayjs().diff(dayjs.utc(bean.time)) + ); + + log.debug("monitor", `[${this.name}] Next heartbeat in: ${intervalRemainingMs}ms`); + + this.heartbeatInterval = setTimeout(safeBeat, intervalRemainingMs); } else { log.info("monitor", `[${this.name}] isStop = true, no next check.`); } }; - /** Get a heartbeat and handle errors */ + /** + * Get a heartbeat and handle errors7 + * @returns {void} + */ const safeBeat = async () => { try { await beat(); @@ -1054,10 +1032,10 @@ class Monitor extends BeanModel { /** * Make a request using axios - * @param {Object} options Options for Axios + * @param {object} options Options for Axios * @param {boolean} finalCall Should this be the final call i.e - * don't retry on faliure - * @returns {Object} Axios response + * don't retry on failure + * @returns {object} Axios response */ async makeAxiosRequest(options, finalCall = false) { try { @@ -1076,24 +1054,44 @@ class Monitor extends BeanModel { } return res; - } catch (e) { + } catch (error) { + + /** + * Make a single attempt to obtain an new access token in the event that + * the recent api request failed for authentication purposes + */ + if (this.auth_method === "oauth2-cc" && error.response.status === 401 && !finalCall) { + this.oauthAccessToken = await this.makeOidcTokenClientCredentialsRequest(); + let oauth2AuthHeader = { + "Authorization": this.oauthAccessToken.token_type + " " + this.oauthAccessToken.access_token, + }; + options.headers = { ...(options.headers), + ...(oauth2AuthHeader) + }; + + return this.makeAxiosRequest(options, true); + } + // Fix #2253 // Read more: https://stackoverflow.com/questions/1759956/curl-error-18-transfer-closed-with-outstanding-read-data-remaining - if (!finalCall && typeof e.message === "string" && e.message.includes("maxContentLength size of -1 exceeded")) { + if (!finalCall && typeof error.message === "string" && error.message.includes("maxContentLength size of -1 exceeded")) { log.debug("monitor", "makeAxiosRequest with gzip"); options.headers["Accept-Encoding"] = "gzip, deflate"; return this.makeAxiosRequest(options, true); } else { - if (typeof e.message === "string" && e.message.includes("maxContentLength size of -1 exceeded")) { - e.message = "response timeout: incomplete response within a interval"; + if (typeof error.message === "string" && error.message.includes("maxContentLength size of -1 exceeded")) { + error.message = "response timeout: incomplete response within a interval"; } - throw e; + throw error; } } } - /** Stop monitor */ - stop() { + /** + * Stop monitor + * @returns {Promise} + */ + async stop() { clearTimeout(this.heartbeatInterval); this.isStop = true; @@ -1102,7 +1100,7 @@ class Monitor extends BeanModel { /** * Get prometheus instance - * @returns {Prometheus|undefined} + * @returns {Prometheus|undefined} Current prometheus instance */ getPrometheus() { return this.prometheus; @@ -1112,7 +1110,7 @@ class Monitor extends BeanModel { * Helper Method: * returns URL object for further usage * returns null if url is invalid - * @returns {(null|URL)} + * @returns {(null|URL)} Monitor URL */ getUrl() { try { @@ -1124,7 +1122,7 @@ class Monitor extends BeanModel { /** * Example: http: or https: - * @returns {(null|string)} + * @returns {(null|string)} URL's protocol */ getURLProtocol() { const url = this.getUrl(); @@ -1137,8 +1135,8 @@ class Monitor extends BeanModel { /** * Store TLS info to database - * @param checkCertificateResult - * @returns {Promise} + * @param {object} checkCertificateResult Certificate to update + * @returns {Promise} Updated certificate */ async updateTlsInfo(checkCertificateResult) { let tlsInfoBean = await R.findOne("monitor_tls_info", "monitor_id = ?", [ @@ -1180,52 +1178,58 @@ class Monitor extends BeanModel { return checkCertificateResult; } + /** + * Checks if the monitor is active based on itself and its parents + * @param {number} monitorID ID of monitor to send + * @param {boolean} active is active + * @returns {Promise} Is the monitor active? + */ + static async isActive(monitorID, active) { + const parentActive = await Monitor.isParentActive(monitorID); + + return (active === 1) && parentActive; + } + /** * Send statistics to clients * @param {Server} io Socket server instance * @param {number} monitorID ID of monitor to send * @param {number} userID ID of user to send to + * @returns {void} */ static async sendStats(io, monitorID, userID) { const hasClients = getTotalClientInRoom(io, userID) > 0; + let uptimeCalculator = await UptimeCalculator.getUptimeCalculator(monitorID); if (hasClients) { - await Monitor.sendAvgPing(24, io, monitorID, userID); - await Monitor.sendUptime(24, io, monitorID, userID); - await Monitor.sendUptime(24 * 30, io, monitorID, userID); + // Send 24 hour average ping + let data24h = await uptimeCalculator.get24Hour(); + io.to(userID).emit("avgPing", monitorID, (data24h.avgPing) ? Number(data24h.avgPing.toFixed(2)) : null); + + // Send 24 hour uptime + io.to(userID).emit("uptime", monitorID, 24, data24h.uptime); + + // Send 30 day uptime + let data30d = await uptimeCalculator.get30Day(); + io.to(userID).emit("uptime", monitorID, 720, data30d.uptime); + + // Send 1-year uptime + let data1y = await uptimeCalculator.get1Year(); + io.to(userID).emit("uptime", monitorID, "1y", data1y.uptime); + + // Send Cert Info await Monitor.sendCertInfo(io, monitorID, userID); } else { log.debug("monitor", "No clients in the room, no need to send stats"); } } - /** - * Send the average ping to user - * @param {number} duration Hours - */ - static async sendAvgPing(duration, io, monitorID, userID) { - const timeLogger = new TimeLogger(); - - let avgPing = parseInt(await R.getCell(` - SELECT AVG(ping) - FROM heartbeat - WHERE time > DATETIME('now', ? || ' hours') - AND ping IS NOT NULL - AND monitor_id = ? `, [ - -duration, - monitorID, - ])); - - timeLogger.print(`[Monitor: ${monitorID}] avgPing`); - - io.to(userID).emit("avgPing", monitorID, avgPing); - } - /** * Send certificate information to client * @param {Server} io Socket server instance * @param {number} monitorID ID of monitor to send * @param {number} userID ID of user to send to + * @returns {void} */ static async sendCertInfo(io, monitorID, userID) { let tlsInfo = await R.findOne("monitor_tls_info", "monitor_id = ?", [ @@ -1236,98 +1240,6 @@ class Monitor extends BeanModel { } } - /** - * Uptime with calculation - * Calculation based on: - * https://www.uptrends.com/support/kb/reporting/calculation-of-uptime-and-downtime - * @param {number} duration Hours - * @param {number} monitorID ID of monitor to calculate - */ - static async calcUptime(duration, monitorID, forceNoCache = false) { - - if (!forceNoCache) { - let cachedUptime = UptimeCacheList.getUptime(monitorID, duration); - if (cachedUptime != null) { - return cachedUptime; - } - } - - const timeLogger = new TimeLogger(); - - const startTime = R.isoDateTime(dayjs.utc().subtract(duration, "hour")); - - // Handle if heartbeat duration longer than the target duration - // e.g. If the last beat's duration is bigger that the 24hrs window, it will use the duration between the (beat time - window margin) (THEN case in SQL) - let result = await R.getRow(` - SELECT - -- SUM all duration, also trim off the beat out of time window - SUM( - CASE - WHEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400 < duration - THEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400 - ELSE duration - END - ) AS total_duration, - - -- SUM all uptime duration, also trim off the beat out of time window - SUM( - CASE - WHEN (status = 1 OR status = 3) - THEN - CASE - WHEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400 < duration - THEN (JULIANDAY(\`time\`) - JULIANDAY(?)) * 86400 - ELSE duration - END - END - ) AS uptime_duration - FROM heartbeat - WHERE time > ? - AND monitor_id = ? - `, [ - startTime, startTime, startTime, startTime, startTime, - monitorID, - ]); - - timeLogger.print(`[Monitor: ${monitorID}][${duration}] sendUptime`); - - let totalDuration = result.total_duration; - let uptimeDuration = result.uptime_duration; - let uptime = 0; - - if (totalDuration > 0) { - uptime = uptimeDuration / totalDuration; - if (uptime < 0) { - uptime = 0; - } - - } else { - // Handle new monitor with only one beat, because the beat's duration = 0 - let status = parseInt(await R.getCell("SELECT `status` FROM heartbeat WHERE monitor_id = ?", [ monitorID ])); - - if (status === UP) { - uptime = 1; - } - } - - // Cache - UptimeCacheList.addUptime(monitorID, duration, uptime); - - return uptime; - } - - /** - * Send Uptime - * @param {number} duration Hours - * @param {Server} io Socket server instance - * @param {number} monitorID ID of monitor to send - * @param {number} userID ID of user to send to - */ - static async sendUptime(duration, io, monitorID, userID) { - const uptime = await this.calcUptime(duration, monitorID); - io.to(userID).emit("uptime", monitorID, duration, uptime); - } - /** * Has status of monitor changed since last beat? * @param {boolean} isFirstBeat Is this the first beat of this monitor? @@ -1396,6 +1308,7 @@ class Monitor extends BeanModel { * @param {boolean} isFirstBeat Is this beat the first of this monitor? * @param {Monitor} monitor The monitor to send a notificaton about * @param {Bean} bean Status information about monitor + * @returns {void} */ static async sendNotification(isFirstBeat, monitor, bean) { if (!isFirstBeat || bean.status === DOWN) { @@ -1413,7 +1326,10 @@ class Monitor extends BeanModel { for (let notification of notificationList) { try { const heartbeatJSON = bean.toJSON(); - + const monitorData = [{ id: monitor.id, + active: monitor.active + }]; + const preloadData = await Monitor.preparePreloadData(monitorData); // Prevent if the msg is undefined, notifications such as Discord cannot send out. if (!heartbeatJSON["msg"]) { heartbeatJSON["msg"] = "N/A"; @@ -1424,7 +1340,7 @@ class Monitor extends BeanModel { heartbeatJSON["timezoneOffset"] = UptimeKumaServer.getInstance().getTimezoneOffset(); heartbeatJSON["localDateTime"] = dayjs.utc(heartbeatJSON["time"]).tz(heartbeatJSON["timezone"]).format(SQL_DATETIME_FORMAT); - await Notification.send(JSON.parse(notification.config), msg, await monitor.toJSON(false), heartbeatJSON); + await Notification.send(JSON.parse(notification.config), msg, monitor.toJSON(preloadData, false), heartbeatJSON); } catch (e) { log.error("monitor", "Cannot send notification to " + notification.name); log.error("monitor", e); @@ -1436,7 +1352,7 @@ class Monitor extends BeanModel { /** * Get list of notification providers for a given monitor * @param {Monitor} monitor Monitor to get notification providers for - * @returns {Promise[]>} + * @returns {Promise[]>} List of notifications */ static async getNotificationList(monitor) { let notificationList = await R.getAll("SELECT notification.* FROM notification, monitor_notification WHERE monitor_id = ? AND monitor_notification.notification_id = notification.id ", [ @@ -1447,7 +1363,8 @@ class Monitor extends BeanModel { /** * checks certificate chain for expiring certificates - * @param {Object} tlsInfoObject Information about certificate + * @param {object} tlsInfoObject Information about certificate + * @returns {void} */ async checkCertExpiryNotifications(tlsInfoObject) { if (tlsInfoObject && tlsInfoObject.certInfo && tlsInfoObject.certInfo.daysRemaining) { @@ -1462,7 +1379,7 @@ class Monitor extends BeanModel { let notifyDays = await setting("tlsExpiryNotifyDays"); if (notifyDays == null || !Array.isArray(notifyDays)) { // Reset Default - setSetting("tlsExpiryNotifyDays", [ 7, 14, 21 ], "general"); + await setSetting("tlsExpiryNotifyDays", [ 7, 14, 21 ], "general"); notifyDays = [ 7, 14, 21 ]; } @@ -1537,13 +1454,10 @@ class Monitor extends BeanModel { /** * Get the status of the previous heartbeat * @param {number} monitorID ID of monitor to check - * @returns {Promise>} + * @returns {Promise>} Previous heartbeat */ static async getPreviousHeartbeat(monitorID) { - return await R.getRow(` - SELECT ping, status, time FROM heartbeat - WHERE id = (select MAX(id) from heartbeat where monitor_id = ?) - `, [ + return await R.findOne("heartbeat", " id = (select MAX(id) from heartbeat where monitor_id = ?)", [ monitorID ]); } @@ -1551,7 +1465,7 @@ class Monitor extends BeanModel { /** * Check if monitor is under maintenance * @param {number} monitorID ID of monitor to check - * @returns {Promise} + * @returns {Promise} Is the monitor under maintenance */ static async isUnderMaintenance(monitorID) { const maintenanceIDList = await R.getCol(` @@ -1574,7 +1488,11 @@ class Monitor extends BeanModel { return false; } - /** Make sure monitor interval is between bounds */ + /** + * Make sure monitor interval is between bounds + * @returns {void} + * @throws Interval is outside of range + */ validate() { if (this.interval > MAX_INTERVAL_SECOND) { throw new Error(`Interval cannot be more than ${MAX_INTERVAL_SECOND} seconds`); @@ -1584,10 +1502,114 @@ class Monitor extends BeanModel { } } + /** + * Gets monitor notification of multiple monitor + * @param {Array} monitorIDs IDs of monitor to get + * @returns {Promise>} object + */ + static async getMonitorNotification(monitorIDs) { + return await R.getAll(` + SELECT monitor_notification.monitor_id, monitor_notification.notification_id + FROM monitor_notification + WHERE monitor_notification.monitor_id IN (${monitorIDs.map((_) => "?").join(",")}) + `, monitorIDs); + } + + /** + * Gets monitor tags of multiple monitor + * @param {Array} monitorIDs IDs of monitor to get + * @returns {Promise>} object + */ + static async getMonitorTag(monitorIDs) { + return await R.getAll(` + SELECT monitor_tag.monitor_id, monitor_tag.tag_id, monitor_tag.value, tag.name, tag.color + FROM monitor_tag + JOIN tag ON monitor_tag.tag_id = tag.id + WHERE monitor_tag.monitor_id IN (${monitorIDs.map((_) => "?").join(",")}) + `, monitorIDs); + } + + /** + * prepare preloaded data for efficient access + * @param {Array} monitorData IDs & active field of monitor to get + * @returns {Promise>} object + */ + static async preparePreloadData(monitorData) { + + const notificationsMap = new Map(); + const tagsMap = new Map(); + const maintenanceStatusMap = new Map(); + const childrenIDsMap = new Map(); + const activeStatusMap = new Map(); + const forceInactiveMap = new Map(); + const pathsMap = new Map(); + + if (monitorData.length > 0) { + const monitorIDs = monitorData.map(monitor => monitor.id); + const notifications = await Monitor.getMonitorNotification(monitorIDs); + const tags = await Monitor.getMonitorTag(monitorIDs); + const maintenanceStatuses = await Promise.all(monitorData.map(monitor => Monitor.isUnderMaintenance(monitor.id))); + const childrenIDs = await Promise.all(monitorData.map(monitor => Monitor.getAllChildrenIDs(monitor.id))); + const activeStatuses = await Promise.all(monitorData.map(monitor => Monitor.isActive(monitor.id, monitor.active))); + const forceInactiveStatuses = await Promise.all(monitorData.map(monitor => Monitor.isParentActive(monitor.id))); + const paths = await Promise.all(monitorData.map(monitor => Monitor.getAllPath(monitor.id, monitor.name))); + + notifications.forEach(row => { + if (!notificationsMap.has(row.monitor_id)) { + notificationsMap.set(row.monitor_id, {}); + } + notificationsMap.get(row.monitor_id)[row.notification_id] = true; + }); + + tags.forEach(row => { + if (!tagsMap.has(row.monitor_id)) { + tagsMap.set(row.monitor_id, []); + } + tagsMap.get(row.monitor_id).push({ + tag_id: row.tag_id, + monitor_id: row.monitor_id, + value: row.value, + name: row.name, + color: row.color + }); + }); + + monitorData.forEach((monitor, index) => { + maintenanceStatusMap.set(monitor.id, maintenanceStatuses[index]); + }); + + monitorData.forEach((monitor, index) => { + childrenIDsMap.set(monitor.id, childrenIDs[index]); + }); + + monitorData.forEach((monitor, index) => { + activeStatusMap.set(monitor.id, activeStatuses[index]); + }); + + monitorData.forEach((monitor, index) => { + forceInactiveMap.set(monitor.id, !forceInactiveStatuses[index]); + }); + + monitorData.forEach((monitor, index) => { + pathsMap.set(monitor.id, paths[index]); + }); + } + + return { + notifications: notificationsMap, + tags: tagsMap, + maintenanceStatus: maintenanceStatusMap, + childrenIDs: childrenIDsMap, + activeStatus: activeStatusMap, + forceInactive: forceInactiveMap, + paths: pathsMap, + }; + } + /** * Gets Parent of the monitor * @param {number} monitorID ID of monitor to get - * @returns {Promise>} + * @returns {Promise>} Parent */ static async getParent(monitorID) { return await R.getRow(` @@ -1603,7 +1625,7 @@ class Monitor extends BeanModel { /** * Gets all Children of the monitor * @param {number} monitorID ID of monitor to get - * @returns {Promise>} + * @returns {Promise>} Children */ static async getChildren(monitorID) { return await R.getAll(` @@ -1615,19 +1637,21 @@ class Monitor extends BeanModel { } /** - * Gets Full Path-Name (Groups and Name) - * @returns {Promise} + * Gets the full path + * @param {number} monitorID ID of the monitor to get + * @param {string} name of the monitor to get + * @returns {Promise} Full path (includes groups and the name) of the monitor */ - async getPathName() { - let path = this.name; + static async getAllPath(monitorID, name) { + const path = [ name ]; if (this.parent === null) { return path; } - let parent = await Monitor.getParent(this.id); + let parent = await Monitor.getParent(monitorID); while (parent !== null) { - path = `${parent.name} / ${path}`; + path.unshift(parent.name); parent = await Monitor.getParent(parent.id); } @@ -1636,8 +1660,8 @@ class Monitor extends BeanModel { /** * Gets recursive all child ids - * @param {number} monitorID ID of the monitor to get - * @returns {Promise} + * @param {number} monitorID ID of the monitor to get + * @returns {Promise} IDs of all children */ static async getAllChildrenIDs(monitorID) { const childs = await Monitor.getChildren(monitorID); @@ -1657,7 +1681,7 @@ class Monitor extends BeanModel { } /** - * Unlinks all children of the the group monitor + * Unlinks all children of the group monitor * @param {number} groupID ID of group to remove children of * @returns {Promise} */ @@ -1668,10 +1692,10 @@ class Monitor extends BeanModel { } /** - * Checks recursive if parent (ancestors) are active - * @param {number} monitorID ID of the monitor to get - * @returns {Promise} - */ + * Checks recursive if parent (ancestors) are active + * @param {number} monitorID ID of the monitor to get + * @returns {Promise} Is the parent monitor active? + */ static async isParentActive(monitorID) { const parent = await Monitor.getParent(monitorID); @@ -1683,9 +1707,25 @@ class Monitor extends BeanModel { return parent.active && parentActive; } + /** + * Obtains a new Oidc Token + * @returns {Promise} OAuthProvider client + */ + async makeOidcTokenClientCredentialsRequest() { + log.debug("monitor", `[${this.name}] The oauth access-token undefined or expired. Requesting a new token`); + const oAuthAccessToken = await getOidcTokenClientCredentials(this.oauth_token_url, this.oauth_client_id, this.oauth_client_secret, this.oauth_scopes, this.oauth_auth_method); + if (this.oauthAccessToken?.expires_at) { + log.debug("monitor", `[${this.name}] Obtained oauth access-token. Expires at ${new Date(this.oauthAccessToken?.expires_at * 1000)}`); + } else { + log.debug("monitor", `[${this.name}] Obtained oauth access-token. Time until expiry was not provided`); + } + + return oAuthAccessToken; + } + /** * Store TLS certificate information and check for expiry - * @param {Object} tlsInfo Information about the TLS connection + * @param {object} tlsInfo Information about the TLS connection * @returns {Promise} */ async handleTlsInfo(tlsInfo) { diff --git a/server/model/proxy.js b/server/model/proxy.js index 4517b11bfc..ec78403d46 100644 --- a/server/model/proxy.js +++ b/server/model/proxy.js @@ -3,7 +3,7 @@ const { BeanModel } = require("redbean-node/dist/bean-model"); class Proxy extends BeanModel { /** * Return an object that ready to parse to JSON - * @returns {Object} + * @returns {object} Object ready to parse */ toJSON() { return { diff --git a/server/model/remote_browser.js b/server/model/remote_browser.js new file mode 100644 index 0000000000..49299ad4fa --- /dev/null +++ b/server/model/remote_browser.js @@ -0,0 +1,17 @@ +const { BeanModel } = require("redbean-node/dist/bean-model"); + +class RemoteBrowser extends BeanModel { + /** + * Returns an object that ready to parse to JSON + * @returns {object} Object ready to parse + */ + toJSON() { + return { + id: this.id, + url: this.url, + name: this.name, + }; + } +} + +module.exports = RemoteBrowser; diff --git a/server/model/status_page.js b/server/model/status_page.js index e168acf2f4..38f548ebba 100644 --- a/server/model/status_page.js +++ b/server/model/status_page.js @@ -4,6 +4,11 @@ const cheerio = require("cheerio"); const { UptimeKumaServer } = require("../uptime-kuma-server"); const jsesc = require("jsesc"); const googleAnalytics = require("../google-analytics"); +const { marked } = require("marked"); +const { Feed } = require("feed"); +const config = require("../config"); + +const { STATUS_PAGE_ALL_DOWN, STATUS_PAGE_ALL_UP, STATUS_PAGE_MAINTENANCE, STATUS_PAGE_PARTIAL_DOWN, UP, MAINTENANCE, DOWN } = require("../../src/util"); class StatusPage extends BeanModel { @@ -14,12 +19,37 @@ class StatusPage extends BeanModel { static domainMappingList = { }; /** - * - * @param {Response} response - * @param {string} indexHTML - * @param {string} slug + * Handle responses to RSS pages + * @param {Response} response Response object + * @param {string} slug Status page slug + * @returns {Promise} + */ + static async handleStatusPageRSSResponse(response, slug) { + let statusPage = await R.findOne("status_page", " slug = ? ", [ + slug + ]); + + if (statusPage) { + response.send(await StatusPage.renderRSS(statusPage, slug)); + } else { + response.status(404).send(UptimeKumaServer.getInstance().indexHTML); + } + } + + /** + * Handle responses to status page + * @param {Response} response Response object + * @param {string} indexHTML HTML to render + * @param {string} slug Status page slug + * @returns {Promise} */ static async handleStatusPageResponse(response, indexHTML, slug) { + // Handle url with trailing slash (http://localhost:3001/status/) + // The slug comes from the route "/status/:slug". If the slug is empty, express converts it to "index.html" + if (slug === "index.html") { + slug = "default"; + } + let statusPage = await R.findOne("status_page", " slug = ? ", [ slug ]); @@ -31,14 +61,51 @@ class StatusPage extends BeanModel { } } + /** + * SSR for RSS feed + * @param {statusPage} statusPage object + * @param {slug} slug from router + * @returns {Promise} the rendered html + */ + static async renderRSS(statusPage, slug) { + const { heartbeats, statusDescription } = await StatusPage.getRSSPageData(statusPage); + + let proto = config.isSSL ? "https" : "http"; + let host = `${proto}://${config.hostname || "localhost"}:${config.port}/status/${slug}`; + + const feed = new Feed({ + title: "uptime kuma rss feed", + description: `current status: ${statusDescription}`, + link: host, + language: "en", // optional, used only in RSS 2.0, possible values: http://www.w3.org/TR/REC-html40/struct/dirlang.html#langcodes + updated: new Date(), // optional, default = today + }); + + heartbeats.forEach(heartbeat => { + feed.addItem({ + title: `${heartbeat.name} is down`, + description: `${heartbeat.name} has been down since ${heartbeat.time}`, + id: heartbeat.monitorID, + date: new Date(heartbeat.time), + }); + }); + + return feed.rss2(); + } + /** * SSR for status pages - * @param {string} indexHTML - * @param {StatusPage} statusPage + * @param {string} indexHTML HTML page to render + * @param {StatusPage} statusPage Status page populate HTML with + * @returns {Promise} the rendered html */ static async renderHTML(indexHTML, statusPage) { const $ = cheerio.load(indexHTML); - const description155 = statusPage.description?.substring(0, 155) ?? ""; + + const description155 = marked(statusPage.description ?? "") + .replace(/<[^>]+>/gm, "") + .trim() + .substring(0, 155); $("title").text(statusPage.title); $("meta[name=description]").attr("content", description155); @@ -85,9 +152,113 @@ class StatusPage extends BeanModel { return $.root().html(); } + /** + * @param {heartbeats} heartbeats from getRSSPageData + * @returns {number} status_page constant from util.ts + */ + static overallStatus(heartbeats) { + if (heartbeats.length === 0) { + return -1; + } + + let status = STATUS_PAGE_ALL_UP; + let hasUp = false; + + for (let beat of heartbeats) { + if (beat.status === MAINTENANCE) { + return STATUS_PAGE_MAINTENANCE; + } else if (beat.status === UP) { + hasUp = true; + } else { + status = STATUS_PAGE_PARTIAL_DOWN; + } + } + + if (! hasUp) { + status = STATUS_PAGE_ALL_DOWN; + } + + return status; + } + + /** + * @param {number} status from overallStatus + * @returns {string} description + */ + static getStatusDescription(status) { + if (status === -1) { + return "No Services"; + } + + if (status === STATUS_PAGE_ALL_UP) { + return "All Systems Operational"; + } + + if (status === STATUS_PAGE_PARTIAL_DOWN) { + return "Partially Degraded Service"; + } + + if (status === STATUS_PAGE_ALL_DOWN) { + return "Degraded Service"; + } + + // TODO: show the real maintenance information: title, description, time + if (status === MAINTENANCE) { + return "Under maintenance"; + } + + return "?"; + } + + /** + * Get all data required for RSS + * @param {StatusPage} statusPage Status page to get data for + * @returns {object} Status page data + */ + static async getRSSPageData(statusPage) { + // get all heartbeats that correspond to this statusPage + const config = await statusPage.toPublicJSON(); + + // Public Group List + const showTags = !!statusPage.show_tags; + + const list = await R.find("group", " public = 1 AND status_page_id = ? ORDER BY weight ", [ + statusPage.id + ]); + + let heartbeats = []; + + for (let groupBean of list) { + let monitorGroup = await groupBean.toPublicJSON(showTags, config?.showCertificateExpiry); + for (const monitor of monitorGroup.monitorList) { + const heartbeat = await R.findOne("heartbeat", "monitor_id = ? ORDER BY time DESC", [ monitor.id ]); + if (heartbeat) { + heartbeats.push({ + ...monitor, + status: heartbeat.status, + time: heartbeat.time + }); + } + } + } + + // calculate RSS feed description + let status = StatusPage.overallStatus(heartbeats); + let statusDescription = StatusPage.getStatusDescription(status); + + // keep only DOWN heartbeats in the RSS feed + heartbeats = heartbeats.filter(heartbeat => heartbeat.status === DOWN); + + return { + heartbeats, + statusDescription + }; + } + /** * Get all status page data in one call - * @param {StatusPage} statusPage + * @param {StatusPage} statusPage Status page to get data for + * @returns {object} Status page data */ static async getStatusPageData(statusPage) { const config = await statusPage.toPublicJSON(); @@ -142,7 +313,7 @@ class StatusPage extends BeanModel { * Send status page list to client * @param {Server} io io Socket server instance * @param {Socket} socket Socket.io instance - * @returns {Promise} + * @returns {Promise} Status page list */ static async sendStatusPageList(io, socket) { let result = {}; @@ -159,7 +330,7 @@ class StatusPage extends BeanModel { /** * Update list of domain names - * @param {string[]} domainNameList + * @param {string[]} domainNameList List of status page domains * @returns {Promise} */ async updateDomainNameList(domainNameList) { @@ -203,7 +374,7 @@ class StatusPage extends BeanModel { /** * Get list of domain names - * @returns {Object[]} + * @returns {object[]} List of status page domains */ getDomainNameList() { let domainList = []; @@ -219,7 +390,7 @@ class StatusPage extends BeanModel { /** * Return an object that ready to parse to JSON - * @returns {Object} + * @returns {object} Object ready to parse */ async toJSON() { return { @@ -229,6 +400,7 @@ class StatusPage extends BeanModel { description: this.description, icon: this.getIcon(), theme: this.theme, + autoRefreshInterval: this.autoRefreshInterval, published: !!this.published, showTags: !!this.show_tags, domainNameList: this.getDomainNameList(), @@ -243,7 +415,7 @@ class StatusPage extends BeanModel { /** * Return an object that ready to parse to JSON for public * Only show necessary data to public - * @returns {Object} + * @returns {object} Object ready to parse */ async toPublicJSON() { return { @@ -251,6 +423,7 @@ class StatusPage extends BeanModel { title: this.title, description: this.description, icon: this.getIcon(), + autoRefreshInterval: this.autoRefreshInterval, theme: this.theme, published: !!this.published, showTags: !!this.show_tags, @@ -264,7 +437,8 @@ class StatusPage extends BeanModel { /** * Convert slug to status page ID - * @param {string} slug + * @param {string} slug Status page slug + * @returns {Promise} ID of status page */ static async slugToID(slug) { return await R.getCell("SELECT id FROM status_page WHERE slug = ? ", [ @@ -274,7 +448,7 @@ class StatusPage extends BeanModel { /** * Get path to the icon for the page - * @returns {string} + * @returns {string} Path */ getIcon() { if (!this.icon) { @@ -287,7 +461,7 @@ class StatusPage extends BeanModel { /** * Get list of maintenances * @param {number} statusPageId ID of status page to get maintenance for - * @returns {Object} Object representing maintenances sanitized for public + * @returns {object} Object representing maintenances sanitized for public */ static async getMaintenanceList(statusPageId) { try { diff --git a/server/model/tag.js b/server/model/tag.js index b31eb86825..bc8a4db199 100644 --- a/server/model/tag.js +++ b/server/model/tag.js @@ -4,7 +4,7 @@ class Tag extends BeanModel { /** * Return an object that ready to parse to JSON - * @returns {Object} + * @returns {object} Object ready to parse */ toJSON() { return { diff --git a/server/model/user.js b/server/model/user.js index 32a5a9613f..329402ff5d 100644 --- a/server/model/user.js +++ b/server/model/user.js @@ -9,7 +9,7 @@ class User extends BeanModel { * Reset user password * Fix #1510, as in the context reset-password.js, there is no auto model mapping. Call this static function instead. * @param {number} userID ID of user to update - * @param {string} newPassword + * @param {string} newPassword Users new password * @returns {Promise} */ static async resetPassword(userID, newPassword) { @@ -21,19 +21,25 @@ class User extends BeanModel { /** * Reset this users password - * @param {string} newPassword + * @param {string} newPassword Users new password * @returns {Promise} */ async resetPassword(newPassword) { - await User.resetPassword(this.id, newPassword); - this.password = newPassword; + const hashedPassword = passwordHash.generate(newPassword); + + await R.exec("UPDATE `user` SET password = ? WHERE id = ? ", [ + hashedPassword, + this.id + ]); + + this.password = hashedPassword; } /** * Create a new JWT for a user - * @param {User} user - * @param {string} jwtSecret - * @return {string} + * @param {User} user The User to create a JsonWebToken for + * @param {string} jwtSecret The key used to sign the JsonWebToken + * @returns {string} the JsonWebToken as a string */ static createJWT(user, jwtSecret) { return jwt.sign({ diff --git a/server/modules/axios-ntlm/LICENSE b/server/modules/axios-ntlm/LICENSE new file mode 100644 index 0000000000..1744ee42ce --- /dev/null +++ b/server/modules/axios-ntlm/LICENSE @@ -0,0 +1,21 @@ +MIT License + +Copyright (c) 2021 CatButtes + +Permission is hereby granted, free of charge, to any person obtaining a copy +of this software and associated documentation files (the "Software"), to deal +in the Software without restriction, including without limitation the rights +to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom the Software is +furnished to do so, subject to the following conditions: + +The above copyright notice and this permission notice shall be included in all +copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +SOFTWARE. diff --git a/server/modules/axios-ntlm/lib/flags.js b/server/modules/axios-ntlm/lib/flags.js new file mode 100644 index 0000000000..c16028cade --- /dev/null +++ b/server/modules/axios-ntlm/lib/flags.js @@ -0,0 +1,77 @@ +'use strict'; +// Original file https://raw.githubusercontent.com/elasticio/node-ntlm-client/master/lib/flags.js +module.exports.NTLMFLAG_NEGOTIATE_UNICODE = 1 << 0; +/* Indicates that Unicode strings are supported for use in security buffer + data. */ +module.exports.NTLMFLAG_NEGOTIATE_OEM = 1 << 1; +/* Indicates that OEM strings are supported for use in security buffer data. */ +module.exports.NTLMFLAG_REQUEST_TARGET = 1 << 2; +/* Requests that the server's authentication realm be included in the Type 2 + message. */ +/* unknown (1<<3) */ +module.exports.NTLMFLAG_NEGOTIATE_SIGN = 1 << 4; +/* Specifies that authenticated communication between the client and server + should carry a digital signature (message integrity). */ +module.exports.NTLMFLAG_NEGOTIATE_SEAL = 1 << 5; +/* Specifies that authenticated communication between the client and server + should be encrypted (message confidentiality). */ +module.exports.NTLMFLAG_NEGOTIATE_DATAGRAM_STYLE = 1 << 6; +/* Indicates that datagram authentication is being used. */ +module.exports.NTLMFLAG_NEGOTIATE_LM_KEY = 1 << 7; +/* Indicates that the LAN Manager session key should be used for signing and + sealing authenticated communications. */ +module.exports.NTLMFLAG_NEGOTIATE_NETWARE = 1 << 8; +/* unknown purpose */ +module.exports.NTLMFLAG_NEGOTIATE_NTLM_KEY = 1 << 9; +/* Indicates that NTLM authentication is being used. */ +/* unknown (1<<10) */ +module.exports.NTLMFLAG_NEGOTIATE_ANONYMOUS = 1 << 11; +/* Sent by the client in the Type 3 message to indicate that an anonymous + context has been established. This also affects the response fields. */ +module.exports.NTLMFLAG_NEGOTIATE_DOMAIN_SUPPLIED = 1 << 12; +/* Sent by the client in the Type 1 message to indicate that a desired + authentication realm is included in the message. */ +module.exports.NTLMFLAG_NEGOTIATE_WORKSTATION_SUPPLIED = 1 << 13; +/* Sent by the client in the Type 1 message to indicate that the client + workstation's name is included in the message. */ +module.exports.NTLMFLAG_NEGOTIATE_LOCAL_CALL = 1 << 14; +/* Sent by the server to indicate that the server and client are on the same + machine. Implies that the client may use a pre-established local security + context rather than responding to the challenge. */ +module.exports.NTLMFLAG_NEGOTIATE_ALWAYS_SIGN = 1 << 15; +/* Indicates that authenticated communication between the client and server + should be signed with a "dummy" signature. */ +module.exports.NTLMFLAG_TARGET_TYPE_DOMAIN = 1 << 16; +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a domain. */ +module.exports.NTLMFLAG_TARGET_TYPE_SERVER = 1 << 17; +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a server. */ +module.exports.NTLMFLAG_TARGET_TYPE_SHARE = 1 << 18; +/* Sent by the server in the Type 2 message to indicate that the target + authentication realm is a share. Presumably, this is for share-level + authentication. Usage is unclear. */ +module.exports.NTLMFLAG_NEGOTIATE_NTLM2_KEY = 1 << 19; +/* Indicates that the NTLM2 signing and sealing scheme should be used for + protecting authenticated communications. */ +module.exports.NTLMFLAG_REQUEST_INIT_RESPONSE = 1 << 20; +/* unknown purpose */ +module.exports.NTLMFLAG_REQUEST_ACCEPT_RESPONSE = 1 << 21; +/* unknown purpose */ +module.exports.NTLMFLAG_REQUEST_NONNT_SESSION_KEY = 1 << 22; +/* unknown purpose */ +module.exports.NTLMFLAG_NEGOTIATE_TARGET_INFO = 1 << 23; +/* Sent by the server in the Type 2 message to indicate that it is including a + Target Information block in the message. */ +/* unknown (1<24) */ +/* unknown (1<25) */ +/* unknown (1<26) */ +/* unknown (1<27) */ +/* unknown (1<28) */ +module.exports.NTLMFLAG_NEGOTIATE_128 = 1 << 29; +/* Indicates that 128-bit encryption is supported. */ +module.exports.NTLMFLAG_NEGOTIATE_KEY_EXCHANGE = 1 << 30; +/* Indicates that the client will provide an encrypted master key in + the "Session Key" field of the Type 3 message. */ +module.exports.NTLMFLAG_NEGOTIATE_56 = 1 << 31; +//# sourceMappingURL=flags.js.map \ No newline at end of file diff --git a/server/modules/axios-ntlm/lib/hash.js b/server/modules/axios-ntlm/lib/hash.js new file mode 100644 index 0000000000..4e5aa26b43 --- /dev/null +++ b/server/modules/axios-ntlm/lib/hash.js @@ -0,0 +1,122 @@ +'use strict'; +// Original source at https://github.com/elasticio/node-ntlm-client/blob/master/lib/hash.js +var crypto = require('crypto'); +function createLMResponse(challenge, lmhash) { + var buf = new Buffer.alloc(24), pwBuffer = new Buffer.alloc(21).fill(0); + lmhash.copy(pwBuffer); + calculateDES(pwBuffer.slice(0, 7), challenge).copy(buf); + calculateDES(pwBuffer.slice(7, 14), challenge).copy(buf, 8); + calculateDES(pwBuffer.slice(14), challenge).copy(buf, 16); + return buf; +} +function createLMHash(password) { + var buf = new Buffer.alloc(16), pwBuffer = new Buffer.alloc(14), magicKey = new Buffer.from('KGS!@#$%', 'ascii'); + if (password.length > 14) { + buf.fill(0); + return buf; + } + pwBuffer.fill(0); + pwBuffer.write(password.toUpperCase(), 0, 'ascii'); + return Buffer.concat([ + calculateDES(pwBuffer.slice(0, 7), magicKey), + calculateDES(pwBuffer.slice(7), magicKey) + ]); +} +function calculateDES(key, message) { + var desKey = new Buffer.alloc(8); + desKey[0] = key[0] & 0xFE; + desKey[1] = ((key[0] << 7) & 0xFF) | (key[1] >> 1); + desKey[2] = ((key[1] << 6) & 0xFF) | (key[2] >> 2); + desKey[3] = ((key[2] << 5) & 0xFF) | (key[3] >> 3); + desKey[4] = ((key[3] << 4) & 0xFF) | (key[4] >> 4); + desKey[5] = ((key[4] << 3) & 0xFF) | (key[5] >> 5); + desKey[6] = ((key[5] << 2) & 0xFF) | (key[6] >> 6); + desKey[7] = (key[6] << 1) & 0xFF; + for (var i = 0; i < 8; i++) { + var parity = 0; + for (var j = 1; j < 8; j++) { + parity += (desKey[i] >> j) % 2; + } + desKey[i] |= (parity % 2) === 0 ? 1 : 0; + } + var des = crypto.createCipheriv('DES-ECB', desKey, ''); + return des.update(message); +} +function createNTLMResponse(challenge, ntlmhash) { + var buf = new Buffer.alloc(24), ntlmBuffer = new Buffer.alloc(21).fill(0); + ntlmhash.copy(ntlmBuffer); + calculateDES(ntlmBuffer.slice(0, 7), challenge).copy(buf); + calculateDES(ntlmBuffer.slice(7, 14), challenge).copy(buf, 8); + calculateDES(ntlmBuffer.slice(14), challenge).copy(buf, 16); + return buf; +} +function createNTLMHash(password) { + var md4sum = crypto.createHash('md4'); + md4sum.update(new Buffer.from(password, 'ucs2')); + return md4sum.digest(); +} +function createNTLMv2Hash(ntlmhash, username, authTargetName) { + var hmac = crypto.createHmac('md5', ntlmhash); + hmac.update(new Buffer.from(username.toUpperCase() + authTargetName, 'ucs2')); + return hmac.digest(); +} +function createLMv2Response(type2message, username, ntlmhash, nonce, targetName) { + var buf = new Buffer.alloc(24), ntlm2hash = createNTLMv2Hash(ntlmhash, username, targetName), hmac = crypto.createHmac('md5', ntlm2hash); + //server challenge + type2message.challenge.copy(buf, 8); + //client nonce + buf.write(nonce || createPseudoRandomValue(16), 16, 'hex'); + //create hash + hmac.update(buf.slice(8)); + var hashedBuffer = hmac.digest(); + hashedBuffer.copy(buf); + return buf; +} +function createNTLMv2Response(type2message, username, ntlmhash, nonce, targetName) { + var buf = new Buffer.alloc(48 + type2message.targetInfo.buffer.length), ntlm2hash = createNTLMv2Hash(ntlmhash, username, targetName), hmac = crypto.createHmac('md5', ntlm2hash); + //the first 8 bytes are spare to store the hashed value before the blob + //server challenge + type2message.challenge.copy(buf, 8); + //blob signature + buf.writeUInt32BE(0x01010000, 16); + //reserved + buf.writeUInt32LE(0, 20); + //timestamp + //TODO: we are loosing precision here since js is not able to handle those large integers + // maybe think about a different solution here + // 11644473600000 = diff between 1970 and 1601 + var timestamp = ((Date.now() + 11644473600000) * 10000).toString(16); + var timestampLow = Number('0x' + timestamp.substring(Math.max(0, timestamp.length - 8))); + var timestampHigh = Number('0x' + timestamp.substring(0, Math.max(0, timestamp.length - 8))); + buf.writeUInt32LE(timestampLow, 24, false); + buf.writeUInt32LE(timestampHigh, 28, false); + //random client nonce + buf.write(nonce || createPseudoRandomValue(16), 32, 'hex'); + //zero + buf.writeUInt32LE(0, 40); + //complete target information block from type 2 message + type2message.targetInfo.buffer.copy(buf, 44); + //zero + buf.writeUInt32LE(0, 44 + type2message.targetInfo.buffer.length); + hmac.update(buf.slice(8)); + var hashedBuffer = hmac.digest(); + hashedBuffer.copy(buf); + return buf; +} +function createPseudoRandomValue(length) { + var str = ''; + while (str.length < length) { + str += Math.floor(Math.random() * 16).toString(16); + } + return str; +} +module.exports = { + createLMHash: createLMHash, + createNTLMHash: createNTLMHash, + createLMResponse: createLMResponse, + createNTLMResponse: createNTLMResponse, + createLMv2Response: createLMv2Response, + createNTLMv2Response: createNTLMv2Response, + createPseudoRandomValue: createPseudoRandomValue +}; +//# sourceMappingURL=hash.js.map \ No newline at end of file diff --git a/server/modules/axios-ntlm/lib/ntlm.js b/server/modules/axios-ntlm/lib/ntlm.js new file mode 100644 index 0000000000..54490c0a60 --- /dev/null +++ b/server/modules/axios-ntlm/lib/ntlm.js @@ -0,0 +1,220 @@ +'use strict'; +// Original file https://raw.githubusercontent.com/elasticio/node-ntlm-client/master/lib/ntlm.js +var os = require('os'), flags = require('./flags'), hash = require('./hash'); +var NTLMSIGNATURE = "NTLMSSP\0"; +function createType1Message(workstation, target) { + var dataPos = 32, pos = 0, buf = new Buffer.alloc(1024); + workstation = workstation === undefined ? os.hostname() : workstation; + target = target === undefined ? '' : target; + //signature + buf.write(NTLMSIGNATURE, pos, NTLMSIGNATURE.length, 'ascii'); + pos += NTLMSIGNATURE.length; + //message type + buf.writeUInt32LE(1, pos); + pos += 4; + //flags + buf.writeUInt32LE(flags.NTLMFLAG_NEGOTIATE_OEM | + flags.NTLMFLAG_REQUEST_TARGET | + flags.NTLMFLAG_NEGOTIATE_NTLM_KEY | + flags.NTLMFLAG_NEGOTIATE_NTLM2_KEY | + flags.NTLMFLAG_NEGOTIATE_ALWAYS_SIGN, pos); + pos += 4; + //domain security buffer + buf.writeUInt16LE(target.length, pos); + pos += 2; + buf.writeUInt16LE(target.length, pos); + pos += 2; + buf.writeUInt32LE(target.length === 0 ? 0 : dataPos, pos); + pos += 4; + if (target.length > 0) { + dataPos += buf.write(target, dataPos, 'ascii'); + } + //workstation security buffer + buf.writeUInt16LE(workstation.length, pos); + pos += 2; + buf.writeUInt16LE(workstation.length, pos); + pos += 2; + buf.writeUInt32LE(workstation.length === 0 ? 0 : dataPos, pos); + pos += 4; + if (workstation.length > 0) { + dataPos += buf.write(workstation, dataPos, 'ascii'); + } + return 'NTLM ' + buf.toString('base64', 0, dataPos); +} +function decodeType2Message(str) { + if (str === undefined) { + throw new Error('Invalid argument'); + } + //convenience + if (Object.prototype.toString.call(str) !== '[object String]') { + if (str.hasOwnProperty('headers') && str.headers.hasOwnProperty('www-authenticate')) { + str = str.headers['www-authenticate']; + } + else { + throw new Error('Invalid argument'); + } + } + var ntlmMatch = /^NTLM ([^,\s]+)/.exec(str); + if (ntlmMatch) { + str = ntlmMatch[1]; + } + var buf = new Buffer.from(str, 'base64'), obj = {}; + //check signature + if (buf.toString('ascii', 0, NTLMSIGNATURE.length) !== NTLMSIGNATURE) { + throw new Error('Invalid message signature: ' + str); + } + //check message type + if (buf.readUInt32LE(NTLMSIGNATURE.length) !== 2) { + throw new Error('Invalid message type (no type 2)'); + } + //read flags + obj.flags = buf.readUInt32LE(20); + obj.encoding = (obj.flags & flags.NTLMFLAG_NEGOTIATE_OEM) ? 'ascii' : 'ucs2'; + obj.version = (obj.flags & flags.NTLMFLAG_NEGOTIATE_NTLM2_KEY) ? 2 : 1; + obj.challenge = buf.slice(24, 32); + //read target name + obj.targetName = (function () { + var length = buf.readUInt16LE(12); + //skipping allocated space + var offset = buf.readUInt32LE(16); + if (length === 0) { + return ''; + } + if ((offset + length) > buf.length || offset < 32) { + throw new Error('Bad type 2 message'); + } + return buf.toString(obj.encoding, offset, offset + length); + })(); + //read target info + if (obj.flags & flags.NTLMFLAG_NEGOTIATE_TARGET_INFO) { + obj.targetInfo = (function () { + var info = {}; + var length = buf.readUInt16LE(40); + //skipping allocated space + var offset = buf.readUInt32LE(44); + var targetInfoBuffer = new Buffer.alloc(length); + buf.copy(targetInfoBuffer, 0, offset, offset + length); + if (length === 0) { + return info; + } + if ((offset + length) > buf.length || offset < 32) { + throw new Error('Bad type 2 message'); + } + var pos = offset; + while (pos < (offset + length)) { + var blockType = buf.readUInt16LE(pos); + pos += 2; + var blockLength = buf.readUInt16LE(pos); + pos += 2; + if (blockType === 0) { + //reached the terminator subblock + break; + } + var blockTypeStr = void 0; + switch (blockType) { + case 1: + blockTypeStr = 'SERVER'; + break; + case 2: + blockTypeStr = 'DOMAIN'; + break; + case 3: + blockTypeStr = 'FQDN'; + break; + case 4: + blockTypeStr = 'DNS'; + break; + case 5: + blockTypeStr = 'PARENT_DNS'; + break; + default: + blockTypeStr = ''; + break; + } + if (blockTypeStr) { + info[blockTypeStr] = buf.toString('ucs2', pos, pos + blockLength); + } + pos += blockLength; + } + return { + parsed: info, + buffer: targetInfoBuffer + }; + })(); + } + return obj; +} +function createType3Message(type2Message, username, password, workstation, target) { + var dataPos = 52, buf = new Buffer.alloc(1024); + if (workstation === undefined) { + workstation = os.hostname(); + } + if (target === undefined) { + target = type2Message.targetName; + } + //signature + buf.write(NTLMSIGNATURE, 0, NTLMSIGNATURE.length, 'ascii'); + //message type + buf.writeUInt32LE(3, 8); + if (type2Message.version === 2) { + dataPos = 64; + var ntlmHash = hash.createNTLMHash(password), nonce = hash.createPseudoRandomValue(16), lmv2 = hash.createLMv2Response(type2Message, username, ntlmHash, nonce, target), ntlmv2 = hash.createNTLMv2Response(type2Message, username, ntlmHash, nonce, target); + //lmv2 security buffer + buf.writeUInt16LE(lmv2.length, 12); + buf.writeUInt16LE(lmv2.length, 14); + buf.writeUInt32LE(dataPos, 16); + lmv2.copy(buf, dataPos); + dataPos += lmv2.length; + //ntlmv2 security buffer + buf.writeUInt16LE(ntlmv2.length, 20); + buf.writeUInt16LE(ntlmv2.length, 22); + buf.writeUInt32LE(dataPos, 24); + ntlmv2.copy(buf, dataPos); + dataPos += ntlmv2.length; + } + else { + var lmHash = hash.createLMHash(password), ntlmHash = hash.createNTLMHash(password), lm = hash.createLMResponse(type2Message.challenge, lmHash), ntlm = hash.createNTLMResponse(type2Message.challenge, ntlmHash); + //lm security buffer + buf.writeUInt16LE(lm.length, 12); + buf.writeUInt16LE(lm.length, 14); + buf.writeUInt32LE(dataPos, 16); + lm.copy(buf, dataPos); + dataPos += lm.length; + //ntlm security buffer + buf.writeUInt16LE(ntlm.length, 20); + buf.writeUInt16LE(ntlm.length, 22); + buf.writeUInt32LE(dataPos, 24); + ntlm.copy(buf, dataPos); + dataPos += ntlm.length; + } + //target name security buffer + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? target.length : target.length * 2, 28); + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? target.length : target.length * 2, 30); + buf.writeUInt32LE(dataPos, 32); + dataPos += buf.write(target, dataPos, type2Message.encoding); + //user name security buffer + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? username.length : username.length * 2, 36); + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? username.length : username.length * 2, 38); + buf.writeUInt32LE(dataPos, 40); + dataPos += buf.write(username, dataPos, type2Message.encoding); + //workstation name security buffer + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? workstation.length : workstation.length * 2, 44); + buf.writeUInt16LE(type2Message.encoding === 'ascii' ? workstation.length : workstation.length * 2, 46); + buf.writeUInt32LE(dataPos, 48); + dataPos += buf.write(workstation, dataPos, type2Message.encoding); + if (type2Message.version === 2) { + //session key security buffer + buf.writeUInt16LE(0, 52); + buf.writeUInt16LE(0, 54); + buf.writeUInt32LE(0, 56); + //flags + buf.writeUInt32LE(type2Message.flags, 60); + } + return 'NTLM ' + buf.toString('base64', 0, dataPos); +} +module.exports = { + createType1Message: createType1Message, + decodeType2Message: decodeType2Message, + createType3Message: createType3Message +}; +//# sourceMappingURL=ntlm.js.map \ No newline at end of file diff --git a/server/modules/axios-ntlm/lib/ntlmClient.js b/server/modules/axios-ntlm/lib/ntlmClient.js new file mode 100644 index 0000000000..682de5f9a3 --- /dev/null +++ b/server/modules/axios-ntlm/lib/ntlmClient.js @@ -0,0 +1,127 @@ +"use strict"; +var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + Object.defineProperty(o, k2, { enumerable: true, get: function() { return m[k]; } }); +}) : (function(o, m, k, k2) { + if (k2 === undefined) k2 = k; + o[k2] = m[k]; +})); +var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { + Object.defineProperty(o, "default", { enumerable: true, value: v }); +}) : function(o, v) { + o["default"] = v; +}); +var __importStar = (this && this.__importStar) || function (mod) { + if (mod && mod.__esModule) return mod; + var result = {}; + if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); + __setModuleDefault(result, mod); + return result; +}; +var __awaiter = (this && this.__awaiter) || function (thisArg, _arguments, P, generator) { + function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); } + return new (P || (P = Promise))(function (resolve, reject) { + function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } } + function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } } + function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); } + step((generator = generator.apply(thisArg, _arguments || [])).next()); + }); +}; +var __generator = (this && this.__generator) || function (thisArg, body) { + var _ = { label: 0, sent: function() { if (t[0] & 1) throw t[1]; return t[1]; }, trys: [], ops: [] }, f, y, t, g; + return g = { next: verb(0), "throw": verb(1), "return": verb(2) }, typeof Symbol === "function" && (g[Symbol.iterator] = function() { return this; }), g; + function verb(n) { return function (v) { return step([n, v]); }; } + function step(op) { + if (f) throw new TypeError("Generator is already executing."); + while (_) try { + if (f = 1, y && (t = op[0] & 2 ? y["return"] : op[0] ? y["throw"] || ((t = y["return"]) && t.call(y), 0) : y.next) && !(t = t.call(y, op[1])).done) return t; + if (y = 0, t) op = [op[0] & 2, t.value]; + switch (op[0]) { + case 0: case 1: t = op; break; + case 4: _.label++; return { value: op[1], done: false }; + case 5: _.label++; y = op[1]; op = [0]; continue; + case 7: op = _.ops.pop(); _.trys.pop(); continue; + default: + if (!(t = _.trys, t = t.length > 0 && t[t.length - 1]) && (op[0] === 6 || op[0] === 2)) { _ = 0; continue; } + if (op[0] === 3 && (!t || (op[1] > t[0] && op[1] < t[3]))) { _.label = op[1]; break; } + if (op[0] === 6 && _.label < t[1]) { _.label = t[1]; t = op; break; } + if (t && _.label < t[2]) { _.label = t[2]; _.ops.push(op); break; } + if (t[2]) _.ops.pop(); + _.trys.pop(); continue; + } + op = body.call(thisArg, _); + } catch (e) { op = [6, e]; y = 0; } finally { f = t = 0; } + if (op[0] & 5) throw op[1]; return { value: op[0] ? op[1] : void 0, done: true }; + } +}; +var __importDefault = (this && this.__importDefault) || function (mod) { + return (mod && mod.__esModule) ? mod : { "default": mod }; +}; +Object.defineProperty(exports, "__esModule", { value: true }); +exports.NtlmClient = void 0; +var axios_1 = __importDefault(require("axios")); +var ntlm = __importStar(require("./ntlm")); +var https = __importStar(require("https")); +var http = __importStar(require("http")); +var dev_null_1 = __importDefault(require("dev-null")); +/** +* @param credentials An NtlmCredentials object containing the username and password +* @param AxiosConfig The Axios config for the instance you wish to create +* +* @returns This function returns an axios instance configured to use the provided credentials +*/ +function NtlmClient(credentials, AxiosConfig) { + var _this = this; + var config = AxiosConfig !== null && AxiosConfig !== void 0 ? AxiosConfig : {}; + if (!config.httpAgent) { + config.httpAgent = new http.Agent({ keepAlive: true }); + } + if (!config.httpsAgent) { + config.httpsAgent = new https.Agent({ keepAlive: true }); + } + var client = axios_1.default.create(config); + client.interceptors.response.use(function (response) { + return response; + }, function (err) { return __awaiter(_this, void 0, void 0, function () { + var error, t1Msg, t2Msg, t3Msg, stream_1; + var _a; + return __generator(this, function (_b) { + switch (_b.label) { + case 0: + error = err.response; + if (!(error && error.status === 401 + && error.headers['www-authenticate'] + && error.headers['www-authenticate'].includes('NTLM'))) return [3 /*break*/, 3]; + // This length check is a hack because SharePoint is awkward and will + // include the Negotiate option when responding with the T2 message + // There is nore we could do to ensure we are processing correctly, + // but this is the easiest option for now + if (error.headers['www-authenticate'].length < 50) { + t1Msg = ntlm.createType1Message(credentials.workstation, credentials.domain); + error.config.headers["Authorization"] = t1Msg; + } + else { + t2Msg = ntlm.decodeType2Message((error.headers['www-authenticate'].match(/^NTLM\s+(.+?)(,|\s+|$)/) || [])[1]); + t3Msg = ntlm.createType3Message(t2Msg, credentials.username, credentials.password, credentials.workstation, credentials.domain); + error.config.headers["X-retry"] = "false"; + error.config.headers["Authorization"] = t3Msg; + } + if (!(error.config.responseType === "stream")) return [3 /*break*/, 2]; + stream_1 = (_a = err.response) === null || _a === void 0 ? void 0 : _a.data; + if (!(stream_1 && !stream_1.readableEnded)) return [3 /*break*/, 2]; + return [4 /*yield*/, new Promise(function (resolve) { + stream_1.pipe((0, dev_null_1.default)()); + stream_1.once('close', resolve); + })]; + case 1: + _b.sent(); + _b.label = 2; + case 2: return [2 /*return*/, client(error.config)]; + case 3: throw err; + } + }); + }); }); + return client; +} +exports.NtlmClient = NtlmClient; +//# sourceMappingURL=ntlmClient.js.map \ No newline at end of file diff --git a/server/monitor-conditions/evaluator.js b/server/monitor-conditions/evaluator.js new file mode 100644 index 0000000000..3860a33252 --- /dev/null +++ b/server/monitor-conditions/evaluator.js @@ -0,0 +1,71 @@ +const { ConditionExpressionGroup, ConditionExpression, LOGICAL } = require("./expression"); +const { operatorMap } = require("./operators"); + +/** + * @param {ConditionExpression} expression Expression to evaluate + * @param {object} context Context to evaluate against; These are values for variables in the expression + * @returns {boolean} Whether the expression evaluates true or false + * @throws {Error} + */ +function evaluateExpression(expression, context) { + /** + * @type {import("./operators").ConditionOperator|null} + */ + const operator = operatorMap.get(expression.operator) || null; + if (operator === null) { + throw new Error("Unexpected expression operator ID '" + expression.operator + "'. Expected one of [" + operatorMap.keys().join(",") + "]"); + } + + if (!Object.prototype.hasOwnProperty.call(context, expression.variable)) { + throw new Error("Variable missing in context: " + expression.variable); + } + + return operator.test(context[expression.variable], expression.value); +} + +/** + * @param {ConditionExpressionGroup} group Group of expressions to evaluate + * @param {object} context Context to evaluate against; These are values for variables in the expression + * @returns {boolean} Whether the group evaluates true or false + * @throws {Error} + */ +function evaluateExpressionGroup(group, context) { + if (!group.children.length) { + throw new Error("ConditionExpressionGroup must contain at least one child."); + } + + let result = null; + + for (const child of group.children) { + let childResult; + + if (child instanceof ConditionExpression) { + childResult = evaluateExpression(child, context); + } else if (child instanceof ConditionExpressionGroup) { + childResult = evaluateExpressionGroup(child, context); + } else { + throw new Error("Invalid child type in ConditionExpressionGroup. Expected ConditionExpression or ConditionExpressionGroup"); + } + + if (result === null) { + result = childResult; // Initialize result with the first child's result + } else if (child.andOr === LOGICAL.OR) { + result = result || childResult; + } else if (child.andOr === LOGICAL.AND) { + result = result && childResult; + } else { + throw new Error("Invalid logical operator in child of ConditionExpressionGroup. Expected 'and' or 'or'. Got '" + group.andOr + "'"); + } + } + + if (result === null) { + throw new Error("ConditionExpressionGroup did not result in a boolean."); + } + + return result; +} + +module.exports = { + evaluateExpression, + evaluateExpressionGroup, +}; diff --git a/server/monitor-conditions/expression.js b/server/monitor-conditions/expression.js new file mode 100644 index 0000000000..1e70369592 --- /dev/null +++ b/server/monitor-conditions/expression.js @@ -0,0 +1,111 @@ +/** + * @readonly + * @enum {string} + */ +const LOGICAL = { + AND: "and", + OR: "or", +}; + +/** + * Recursively processes an array of raw condition objects and populates the given parent group with + * corresponding ConditionExpression or ConditionExpressionGroup instances. + * @param {Array} conditions Array of raw condition objects, where each object represents either a group or an expression. + * @param {ConditionExpressionGroup} parentGroup The parent group to which the instantiated ConditionExpression or ConditionExpressionGroup objects will be added. + * @returns {void} + */ +function processMonitorConditions(conditions, parentGroup) { + conditions.forEach(condition => { + const andOr = condition.andOr === LOGICAL.OR ? LOGICAL.OR : LOGICAL.AND; + + if (condition.type === "group") { + const group = new ConditionExpressionGroup([], andOr); + + // Recursively process the group's children + processMonitorConditions(condition.children, group); + + parentGroup.children.push(group); + } else if (condition.type === "expression") { + const expression = new ConditionExpression(condition.variable, condition.operator, condition.value, andOr); + parentGroup.children.push(expression); + } + }); +} + +class ConditionExpressionGroup { + /** + * @type {ConditionExpressionGroup[]|ConditionExpression[]} Groups and/or expressions to test + */ + children = []; + + /** + * @type {LOGICAL} Connects group result with previous group/expression results + */ + andOr; + + /** + * @param {ConditionExpressionGroup[]|ConditionExpression[]} children Groups and/or expressions to test + * @param {LOGICAL} andOr Connects group result with previous group/expression results + */ + constructor(children = [], andOr = LOGICAL.AND) { + this.children = children; + this.andOr = andOr; + } + + /** + * @param {Monitor} monitor Monitor instance + * @returns {ConditionExpressionGroup|null} A ConditionExpressionGroup with the Monitor's conditions + */ + static fromMonitor(monitor) { + const conditions = JSON.parse(monitor.conditions); + if (conditions.length === 0) { + return null; + } + + const root = new ConditionExpressionGroup(); + processMonitorConditions(conditions, root); + + return root; + } +} + +class ConditionExpression { + /** + * @type {string} ID of variable + */ + variable; + + /** + * @type {string} ID of operator + */ + operator; + + /** + * @type {string} Value to test with the operator + */ + value; + + /** + * @type {LOGICAL} Connects expression result with previous group/expression results + */ + andOr; + + /** + * @param {string} variable ID of variable to test against + * @param {string} operator ID of operator to test the variable with + * @param {string} value Value to test with the operator + * @param {LOGICAL} andOr Connects expression result with previous group/expression results + */ + constructor(variable, operator, value, andOr = LOGICAL.AND) { + this.variable = variable; + this.operator = operator; + this.value = value; + this.andOr = andOr; + } +} + +module.exports = { + LOGICAL, + ConditionExpressionGroup, + ConditionExpression, +}; diff --git a/server/monitor-conditions/operators.js b/server/monitor-conditions/operators.js new file mode 100644 index 0000000000..d900dff9d8 --- /dev/null +++ b/server/monitor-conditions/operators.js @@ -0,0 +1,318 @@ +class ConditionOperator { + id = undefined; + caption = undefined; + + /** + * @type {mixed} variable + * @type {mixed} value + */ + test(variable, value) { + throw new Error("You need to override test()"); + } +} + +const OP_STR_EQUALS = "equals"; + +const OP_STR_NOT_EQUALS = "not_equals"; + +const OP_CONTAINS = "contains"; + +const OP_NOT_CONTAINS = "not_contains"; + +const OP_STARTS_WITH = "starts_with"; + +const OP_NOT_STARTS_WITH = "not_starts_with"; + +const OP_ENDS_WITH = "ends_with"; + +const OP_NOT_ENDS_WITH = "not_ends_with"; + +const OP_NUM_EQUALS = "num_equals"; + +const OP_NUM_NOT_EQUALS = "num_not_equals"; + +const OP_LT = "lt"; + +const OP_GT = "gt"; + +const OP_LTE = "lte"; + +const OP_GTE = "gte"; + +/** + * Asserts a variable is equal to a value. + */ +class StringEqualsOperator extends ConditionOperator { + id = OP_STR_EQUALS; + caption = "equals"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable === value; + } +} + +/** + * Asserts a variable is not equal to a value. + */ +class StringNotEqualsOperator extends ConditionOperator { + id = OP_STR_NOT_EQUALS; + caption = "not equals"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable !== value; + } +} + +/** + * Asserts a variable contains a value. + * Handles both Array and String variable types. + */ +class ContainsOperator extends ConditionOperator { + id = OP_CONTAINS; + caption = "contains"; + + /** + * @inheritdoc + */ + test(variable, value) { + if (Array.isArray(variable)) { + return variable.includes(value); + } + + return variable.indexOf(value) !== -1; + } +} + +/** + * Asserts a variable does not contain a value. + * Handles both Array and String variable types. + */ +class NotContainsOperator extends ConditionOperator { + id = OP_NOT_CONTAINS; + caption = "not contains"; + + /** + * @inheritdoc + */ + test(variable, value) { + if (Array.isArray(variable)) { + return !variable.includes(value); + } + + return variable.indexOf(value) === -1; + } +} + +/** + * Asserts a variable starts with a value. + */ +class StartsWithOperator extends ConditionOperator { + id = OP_STARTS_WITH; + caption = "starts with"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable.startsWith(value); + } +} + +/** + * Asserts a variable does not start with a value. + */ +class NotStartsWithOperator extends ConditionOperator { + id = OP_NOT_STARTS_WITH; + caption = "not starts with"; + + /** + * @inheritdoc + */ + test(variable, value) { + return !variable.startsWith(value); + } +} + +/** + * Asserts a variable ends with a value. + */ +class EndsWithOperator extends ConditionOperator { + id = OP_ENDS_WITH; + caption = "ends with"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable.endsWith(value); + } +} + +/** + * Asserts a variable does not end with a value. + */ +class NotEndsWithOperator extends ConditionOperator { + id = OP_NOT_ENDS_WITH; + caption = "not ends with"; + + /** + * @inheritdoc + */ + test(variable, value) { + return !variable.endsWith(value); + } +} + +/** + * Asserts a numeric variable is equal to a value. + */ +class NumberEqualsOperator extends ConditionOperator { + id = OP_NUM_EQUALS; + caption = "equals"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable === Number(value); + } +} + +/** + * Asserts a numeric variable is not equal to a value. + */ +class NumberNotEqualsOperator extends ConditionOperator { + id = OP_NUM_NOT_EQUALS; + caption = "not equals"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable !== Number(value); + } +} + +/** + * Asserts a variable is less than a value. + */ +class LessThanOperator extends ConditionOperator { + id = OP_LT; + caption = "less than"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable < Number(value); + } +} + +/** + * Asserts a variable is greater than a value. + */ +class GreaterThanOperator extends ConditionOperator { + id = OP_GT; + caption = "greater than"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable > Number(value); + } +} + +/** + * Asserts a variable is less than or equal to a value. + */ +class LessThanOrEqualToOperator extends ConditionOperator { + id = OP_LTE; + caption = "less than or equal to"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable <= Number(value); + } +} + +/** + * Asserts a variable is greater than or equal to a value. + */ +class GreaterThanOrEqualToOperator extends ConditionOperator { + id = OP_GTE; + caption = "greater than or equal to"; + + /** + * @inheritdoc + */ + test(variable, value) { + return variable >= Number(value); + } +} + +const operatorMap = new Map([ + [ OP_STR_EQUALS, new StringEqualsOperator ], + [ OP_STR_NOT_EQUALS, new StringNotEqualsOperator ], + [ OP_CONTAINS, new ContainsOperator ], + [ OP_NOT_CONTAINS, new NotContainsOperator ], + [ OP_STARTS_WITH, new StartsWithOperator ], + [ OP_NOT_STARTS_WITH, new NotStartsWithOperator ], + [ OP_ENDS_WITH, new EndsWithOperator ], + [ OP_NOT_ENDS_WITH, new NotEndsWithOperator ], + [ OP_NUM_EQUALS, new NumberEqualsOperator ], + [ OP_NUM_NOT_EQUALS, new NumberNotEqualsOperator ], + [ OP_LT, new LessThanOperator ], + [ OP_GT, new GreaterThanOperator ], + [ OP_LTE, new LessThanOrEqualToOperator ], + [ OP_GTE, new GreaterThanOrEqualToOperator ], +]); + +const defaultStringOperators = [ + operatorMap.get(OP_STR_EQUALS), + operatorMap.get(OP_STR_NOT_EQUALS), + operatorMap.get(OP_CONTAINS), + operatorMap.get(OP_NOT_CONTAINS), + operatorMap.get(OP_STARTS_WITH), + operatorMap.get(OP_NOT_STARTS_WITH), + operatorMap.get(OP_ENDS_WITH), + operatorMap.get(OP_NOT_ENDS_WITH) +]; + +const defaultNumberOperators = [ + operatorMap.get(OP_NUM_EQUALS), + operatorMap.get(OP_NUM_NOT_EQUALS), + operatorMap.get(OP_LT), + operatorMap.get(OP_GT), + operatorMap.get(OP_LTE), + operatorMap.get(OP_GTE) +]; + +module.exports = { + OP_STR_EQUALS, + OP_STR_NOT_EQUALS, + OP_CONTAINS, + OP_NOT_CONTAINS, + OP_STARTS_WITH, + OP_NOT_STARTS_WITH, + OP_ENDS_WITH, + OP_NOT_ENDS_WITH, + OP_NUM_EQUALS, + OP_NUM_NOT_EQUALS, + OP_LT, + OP_GT, + OP_LTE, + OP_GTE, + operatorMap, + defaultStringOperators, + defaultNumberOperators, + ConditionOperator, +}; diff --git a/server/monitor-conditions/variables.js b/server/monitor-conditions/variables.js new file mode 100644 index 0000000000..af98d2f295 --- /dev/null +++ b/server/monitor-conditions/variables.js @@ -0,0 +1,31 @@ +/** + * Represents a variable used in a condition and the set of operators that can be applied to this variable. + * + * A `ConditionVariable` holds the ID of the variable and a list of operators that define how this variable can be evaluated + * in conditions. For example, if the variable is a request body or a specific field in a request, the operators can include + * operations such as equality checks, comparisons, or other custom evaluations. + */ +class ConditionVariable { + /** + * @type {string} + */ + id; + + /** + * @type {import("./operators").ConditionOperator[]} + */ + operators = {}; + + /** + * @param {string} id ID of variable + * @param {import("./operators").ConditionOperator[]} operators Operators the condition supports + */ + constructor(id, operators = []) { + this.id = id; + this.operators = operators; + } +} + +module.exports = { + ConditionVariable, +}; diff --git a/server/monitor-types/dns.js b/server/monitor-types/dns.js new file mode 100644 index 0000000000..8b87932feb --- /dev/null +++ b/server/monitor-types/dns.js @@ -0,0 +1,85 @@ +const { MonitorType } = require("./monitor-type"); +const { UP, DOWN } = require("../../src/util"); +const dayjs = require("dayjs"); +const { dnsResolve } = require("../util-server"); +const { R } = require("redbean-node"); +const { ConditionVariable } = require("../monitor-conditions/variables"); +const { defaultStringOperators } = require("../monitor-conditions/operators"); +const { ConditionExpressionGroup } = require("../monitor-conditions/expression"); +const { evaluateExpressionGroup } = require("../monitor-conditions/evaluator"); + +class DnsMonitorType extends MonitorType { + name = "dns"; + + supportsConditions = true; + + conditionVariables = [ + new ConditionVariable("record", defaultStringOperators ), + ]; + + /** + * @inheritdoc + */ + async check(monitor, heartbeat, _server) { + let startTime = dayjs().valueOf(); + let dnsMessage = ""; + + let dnsRes = await dnsResolve(monitor.hostname, monitor.dns_resolve_server, monitor.port, monitor.dns_resolve_type); + heartbeat.ping = dayjs().valueOf() - startTime; + + const conditions = ConditionExpressionGroup.fromMonitor(monitor); + let conditionsResult = true; + const handleConditions = (data) => conditions ? evaluateExpressionGroup(conditions, data) : true; + + switch (monitor.dns_resolve_type) { + case "A": + case "AAAA": + case "TXT": + case "PTR": + dnsMessage = `Records: ${dnsRes.join(" | ")}`; + conditionsResult = dnsRes.some(record => handleConditions({ record })); + break; + + case "CNAME": + dnsMessage = dnsRes[0]; + conditionsResult = handleConditions({ record: dnsRes[0] }); + break; + + case "CAA": + dnsMessage = dnsRes[0].issue; + conditionsResult = handleConditions({ record: dnsRes[0].issue }); + break; + + case "MX": + dnsMessage = dnsRes.map(record => `Hostname: ${record.exchange} - Priority: ${record.priority}`).join(" | "); + conditionsResult = dnsRes.some(record => handleConditions({ record: record.exchange })); + break; + + case "NS": + dnsMessage = `Servers: ${dnsRes.join(" | ")}`; + conditionsResult = dnsRes.some(record => handleConditions({ record })); + break; + + case "SOA": + dnsMessage = `NS-Name: ${dnsRes.nsname} | Hostmaster: ${dnsRes.hostmaster} | Serial: ${dnsRes.serial} | Refresh: ${dnsRes.refresh} | Retry: ${dnsRes.retry} | Expire: ${dnsRes.expire} | MinTTL: ${dnsRes.minttl}`; + conditionsResult = handleConditions({ record: dnsRes.nsname }); + break; + + case "SRV": + dnsMessage = dnsRes.map(record => `Name: ${record.name} | Port: ${record.port} | Priority: ${record.priority} | Weight: ${record.weight}`).join(" | "); + conditionsResult = dnsRes.some(record => handleConditions({ record: record.name })); + break; + } + + if (monitor.dns_last_result !== dnsMessage && dnsMessage !== undefined) { + await R.exec("UPDATE `monitor` SET dns_last_result = ? WHERE id = ? ", [ dnsMessage, monitor.id ]); + } + + heartbeat.msg = dnsMessage; + heartbeat.status = conditionsResult ? UP : DOWN; + } +} + +module.exports = { + DnsMonitorType, +}; diff --git a/server/monitor-types/mongodb.js b/server/monitor-types/mongodb.js new file mode 100644 index 0000000000..73747db9cc --- /dev/null +++ b/server/monitor-types/mongodb.js @@ -0,0 +1,63 @@ +const { MonitorType } = require("./monitor-type"); +const { UP } = require("../../src/util"); +const { MongoClient } = require("mongodb"); +const jsonata = require("jsonata"); + +class MongodbMonitorType extends MonitorType { + name = "mongodb"; + + /** + * @inheritdoc + */ + async check(monitor, heartbeat, _server) { + let command = { "ping": 1 }; + if (monitor.databaseQuery) { + command = JSON.parse(monitor.databaseQuery); + } + + let result = await this.runMongodbCommand(monitor.databaseConnectionString, command); + + if (result["ok"] !== 1) { + throw new Error("MongoDB command failed"); + } else { + heartbeat.msg = "Command executed successfully"; + } + + if (monitor.jsonPath) { + let expression = jsonata(monitor.jsonPath); + result = await expression.evaluate(result); + if (result) { + heartbeat.msg = "Command executed successfully and the jsonata expression produces a result."; + } else { + throw new Error("Queried value not found."); + } + } + + if (monitor.expectedValue) { + if (result.toString() === monitor.expectedValue) { + heartbeat.msg = "Command executed successfully and expected value was found"; + } else { + throw new Error("Query executed, but value is not equal to expected value, value was: [" + JSON.stringify(result) + "]"); + } + } + + heartbeat.status = UP; + } + + /** + * Connect to and run MongoDB command on a MongoDB database + * @param {string} connectionString The database connection string + * @param {object} command MongoDB command to run on the database + * @returns {Promise<(string[] | object[] | object)>} Response from server + */ + async runMongodbCommand(connectionString, command) { + let client = await MongoClient.connect(connectionString); + let result = await client.db().command(command); + await client.close(); + return result; + } +} + +module.exports = { + MongodbMonitorType, +}; diff --git a/server/monitor-types/monitor-type.js b/server/monitor-types/monitor-type.js index 80a0a7d928..8f3cbcac40 100644 --- a/server/monitor-types/monitor-type.js +++ b/server/monitor-types/monitor-type.js @@ -1,18 +1,29 @@ class MonitorType { - name = undefined; /** - * - * @param {Monitor} monitor - * @param {Heartbeat} heartbeat - * @param {UptimeKumaServer} server + * Whether or not this type supports monitor conditions. Controls UI visibility in monitor form. + * @type {boolean} + */ + supportsConditions = false; + + /** + * Variables supported by this type. e.g. an HTTP type could have a "response_code" variable to test against. + * This property controls the choices displayed in the monitor edit form. + * @type {import("../monitor-conditions/variables").ConditionVariable[]} + */ + conditionVariables = []; + + /** + * Run the monitoring check on the given monitor + * @param {Monitor} monitor Monitor to check + * @param {Heartbeat} heartbeat Monitor heartbeat to update + * @param {UptimeKumaServer} server Uptime Kuma server * @returns {Promise} */ async check(monitor, heartbeat, server) { throw new Error("You need to override check()"); } - } module.exports = { diff --git a/server/monitor-types/mqtt.js b/server/monitor-types/mqtt.js new file mode 100644 index 0000000000..ad734ce8ed --- /dev/null +++ b/server/monitor-types/mqtt.js @@ -0,0 +1,117 @@ +const { MonitorType } = require("./monitor-type"); +const { log, UP } = require("../../src/util"); +const mqtt = require("mqtt"); +const jsonata = require("jsonata"); + +class MqttMonitorType extends MonitorType { + name = "mqtt"; + + /** + * @inheritdoc + */ + async check(monitor, heartbeat, server) { + const receivedMessage = await this.mqttAsync(monitor.hostname, monitor.mqttTopic, { + port: monitor.port, + username: monitor.mqttUsername, + password: monitor.mqttPassword, + interval: monitor.interval, + }); + + if (monitor.mqttCheckType == null || monitor.mqttCheckType === "") { + // use old default + monitor.mqttCheckType = "keyword"; + } + + if (monitor.mqttCheckType === "keyword") { + if (receivedMessage != null && receivedMessage.includes(monitor.mqttSuccessMessage)) { + heartbeat.msg = `Topic: ${monitor.mqttTopic}; Message: ${receivedMessage}`; + heartbeat.status = UP; + } else { + throw Error(`Message Mismatch - Topic: ${monitor.mqttTopic}; Message: ${receivedMessage}`); + } + } else if (monitor.mqttCheckType === "json-query") { + const parsedMessage = JSON.parse(receivedMessage); + + let expression = jsonata(monitor.jsonPath); + + let result = await expression.evaluate(parsedMessage); + + if (result?.toString() === monitor.expectedValue) { + heartbeat.msg = "Message received, expected value is found"; + heartbeat.status = UP; + } else { + throw new Error("Message received but value is not equal to expected value, value was: [" + result + "]"); + } + } else { + throw Error("Unknown MQTT Check Type"); + } + } + + /** + * Connect to MQTT Broker, subscribe to topic and receive message as String + * @param {string} hostname Hostname / address of machine to test + * @param {string} topic MQTT topic + * @param {object} options MQTT options. Contains port, username, + * password and interval (interval defaults to 20) + * @returns {Promise} Received MQTT message + */ + mqttAsync(hostname, topic, options = {}) { + return new Promise((resolve, reject) => { + const { port, username, password, interval = 20 } = options; + + // Adds MQTT protocol to the hostname if not already present + if (!/^(?:http|mqtt|ws)s?:\/\//.test(hostname)) { + hostname = "mqtt://" + hostname; + } + + const timeoutID = setTimeout(() => { + log.debug("mqtt", "MQTT timeout triggered"); + client.end(); + reject(new Error("Timeout, Message not received")); + }, interval * 1000 * 0.8); + + const mqttUrl = `${hostname}:${port}`; + + log.debug("mqtt", `MQTT connecting to ${mqttUrl}`); + + let client = mqtt.connect(mqttUrl, { + username, + password, + clientId: "uptime-kuma_" + Math.random().toString(16).substr(2, 8) + }); + + client.on("connect", () => { + log.debug("mqtt", "MQTT connected"); + + try { + client.subscribe(topic, () => { + log.debug("mqtt", "MQTT subscribed to topic"); + }); + } catch (e) { + client.end(); + clearTimeout(timeoutID); + reject(new Error("Cannot subscribe topic")); + } + }); + + client.on("error", (error) => { + client.end(); + clearTimeout(timeoutID); + reject(error); + }); + + client.on("message", (messageTopic, message) => { + if (messageTopic === topic) { + client.end(); + clearTimeout(timeoutID); + resolve(message.toString("utf8")); + } + }); + + }); + } +} + +module.exports = { + MqttMonitorType, +}; diff --git a/server/monitor-types/rabbitmq.js b/server/monitor-types/rabbitmq.js new file mode 100644 index 0000000000..165a0ed915 --- /dev/null +++ b/server/monitor-types/rabbitmq.js @@ -0,0 +1,67 @@ +const { MonitorType } = require("./monitor-type"); +const { log, UP, DOWN } = require("../../src/util"); +const { axiosAbortSignal } = require("../util-server"); +const axios = require("axios"); + +class RabbitMqMonitorType extends MonitorType { + name = "rabbitmq"; + + /** + * @inheritdoc + */ + async check(monitor, heartbeat, server) { + let baseUrls = []; + try { + baseUrls = JSON.parse(monitor.rabbitmqNodes); + } catch (error) { + throw new Error("Invalid RabbitMQ Nodes"); + } + + heartbeat.status = DOWN; + for (let baseUrl of baseUrls) { + try { + // Without a trailing slash, path in baseUrl will be removed. https://example.com/api -> https://example.com + if ( !baseUrl.endsWith("/") ) { + baseUrl += "/"; + } + const options = { + // Do not start with slash, it will strip the trailing slash from baseUrl + url: new URL("api/health/checks/alarms/", baseUrl).href, + method: "get", + timeout: monitor.timeout * 1000, + headers: { + "Accept": "application/json", + "Authorization": "Basic " + Buffer.from(`${monitor.rabbitmqUsername || ""}:${monitor.rabbitmqPassword || ""}`).toString("base64"), + }, + signal: axiosAbortSignal((monitor.timeout + 10) * 1000), + // Capture reason for 503 status + validateStatus: (status) => status === 200 || status === 503, + }; + log.debug("monitor", `[${monitor.name}] Axios Request: ${JSON.stringify(options)}`); + const res = await axios.request(options); + log.debug("monitor", `[${monitor.name}] Axios Response: status=${res.status} body=${JSON.stringify(res.data)}`); + if (res.status === 200) { + heartbeat.status = UP; + heartbeat.msg = "OK"; + break; + } else if (res.status === 503) { + heartbeat.msg = res.data.reason; + } else { + heartbeat.msg = `${res.status} - ${res.statusText}`; + } + } catch (error) { + if (axios.isCancel(error)) { + heartbeat.msg = "Request timed out"; + log.debug("monitor", `[${monitor.name}] Request timed out`); + } else { + log.debug("monitor", `[${monitor.name}] Axios Error: ${JSON.stringify(error.message)}`); + heartbeat.msg = error.message; + } + } + } + } +} + +module.exports = { + RabbitMqMonitorType, +}; diff --git a/server/monitor-types/real-browser-monitor-type.js b/server/monitor-types/real-browser-monitor-type.js index eee1399ff9..2a2871d2c5 100644 --- a/server/monitor-types/real-browser-monitor-type.js +++ b/server/monitor-types/real-browser-monitor-type.js @@ -8,6 +8,7 @@ const path = require("path"); const Database = require("../database"); const jwt = require("jsonwebtoken"); const config = require("../config"); +const { RemoteBrowser } = require("../remote-browser"); /** * Cached instance of a browser @@ -28,6 +29,9 @@ if (process.platform === "win32") { allowedList.push(process.env.PROGRAMFILES + "\\Chromium\\Application\\chrome.exe"); allowedList.push(process.env["ProgramFiles(x86)"] + "\\Chromium\\Application\\chrome.exe"); + // Allow MS Edge + allowedList.push(process.env["ProgramFiles(x86)"] + "\\Microsoft\\Edge\\Application\\msedge.exe"); + // For Loop A to Z for (let i = 65; i <= 90; i++) { let drive = String.fromCharCode(i); @@ -47,15 +51,17 @@ if (process.platform === "win32") { "/snap/bin/chromium", // Ubuntu ]; } else if (process.platform === "darwin") { - // TODO: Generated by GitHub Copilot, but not sure if it's correct allowedList = [ "/Applications/Google Chrome.app/Contents/MacOS/Google Chrome", "/Applications/Chromium.app/Contents/MacOS/Chromium", ]; } -log.debug("chrome", allowedList); - +/** + * Is the executable path allowed? + * @param {string} executablePath Path to executable + * @returns {Promise} The executable is allowed? + */ async function isAllowedChromeExecutable(executablePath) { console.log(config.args); if (config.args["allow-all-chrome-exec"] || process.env.UPTIME_KUMA_ALLOW_ALL_CHROME_EXEC === "1") { @@ -88,6 +94,24 @@ async function getBrowser() { } } +/** + * Get the current instance of the browser. If there isn't one, create it + * @param {integer} remoteBrowserID Path to executable + * @param {integer} userId User ID + * @returns {Promise} The browser + */ +async function getRemoteBrowser(remoteBrowserID, userId) { + let remoteBrowser = await RemoteBrowser.get(remoteBrowserID, userId); + log.debug("MONITOR", `Using remote browser: ${remoteBrowser.name} (${remoteBrowser.id})`); + browser = await chromium.connect(remoteBrowser.url); + return browser; +} + +/** + * Prepare the chrome executable path + * @param {string} executablePath Path to chrome executable + * @returns {Promise} Executable path + */ async function prepareChromeExecutable(executablePath) { // Special code for using the playwright_chromium if (typeof executablePath === "string" && executablePath.toLocaleLowerCase() === "#playwright_chromium") { @@ -134,6 +158,12 @@ async function prepareChromeExecutable(executablePath) { return executablePath; } +/** + * Find the chrome executable + * @param {any[]} executables Executables to search through + * @returns {any} Executable + * @throws Could not find executable + */ function findChrome(executables) { // Use the last working executable, so we don't have to search for it again if (lastAutoDetectChromeExecutable) { @@ -151,6 +181,10 @@ function findChrome(executables) { throw new Error("Chromium not found, please specify Chromium executable path in the settings page."); } +/** + * Reset chrome + * @returns {Promise} + */ async function resetChrome() { if (browser) { await browser.close(); @@ -160,8 +194,8 @@ async function resetChrome() { /** * Test if the chrome executable is valid and return the version - * @param executablePath - * @returns {Promise} + * @param {string} executablePath Path to executable + * @returns {Promise} Chrome version */ async function testChrome(executablePath) { try { @@ -179,17 +213,30 @@ async function testChrome(executablePath) { throw new Error(e.message); } } - +// test remote browser /** - * TODO: connect remote browser? https://playwright.dev/docs/api/class-browsertype#browser-type-connect - * + * @param {string} remoteBrowserURL Remote Browser URL + * @returns {Promise} Returns if connection worked */ +async function testRemoteBrowser(remoteBrowserURL) { + try { + const browser = await chromium.connect(remoteBrowserURL); + browser.version(); + await browser.close(); + return true; + } catch (e) { + throw new Error(e.message); + } +} class RealBrowserMonitorType extends MonitorType { name = "real-browser"; + /** + * @inheritdoc + */ async check(monitor, heartbeat, server) { - const browser = await getBrowser(); + const browser = monitor.remote_browser ? await getRemoteBrowser(monitor.remote_browser, monitor.user_id) : await getBrowser(); const context = await browser.newContext(); const page = await context.newPage(); @@ -230,4 +277,5 @@ module.exports = { RealBrowserMonitorType, testChrome, resetChrome, + testRemoteBrowser, }; diff --git a/server/monitor-types/snmp.js b/server/monitor-types/snmp.js new file mode 100644 index 0000000000..a1760fa3df --- /dev/null +++ b/server/monitor-types/snmp.js @@ -0,0 +1,63 @@ +const { MonitorType } = require("./monitor-type"); +const { UP, log, evaluateJsonQuery } = require("../../src/util"); +const snmp = require("net-snmp"); + +class SNMPMonitorType extends MonitorType { + name = "snmp"; + + /** + * @inheritdoc + */ + async check(monitor, heartbeat, _server) { + let session; + try { + const sessionOptions = { + port: monitor.port || "161", + retries: monitor.maxretries, + timeout: monitor.timeout * 1000, + version: snmp.Version[monitor.snmpVersion], + }; + session = snmp.createSession(monitor.hostname, monitor.radiusPassword, sessionOptions); + + // Handle errors during session creation + session.on("error", (error) => { + throw new Error(`Error creating SNMP session: ${error.message}`); + }); + + const varbinds = await new Promise((resolve, reject) => { + session.get([ monitor.snmpOid ], (error, varbinds) => { + error ? reject(error) : resolve(varbinds); + }); + }); + log.debug("monitor", `SNMP: Received varbinds (Type: ${snmp.ObjectType[varbinds[0].type]} Value: ${varbinds[0].value})`); + + if (varbinds.length === 0) { + throw new Error(`No varbinds returned from SNMP session (OID: ${monitor.snmpOid})`); + } + + if (varbinds[0].type === snmp.ObjectType.NoSuchInstance) { + throw new Error(`The SNMP query returned that no instance exists for OID ${monitor.snmpOid}`); + } + + // We restrict querying to one OID per monitor, therefore `varbinds[0]` will always contain the value we're interested in. + const value = varbinds[0].value; + + const { status, response } = await evaluateJsonQuery(value, monitor.jsonPath, monitor.jsonPathOperator, monitor.expectedValue); + + if (status) { + heartbeat.status = UP; + heartbeat.msg = `JSON query passes (comparing ${response} ${monitor.jsonPathOperator} ${monitor.expectedValue})`; + } else { + throw new Error(`JSON query does not pass (comparing ${response} ${monitor.jsonPathOperator} ${monitor.expectedValue})`); + } + } finally { + if (session) { + session.close(); + } + } + } +} + +module.exports = { + SNMPMonitorType, +}; diff --git a/server/monitor-types/tailscale-ping.js b/server/monitor-types/tailscale-ping.js index 84b913d012..8537651cd3 100644 --- a/server/monitor-types/tailscale-ping.js +++ b/server/monitor-types/tailscale-ping.js @@ -2,23 +2,13 @@ const { MonitorType } = require("./monitor-type"); const { UP } = require("../../src/util"); const childProcessAsync = require("promisify-child-process"); -/** - * A TailscalePing class extends the MonitorType. - * It runs Tailscale ping to monitor the status of a specific node. - */ class TailscalePing extends MonitorType { - name = "tailscale-ping"; /** - * Checks the ping status of the URL associated with the monitor. - * It then parses the Tailscale ping command output to update the heatrbeat. - * - * @param {Object} monitor - The monitor object associated with the check. - * @param {Object} heartbeat - The heartbeat object to update. - * @throws Will throw an error if checking Tailscale ping encounters any error + * @inheritdoc */ - async check(monitor, heartbeat) { + async check(monitor, heartbeat, _server) { try { let tailscaleOutput = await this.runTailscalePing(monitor.hostname, monitor.interval); this.parseTailscaleOutput(tailscaleOutput, heartbeat); @@ -30,10 +20,9 @@ class TailscalePing extends MonitorType { /** * Runs the Tailscale ping command to the given URL. - * - * @param {string} hostname - The hostname to ping. - * @param {number} interval - * @returns {Promise} - A Promise that resolves to the output of the Tailscale ping command + * @param {string} hostname The hostname to ping. + * @param {number} interval Interval to send ping + * @returns {Promise} A Promise that resolves to the output of the Tailscale ping command * @throws Will throw an error if the command execution encounters any error. */ async runTailscalePing(hostname, interval) { @@ -54,9 +43,9 @@ class TailscalePing extends MonitorType { /** * Parses the output of the Tailscale ping command to update the heartbeat. - * - * @param {string} tailscaleOutput - The output of the Tailscale ping command. - * @param {Object} heartbeat - The heartbeat object to update. + * @param {string} tailscaleOutput The output of the Tailscale ping command. + * @param {object} heartbeat The heartbeat object to update. + * @returns {void} * @throws Will throw an eror if the output contains any unexpected string. */ parseTailscaleOutput(tailscaleOutput, heartbeat) { diff --git a/server/notification-providers/46elks.js b/server/notification-providers/46elks.js new file mode 100644 index 0000000000..4b15e9fad7 --- /dev/null +++ b/server/notification-providers/46elks.js @@ -0,0 +1,35 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class Elks extends NotificationProvider { + name = "Elks"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + const url = "https://api.46elks.com/a1/sms"; + + try { + let data = new URLSearchParams(); + data.append("from", notification.elksFromNumber); + data.append("to", notification.elksToNumber ); + data.append("message", msg); + + const config = { + headers: { + "Authorization": "Basic " + Buffer.from(`${notification.elksUsername}:${notification.elksAuthToken}`).toString("base64") + } + }; + + await axios.post(url, data, config); + + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = Elks; diff --git a/server/notification-providers/alerta.js b/server/notification-providers/alerta.js index 2b85d67a69..f9a273b49f 100644 --- a/server/notification-providers/alerta.js +++ b/server/notification-providers/alerta.js @@ -3,14 +3,15 @@ const { DOWN, UP } = require("../../src/util"); const axios = require("axios"); class Alerta extends NotificationProvider { - name = "alerta"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { - let alertaUrl = `${notification.alertaApiEndpoint}`; let config = { headers: { "Content-Type": "application/json;charset=UTF-8", @@ -37,7 +38,7 @@ class Alerta extends NotificationProvider { resource: "Message", }, data); - await axios.post(alertaUrl, postData, config); + await axios.post(notification.alertaApiEndpoint, postData, config); } else { let datadup = Object.assign( { correlate: [ "service_up", "service_down" ], @@ -49,11 +50,11 @@ class Alerta extends NotificationProvider { if (heartbeatJSON["status"] === DOWN) { datadup.severity = notification.alertaAlertState; // critical datadup.text = "Service " + monitorJSON["type"] + " is down."; - await axios.post(alertaUrl, datadup, config); + await axios.post(notification.alertaApiEndpoint, datadup, config); } else if (heartbeatJSON["status"] === UP) { datadup.severity = notification.alertaRecoverState; // cleaned datadup.text = "Service " + monitorJSON["type"] + " is up."; - await axios.post(alertaUrl, datadup, config); + await axios.post(notification.alertaApiEndpoint, datadup, config); } } return okMsg; diff --git a/server/notification-providers/alertnow.js b/server/notification-providers/alertnow.js index d778b01d35..4257ca9cd1 100644 --- a/server/notification-providers/alertnow.js +++ b/server/notification-providers/alertnow.js @@ -4,11 +4,14 @@ const { setting } = require("../util-server"); const { getMonitorRelativeURL, UP, DOWN } = require("../../src/util"); class AlertNow extends NotificationProvider { - name = "AlertNow"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + try { let textMsg = ""; let status = "open"; diff --git a/server/notification-providers/aliyun-sms.js b/server/notification-providers/aliyun-sms.js index f0530b4998..ff38bd0d97 100644 --- a/server/notification-providers/aliyun-sms.js +++ b/server/notification-providers/aliyun-sms.js @@ -7,8 +7,11 @@ const qs = require("qs"); class AliyunSMS extends NotificationProvider { name = "AliyunSMS"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { if (heartbeatJSON != null) { @@ -41,7 +44,7 @@ class AliyunSMS extends NotificationProvider { * Send the SMS notification * @param {BeanModel} notification Notification details * @param {string} msgbody Message template - * @returns {boolean} True if successful else false + * @returns {Promise} True if successful else false */ async sendSms(notification, msgbody) { let params = { @@ -79,9 +82,9 @@ class AliyunSMS extends NotificationProvider { /** * Aliyun request sign - * @param {Object} param Parameters object to sign + * @param {object} param Parameters object to sign * @param {string} AccessKeySecret Secret key to sign parameters with - * @returns {string} + * @returns {string} Base64 encoded request */ sign(param, AccessKeySecret) { let param2 = {}; @@ -123,7 +126,7 @@ class AliyunSMS extends NotificationProvider { /** * Convert status constant to string * @param {const} status The status constant - * @returns {string} + * @returns {string} Status */ statusToString(status) { switch (status) { diff --git a/server/notification-providers/apprise.js b/server/notification-providers/apprise.js index 045e65cc4d..0f6982140f 100644 --- a/server/notification-providers/apprise.js +++ b/server/notification-providers/apprise.js @@ -2,10 +2,14 @@ const NotificationProvider = require("./notification-provider"); const childProcessAsync = require("promisify-child-process"); class Apprise extends NotificationProvider { - name = "apprise"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + const args = [ "-vv", "-b", msg, notification.appriseURL ]; if (notification.title) { args.push("-t"); @@ -20,7 +24,7 @@ class Apprise extends NotificationProvider { if (output) { if (! output.includes("ERROR")) { - return "Sent Successfully"; + return okMsg; } throw new Error(output); diff --git a/server/notification-providers/bark.js b/server/notification-providers/bark.js index bcd3c68234..0907d5f108 100644 --- a/server/notification-providers/bark.js +++ b/server/notification-providers/bark.js @@ -18,6 +18,9 @@ const successMessage = "Successes!"; class Bark extends NotificationProvider { name = "Bark"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { let barkEndpoint = notification.barkEndpoint; @@ -43,34 +46,35 @@ class Bark extends NotificationProvider { } /** - * Add additional parameter for better on device styles (iOS 15 - * optimized) - * @param {string} postUrl URL to append parameters to - * @returns {string} + * Add additional parameter for Bark v1 endpoints. + * Leads to better on device styles (iOS 15 optimized) + * @param {BeanModel} notification Notification to send + * @returns {string} Additional URL parameters */ - appendAdditionalParameters(notification, postUrl) { + additionalParameters(notification) { // set icon to uptime kuma icon, 11kb should be fine - postUrl += "?icon=" + barkNotificationAvatar; + let params = "?icon=" + barkNotificationAvatar; // grouping all our notifications if (notification.barkGroup != null) { - postUrl += "&group=" + notification.barkGroup; + params += "&group=" + notification.barkGroup; } else { // default name - postUrl += "&group=" + "UptimeKuma"; + params += "&group=" + "UptimeKuma"; } // picked a sound, this should follow system's mute status when arrival if (notification.barkSound != null) { - postUrl += "&sound=" + notification.barkSound; + params += "&sound=" + notification.barkSound; } else { // default sound - postUrl += "&sound=" + "telegraph"; + params += "&sound=" + "telegraph"; } - return postUrl; + return params; } /** * Check if result is successful - * @param {Object} result Axios response object + * @param {object} result Axios response object + * @returns {void} * @throws {Error} The status code is not in range 2xx */ checkResult(result) { @@ -84,18 +88,29 @@ class Bark extends NotificationProvider { /** * Send the message + * @param {BeanModel} notification Notification to send * @param {string} title Message title * @param {string} subtitle Message * @param {string} endpoint Endpoint to send request to - * @returns {string} + * @returns {Promise} Success message */ async postNotification(notification, title, subtitle, endpoint) { - // url encode title and subtitle - title = encodeURIComponent(title); - subtitle = encodeURIComponent(subtitle); - let postUrl = endpoint + "/" + title + "/" + subtitle; - postUrl = this.appendAdditionalParameters(notification, postUrl); - let result = await axios.get(postUrl); + let result; + if (notification.apiVersion === "v1" || notification.apiVersion == null) { + // url encode title and subtitle + title = encodeURIComponent(title); + subtitle = encodeURIComponent(subtitle); + const params = this.additionalParameters(notification); + result = await axios.get(`${endpoint}/${title}/${subtitle}${params}`); + } else { + result = await axios.post(`${endpoint}/push`, { + title, + body: subtitle, + icon: barkNotificationAvatar, + sound: notification.barkSound || "telegraph", // default sound is telegraph + group: notification.barkGroup || "UptimeKuma", // default group is UptimeKuma + }); + } this.checkResult(result); if (result.statusText != null) { return "Bark notification succeed: " + result.statusText; diff --git a/server/notification-providers/bitrix24.js b/server/notification-providers/bitrix24.js new file mode 100644 index 0000000000..ba12126c54 --- /dev/null +++ b/server/notification-providers/bitrix24.js @@ -0,0 +1,31 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); +const { UP } = require("../../src/util"); + +class Bitrix24 extends NotificationProvider { + name = "Bitrix24"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + try { + const params = { + user_id: notification.bitrix24UserID, + message: "[B]Uptime Kuma[/B]", + "ATTACH[COLOR]": (heartbeatJSON ?? {})["status"] === UP ? "#b73419" : "#67b518", + "ATTACH[BLOCKS][0][MESSAGE]": msg + }; + + await axios.get(`${notification.bitrix24WebhookURL}/im.notify.system.add.json`, { params }); + return okMsg; + + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = Bitrix24; diff --git a/server/notification-providers/call-me-bot.js b/server/notification-providers/call-me-bot.js new file mode 100644 index 0000000000..daa9ccdeb5 --- /dev/null +++ b/server/notification-providers/call-me-bot.js @@ -0,0 +1,23 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class CallMeBot extends NotificationProvider { + name = "CallMeBot"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + try { + const url = new URL(notification.callMeBotEndpoint); + url.searchParams.set("text", msg); + await axios.get(url.toString()); + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = CallMeBot; diff --git a/server/notification-providers/cellsynt.js b/server/notification-providers/cellsynt.js new file mode 100644 index 0000000000..e842237b6a --- /dev/null +++ b/server/notification-providers/cellsynt.js @@ -0,0 +1,39 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class Cellsynt extends NotificationProvider { + name = "Cellsynt"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + const data = { + // docs at https://www.cellsynt.com/en/sms/api-integration + params: { + "username": notification.cellsyntLogin, + "password": notification.cellsyntPassword, + "destination": notification.cellsyntDestination, + "text": msg.replace(/[^\x00-\x7F]/g, ""), + "originatortype": notification.cellsyntOriginatortype, + "originator": notification.cellsyntOriginator, + "allowconcat": notification.cellsyntAllowLongSMS ? 6 : 1 + } + }; + try { + const resp = await axios.post("https://se-1.cellsynt.net/sms.php", null, data); + if (resp.data == null ) { + throw new Error("Could not connect to Cellsynt, please try again."); + } else if (resp.data.includes("Error:")) { + resp.data = resp.data.replaceAll("Error:", ""); + throw new Error(resp.data); + } + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = Cellsynt; diff --git a/server/notification-providers/clicksendsms.js b/server/notification-providers/clicksendsms.js index 1df0530986..c090b7f368 100644 --- a/server/notification-providers/clicksendsms.js +++ b/server/notification-providers/clicksendsms.js @@ -2,11 +2,15 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class ClickSendSMS extends NotificationProvider { - name = "clicksendsms"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + const url = "https://rest.clicksend.com/v3/sms/send"; + try { let config = { headers: { @@ -25,7 +29,7 @@ class ClickSendSMS extends NotificationProvider { } ] }; - let resp = await axios.post("https://rest.clicksend.com/v3/sms/send", data, config); + let resp = await axios.post(url, data, config); if (resp.data.data.messages[0].status !== "SUCCESS") { let error = "Something gone wrong. Api returned " + resp.data.data.messages[0].status + "."; this.throwGeneralAxiosError(error); diff --git a/server/notification-providers/dingding.js b/server/notification-providers/dingding.js index 8f4bd48268..c66f270a75 100644 --- a/server/notification-providers/dingding.js +++ b/server/notification-providers/dingding.js @@ -6,8 +6,11 @@ const Crypto = require("crypto"); class DingDing extends NotificationProvider { name = "DingDing"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { if (heartbeatJSON != null) { @@ -16,6 +19,9 @@ class DingDing extends NotificationProvider { markdown: { title: `[${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]}`, text: `## [${this.statusToString(heartbeatJSON["status"])}] ${monitorJSON["name"]} \n> ${heartbeatJSON["msg"]}\n> Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`, + }, + "at": { + "isAtAll": notification.mentioning === "everyone" } }; if (await this.sendToDingDing(notification, params)) { @@ -39,9 +45,9 @@ class DingDing extends NotificationProvider { /** * Send message to DingDing - * @param {BeanModel} notification - * @param {Object} params Parameters of message - * @returns {boolean} True if successful else false + * @param {BeanModel} notification Notification to send + * @param {object} params Parameters of message + * @returns {Promise} True if successful else false */ async sendToDingDing(notification, params) { let timestamp = Date.now(); @@ -66,7 +72,7 @@ class DingDing extends NotificationProvider { * DingDing sign * @param {Date} timestamp Timestamp of message * @param {string} secretKey Secret key to sign data with - * @returns {string} + * @returns {string} Base64 encoded signature */ sign(timestamp, secretKey) { return Crypto @@ -78,10 +84,9 @@ class DingDing extends NotificationProvider { /** * Convert status constant to string * @param {const} status The status constant - * @returns {string} + * @returns {string} Status */ statusToString(status) { - // TODO: Move to notification-provider.js to avoid repetition in classes switch (status) { case DOWN: return "DOWN"; diff --git a/server/notification-providers/discord.js b/server/notification-providers/discord.js index 2d7c748d9d..6a52f8f3e4 100644 --- a/server/notification-providers/discord.js +++ b/server/notification-providers/discord.js @@ -3,14 +3,20 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class Discord extends NotificationProvider { - name = "discord"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { const discordDisplayName = notification.discordUsername || "Uptime Kuma"; + const webhookUrl = new URL(notification.discordWebhookUrl); + if (notification.discordChannelType === "postToThread") { + webhookUrl.searchParams.append("thread_id", notification.threadId); + } // If heartbeatJSON is null, assume we're testing. if (heartbeatJSON == null) { @@ -18,28 +24,13 @@ class Discord extends NotificationProvider { username: discordDisplayName, content: msg, }; - await axios.post(notification.discordWebhookUrl, discordtestdata); - return okMsg; - } - let address; + if (notification.discordChannelType === "createNewForumPost") { + discordtestdata.thread_name = notification.postName; + } - switch (monitorJSON["type"]) { - case "ping": - address = monitorJSON["hostname"]; - break; - case "port": - case "dns": - case "gamedig": - case "steam": - address = monitorJSON["hostname"]; - if (monitorJSON["port"]) { - address += ":" + monitorJSON["port"]; - } - break; - default: - address = monitorJSON["url"]; - break; + await axios.post(webhookUrl.toString(), discordtestdata); + return okMsg; } // If heartbeatJSON is not null, we go into the normal alerting loop. @@ -57,7 +48,7 @@ class Discord extends NotificationProvider { }, { name: monitorJSON["type"] === "push" ? "Service Type" : "Service URL", - value: monitorJSON["type"] === "push" ? "Heartbeat" : address, + value: this.extractAddress(monitorJSON), }, { name: `Time (${heartbeatJSON["timezone"]})`, @@ -70,12 +61,14 @@ class Discord extends NotificationProvider { ], }], }; - + if (notification.discordChannelType === "createNewForumPost") { + discorddowndata.thread_name = notification.postName; + } if (notification.discordPrefixMessage) { discorddowndata.content = notification.discordPrefixMessage; } - await axios.post(notification.discordWebhookUrl, discorddowndata); + await axios.post(webhookUrl.toString(), discorddowndata); return okMsg; } else if (heartbeatJSON["status"] === UP) { @@ -92,7 +85,7 @@ class Discord extends NotificationProvider { }, { name: monitorJSON["type"] === "push" ? "Service Type" : "Service URL", - value: monitorJSON["type"] === "push" ? "Heartbeat" : address, + value: this.extractAddress(monitorJSON), }, { name: `Time (${heartbeatJSON["timezone"]})`, @@ -106,11 +99,15 @@ class Discord extends NotificationProvider { }], }; + if (notification.discordChannelType === "createNewForumPost") { + discordupdata.thread_name = notification.postName; + } + if (notification.discordPrefixMessage) { discordupdata.content = notification.discordPrefixMessage; } - await axios.post(notification.discordWebhookUrl, discordupdata); + await axios.post(webhookUrl.toString(), discordupdata); return okMsg; } } catch (error) { diff --git a/server/notification-providers/feishu.js b/server/notification-providers/feishu.js index 683a3653d0..cd5331d2ab 100644 --- a/server/notification-providers/feishu.js +++ b/server/notification-providers/feishu.js @@ -5,9 +5,11 @@ const { DOWN, UP } = require("../../src/util"); class Feishu extends NotificationProvider { name = "Feishu"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; - let feishuWebHookUrl = notification.feishuWebHookUrl; + const okMsg = "Sent Successfully."; try { if (heartbeatJSON == null) { @@ -17,59 +19,67 @@ class Feishu extends NotificationProvider { text: msg, }, }; - await axios.post(feishuWebHookUrl, testdata); + await axios.post(notification.feishuWebHookUrl, testdata); return okMsg; } if (heartbeatJSON["status"] === DOWN) { let downdata = { - msg_type: "post", - content: { - post: { - zh_cn: { - title: "UptimeKuma Alert: [Down] " + monitorJSON["name"], - content: [ - [ - { - tag: "text", - text: - "[Down] " + - heartbeatJSON["msg"] + - `\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}` - }, - ], - ], + msg_type: "interactive", + card: { + config: { + update_multi: false, + wide_screen_mode: true, + }, + header: { + title: { + tag: "plain_text", + content: "UptimeKuma Alert: [Down] " + monitorJSON["name"], }, + template: "red", }, - }, + elements: [ + { + tag: "div", + text: { + tag: "lark_md", + content: getContent(heartbeatJSON), + }, + } + ] + } }; - await axios.post(feishuWebHookUrl, downdata); + await axios.post(notification.feishuWebHookUrl, downdata); return okMsg; } if (heartbeatJSON["status"] === UP) { let updata = { - msg_type: "post", - content: { - post: { - zh_cn: { - title: "UptimeKuma Alert: [Up] " + monitorJSON["name"], - content: [ - [ - { - tag: "text", - text: - "[Up] " + - heartbeatJSON["msg"] + - `\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`, - }, - ], - ], + msg_type: "interactive", + card: { + config: { + update_multi: false, + wide_screen_mode: true, + }, + header: { + title: { + tag: "plain_text", + content: "UptimeKuma Alert: [UP] " + monitorJSON["name"], }, + template: "green", }, - }, + elements: [ + { + tag: "div", + text: { + tag: "lark_md", + content: getContent(heartbeatJSON), + }, + }, + ] + } }; - await axios.post(feishuWebHookUrl, updata); + await axios.post(notification.feishuWebHookUrl, updata); return okMsg; } } catch (error) { @@ -78,4 +88,17 @@ class Feishu extends NotificationProvider { } } +/** + * Get content + * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only) + * @returns {string} Return Successful Message + */ +function getContent(heartbeatJSON) { + return [ + "**Message**: " + heartbeatJSON["msg"], + "**Ping**: " + (heartbeatJSON["ping"] == null ? "N/A" : heartbeatJSON["ping"] + " ms"), + `**Time (${heartbeatJSON["timezone"]})**: ${heartbeatJSON["localDateTime"]}` + ].join("\n"); +} + module.exports = Feishu; diff --git a/server/notification-providers/flashduty.js b/server/notification-providers/flashduty.js index 0d6f69e59c..c340ed06f1 100644 --- a/server/notification-providers/flashduty.js +++ b/server/notification-providers/flashduty.js @@ -7,6 +7,9 @@ const successMessage = "Sent Successfully."; class FlashDuty extends NotificationProvider { name = "FlashDuty"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { try { if (heartbeatJSON == null) { @@ -33,12 +36,12 @@ class FlashDuty extends NotificationProvider { this.throwGeneralAxiosError(error); } } + /** * Generate a monitor url from the monitors infomation - * @param {Object} monitorInfo Monitor details - * @returns {string|undefined} + * @param {object} monitorInfo Monitor details + * @returns {string|undefined} Monitor URL */ - genMonitorUrl(monitorInfo) { if (monitorInfo.type === "port" && monitorInfo.port) { return monitorInfo.hostname + ":" + monitorInfo.port; @@ -54,11 +57,20 @@ class FlashDuty extends NotificationProvider { * @param {BeanModel} notification Message title * @param {string} title Message * @param {string} body Message - * @param {Object} monitorInfo Monitor details + * @param {object} monitorInfo Monitor details * @param {string} eventStatus Monitor status (Info, Warning, Critical, Ok) - * @returns {string} + * @returns {string} Success message */ async postNotification(notification, title, body, monitorInfo, eventStatus) { + let labels = { + resource: this.genMonitorUrl(monitorInfo), + check: monitorInfo.name, + }; + if (monitorInfo.tags && monitorInfo.tags.length > 0) { + for (let tag of monitorInfo.tags) { + labels[tag.name] = tag.value; + } + } const options = { method: "POST", url: "https://api.flashcat.cloud/event/push/alert/standard?integration_key=" + notification.flashdutyIntegrationKey, @@ -68,9 +80,7 @@ class FlashDuty extends NotificationProvider { title, event_status: eventStatus || "Info", alert_key: String(monitorInfo.id) || Math.random().toString(36).substring(7), - labels: monitorInfo?.tags?.reduce((acc, item) => ({ ...acc, - [item.name]: item.value - }), { resource: this.genMonitorUrl(monitorInfo) }), + labels, } }; diff --git a/server/notification-providers/freemobile.js b/server/notification-providers/freemobile.js index 919150fa05..4de45acdd4 100644 --- a/server/notification-providers/freemobile.js +++ b/server/notification-providers/freemobile.js @@ -2,11 +2,14 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class FreeMobile extends NotificationProvider { - name = "FreeMobile"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + try { await axios.post(`https://smsapi.free-mobile.fr/sendmsg?msg=${encodeURIComponent(msg.replace("🔴", "⛔️"))}`, { "user": notification.freemobileUser, diff --git a/server/notification-providers/goalert.js b/server/notification-providers/goalert.js index 73e0375ac7..847c6a003f 100644 --- a/server/notification-providers/goalert.js +++ b/server/notification-providers/goalert.js @@ -3,18 +3,20 @@ const axios = require("axios"); const { UP } = require("../../src/util"); class GoAlert extends NotificationProvider { - name = "GoAlert"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + try { - let closeAction = "close"; let data = { summary: msg, }; if (heartbeatJSON != null && heartbeatJSON["status"] === UP) { - data["action"] = closeAction; + data["action"] = "close"; } let headers = { "Content-Type": "multipart/form-data", @@ -24,7 +26,6 @@ class GoAlert extends NotificationProvider { }; await axios.post(`${notification.goAlertBaseURL}/api/v2/generic/incoming?token=${notification.goAlertToken}`, data, config); return okMsg; - } catch (error) { let msg = (error.response.data) ? error.response.data : "Error without response"; throw new Error(msg); diff --git a/server/notification-providers/google-chat.js b/server/notification-providers/google-chat.js index 02cb4823c3..0b72fea95f 100644 --- a/server/notification-providers/google-chat.js +++ b/server/notification-providers/google-chat.js @@ -1,38 +1,85 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const { setting } = require("../util-server"); -const { getMonitorRelativeURL } = require("../../src/util"); -const { DOWN, UP } = require("../../src/util"); +const { getMonitorRelativeURL, UP } = require("../../src/util"); class GoogleChat extends NotificationProvider { - name = "GoogleChat"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + try { // Google Chat message formatting: https://developers.google.com/chat/api/guides/message-formats/basic - let textMsg = ""; - if (heartbeatJSON && heartbeatJSON.status === UP) { - textMsg = "✅ Application is back online\n"; - } else if (heartbeatJSON && heartbeatJSON.status === DOWN) { - textMsg = "🔴 Application went down\n"; - } + let chatHeader = { + title: "Uptime Kuma Alert", + }; - if (monitorJSON && monitorJSON.name) { - textMsg += `*${monitorJSON.name}*\n`; + if (monitorJSON && heartbeatJSON) { + chatHeader["title"] = + heartbeatJSON["status"] === UP + ? `✅ ${monitorJSON["name"]} is back online` + : `🔴 ${monitorJSON["name"]} went down`; } - textMsg += `${msg}`; + // always show msg + let sectionWidgets = [ + { + textParagraph: { + text: `Message:\n${msg}`, + }, + }, + ]; + // add time if available + if (heartbeatJSON) { + sectionWidgets.push({ + textParagraph: { + text: `Time (${heartbeatJSON["timezone"]}):\n${heartbeatJSON["localDateTime"]}`, + }, + }); + } + + // add button for monitor link if available const baseURL = await setting("primaryBaseURL"); - if (baseURL && monitorJSON) { - textMsg += `\n${baseURL + getMonitorRelativeURL(monitorJSON.id)}`; + if (baseURL) { + const urlPath = monitorJSON ? getMonitorRelativeURL(monitorJSON.id) : "/"; + sectionWidgets.push({ + buttonList: { + buttons: [ + { + text: "Visit Uptime Kuma", + onClick: { + openLink: { + url: baseURL + urlPath, + }, + }, + }, + ], + }, + }); } - const data = { - "text": textMsg, + let chatSections = [ + { + widgets: sectionWidgets, + }, + ]; + + // construct json data + let data = { + cardsV2: [ + { + card: { + header: chatHeader, + sections: chatSections, + }, + }, + ], }; await axios.post(notification.googleChatWebhookURL, data); diff --git a/server/notification-providers/gorush.js b/server/notification-providers/gorush.js index 6d756e46c2..ba9d470f7c 100644 --- a/server/notification-providers/gorush.js +++ b/server/notification-providers/gorush.js @@ -2,11 +2,13 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class Gorush extends NotificationProvider { - name = "gorush"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; let platformMapping = { "ios": 1, diff --git a/server/notification-providers/gotify.js b/server/notification-providers/gotify.js index 0c52449397..a52ef511a6 100644 --- a/server/notification-providers/gotify.js +++ b/server/notification-providers/gotify.js @@ -2,11 +2,14 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class Gotify extends NotificationProvider { - name = "gotify"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + try { if (notification.gotifyserverurl && notification.gotifyserverurl.endsWith("/")) { notification.gotifyserverurl = notification.gotifyserverurl.slice(0, -1); diff --git a/server/notification-providers/grafana-oncall.js b/server/notification-providers/grafana-oncall.js new file mode 100644 index 0000000000..e93c77cd99 --- /dev/null +++ b/server/notification-providers/grafana-oncall.js @@ -0,0 +1,51 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); +const { DOWN, UP } = require("../../src/util"); + +class GrafanaOncall extends NotificationProvider { + name = "GrafanaOncall"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + if (!notification.GrafanaOncallURL) { + throw new Error("GrafanaOncallURL cannot be empty"); + } + + try { + if (heartbeatJSON === null) { + let grafanaupdata = { + title: "General notification", + message: msg, + state: "alerting", + }; + await axios.post(notification.GrafanaOncallURL, grafanaupdata); + return okMsg; + } else if (heartbeatJSON["status"] === DOWN) { + let grafanadowndata = { + title: monitorJSON["name"] + " is down", + message: heartbeatJSON["msg"], + state: "alerting", + }; + await axios.post(notification.GrafanaOncallURL, grafanadowndata); + return okMsg; + } else if (heartbeatJSON["status"] === UP) { + let grafanaupdata = { + title: monitorJSON["name"] + " is up", + message: heartbeatJSON["msg"], + state: "ok", + }; + await axios.post(notification.GrafanaOncallURL, grafanaupdata); + return okMsg; + } + } catch (error) { + this.throwGeneralAxiosError(error); + } + + } +} + +module.exports = GrafanaOncall; diff --git a/server/notification-providers/gtx-messaging.js b/server/notification-providers/gtx-messaging.js new file mode 100644 index 0000000000..1ff97d11f5 --- /dev/null +++ b/server/notification-providers/gtx-messaging.js @@ -0,0 +1,33 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class GtxMessaging extends NotificationProvider { + name = "gtxmessaging"; + + /** + * @inheritDoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + // The UP/DOWN symbols will be replaced with `???` by gtx-messaging + const text = msg.replaceAll("🔴 ", "").replaceAll("✅ ", ""); + + try { + const data = new URLSearchParams(); + data.append("from", notification.gtxMessagingFrom.trim()); + data.append("to", notification.gtxMessagingTo.trim()); + data.append("text", text); + + const url = `https://rest.gtx-messaging.net/smsc/sendsms/${notification.gtxMessagingApiKey}/json`; + + await axios.post(url, data); + + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = GtxMessaging; diff --git a/server/notification-providers/heii-oncall.js b/server/notification-providers/heii-oncall.js new file mode 100644 index 0000000000..20b53e6afa --- /dev/null +++ b/server/notification-providers/heii-oncall.js @@ -0,0 +1,52 @@ +const { UP, DOWN, getMonitorRelativeURL } = require("../../src/util"); +const { setting } = require("../util-server"); + +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); +class HeiiOnCall extends NotificationProvider { + name = "HeiiOnCall"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + const payload = heartbeatJSON || {}; + + const baseURL = await setting("primaryBaseURL"); + if (baseURL && monitorJSON) { + payload["url"] = baseURL + getMonitorRelativeURL(monitorJSON.id); + } + + const config = { + headers: { + Accept: "application/json", + "Content-Type": "application/json", + Authorization: "Bearer " + notification.heiiOnCallApiKey, + }, + }; + const heiiUrl = `https://heiioncall.com/triggers/${notification.heiiOnCallTriggerId}/`; + // docs https://heiioncall.com/docs#manual-triggers + try { + if (!heartbeatJSON) { + // Testing or general notification like certificate expiry + payload["msg"] = msg; + await axios.post(heiiUrl + "alert", payload, config); + return okMsg; + } + + if (heartbeatJSON.status === DOWN) { + await axios.post(heiiUrl + "alert", payload, config); + return okMsg; + } + if (heartbeatJSON.status === UP) { + await axios.post(heiiUrl + "resolve", payload, config); + return okMsg; + } + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = HeiiOnCall; diff --git a/server/notification-providers/home-assistant.js b/server/notification-providers/home-assistant.js index 6b9504767a..4536b2a43f 100644 --- a/server/notification-providers/home-assistant.js +++ b/server/notification-providers/home-assistant.js @@ -6,7 +6,12 @@ const defaultNotificationService = "notify"; class HomeAssistant extends NotificationProvider { name = "HomeAssistant"; - async send(notification, message, monitor = null, heartbeat = null) { + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + const notificationService = notification?.notificationService || defaultNotificationService; try { @@ -14,10 +19,12 @@ class HomeAssistant extends NotificationProvider { `${notification.homeAssistantUrl.trim().replace(/\/*$/, "")}/api/services/notify/${notificationService}`, { title: "Uptime Kuma", - message, + message: msg, ...(notificationService !== "persistent_notification" && { data: { - name: monitor?.name, - status: heartbeat?.status, + name: monitorJSON?.name, + status: heartbeatJSON?.status, + channel: "Uptime Kuma", + icon_url: "https://github.com/louislam/uptime-kuma/blob/master/public/icon.png?raw=true", } }), }, { @@ -28,7 +35,7 @@ class HomeAssistant extends NotificationProvider { } ); - return "Sent Successfully."; + return okMsg; } catch (error) { this.throwGeneralAxiosError(error); } diff --git a/server/notification-providers/keep.js b/server/notification-providers/keep.js new file mode 100644 index 0000000000..aa65a867b9 --- /dev/null +++ b/server/notification-providers/keep.js @@ -0,0 +1,42 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class Keep extends NotificationProvider { + name = "Keep"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + try { + let data = { + heartbeat: heartbeatJSON, + monitor: monitorJSON, + msg, + }; + let config = { + headers: { + "x-api-key": notification.webhookAPIKey, + "content-type": "application/json", + }, + }; + + let url = notification.webhookURL; + + if (url.endsWith("/")) { + url = url.slice(0, -1); + } + + let webhookURL = url + "/alerts/event/uptimekuma"; + + await axios.post(webhookURL, data, config); + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = Keep; diff --git a/server/notification-providers/kook.js b/server/notification-providers/kook.js index b37b75ab1e..dab19513a9 100644 --- a/server/notification-providers/kook.js +++ b/server/notification-providers/kook.js @@ -2,12 +2,15 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class Kook extends NotificationProvider { - name = "Kook"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; - let url = "https://www.kookapp.cn/api/v3/message/create"; + const okMsg = "Sent Successfully."; + const url = "https://www.kookapp.cn/api/v3/message/create"; + let data = { target_id: notification.kookGuildID, content: msg, diff --git a/server/notification-providers/line.js b/server/notification-providers/line.js index 10b7f2c9b1..57dc87e78e 100644 --- a/server/notification-providers/line.js +++ b/server/notification-providers/line.js @@ -3,13 +3,16 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class Line extends NotificationProvider { - name = "line"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + const url = "https://api.line.me/v2/bot/message/push"; + try { - let lineAPIUrl = "https://api.line.me/v2/bot/message/push"; let config = { headers: { "Content-Type": "application/json", @@ -26,7 +29,7 @@ class Line extends NotificationProvider { } ] }; - await axios.post(lineAPIUrl, testMessage, config); + await axios.post(url, testMessage, config); } else if (heartbeatJSON["status"] === DOWN) { let downMessage = { "to": notification.lineUserID, @@ -40,7 +43,7 @@ class Line extends NotificationProvider { } ] }; - await axios.post(lineAPIUrl, downMessage, config); + await axios.post(url, downMessage, config); } else if (heartbeatJSON["status"] === UP) { let upMessage = { "to": notification.lineUserID, @@ -54,7 +57,7 @@ class Line extends NotificationProvider { } ] }; - await axios.post(lineAPIUrl, upMessage, config); + await axios.post(url, upMessage, config); } return okMsg; } catch (error) { diff --git a/server/notification-providers/linenotify.js b/server/notification-providers/linenotify.js index 279acb7d43..2622e3f1ca 100644 --- a/server/notification-providers/linenotify.js +++ b/server/notification-providers/linenotify.js @@ -4,13 +4,16 @@ const qs = require("qs"); const { DOWN, UP } = require("../../src/util"); class LineNotify extends NotificationProvider { - name = "LineNotify"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + const url = "https://notify-api.line.me/api/notify"; + try { - let lineAPIUrl = "https://notify-api.line.me/api/notify"; let config = { headers: { "Content-Type": "application/x-www-form-urlencoded", @@ -21,7 +24,7 @@ class LineNotify extends NotificationProvider { let testMessage = { "message": msg, }; - await axios.post(lineAPIUrl, qs.stringify(testMessage), config); + await axios.post(url, qs.stringify(testMessage), config); } else if (heartbeatJSON["status"] === DOWN) { let downMessage = { "message": "\n[🔴 Down]\n" + @@ -29,7 +32,7 @@ class LineNotify extends NotificationProvider { heartbeatJSON["msg"] + "\n" + `Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}` }; - await axios.post(lineAPIUrl, qs.stringify(downMessage), config); + await axios.post(url, qs.stringify(downMessage), config); } else if (heartbeatJSON["status"] === UP) { let upMessage = { "message": "\n[✅ Up]\n" + @@ -37,7 +40,7 @@ class LineNotify extends NotificationProvider { heartbeatJSON["msg"] + "\n" + `Time (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}` }; - await axios.post(lineAPIUrl, qs.stringify(upMessage), config); + await axios.post(url, qs.stringify(upMessage), config); } return okMsg; } catch (error) { diff --git a/server/notification-providers/lunasea.js b/server/notification-providers/lunasea.js index 0a5fea7b02..787a704a96 100644 --- a/server/notification-providers/lunasea.js +++ b/server/notification-providers/lunasea.js @@ -3,25 +3,23 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class LunaSea extends NotificationProvider { - name = "lunasea"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; - let lunaseaurl = ""; - if (notification.lunaseaTarget === "user") { - lunaseaurl = "https://notify.lunasea.app/v1/custom/user/" + notification.lunaseaUserID; - } else { - lunaseaurl = "https://notify.lunasea.app/v1/custom/device/" + notification.lunaseaDevice; - } + const okMsg = "Sent Successfully."; + const url = "https://notify.lunasea.app/v1"; try { + const target = this.getTarget(notification); if (heartbeatJSON == null) { let testdata = { "title": "Uptime Kuma Alert", "body": msg, }; - await axios.post(lunaseaurl, testdata); + await axios.post(`${url}/custom/${target}`, testdata); return okMsg; } @@ -32,7 +30,7 @@ class LunaSea extends NotificationProvider { heartbeatJSON["msg"] + `\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}` }; - await axios.post(lunaseaurl, downdata); + await axios.post(`${url}/custom/${target}`, downdata); return okMsg; } @@ -43,13 +41,25 @@ class LunaSea extends NotificationProvider { heartbeatJSON["msg"] + `\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}` }; - await axios.post(lunaseaurl, updata); + await axios.post(`${url}/custom/${target}`, updata); return okMsg; } } catch (error) { this.throwGeneralAxiosError(error); } + } + + /** + * Generates the lunasea target to send the notification to + * @param {BeanModel} notification Notification details + * @returns {string} The target to send the notification to + */ + getTarget(notification) { + if (notification.lunaseaTarget === "user") { + return "user/" + notification.lunaseaUserID; + } + return "device/" + notification.lunaseaDevice; } } diff --git a/server/notification-providers/matrix.js b/server/notification-providers/matrix.js index 915c772d77..805a494705 100644 --- a/server/notification-providers/matrix.js +++ b/server/notification-providers/matrix.js @@ -6,8 +6,11 @@ const { log } = require("../../src/util"); class Matrix extends NotificationProvider { name = "matrix"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; const size = 20; const randomString = encodeURIComponent( diff --git a/server/notification-providers/mattermost.js b/server/notification-providers/mattermost.js index d4997392cf..9946d02b2a 100644 --- a/server/notification-providers/mattermost.js +++ b/server/notification-providers/mattermost.js @@ -3,11 +3,14 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class Mattermost extends NotificationProvider { - name = "mattermost"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + try { const mattermostUserName = notification.mattermostusername || "Uptime Kuma"; // If heartbeatJSON is null, assume non monitoring notification (Certificate warning) or testing. @@ -75,12 +78,12 @@ class Mattermost extends NotificationProvider { { fallback: "Your " + - monitorJSON.name + + monitorJSON.pathName + " service went " + statusText, color: color, title: - monitorJSON.name + + monitorJSON.pathName + " service went " + statusText, title_link: monitorJSON.url, @@ -95,10 +98,7 @@ class Mattermost extends NotificationProvider { }, ], }; - await axios.post( - notification.mattermostWebhookUrl, - mattermostdata - ); + await axios.post(notification.mattermostWebhookUrl, mattermostdata); return okMsg; } catch (error) { this.throwGeneralAxiosError(error); diff --git a/server/notification-providers/nostr.js b/server/notification-providers/nostr.js index 2c17840d69..87847382e3 100644 --- a/server/notification-providers/nostr.js +++ b/server/notification-providers/nostr.js @@ -1,4 +1,3 @@ -const { log } = require("../../src/util"); const NotificationProvider = require("./notification-provider"); const { relayInit, @@ -12,16 +11,7 @@ const { // polyfills for node versions const semver = require("semver"); const nodeVersion = process.version; -if (semver.lt(nodeVersion, "16.0.0")) { - log.warn("monitor", "Node <= 16 is unsupported for nostr, sorry :("); -} else if (semver.lt(nodeVersion, "18.0.0")) { - // polyfills for node 16 - global.crypto = require("crypto"); - global.WebSocket = require("isomorphic-ws"); - if (typeof crypto !== "undefined" && !crypto.subtle && crypto.webcrypto) { - crypto.subtle = crypto.webcrypto.subtle; - } -} else if (semver.lt(nodeVersion, "20.0.0")) { +if (semver.lt(nodeVersion, "20.0.0")) { // polyfills for node 18 global.crypto = require("crypto"); global.WebSocket = require("isomorphic-ws"); @@ -33,6 +23,9 @@ if (semver.lt(nodeVersion, "16.0.0")) { class Nostr extends NotificationProvider { name = "nostr"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { // All DMs should have same timestamp const createdAt = Math.floor(Date.now() / 1000); @@ -86,6 +79,11 @@ class Nostr extends NotificationProvider { return `${successfulRelays}/${relays.length} relays connected.`; } + /** + * Get the private key for the sender + * @param {string} sender Sender to retrieve key for + * @returns {nip19.DecodeResult} Private key + */ async getPrivateKey(sender) { try { const senderDecodeResult = await nip19.decode(sender); @@ -96,6 +94,11 @@ class Nostr extends NotificationProvider { } } + /** + * Get public keys for recipients + * @param {string} recipients Newline delimited list of recipients + * @returns {Promise} Public keys + */ async getPublicKeys(recipients) { const recipientsList = recipients.split("\n"); const publicKeys = []; diff --git a/server/notification-providers/notification-provider.js b/server/notification-providers/notification-provider.js index 2a182d4252..b9fb3d863e 100644 --- a/server/notification-providers/notification-provider.js +++ b/server/notification-providers/notification-provider.js @@ -2,16 +2,16 @@ class NotificationProvider { /** * Notification Provider Name - * @type string + * @type {string} */ name = undefined; /** * Send a notification - * @param {BeanModel} notification + * @param {BeanModel} notification Notification to send * @param {string} msg General Message - * @param {?Object} monitorJSON Monitor details (For Up/Down only) - * @param {?Object} heartbeatJSON Heartbeat details (For Up/Down only) + * @param {?object} monitorJSON Monitor details (For Up/Down only) + * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only) * @returns {Promise} Return Successful Message * @throws Error with fail msg */ @@ -19,9 +19,40 @@ class NotificationProvider { throw new Error("Have to override Notification.send(...)"); } + /** + * Extracts the address from a monitor JSON object based on its type. + * @param {?object} monitorJSON Monitor details (For Up/Down only) + * @returns {string} The extracted address based on the monitor type. + */ + extractAddress(monitorJSON) { + if (!monitorJSON) { + return ""; + } + switch (monitorJSON["type"]) { + case "push": + return "Heartbeat"; + case "ping": + return monitorJSON["hostname"]; + case "port": + case "dns": + case "gamedig": + case "steam": + if (monitorJSON["port"]) { + return monitorJSON["hostname"] + ":" + monitorJSON["port"]; + } + return monitorJSON["hostname"]; + default: + if (![ "https://", "http://", "" ].includes(monitorJSON["url"])) { + return monitorJSON["url"]; + } + return ""; + } + } + /** * Throws an error * @param {any} error The error to throw + * @returns {void} * @throws {any} The error specified */ throwGeneralAxiosError(error) { diff --git a/server/notification-providers/ntfy.js b/server/notification-providers/ntfy.js index 2d8378e57c..ad1d39f8f3 100644 --- a/server/notification-providers/ntfy.js +++ b/server/notification-providers/ntfy.js @@ -3,11 +3,14 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class Ntfy extends NotificationProvider { - name = "ntfy"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + try { let headers = {}; if (notification.ntfyAuthenticationMethod === "usernamePassword") { @@ -28,7 +31,7 @@ class Ntfy extends NotificationProvider { "priority": notification.ntfyPriority, "tags": [ "test_tube" ], }; - await axios.post(`${notification.ntfyserverurl}`, ntfyTestData, { headers: headers }); + await axios.post(notification.ntfyserverurl, ntfyTestData, { headers: headers }); return okMsg; } let tags = []; @@ -51,20 +54,23 @@ class Ntfy extends NotificationProvider { "priority": priority, "title": monitorJSON.name + " " + status + " [Uptime-Kuma]", "tags": tags, - "actions": [ + }; + + if (monitorJSON.url && monitorJSON.url !== "https://") { + data.actions = [ { "action": "view", "label": "Open " + monitorJSON.name, "url": monitorJSON.url, - } - ] - }; + }, + ]; + } if (notification.ntfyIcon) { data.icon = notification.ntfyIcon; } - await axios.post(`${notification.ntfyserverurl}`, data, { headers: headers }); + await axios.post(notification.ntfyserverurl, data, { headers: headers }); return okMsg; diff --git a/server/notification-providers/octopush.js b/server/notification-providers/octopush.js index d5c475d3d4..7576e0ad6a 100644 --- a/server/notification-providers/octopush.js +++ b/server/notification-providers/octopush.js @@ -2,11 +2,15 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class Octopush extends NotificationProvider { - name = "octopush"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + const urlV2 = "https://api.octopush.com/v1/public/sms-campaign/send"; + const urlV1 = "https://www.octopush-dm.com/api/sms/json"; try { // Default - V2 @@ -30,7 +34,7 @@ class Octopush extends NotificationProvider { "purpose": "alert", "sender": notification.octopushSenderName }; - await axios.post("https://api.octopush.com/v1/public/sms-campaign/send", data, config); + await axios.post(urlV2, data, config); } else if (notification.octopushVersion === "1") { let data = { "user_login": notification.octopushDMLogin, @@ -52,7 +56,7 @@ class Octopush extends NotificationProvider { // V1 API returns 200 even on error so we must check // response data - let response = await axios.post("https://www.octopush-dm.com/api/sms/json", {}, config); + let response = await axios.post(urlV1, {}, config); if ("error_code" in response.data) { if (response.data.error_code !== "000") { this.throwGeneralAxiosError(`Octopush error ${JSON.stringify(response.data)}`); diff --git a/server/notification-providers/onebot.js b/server/notification-providers/onebot.js index 6c62eccb5d..b04794dee1 100644 --- a/server/notification-providers/onebot.js +++ b/server/notification-providers/onebot.js @@ -2,20 +2,23 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class OneBot extends NotificationProvider { - name = "OneBot"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + try { - let httpAddr = notification.httpAddr; - if (!httpAddr.startsWith("http")) { - httpAddr = "http://" + httpAddr; + let url = notification.httpAddr; + if (!url.startsWith("http")) { + url = "http://" + url; } - if (!httpAddr.endsWith("/")) { - httpAddr += "/"; + if (!url.endsWith("/")) { + url += "/"; } - let onebotAPIUrl = httpAddr + "send_msg"; + url += "send_msg"; let config = { headers: { "Content-Type": "application/json", @@ -34,7 +37,7 @@ class OneBot extends NotificationProvider { data["message_type"] = "private"; data["user_id"] = notification.recieverId; } - await axios.post(onebotAPIUrl, data, config); + await axios.post(url, data, config); return okMsg; } catch (error) { this.throwGeneralAxiosError(error); diff --git a/server/notification-providers/onesender.js b/server/notification-providers/onesender.js new file mode 100644 index 0000000000..4a33931a24 --- /dev/null +++ b/server/notification-providers/onesender.js @@ -0,0 +1,47 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class Onesender extends NotificationProvider { + name = "Onesender"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + try { + let data = { + heartbeat: heartbeatJSON, + monitor: monitorJSON, + msg, + to: notification.onesenderReceiver, + type: "text", + recipient_type: "individual", + text: { + body: msg + } + }; + if (notification.onesenderTypeReceiver === "private") { + data.to = notification.onesenderReceiver + "@s.whatsapp.net"; + } else { + data.recipient_type = "group"; + data.to = notification.onesenderReceiver + "@g.us"; + } + let config = { + headers: { + "Authorization": "Bearer " + notification.onesenderToken, + } + }; + await axios.post(notification.onesenderURL, data, config); + return okMsg; + + } catch (error) { + this.throwGeneralAxiosError(error); + } + + } + +} + +module.exports = Onesender; diff --git a/server/notification-providers/opsgenie.js b/server/notification-providers/opsgenie.js index 39cdec9fb7..59a7970553 100644 --- a/server/notification-providers/opsgenie.js +++ b/server/notification-providers/opsgenie.js @@ -4,10 +4,9 @@ const { UP, DOWN } = require("../../src/util"); const opsgenieAlertsUrlEU = "https://api.eu.opsgenie.com/v2/alerts"; const opsgenieAlertsUrlUS = "https://api.opsgenie.com/v2/alerts"; -let okMsg = "Sent Successfully."; +const okMsg = "Sent Successfully."; class Opsgenie extends NotificationProvider { - name = "Opsgenie"; /** @@ -68,11 +67,11 @@ class Opsgenie extends NotificationProvider { } /** - * - * @param {BeanModel} notification + * Make POST request to Opsgenie + * @param {BeanModel} notification Notification to send * @param {string} url Request url - * @param {Object} data Request body - * @returns {Promise} + * @param {object} data Request body + * @returns {Promise} Success message */ async post(notification, url, data) { let config = { diff --git a/server/notification-providers/pagerduty.js b/server/notification-providers/pagerduty.js index 86e9a09928..c60d782e76 100644 --- a/server/notification-providers/pagerduty.js +++ b/server/notification-providers/pagerduty.js @@ -39,7 +39,8 @@ class PagerDuty extends NotificationProvider { /** * Check if result is successful, result code should be in range 2xx - * @param {Object} result Axios response object + * @param {object} result Axios response object + * @returns {void} * @throws {Error} The status code is not in range 2xx */ checkResult(result) { @@ -56,9 +57,9 @@ class PagerDuty extends NotificationProvider { * @param {BeanModel} notification Message title * @param {string} title Message title * @param {string} body Message - * @param {Object} monitorInfo Monitor details (For Up/Down only) + * @param {object} monitorInfo Monitor details (For Up/Down only) * @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve) - * @returns {string} + * @returns {Promise} Success message */ async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") { diff --git a/server/notification-providers/pagertree.js b/server/notification-providers/pagertree.js index 8a0c4e3686..c7a5338d1f 100644 --- a/server/notification-providers/pagertree.js +++ b/server/notification-providers/pagertree.js @@ -32,7 +32,8 @@ class PagerTree extends NotificationProvider { /** * Check if result is successful, result code should be in range 2xx - * @param {Object} result Axios response object + * @param {object} result Axios response object + * @returns {void} * @throws {Error} The status code is not in range 2xx */ checkResult(result) { @@ -48,9 +49,10 @@ class PagerTree extends NotificationProvider { * Send the message * @param {BeanModel} notification Message title * @param {string} title Message title - * @param {Object} monitorJSON Monitor details (For Up/Down only) + * @param {object} monitorJSON Monitor details (For Up/Down only) + * @param {object} heartbeatJSON Heartbeat details (For Up/Down only) * @param {?string} eventAction Action event for PagerTree (create, resolve) - * @returns {string} + * @returns {Promise} Success state */ async postNotification(notification, title, monitorJSON, heartbeatJSON, eventAction = "create") { diff --git a/server/notification-providers/promosms.js b/server/notification-providers/promosms.js index 572a213258..05334e902e 100644 --- a/server/notification-providers/promosms.js +++ b/server/notification-providers/promosms.js @@ -2,11 +2,14 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class PromoSMS extends NotificationProvider { - name = "promosms"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + const url = "https://promosms.com/api/rest/v3_2/sms"; if (notification.promosmsAllowLongSMS === undefined) { notification.promosmsAllowLongSMS = false; @@ -33,7 +36,7 @@ class PromoSMS extends NotificationProvider { "sender": notification.promosmsSenderName }; - let resp = await axios.post("https://promosms.com/api/rest/v3_2/sms", data, config); + let resp = await axios.post(url, data, config); if (resp.data.response.status !== 0) { let error = "Something gone wrong. Api returned " + resp.data.response.status + "."; diff --git a/server/notification-providers/pushbullet.js b/server/notification-providers/pushbullet.js index f3d95a85e1..0b73031039 100644 --- a/server/notification-providers/pushbullet.js +++ b/server/notification-providers/pushbullet.js @@ -4,14 +4,16 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class Pushbullet extends NotificationProvider { - name = "pushbullet"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + const url = "https://api.pushbullet.com/v2/pushes"; try { - let pushbulletUrl = "https://api.pushbullet.com/v2/pushes"; let config = { headers: { "Access-Token": notification.pushbulletAccessToken, @@ -24,7 +26,7 @@ class Pushbullet extends NotificationProvider { "title": "Uptime Kuma Alert", "body": msg, }; - await axios.post(pushbulletUrl, data, config); + await axios.post(url, data, config); } else if (heartbeatJSON["status"] === DOWN) { let downData = { "type": "note", @@ -33,7 +35,7 @@ class Pushbullet extends NotificationProvider { heartbeatJSON["msg"] + `\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`, }; - await axios.post(pushbulletUrl, downData, config); + await axios.post(url, downData, config); } else if (heartbeatJSON["status"] === UP) { let upData = { "type": "note", @@ -42,7 +44,7 @@ class Pushbullet extends NotificationProvider { heartbeatJSON["msg"] + `\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`, }; - await axios.post(pushbulletUrl, upData, config); + await axios.post(url, upData, config); } return okMsg; } catch (error) { diff --git a/server/notification-providers/pushdeer.js b/server/notification-providers/pushdeer.js index 288137d180..276c2f476b 100644 --- a/server/notification-providers/pushdeer.js +++ b/server/notification-providers/pushdeer.js @@ -3,14 +3,15 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class PushDeer extends NotificationProvider { - name = "PushDeer"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; - let endpoint = "/message/push"; - let serverUrl = notification.pushdeerServer || "https://api2.pushdeer.com"; - let pushdeerlink = `${serverUrl.trim().replace(/\/*$/, "")}${endpoint}`; + const okMsg = "Sent Successfully."; + const serverUrl = notification.pushdeerServer || "https://api2.pushdeer.com"; + const url = `${serverUrl.trim().replace(/\/*$/, "")}/message/push`; let valid = msg != null && monitorJSON != null && heartbeatJSON != null; @@ -31,7 +32,7 @@ class PushDeer extends NotificationProvider { }; try { - let res = await axios.post(pushdeerlink, data); + let res = await axios.post(url, data); if ("error" in res.data) { let error = res.data.error; diff --git a/server/notification-providers/pushover.js b/server/notification-providers/pushover.js index b333b476eb..8422b64c27 100644 --- a/server/notification-providers/pushover.js +++ b/server/notification-providers/pushover.js @@ -1,13 +1,18 @@ +const { getMonitorRelativeURL } = require("../../src/util"); +const { setting } = require("../util-server"); + const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class Pushover extends NotificationProvider { - name = "pushover"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; - let pushoverlink = "https://api.pushover.net/1/messages.json"; + const okMsg = "Sent Successfully."; + const url = "https://api.pushover.net/1/messages.json"; let data = { "message": msg, @@ -21,6 +26,12 @@ class Pushover extends NotificationProvider { "html": 1, }; + const baseURL = await setting("primaryBaseURL"); + if (baseURL && monitorJSON) { + data["url"] = baseURL + getMonitorRelativeURL(monitorJSON.id); + data["url_title"] = "Link to Monitor"; + } + if (notification.pushoverdevice) { data.device = notification.pushoverdevice; } @@ -30,11 +41,11 @@ class Pushover extends NotificationProvider { try { if (heartbeatJSON == null) { - await axios.post(pushoverlink, data); + await axios.post(url, data); return okMsg; } else { data.message += `\nTime (${heartbeatJSON["timezone"]}):${heartbeatJSON["localDateTime"]}`; - await axios.post(pushoverlink, data); + await axios.post(url, data); return okMsg; } } catch (error) { diff --git a/server/notification-providers/pushy.js b/server/notification-providers/pushy.js index 1d6e7f32f2..cb700229ad 100644 --- a/server/notification-providers/pushy.js +++ b/server/notification-providers/pushy.js @@ -2,11 +2,13 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class Pushy extends NotificationProvider { - name = "pushy"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { await axios.post(`https://api.pushy.me/push?api_key=${notification.pushyAPIKey}`, { diff --git a/server/notification-providers/rocket-chat.js b/server/notification-providers/rocket-chat.js index 76b964a3a0..690e33a86e 100644 --- a/server/notification-providers/rocket-chat.js +++ b/server/notification-providers/rocket-chat.js @@ -5,11 +5,14 @@ const { setting } = require("../util-server"); const { getMonitorRelativeURL, DOWN } = require("../../src/util"); class RocketChat extends NotificationProvider { - name = "rocket.chat"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + try { if (heartbeatJSON == null) { let data = { diff --git a/server/notification-providers/send-grid.js b/server/notification-providers/send-grid.js new file mode 100644 index 0000000000..3489f63850 --- /dev/null +++ b/server/notification-providers/send-grid.js @@ -0,0 +1,65 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class SendGrid extends NotificationProvider { + name = "SendGrid"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + try { + let config = { + headers: { + "Content-Type": "application/json", + Authorization: `Bearer ${notification.sendgridApiKey}`, + }, + }; + + let personalizations = { + to: [{ email: notification.sendgridToEmail }], + }; + + // Add CC recipients if provided + if (notification.sendgridCcEmail) { + personalizations.cc = notification.sendgridCcEmail + .split(",") + .map((email) => ({ email: email.trim() })); + } + + // Add BCC recipients if provided + if (notification.sendgridBccEmail) { + personalizations.bcc = notification.sendgridBccEmail + .split(",") + .map((email) => ({ email: email.trim() })); + } + + let data = { + personalizations: [ personalizations ], + from: { email: notification.sendgridFromEmail.trim() }, + subject: + notification.sendgridSubject || + "Notification from Your Uptime Kuma", + content: [ + { + type: "text/plain", + value: msg, + }, + ], + }; + + await axios.post( + "https://api.sendgrid.com/v3/mail/send", + data, + config + ); + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = SendGrid; diff --git a/server/notification-providers/serverchan.js b/server/notification-providers/serverchan.js index d631c8e610..aee22f83f7 100644 --- a/server/notification-providers/serverchan.js +++ b/server/notification-providers/serverchan.js @@ -3,13 +3,22 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class ServerChan extends NotificationProvider { - name = "ServerChan"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + + // serverchan3 requires sending via ft07.com + const matchResult = String(notification.serverChanSendKey).match(/^sctp(\d+)t/i); + const url = matchResult && matchResult[1] + ? `https://${matchResult[1]}.push.ft07.com/send/${notification.serverChanSendKey}.send` + : `https://sctapi.ftqq.com/${notification.serverChanSendKey}.send`; + try { - await axios.post(`https://sctapi.ftqq.com/${notification.serverChanSendKey}.send`, { + await axios.post(url, { "title": this.checkStatus(heartbeatJSON, monitorJSON), "desp": msg, }); @@ -23,8 +32,8 @@ class ServerChan extends NotificationProvider { /** * Get the formatted title for message - * @param {?Object} monitorJSON Monitor details (For Up/Down only) - * @param {?Object} heartbeatJSON Heartbeat details (For Up/Down only) + * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only) + * @param {?object} monitorJSON Monitor details (For Up/Down only) * @returns {string} Formatted title */ checkStatus(heartbeatJSON, monitorJSON) { diff --git a/server/notification-providers/serwersms.js b/server/notification-providers/serwersms.js index 14fe691a80..f7c8644afb 100644 --- a/server/notification-providers/serwersms.js +++ b/server/notification-providers/serwersms.js @@ -2,11 +2,14 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class SerwerSMS extends NotificationProvider { - name = "serwersms"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + const url = "https://api2.serwersms.pl/messages/send_sms"; try { let config = { @@ -22,7 +25,7 @@ class SerwerSMS extends NotificationProvider { "sender": notification.serwersmsSenderName, }; - let resp = await axios.post("https://api2.serwersms.pl/messages/send_sms", data, config); + let resp = await axios.post(url, data, config); if (!resp.data.success) { if (resp.data.error) { diff --git a/server/notification-providers/sevenio.js b/server/notification-providers/sevenio.js new file mode 100644 index 0000000000..eac38a26ee --- /dev/null +++ b/server/notification-providers/sevenio.js @@ -0,0 +1,57 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); +const { DOWN, UP } = require("../../src/util"); + +class SevenIO extends NotificationProvider { + name = "SevenIO"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + const data = { + to: notification.sevenioTo, + from: notification.sevenioSender || "Uptime Kuma", + text: msg, + }; + + const config = { + baseURL: "https://gateway.seven.io/api/", + headers: { + "Content-Type": "application/json", + "X-API-Key": notification.sevenioApiKey, + }, + }; + + try { + // testing or certificate expiry notification + if (heartbeatJSON == null) { + await axios.post("sms", data, config); + return okMsg; + } + + let address = this.extractAddress(monitorJSON); + if (address !== "") { + address = `(${address}) `; + } + + // If heartbeatJSON is not null, we go into the normal alerting loop. + if (heartbeatJSON["status"] === DOWN) { + data.text = `Your service ${monitorJSON["name"]} ${address}went down at ${heartbeatJSON["localDateTime"]} ` + + `(${heartbeatJSON["timezone"]}). Error: ${heartbeatJSON["msg"]}`; + } else if (heartbeatJSON["status"] === UP) { + data.text = `Your service ${monitorJSON["name"]} ${address}went back up at ${heartbeatJSON["localDateTime"]} ` + + `(${heartbeatJSON["timezone"]}).`; + } + await axios.post("sms", data, config); + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } + +} + +module.exports = SevenIO; diff --git a/server/notification-providers/signal.js b/server/notification-providers/signal.js index 677208ee63..9702d06bbf 100644 --- a/server/notification-providers/signal.js +++ b/server/notification-providers/signal.js @@ -2,11 +2,13 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class Signal extends NotificationProvider { - name = "signal"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { let data = { diff --git a/server/notification-providers/signl4.js b/server/notification-providers/signl4.js new file mode 100644 index 0000000000..8261a73f36 --- /dev/null +++ b/server/notification-providers/signl4.js @@ -0,0 +1,52 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); +const { UP, DOWN } = require("../../src/util"); + +class SIGNL4 extends NotificationProvider { + name = "SIGNL4"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + try { + let data = { + heartbeat: heartbeatJSON, + monitor: monitorJSON, + msg, + // Source system + "X-S4-SourceSystem": "UptimeKuma", + monitorUrl: this.extractAddress(monitorJSON), + }; + + const config = { + headers: { + "Content-Type": "application/json" + } + }; + + if (heartbeatJSON == null) { + // Test alert + data.title = "Uptime Kuma Alert"; + data.message = msg; + } else if (heartbeatJSON.status === UP) { + data.title = "Uptime Kuma Monitor ✅ Up"; + data["X-S4-ExternalID"] = "UptimeKuma-" + monitorJSON.monitorID; + data["X-S4-Status"] = "resolved"; + } else if (heartbeatJSON.status === DOWN) { + data.title = "Uptime Kuma Monitor 🔴 Down"; + data["X-S4-ExternalID"] = "UptimeKuma-" + monitorJSON.monitorID; + data["X-S4-Status"] = "new"; + } + + await axios.post(notification.webhookURL, data, config); + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = SIGNL4; diff --git a/server/notification-providers/slack.js b/server/notification-providers/slack.js index 41c2bd02c3..5e25a1fbc2 100644 --- a/server/notification-providers/slack.js +++ b/server/notification-providers/slack.js @@ -1,16 +1,17 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); const { setSettings, setting } = require("../util-server"); -const { getMonitorRelativeURL, UP } = require("../../src/util"); +const { getMonitorRelativeURL, UP, log } = require("../../src/util"); class Slack extends NotificationProvider { - name = "slack"; /** * Deprecated property notification.slackbutton * Set it as primary base url if this is not yet set. + * @deprecated * @param {string} url The primary base URL to use + * @returns {Promise} */ static async deprecateURL(url) { let currentPrimaryBaseURL = await setting("primaryBaseURL"); @@ -25,8 +26,104 @@ class Slack extends NotificationProvider { } } + /** + * Builds the actions available in the slack message + * @param {string} baseURL Uptime Kuma base URL + * @param {object} monitorJSON The monitor config + * @returns {Array} The relevant action objects + */ + buildActions(baseURL, monitorJSON) { + const actions = []; + + if (baseURL) { + actions.push({ + "type": "button", + "text": { + "type": "plain_text", + "text": "Visit Uptime Kuma", + }, + "value": "Uptime-Kuma", + "url": baseURL + getMonitorRelativeURL(monitorJSON.id), + }); + + } + + const address = this.extractAddress(monitorJSON); + if (address) { + try { + actions.push({ + "type": "button", + "text": { + "type": "plain_text", + "text": "Visit site", + }, + "value": "Site", + "url": new URL(address), + }); + + } catch (e) { + log.debug("slack", `Failed to parse address ${address} as URL`); + } + } + + return actions; + } + + /** + * Builds the different blocks the Slack message consists of. + * @param {string} baseURL Uptime Kuma base URL + * @param {object} monitorJSON The monitor object + * @param {object} heartbeatJSON The heartbeat object + * @param {string} title The message title + * @param {string} msg The message body + * @returns {Array} The rich content blocks for the Slack message + */ + buildBlocks(baseURL, monitorJSON, heartbeatJSON, title, msg) { + + //create an array to dynamically add blocks + const blocks = []; + + // the header block + blocks.push({ + "type": "header", + "text": { + "type": "plain_text", + "text": title, + }, + }); + + // the body block, containing the details + blocks.push({ + "type": "section", + "fields": [ + { + "type": "mrkdwn", + "text": "*Message*\n" + msg, + }, + { + "type": "mrkdwn", + "text": `*Time (${heartbeatJSON["timezone"]})*\n${heartbeatJSON["localDateTime"]}`, + } + ], + }); + + const actions = this.buildActions(baseURL, monitorJSON); + if (actions.length > 0) { + //the actions block, containing buttons + blocks.push({ + "type": "actions", + "elements": actions, + }); + } + + return blocks; + } + + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; if (notification.slackchannelnotify) { msg += " "; @@ -44,63 +141,31 @@ class Slack extends NotificationProvider { return okMsg; } - const textMsg = "Uptime Kuma Alert"; + const baseURL = await setting("primaryBaseURL"); + + const title = "Uptime Kuma Alert"; let data = { - "text": `${textMsg}\n${msg}`, "channel": notification.slackchannel, "username": notification.slackusername, "icon_emoji": notification.slackiconemo, - "attachments": [ + "attachments": [], + }; + + if (notification.slackrichmessage) { + data.attachments.push( { "color": (heartbeatJSON["status"] === UP) ? "#2eb886" : "#e01e5a", - "blocks": [ - { - "type": "header", - "text": { - "type": "plain_text", - "text": textMsg, - }, - }, - { - "type": "section", - "fields": [{ - "type": "mrkdwn", - "text": "*Message*\n" + msg, - }, - { - "type": "mrkdwn", - "text": `*Time (${heartbeatJSON["timezone"]})*\n${heartbeatJSON["localDateTime"]}`, - }], - } - ], + "blocks": this.buildBlocks(baseURL, monitorJSON, heartbeatJSON, title, msg), } - ] - }; + ); + } else { + data.text = `${title}\n${msg}`; + } if (notification.slackbutton) { await Slack.deprecateURL(notification.slackbutton); } - const baseURL = await setting("primaryBaseURL"); - - // Button - if (baseURL) { - data.attachments.forEach(element => { - element.blocks.push({ - "type": "actions", - "elements": [{ - "type": "button", - "text": { - "type": "plain_text", - "text": "Visit Uptime Kuma", - }, - "value": "Uptime-Kuma", - "url": baseURL + getMonitorRelativeURL(monitorJSON.id), - }], - }); - }); - } - await axios.post(notification.slackwebhookURL, data); return okMsg; } catch (error) { diff --git a/server/notification-providers/smsc.js b/server/notification-providers/smsc.js index 251bc45540..89f01d01d1 100644 --- a/server/notification-providers/smsc.js +++ b/server/notification-providers/smsc.js @@ -4,8 +4,13 @@ const axios = require("axios"); class SMSC extends NotificationProvider { name = "smsc"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + const url = "https://smsc.kz/sys/send.php?"; + try { let config = { headers: { @@ -26,7 +31,7 @@ class SMSC extends NotificationProvider { getArray.push("sender=" + notification.smscSenderName); } - let resp = await axios.get("https://smsc.kz/sys/send.php?" + getArray.join("&"), config); + let resp = await axios.get(url + getArray.join("&"), config); if (resp.data.id === undefined) { let error = `Something gone wrong. Api returned code ${resp.data.error_code}: ${resp.data.error}`; this.throwGeneralAxiosError(error); diff --git a/server/notification-providers/smseagle.js b/server/notification-providers/smseagle.js index c431297ec2..4e897006c7 100644 --- a/server/notification-providers/smseagle.js +++ b/server/notification-providers/smseagle.js @@ -2,11 +2,13 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class SMSEagle extends NotificationProvider { - name = "SMSEagle"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { let config = { diff --git a/server/notification-providers/smsmanager.js b/server/notification-providers/smsmanager.js index 833bff60fa..d01285d88d 100644 --- a/server/notification-providers/smsmanager.js +++ b/server/notification-providers/smsmanager.js @@ -2,20 +2,24 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class SMSManager extends NotificationProvider { - name = "SMSManager"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + const url = "https://http-api.smsmanager.cz/Send"; + try { let data = { apikey: notification.smsmanagerApiKey, - endpoint: "https://http-api.smsmanager.cz/Send", message: msg.replace(/[^\x00-\x7F]/g, ""), - to: notification.numbers, - messageType: notification.messageType, + number: notification.numbers, + gateway: notification.messageType, }; - await axios.get(`${data.endpoint}?apikey=${data.apikey}&message=${data.message}&number=${data.to}&gateway=${data.messageType}`); - return "SMS sent sucessfully."; + await axios.get(`${url}?apikey=${data.apikey}&message=${data.message}&number=${data.number}&gateway=${data.messageType}`); + return okMsg; } catch (error) { this.throwGeneralAxiosError(error); } diff --git a/server/notification-providers/smspartner.js b/server/notification-providers/smspartner.js new file mode 100644 index 0000000000..5595217a48 --- /dev/null +++ b/server/notification-providers/smspartner.js @@ -0,0 +1,46 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class SMSPartner extends NotificationProvider { + name = "SMSPartner"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + const url = "https://api.smspartner.fr/v1/send"; + + try { + // smspartner does not support non ascii characters and only a maximum 639 characters + let cleanMsg = msg.replace(/[^\x00-\x7F]/g, "").substring(0, 639); + + let data = { + "apiKey": notification.smspartnerApikey, + "sender": notification.smspartnerSenderName.substring(0, 11), + "phoneNumbers": notification.smspartnerPhoneNumber, + "message": cleanMsg, + }; + + let config = { + headers: { + "Content-Type": "application/json", + "cache-control": "no-cache", + "Accept": "application/json", + } + }; + + let resp = await axios.post(url, data, config); + + if (resp.data.success !== true) { + throw Error(`Api returned ${resp.data.response.status}.`); + } + + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } +} + +module.exports = SMSPartner; diff --git a/server/notification-providers/smtp.js b/server/notification-providers/smtp.js index 9b59ec09be..9f3defa5ee 100644 --- a/server/notification-providers/smtp.js +++ b/server/notification-providers/smtp.js @@ -1,12 +1,16 @@ const nodemailer = require("nodemailer"); const NotificationProvider = require("./notification-provider"); const { DOWN } = require("../../src/util"); +const { Liquid } = require("liquidjs"); class SMTP extends NotificationProvider { - name = "smtp"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; const config = { host: notification.smtpHost, @@ -36,75 +40,80 @@ class SMTP extends NotificationProvider { pass: notification.smtpPassword, }; } - // Lets start with default subject and empty string for custom one - let subject = msg; - // Change the subject if: - // - The msg ends with "Testing" or - // - Actual Up/Down Notification + // default values in case the user does not want to template + let subject = msg; + let body = msg; + if (heartbeatJSON) { + body = `${msg}\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`; + } + // subject and body are templated if ((monitorJSON && heartbeatJSON) || msg.endsWith("Testing")) { - let customSubject = ""; - - // Our subject cannot end with whitespace it's often raise spam score - // Once I got "Cannot read property 'trim' of undefined", better be safe than sorry - if (notification.customSubject) { - customSubject = notification.customSubject.trim(); - } + // cannot end with whitespace as this often raises spam scores + const customSubject = notification.customSubject?.trim() || ""; + const customBody = notification.customBody?.trim() || ""; - // If custom subject is not empty, change subject for notification + const context = this.generateContext(msg, monitorJSON, heartbeatJSON); + const engine = new Liquid(); if (customSubject !== "") { - - // Replace "MACROS" with corresponding variable - let replaceName = new RegExp("{{NAME}}", "g"); - let replaceHostnameOrURL = new RegExp("{{HOSTNAME_OR_URL}}", "g"); - let replaceStatus = new RegExp("{{STATUS}}", "g"); - - // Lets start with dummy values to simplify code - let monitorName = "Test"; - let monitorHostnameOrURL = "testing.hostname"; - let serviceStatus = "⚠️ Test"; - - if (monitorJSON !== null) { - monitorName = monitorJSON["name"]; - - if (monitorJSON["type"] === "http" || monitorJSON["type"] === "keyword" || monitorJSON["type"] === "json-query") { - monitorHostnameOrURL = monitorJSON["url"]; - } else { - monitorHostnameOrURL = monitorJSON["hostname"]; - } - } - - if (heartbeatJSON !== null) { - serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up"; - } - - // Break replace to one by line for better readability - customSubject = customSubject.replace(replaceStatus, serviceStatus); - customSubject = customSubject.replace(replaceName, monitorName); - customSubject = customSubject.replace(replaceHostnameOrURL, monitorHostnameOrURL); - - subject = customSubject; + const tpl = engine.parse(customSubject); + subject = await engine.render(tpl, context); + } + if (customBody !== "") { + const tpl = engine.parse(customBody); + body = await engine.render(tpl, context); } - } - - let transporter = nodemailer.createTransport(config); - - let bodyTextContent = msg; - if (heartbeatJSON) { - bodyTextContent = `${msg}\nTime (${heartbeatJSON["timezone"]}): ${heartbeatJSON["localDateTime"]}`; } // send mail with defined transport object + let transporter = nodemailer.createTransport(config); await transporter.sendMail({ from: notification.smtpFrom, cc: notification.smtpCC, bcc: notification.smtpBCC, to: notification.smtpTo, subject: subject, - text: bodyTextContent, + text: body, }); - return "Sent Successfully."; + return okMsg; + } + + /** + * Generate context for LiquidJS + * @param {string} msg the message that will be included in the context + * @param {?object} monitorJSON Monitor details (For Up/Down/Cert-Expiry only) + * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only) + * @returns {{STATUS: string, status: string, HOSTNAME_OR_URL: string, hostnameOrUrl: string, NAME: string, name: string, monitorJSON: ?object, heartbeatJSON: ?object, msg: string}} the context + */ + generateContext(msg, monitorJSON, heartbeatJSON) { + // Let's start with dummy values to simplify code + let monitorName = "Monitor Name not available"; + let monitorHostnameOrURL = "testing.hostname"; + + if (monitorJSON !== null) { + monitorName = monitorJSON["name"]; + monitorHostnameOrURL = this.extractAddress(monitorJSON); + } + + let serviceStatus = "⚠️ Test"; + if (heartbeatJSON !== null) { + serviceStatus = (heartbeatJSON["status"] === DOWN) ? "🔴 Down" : "✅ Up"; + } + return { + // for v1 compatibility, to be removed in v3 + "STATUS": serviceStatus, + "NAME": monitorName, + "HOSTNAME_OR_URL": monitorHostnameOrURL, + + // variables which are officially supported + "status": serviceStatus, + "name": monitorName, + "hostnameOrURL": monitorHostnameOrURL, + monitorJSON, + heartbeatJSON, + msg, + }; } } diff --git a/server/notification-providers/splunk.js b/server/notification-providers/splunk.js index 2d82dd397a..e07c51039b 100644 --- a/server/notification-providers/splunk.js +++ b/server/notification-providers/splunk.js @@ -37,7 +37,8 @@ class Splunk extends NotificationProvider { /** * Check if result is successful, result code should be in range 2xx - * @param {Object} result Axios response object + * @param {object} result Axios response object + * @returns {void} * @throws {Error} The status code is not in range 2xx */ checkResult(result) { @@ -54,9 +55,9 @@ class Splunk extends NotificationProvider { * @param {BeanModel} notification Message title * @param {string} title Message title * @param {string} body Message - * @param {Object} monitorInfo Monitor details (For Up/Down only) + * @param {object} monitorInfo Monitor details (For Up/Down only) * @param {?string} eventAction Action event for PagerDuty (trigger, acknowledge, resolve) - * @returns {string} + * @returns {Promise} Success state */ async postNotification(notification, title, body, monitorInfo, eventAction = "trigger") { diff --git a/server/notification-providers/squadcast.js b/server/notification-providers/squadcast.js index 15553ff7e3..5713783c0b 100644 --- a/server/notification-providers/squadcast.js +++ b/server/notification-providers/squadcast.js @@ -3,11 +3,13 @@ const axios = require("axios"); const { DOWN } = require("../../src/util"); class Squadcast extends NotificationProvider { - name = "squadcast"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { @@ -32,25 +34,7 @@ class Squadcast extends NotificationProvider { data.status = "resolve"; } - let address; - switch (monitorJSON["type"]) { - case "ping": - address = monitorJSON["hostname"]; - break; - case "port": - case "dns": - case "steam": - address = monitorJSON["hostname"]; - if (monitorJSON["port"]) { - address += ":" + monitorJSON["port"]; - } - break; - default: - address = monitorJSON["url"]; - break; - } - - data.tags["AlertAddress"] = address; + data.tags["AlertAddress"] = this.extractAddress(monitorJSON); monitorJSON["tags"].forEach(tag => { data.tags[tag["name"]] = { diff --git a/server/notification-providers/stackfield.js b/server/notification-providers/stackfield.js index 7f22634e39..65a92459ab 100644 --- a/server/notification-providers/stackfield.js +++ b/server/notification-providers/stackfield.js @@ -4,11 +4,14 @@ const { setting } = require("../util-server"); const { getMonitorRelativeURL } = require("../../src/util"); class Stackfield extends NotificationProvider { - name = "stackfield"; - async send(notification, msg, monitorJSON = null) { - let okMsg = "Sent Successfully."; + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + try { // Stackfield message formatting: https://www.stackfield.com/help/formatting-messages-2001 diff --git a/server/notification-providers/teams.js b/server/notification-providers/teams.js index bcfc82c246..2793604cc7 100644 --- a/server/notification-providers/teams.js +++ b/server/notification-providers/teams.js @@ -1,6 +1,7 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); -const { DOWN, UP } = require("../../src/util"); +const { setting } = require("../util-server"); +const { DOWN, UP, getMonitorRelativeURL } = require("../../src/util"); class Teams extends NotificationProvider { name = "teams"; @@ -9,94 +10,179 @@ class Teams extends NotificationProvider { * Generate the message to send * @param {const} status The status constant * @param {string} monitorName Name of monitor - * @returns {string} + * @param {boolean} withStatusSymbol If the status should be prepended as symbol + * @returns {string} Status message */ - _statusMessageFactory = (status, monitorName) => { + _statusMessageFactory = (status, monitorName, withStatusSymbol) => { if (status === DOWN) { - return `🔴 Application [${monitorName}] went down`; + return (withStatusSymbol ? "🔴 " : "") + `[${monitorName}] went down`; } else if (status === UP) { - return `✅ Application [${monitorName}] is back online`; + return (withStatusSymbol ? "✅ " : "") + `[${monitorName}] is back online`; } return "Notification"; }; /** - * Select theme color to use based on status + * Select the style to use based on status * @param {const} status The status constant - * @returns {string} Selected color in hex RGB format + * @returns {string} Selected style for adaptive cards */ - _getThemeColor = (status) => { + _getStyle = (status) => { if (status === DOWN) { - return "ff0000"; + return "attention"; } if (status === UP) { - return "00e804"; + return "good"; } - return "008cff"; + return "emphasis"; }; /** * Generate payload for notification - * @param {const} status The status of the monitor - * @param {string} monitorMessage Message to send - * @param {string} monitorName Name of monitor affected - * @param {string} monitorUrl URL of monitor affected - * @returns {Object} + * @param {object} args Method arguments + * @param {object} args.heartbeatJSON Heartbeat details + * @param {string} args.monitorName Name of the monitor affected + * @param {string} args.monitorUrl URL of the monitor affected + * @param {string} args.dashboardUrl URL of the dashboard affected + * @returns {object} Notification payload */ _notificationPayloadFactory = ({ - status, - monitorMessage, + heartbeatJSON, monitorName, monitorUrl, + dashboardUrl, }) => { - const notificationMessage = this._statusMessageFactory( - status, - monitorName - ); - + const status = heartbeatJSON?.status; const facts = []; + const actions = []; + + if (dashboardUrl) { + actions.push({ + "type": "Action.OpenUrl", + "title": "Visit Uptime Kuma", + "url": dashboardUrl + }); + } + + if (heartbeatJSON?.msg) { + facts.push({ + title: "Description", + value: heartbeatJSON.msg, + }); + } if (monitorName) { facts.push({ - name: "Monitor", + title: "Monitor", value: monitorName, }); } if (monitorUrl && monitorUrl !== "https://") { facts.push({ - name: "URL", - value: monitorUrl, + title: "URL", + // format URL as markdown syntax, to be clickable + value: `[${monitorUrl}](${monitorUrl})`, + }); + actions.push({ + "type": "Action.OpenUrl", + "title": "Visit Monitor URL", + "url": monitorUrl }); } - return { - "@context": "https://schema.org/extensions", - "@type": "MessageCard", - themeColor: this._getThemeColor(status), - summary: notificationMessage, - sections: [ - { - activityImage: - "https://raw.githubusercontent.com/louislam/uptime-kuma/master/public/icon.png", - activityTitle: "**Uptime Kuma**", - }, - { - activityTitle: notificationMessage, - }, + if (heartbeatJSON?.localDateTime) { + facts.push({ + title: "Time", + value: heartbeatJSON.localDateTime + (heartbeatJSON.timezone ? ` (${heartbeatJSON.timezone})` : ""), + }); + } + + const payload = { + "type": "message", + // message with status prefix as notification text + "summary": this._statusMessageFactory(status, monitorName, true), + "attachments": [ { - activityTitle: "**Description**", - text: monitorMessage, - facts, - }, - ], + "contentType": "application/vnd.microsoft.card.adaptive", + "contentUrl": "", + "content": { + "type": "AdaptiveCard", + "body": [ + { + "type": "Container", + "verticalContentAlignment": "Center", + "items": [ + { + "type": "ColumnSet", + "style": this._getStyle(status), + "columns": [ + { + "type": "Column", + "width": "auto", + "verticalContentAlignment": "Center", + "items": [ + { + "type": "Image", + "width": "32px", + "style": "Person", + "url": "https://raw.githubusercontent.com/louislam/uptime-kuma/master/public/icon.png", + "altText": "Uptime Kuma Logo" + } + ] + }, + { + "type": "Column", + "width": "stretch", + "items": [ + { + "type": "TextBlock", + "size": "Medium", + "weight": "Bolder", + "text": `**${this._statusMessageFactory(status, monitorName, false)}**`, + }, + { + "type": "TextBlock", + "size": "Small", + "weight": "Default", + "text": "Uptime Kuma Alert", + "isSubtle": true, + "spacing": "None" + } + ] + } + ] + } + ] + }, + { + "type": "FactSet", + "separator": false, + "facts": facts + } + ], + "$schema": "http://adaptivecards.io/schemas/adaptive-card.json", + "version": "1.5" + } + } + ] }; + + if (actions) { + payload.attachments[0].content.body.push({ + "type": "ActionSet", + "actions": actions, + }); + } + + return payload; }; /** * Send the notification * @param {string} webhookUrl URL to send the request to - * @param {Object} payload Payload generated by _notificationPayloadFactory + * @param {object} payload Payload generated by _notificationPayloadFactory + * @returns {Promise} */ _sendNotification = async (webhookUrl, payload) => { await axios.post(webhookUrl, payload); @@ -110,14 +196,19 @@ class Teams extends NotificationProvider { */ _handleGeneralNotification = (webhookUrl, msg) => { const payload = this._notificationPayloadFactory({ - monitorMessage: msg + heartbeatJSON: { + msg: msg + } }); return this._sendNotification(webhookUrl, payload); }; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { if (heartbeatJSON == null) { @@ -125,26 +216,17 @@ class Teams extends NotificationProvider { return okMsg; } - let url; - - switch (monitorJSON["type"]) { - case "http": - case "keywork": - url = monitorJSON["url"]; - break; - case "docker": - url = monitorJSON["docker_host"]; - break; - default: - url = monitorJSON["hostname"]; - break; + const baseURL = await setting("primaryBaseURL"); + let dashboardUrl; + if (baseURL) { + dashboardUrl = baseURL + getMonitorRelativeURL(monitorJSON.id); } const payload = this._notificationPayloadFactory({ - monitorMessage: heartbeatJSON.msg, + heartbeatJSON: heartbeatJSON, monitorName: monitorJSON.name, - monitorUrl: url, - status: heartbeatJSON.status, + monitorUrl: this.extractAddress(monitorJSON), + dashboardUrl: dashboardUrl, }); await this._sendNotification(notification.webhookUrl, payload); diff --git a/server/notification-providers/techulus-push.js b/server/notification-providers/techulus-push.js index 751ff4c3af..bf688b194d 100644 --- a/server/notification-providers/techulus-push.js +++ b/server/notification-providers/techulus-push.js @@ -2,17 +2,30 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class TechulusPush extends NotificationProvider { - name = "PushByTechulus"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + + let data = { + "title": notification?.pushTitle?.length ? notification.pushTitle : "Uptime-Kuma", + "body": msg, + "timeSensitive": notification.pushTimeSensitive ?? true, + }; + + if (notification.pushChannel) { + data.channel = notification.pushChannel; + } + + if (notification.pushSound) { + data.sound = notification.pushSound; + } try { - await axios.post(`https://push.techulus.com/api/v1/notify/${notification.pushAPIKey}`, { - "title": "Uptime-Kuma", - "body": msg, - }); + await axios.post(`https://push.techulus.com/api/v1/notify/${notification.pushAPIKey}`, data); return okMsg; } catch (error) { this.throwGeneralAxiosError(error); diff --git a/server/notification-providers/telegram.js b/server/notification-providers/telegram.js index 561cabd87d..c5bbb1909a 100644 --- a/server/notification-providers/telegram.js +++ b/server/notification-providers/telegram.js @@ -2,11 +2,14 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class Telegram extends NotificationProvider { - name = "telegram"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; + const url = "https://api.telegram.org"; try { let params = { @@ -19,17 +22,13 @@ class Telegram extends NotificationProvider { params.message_thread_id = notification.telegramMessageThreadID; } - await axios.get(`https://api.telegram.org/bot${notification.telegramBotToken}/sendMessage`, { + await axios.get(`${url}/bot${notification.telegramBotToken}/sendMessage`, { params: params, }); return okMsg; } catch (error) { - if (error.response && error.response.data && error.response.data.description) { - throw new Error(error.response.data.description); - } else { - throw new Error(error.message); - } + this.throwGeneralAxiosError(error); } } } diff --git a/server/notification-providers/threema.js b/server/notification-providers/threema.js new file mode 100644 index 0000000000..07a54ab6ea --- /dev/null +++ b/server/notification-providers/threema.js @@ -0,0 +1,77 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class Threema extends NotificationProvider { + name = "threema"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const url = "https://msgapi.threema.ch/send_simple"; + + const config = { + headers: { + "Accept": "*/*", + "Content-Type": "application/x-www-form-urlencoded; charset=utf-8" + } + }; + + const data = { + from: notification.threemaSenderIdentity, + secret: notification.threemaSecret, + text: msg + }; + + switch (notification.threemaRecipientType) { + case "identity": + data.to = notification.threemaRecipient; + break; + case "phone": + data.phone = notification.threemaRecipient; + break; + case "email": + data.email = notification.threemaRecipient; + break; + default: + throw new Error(`Unsupported recipient type: ${notification.threemaRecipientType}`); + } + + try { + await axios.post(url, new URLSearchParams(data), config); + return "Threema notification sent successfully."; + } catch (error) { + const errorMessage = this.handleApiError(error); + this.throwGeneralAxiosError(errorMessage); + } + } + + /** + * Handle Threema API errors + * @param {any} error The error to handle + * @returns {string} Additional error context + */ + handleApiError(error) { + if (!error.response) { + return error.message; + } + switch (error.response.status) { + case 400: + return "Invalid recipient identity or account not set up for basic mode (400)."; + case 401: + return "Incorrect API identity or secret (401)."; + case 402: + return "No credits remaining (402)."; + case 404: + return "Recipient not found (404)."; + case 413: + return "Message is too long (413)."; + case 500: + return "Temporary internal server error (500)."; + default: + return error.message; + } + } +} + +module.exports = Threema; diff --git a/server/notification-providers/twilio.js b/server/notification-providers/twilio.js index a908fb21e3..c38a6d7edc 100644 --- a/server/notification-providers/twilio.js +++ b/server/notification-providers/twilio.js @@ -2,23 +2,21 @@ const NotificationProvider = require("./notification-provider"); const axios = require("axios"); class Twilio extends NotificationProvider { - name = "twilio"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; - let okMsg = "Sent Successfully."; - - let accountSID = notification.twilioAccountSID; - let apiKey = notification.twilioApiKey ? notification.twilioApiKey : accountSID; - let authToken = notification.twilioAuthToken; + let apiKey = notification.twilioApiKey ? notification.twilioApiKey : notification.twilioAccountSID; try { - let config = { headers: { "Content-Type": "application/x-www-form-urlencoded;charset=utf-8", - "Authorization": "Basic " + Buffer.from(apiKey + ":" + authToken).toString("base64"), + "Authorization": "Basic " + Buffer.from(apiKey + ":" + notification.twilioAuthToken).toString("base64"), } }; @@ -27,9 +25,7 @@ class Twilio extends NotificationProvider { data.append("From", notification.twilioFromNumber); data.append("Body", msg); - let url = "https://api.twilio.com/2010-04-01/Accounts/" + accountSID + "/Messages.json"; - - await axios.post(url, data, config); + await axios.post(`https://api.twilio.com/2010-04-01/Accounts/${(notification.twilioAccountSID)}/Messages.json`, data, config); return okMsg; } catch (error) { diff --git a/server/notification-providers/webhook.js b/server/notification-providers/webhook.js index 9f5643b4e0..986986d443 100644 --- a/server/notification-providers/webhook.js +++ b/server/notification-providers/webhook.js @@ -4,11 +4,13 @@ const FormData = require("form-data"); const { Liquid } = require("liquidjs"); class Webhook extends NotificationProvider { - name = "webhook"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { let data = { diff --git a/server/notification-providers/wecom.js b/server/notification-providers/wecom.js index 1825419ad5..1eb0690955 100644 --- a/server/notification-providers/wecom.js +++ b/server/notification-providers/wecom.js @@ -3,21 +3,22 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class WeCom extends NotificationProvider { - name = "WeCom"; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { - let WeComUrl = "https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=" + notification.weComBotKey; let config = { headers: { "Content-Type": "application/json" } }; let body = this.composeMessage(heartbeatJSON, msg); - await axios.post(WeComUrl, body, config); + await axios.post(`https://qyapi.weixin.qq.com/cgi-bin/webhook/send?key=${notification.weComBotKey}`, body, config); return okMsg; } catch (error) { this.throwGeneralAxiosError(error); @@ -26,25 +27,22 @@ class WeCom extends NotificationProvider { /** * Generate the message to send - * @param {Object} heartbeatJSON Heartbeat details (For Up/Down only) + * @param {object} heartbeatJSON Heartbeat details (For Up/Down only) * @param {string} msg General message - * @returns {Object} + * @returns {object} Message */ composeMessage(heartbeatJSON, msg) { - let title; + let title = "UptimeKuma Message"; if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === UP) { title = "UptimeKuma Monitor Up"; } if (msg != null && heartbeatJSON != null && heartbeatJSON["status"] === DOWN) { title = "UptimeKuma Monitor Down"; } - if (msg != null) { - title = "UptimeKuma Message"; - } return { msgtype: "text", text: { - content: title + msg + content: title + "\n" + msg } }; } diff --git a/server/notification-providers/whapi.js b/server/notification-providers/whapi.js new file mode 100644 index 0000000000..70e0fbb4c7 --- /dev/null +++ b/server/notification-providers/whapi.js @@ -0,0 +1,39 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); + +class Whapi extends NotificationProvider { + name = "whapi"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + try { + const config = { + headers: { + "Accept": "application/json", + "Content-Type": "application/json", + "Authorization": "Bearer " + notification.whapiAuthToken, + } + }; + + let data = { + "to": notification.whapiRecipient, + "body": msg, + }; + + let url = (notification.whapiApiUrl || "https://gate.whapi.cloud/").replace(/\/+$/, "") + "/messages/text"; + + await axios.post(url, data, config); + + return okMsg; + } catch (error) { + this.throwGeneralAxiosError(error); + } + } + +} + +module.exports = Whapi; diff --git a/server/notification-providers/wpush.js b/server/notification-providers/wpush.js new file mode 100644 index 0000000000..db043f9c55 --- /dev/null +++ b/server/notification-providers/wpush.js @@ -0,0 +1,51 @@ +const NotificationProvider = require("./notification-provider"); +const axios = require("axios"); +const { DOWN, UP } = require("../../src/util"); + +class WPush extends NotificationProvider { + name = "WPush"; + + /** + * @inheritdoc + */ + async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { + const okMsg = "Sent Successfully."; + + try { + const context = { + "title": this.checkStatus(heartbeatJSON, monitorJSON), + "content": msg, + "apikey": notification.wpushAPIkey, + "channel": notification.wpushChannel + }; + const result = await axios.post("https://api.wpush.cn/api/v1/send", context); + if (result.data.code !== 0) { + throw result.data.message; + } + + return okMsg; + + } catch (error) { + this.throwGeneralAxiosError(error); + } + } + + /** + * Get the formatted title for message + * @param {?object} heartbeatJSON Heartbeat details (For Up/Down only) + * @param {?object} monitorJSON Monitor details (For Up/Down only) + * @returns {string} Formatted title + */ + checkStatus(heartbeatJSON, monitorJSON) { + let title = "UptimeKuma Message"; + if (heartbeatJSON != null && heartbeatJSON["status"] === UP) { + title = "UptimeKuma Monitor Up " + monitorJSON["name"]; + } + if (heartbeatJSON != null && heartbeatJSON["status"] === DOWN) { + title = "UptimeKuma Monitor Down " + monitorJSON["name"]; + } + return title; + } +} + +module.exports = WPush; diff --git a/server/notification-providers/zoho-cliq.js b/server/notification-providers/zoho-cliq.js index 749647d066..3a504de8c4 100644 --- a/server/notification-providers/zoho-cliq.js +++ b/server/notification-providers/zoho-cliq.js @@ -3,20 +3,19 @@ const axios = require("axios"); const { DOWN, UP } = require("../../src/util"); class ZohoCliq extends NotificationProvider { - name = "ZohoCliq"; /** * Generate the message to send * @param {const} status The status constant * @param {string} monitorName Name of monitor - * @returns {string} + * @returns {string} Status message */ _statusMessageFactory = (status, monitorName) => { if (status === DOWN) { - return `🔴 Application [${monitorName}] went down\n`; + return `🔴 [${monitorName}] went down\n`; } else if (status === UP) { - return `✅ Application [${monitorName}] is back online\n`; + return `### ✅ [${monitorName}] is back online\n`; } return "Notification\n"; }; @@ -25,6 +24,7 @@ class ZohoCliq extends NotificationProvider { * Send the notification * @param {string} webhookUrl URL to send the request to * @param {Array} payload Payload generated by _notificationPayloadFactory + * @returns {Promise} */ _sendNotification = async (webhookUrl, payload) => { await axios.post(webhookUrl, { text: payload.join("\n") }); @@ -32,11 +32,12 @@ class ZohoCliq extends NotificationProvider { /** * Generate payload for notification - * @param {const} status The status of the monitor - * @param {string} monitorMessage Message to send - * @param {string} monitorName Name of monitor affected - * @param {string} monitorUrl URL of monitor affected - * @returns {Array} + * @param {object} args Method arguments + * @param {const} args.status The status of the monitor + * @param {string} args.monitorMessage Message to send + * @param {string} args.monitorName Name of monitor affected + * @param {string} args.monitorUrl URL of monitor affected + * @returns {Array} Notification payload */ _notificationPayloadFactory = ({ status, @@ -45,16 +46,11 @@ class ZohoCliq extends NotificationProvider { monitorUrl, }) => { const payload = []; - payload.push("### Uptime Kuma\n"); payload.push(this._statusMessageFactory(status, monitorName)); payload.push(`*Description:* ${monitorMessage}`); - if (monitorName) { - payload.push(`*Monitor:* ${monitorName}`); - } - if (monitorUrl && monitorUrl !== "https://") { - payload.push(`*URL:* [${monitorUrl}](${monitorUrl})`); + payload.push(`*URL:* ${monitorUrl}`); } return payload; @@ -74,8 +70,11 @@ class ZohoCliq extends NotificationProvider { return this._sendNotification(webhookUrl, payload); }; + /** + * @inheritdoc + */ async send(notification, msg, monitorJSON = null, heartbeatJSON = null) { - let okMsg = "Sent Successfully."; + const okMsg = "Sent Successfully."; try { if (heartbeatJSON == null) { @@ -83,24 +82,10 @@ class ZohoCliq extends NotificationProvider { return okMsg; } - let url; - switch (monitorJSON["type"]) { - case "http": - case "keywork": - url = monitorJSON["url"]; - break; - case "docker": - url = monitorJSON["docker_host"]; - break; - default: - url = monitorJSON["hostname"]; - break; - } - const payload = this._notificationPayloadFactory({ monitorMessage: heartbeatJSON.msg, monitorName: monitorJSON.name, - monitorUrl: url, + monitorUrl: this.extractAddress(monitorJSON), status: heartbeatJSON.status }); diff --git a/server/notification.js b/server/notification.js index 570c440dfd..e7977eb4af 100644 --- a/server/notification.js +++ b/server/notification.js @@ -5,16 +5,22 @@ const AlertNow = require("./notification-providers/alertnow"); const AliyunSms = require("./notification-providers/aliyun-sms"); const Apprise = require("./notification-providers/apprise"); const Bark = require("./notification-providers/bark"); +const Bitrix24 = require("./notification-providers/bitrix24"); const ClickSendSMS = require("./notification-providers/clicksendsms"); +const CallMeBot = require("./notification-providers/call-me-bot"); const SMSC = require("./notification-providers/smsc"); const DingDing = require("./notification-providers/dingding"); const Discord = require("./notification-providers/discord"); +const Elks = require("./notification-providers/46elks"); const Feishu = require("./notification-providers/feishu"); const FreeMobile = require("./notification-providers/freemobile"); const GoogleChat = require("./notification-providers/google-chat"); const Gorush = require("./notification-providers/gorush"); const Gotify = require("./notification-providers/gotify"); +const GrafanaOncall = require("./notification-providers/grafana-oncall"); const HomeAssistant = require("./notification-providers/home-assistant"); +const HeiiOnCall = require("./notification-providers/heii-oncall"); +const Keep = require("./notification-providers/keep"); const Kook = require("./notification-providers/kook"); const Line = require("./notification-providers/line"); const LineNotify = require("./notification-providers/linenotify"); @@ -37,7 +43,9 @@ const Pushy = require("./notification-providers/pushy"); const RocketChat = require("./notification-providers/rocket-chat"); const SerwerSMS = require("./notification-providers/serwersms"); const Signal = require("./notification-providers/signal"); +const SIGNL4 = require("./notification-providers/signl4"); const Slack = require("./notification-providers/slack"); +const SMSPartner = require("./notification-providers/smspartner"); const SMSEagle = require("./notification-providers/smseagle"); const SMTP = require("./notification-providers/smtp"); const Squadcast = require("./notification-providers/squadcast"); @@ -45,6 +53,7 @@ const Stackfield = require("./notification-providers/stackfield"); const Teams = require("./notification-providers/teams"); const TechulusPush = require("./notification-providers/techulus-push"); const Telegram = require("./notification-providers/telegram"); +const Threema = require("./notification-providers/threema"); const Twilio = require("./notification-providers/twilio"); const Splunk = require("./notification-providers/splunk"); const Webhook = require("./notification-providers/webhook"); @@ -53,14 +62,26 @@ const GoAlert = require("./notification-providers/goalert"); const SMSManager = require("./notification-providers/smsmanager"); const ServerChan = require("./notification-providers/serverchan"); const ZohoCliq = require("./notification-providers/zoho-cliq"); +const SevenIO = require("./notification-providers/sevenio"); +const Whapi = require("./notification-providers/whapi"); +const GtxMessaging = require("./notification-providers/gtx-messaging"); +const Cellsynt = require("./notification-providers/cellsynt"); +const Onesender = require("./notification-providers/onesender"); +const Wpush = require("./notification-providers/wpush"); +const SendGrid = require("./notification-providers/send-grid"); class Notification { providerList = {}; - /** Initialize the notification providers */ + /** + * Initialize the notification providers + * @returns {void} + * @throws Notification provider does not have a name + * @throws Duplicate notification providers in list + */ static init() { - log.info("notification", "Prepare Notification Providers"); + log.debug("notification", "Prepare Notification Providers"); this.providerList = {}; @@ -70,16 +91,22 @@ class Notification { new AliyunSms(), new Apprise(), new Bark(), + new Bitrix24(), new ClickSendSMS(), + new CallMeBot(), new SMSC(), new DingDing(), new Discord(), + new Elks(), new Feishu(), new FreeMobile(), new GoogleChat(), new Gorush(), new Gotify(), + new GrafanaOncall(), new HomeAssistant(), + new HeiiOnCall(), + new Keep(), new Kook(), new Line(), new LineNotify(), @@ -90,6 +117,7 @@ class Notification { new Ntfy(), new Octopush(), new OneBot(), + new Onesender(), new Opsgenie(), new PagerDuty(), new FlashDuty(), @@ -103,7 +131,9 @@ class Notification { new ServerChan(), new SerwerSMS(), new Signal(), + new SIGNL4(), new SMSManager(), + new SMSPartner(), new Slack(), new SMSEagle(), new SMTP(), @@ -112,12 +142,19 @@ class Notification { new Teams(), new TechulusPush(), new Telegram(), + new Threema(), new Twilio(), new Splunk(), new Webhook(), new WeCom(), new GoAlert(), - new ZohoCliq() + new ZohoCliq(), + new SevenIO(), + new Whapi(), + new GtxMessaging(), + new Cellsynt(), + new Wpush(), + new SendGrid() ]; for (let item of list) { if (! item.name) { @@ -133,10 +170,10 @@ class Notification { /** * Send a notification - * @param {BeanModel} notification + * @param {BeanModel} notification Notification to send * @param {string} msg General Message - * @param {Object} monitorJSON Monitor details (For Up/Down only) - * @param {Object} heartbeatJSON Heartbeat details (For Up/Down only) + * @param {object} monitorJSON Monitor details (For Up/Down only) + * @param {object} heartbeatJSON Heartbeat details (For Up/Down only) * @returns {Promise} Successful msg * @throws Error with fail msg */ @@ -150,10 +187,10 @@ class Notification { /** * Save a notification - * @param {Object} notification Notification to save + * @param {object} notification Notification to save * @param {?number} notificationID ID of notification to update * @param {number} userID ID of user who adds notification - * @returns {Promise} + * @returns {Promise} Notification that was saved */ static async save(notification, notificationID, userID) { let bean; diff --git a/server/password-hash.js b/server/password-hash.js index ba228f6b1a..83a23d9e62 100644 --- a/server/password-hash.js +++ b/server/password-hash.js @@ -4,8 +4,8 @@ const saltRounds = 10; /** * Hash a password - * @param {string} password - * @returns {string} + * @param {string} password Password to hash + * @returns {string} Hash */ exports.generate = function (password) { return bcrypt.hashSync(password, saltRounds); @@ -13,8 +13,8 @@ exports.generate = function (password) { /** * Verify a password against a hash - * @param {string} password - * @param {string} hash + * @param {string} password Password to verify + * @param {string} hash Hash to verify against * @returns {boolean} Does the password match the hash? */ exports.verify = function (password, hash) { @@ -27,8 +27,8 @@ exports.verify = function (password, hash) { /** * Is the hash a SHA1 hash - * @param {string} hash - * @returns {boolean} + * @param {string} hash Hash to check + * @returns {boolean} Is SHA1 hash? */ function isSHA1(hash) { return (typeof hash === "string" && hash.startsWith("sha1")); @@ -36,7 +36,8 @@ function isSHA1(hash) { /** * Does the hash need to be rehashed? - * @returns {boolean} + * @param {string} hash Hash to check + * @returns {boolean} Needs to be rehashed? */ exports.needRehash = function (hash) { return isSHA1(hash); diff --git a/server/prometheus.js b/server/prometheus.js index fa7f608553..f26125d2c5 100644 --- a/server/prometheus.js +++ b/server/prometheus.js @@ -36,7 +36,7 @@ class Prometheus { monitorLabelValues = {}; /** - * @param {Object} monitor Monitor object to monitor + * @param {object} monitor Monitor object to monitor */ constructor(monitor) { this.monitorLabelValues = { @@ -50,8 +50,9 @@ class Prometheus { /** * Update the metrics page - * @param {Object} heartbeat Heartbeat details - * @param {Object} tlsInfo TLS details + * @param {object} heartbeat Heartbeat details + * @param {object} tlsInfo TLS details + * @returns {void} */ update(heartbeat, tlsInfo) { @@ -101,7 +102,10 @@ class Prometheus { } } - /** Remove monitor from prometheus */ + /** + * Remove monitor from prometheus + * @returns {void} + */ remove() { try { monitorCertDaysRemaining.remove(this.monitorLabelValues); diff --git a/server/proxy.js b/server/proxy.js index 660b9b411d..3f3771ab98 100644 --- a/server/proxy.js +++ b/server/proxy.js @@ -4,6 +4,8 @@ const HttpsProxyAgent = require("https-proxy-agent"); const SocksProxyAgent = require("socks-proxy-agent"); const { debug } = require("../src/util"); const { UptimeKumaServer } = require("./uptime-kuma-server"); +const { CookieJar } = require("tough-cookie"); +const { createCookieAgent } = require("http-cookie-agent/http"); class Proxy { @@ -11,11 +13,10 @@ class Proxy { /** * Saves and updates given proxy entity - * - * @param proxy - * @param proxyID - * @param userID - * @return {Promise} + * @param {object} proxy Proxy to store + * @param {number} proxyID ID of proxy to update + * @param {number} userID ID of user the proxy belongs to + * @returns {Promise} Updated proxy */ static async save(proxy, proxyID, userID) { let bean; @@ -65,10 +66,9 @@ class Proxy { /** * Deletes proxy with given id and removes it from monitors - * - * @param proxyID - * @param userID - * @return {Promise} + * @param {number} proxyID ID of proxy to delete + * @param {number} userID ID of proxy owner + * @returns {Promise} */ static async delete(proxyID, userID) { const bean = await R.findOne("proxy", " id = ? AND user_id = ? ", [ proxyID, userID ]); @@ -86,10 +86,10 @@ class Proxy { /** * Create HTTP and HTTPS agents related with given proxy bean object - * - * @param proxy proxy bean object - * @param options http and https agent options - * @return {{httpAgent: Agent, httpsAgent: Agent}} + * @param {object} proxy proxy bean object + * @param {object} options http and https agent options + * @returns {{httpAgent: Agent, httpsAgent: Agent}} New HTTP and HTTPS agents + * @throws Proxy protocol is unsupported */ static createAgents(proxy, options) { const { httpAgentOptions, httpsAgentOptions } = options || {}; @@ -97,10 +97,13 @@ class Proxy { let httpAgent; let httpsAgent; + let jar = new CookieJar(); + const proxyOptions = { protocol: proxy.protocol, host: proxy.host, port: proxy.port, + cookies: { jar }, }; if (proxy.auth) { @@ -114,12 +117,17 @@ class Proxy { switch (proxy.protocol) { case "http": case "https": - httpAgent = new HttpProxyAgent({ + // eslint-disable-next-line no-case-declarations + const HttpCookieProxyAgent = createCookieAgent(HttpProxyAgent); + // eslint-disable-next-line no-case-declarations + const HttpsCookieProxyAgent = createCookieAgent(HttpsProxyAgent); + + httpAgent = new HttpCookieProxyAgent({ ...httpAgentOptions || {}, - ...proxyOptions + ...proxyOptions, }); - httpsAgent = new HttpsProxyAgent({ + httpsAgent = new HttpsCookieProxyAgent({ ...httpsAgentOptions || {}, ...proxyOptions, }); @@ -128,7 +136,9 @@ class Proxy { case "socks5": case "socks5h": case "socks4": - agent = new SocksProxyAgent({ + // eslint-disable-next-line no-case-declarations + const SocksCookieProxyAgent = createCookieAgent(SocksProxyAgent); + agent = new SocksCookieProxyAgent({ ...httpAgentOptions, ...httpsAgentOptions, ...proxyOptions, @@ -171,10 +181,9 @@ class Proxy { /** * Applies given proxy id to monitors - * - * @param proxyID - * @param userID - * @return {Promise} + * @param {number} proxyID ID of proxy to apply + * @param {number} userID ID of proxy owner + * @returns {Promise} */ async function applyProxyEveryMonitor(proxyID, userID) { // Find all monitors with id and proxy id diff --git a/server/rate-limiter.js b/server/rate-limiter.js index ec77f1a4ec..3c269b6f03 100644 --- a/server/rate-limiter.js +++ b/server/rate-limiter.js @@ -3,7 +3,7 @@ const { log } = require("../src/util"); class KumaRateLimiter { /** - * @param {Object} config Rate limiter configuration object + * @param {object} config Rate limiter configuration object */ constructor(config) { this.errorMessage = config.errorMessage; @@ -13,14 +13,14 @@ class KumaRateLimiter { /** * Callback for pass * @callback passCB - * @param {Object} err Too many requests + * @param {object} err Too many requests */ /** * Should the request be passed through - * @param {passCB} callback - * @param {number} [num=1] Number of tokens to remove - * @returns {Promise} + * @param {passCB} callback Callback function to call with decision + * @param {number} num Number of tokens to remove + * @returns {Promise} Should the request be allowed? */ async pass(callback, num = 1) { const remainingRequests = await this.removeTokens(num); @@ -39,8 +39,8 @@ class KumaRateLimiter { /** * Remove a given number of tokens - * @param {number} [num=1] Number of tokens to remove - * @returns {Promise} + * @param {number} num Number of tokens to remove + * @returns {Promise} Number of remaining tokens */ async removeTokens(num = 1) { return await this.rateLimiter.removeTokens(num); diff --git a/server/remote-browser.js b/server/remote-browser.js new file mode 100644 index 0000000000..da8e9a5ec6 --- /dev/null +++ b/server/remote-browser.js @@ -0,0 +1,74 @@ +const { R } = require("redbean-node"); + +class RemoteBrowser { + + /** + * Gets remote browser from ID + * @param {number} remoteBrowserID ID of the remote browser + * @param {number} userID ID of the user who created the remote browser + * @returns {Promise} Remote Browser + */ + static async get(remoteBrowserID, userID) { + let bean = await R.findOne("remote_browser", " id = ? AND user_id = ? ", [ remoteBrowserID, userID ]); + + if (!bean) { + throw new Error("Remote browser not found"); + } + + return bean; + } + + /** + * Save a Remote Browser + * @param {object} remoteBrowser Remote Browser to save + * @param {?number} remoteBrowserID ID of the Remote Browser to update + * @param {number} userID ID of the user who adds the Remote Browser + * @returns {Promise} Updated Remote Browser + */ + static async save(remoteBrowser, remoteBrowserID, userID) { + let bean; + + if (remoteBrowserID) { + bean = await R.findOne("remote_browser", " id = ? AND user_id = ? ", [ remoteBrowserID, userID ]); + + if (!bean) { + throw new Error("Remote browser not found"); + } + + } else { + bean = R.dispense("remote_browser"); + } + + bean.user_id = userID; + bean.name = remoteBrowser.name; + bean.url = remoteBrowser.url; + + await R.store(bean); + + return bean; + } + + /** + * Delete a Remote Browser + * @param {number} remoteBrowserID ID of the Remote Browser to delete + * @param {number} userID ID of the user who created the Remote Browser + * @returns {Promise} + */ + static async delete(remoteBrowserID, userID) { + let bean = await R.findOne("remote_browser", " id = ? AND user_id = ? ", [ remoteBrowserID, userID ]); + + if (!bean) { + throw new Error("Remote Browser not found"); + } + + // Delete removed remote browser from monitors if exists + await R.exec("UPDATE monitor SET remote_browser = null WHERE remote_browser = ?", [ remoteBrowserID ]); + + await R.trash(bean); + } + +} + +module.exports = { + RemoteBrowser, +}; diff --git a/server/routers/api-router.js b/server/routers/api-router.js index c9b2ec8846..ed6db2cd1c 100644 --- a/server/routers/api-router.js +++ b/server/routers/api-router.js @@ -14,9 +14,10 @@ const dayjs = require("dayjs"); const { UP, MAINTENANCE, DOWN, PENDING, flipStatus, log, badgeConstants } = require("../../src/util"); const StatusPage = require("../model/status_page"); const { UptimeKumaServer } = require("../uptime-kuma-server"); -const { UptimeCacheList } = require("../uptime-cache-list"); const { makeBadge } = require("badge-maker"); const { Prometheus } = require("../prometheus"); +const Database = require("../database"); +const { UptimeCalculator } = require("../uptime-calculator"); let router = express.Router(); @@ -43,9 +44,8 @@ router.get("/api/entry-page", async (request, response) => { response.json(result); }); -router.get("/api/push/:pushToken", async (request, response) => { +router.all("/api/push/:pushToken", async (request, response) => { try { - let pushToken = request.params.pushToken; let msg = request.query.msg || "OK"; let ping = parseFloat(request.query.ping) || null; @@ -62,54 +62,68 @@ router.get("/api/push/:pushToken", async (request, response) => { const previousHeartbeat = await Monitor.getPreviousHeartbeat(monitor.id); - if (monitor.isUpsideDown()) { - status = flipStatus(status); - } - let isFirstBeat = true; - let previousStatus = status; - let duration = 0; let bean = R.dispense("heartbeat"); bean.time = R.isoDateTimeMillis(dayjs.utc()); + bean.monitor_id = monitor.id; + bean.ping = ping; + bean.msg = msg; + bean.downCount = previousHeartbeat?.downCount || 0; if (previousHeartbeat) { isFirstBeat = false; - previousStatus = previousHeartbeat.status; - duration = dayjs(bean.time).diff(dayjs(previousHeartbeat.time), "second"); + bean.duration = dayjs(bean.time).diff(dayjs(previousHeartbeat.time), "second"); } if (await Monitor.isUnderMaintenance(monitor.id)) { msg = "Monitor under maintenance"; - status = MAINTENANCE; + bean.status = MAINTENANCE; + } else { + determineStatus(status, previousHeartbeat, monitor.maxretries, monitor.isUpsideDown(), bean); } + // Calculate uptime + let uptimeCalculator = await UptimeCalculator.getUptimeCalculator(monitor.id); + let endTimeDayjs = await uptimeCalculator.update(bean.status, parseFloat(bean.ping)); + bean.end_time = R.isoDateTimeMillis(endTimeDayjs); + log.debug("router", `/api/push/ called at ${dayjs().format("YYYY-MM-DD HH:mm:ss.SSS")}`); - log.debug("router", "PreviousStatus: " + previousStatus); - log.debug("router", "Current Status: " + status); + log.debug("router", "PreviousStatus: " + previousHeartbeat?.status); + log.debug("router", "Current Status: " + bean.status); - bean.important = Monitor.isImportantBeat(isFirstBeat, previousStatus, status); - bean.monitor_id = monitor.id; - bean.status = status; - bean.msg = msg; - bean.ping = ping; - bean.duration = duration; + bean.important = Monitor.isImportantBeat(isFirstBeat, previousHeartbeat?.status, status); + + if (Monitor.isImportantForNotification(isFirstBeat, previousHeartbeat?.status, status)) { + // Reset down count + bean.downCount = 0; + + log.debug("monitor", `[${this.name}] sendNotification`); + await Monitor.sendNotification(isFirstBeat, monitor, bean); + } else { + if (bean.status === DOWN && this.resendInterval > 0) { + ++bean.downCount; + if (bean.downCount >= this.resendInterval) { + // Send notification again, because we are still DOWN + log.debug("monitor", `[${this.name}] sendNotification again: Down Count: ${bean.downCount} | Resend Interval: ${this.resendInterval}`); + await Monitor.sendNotification(isFirstBeat, this, bean); + + // Reset down count + bean.downCount = 0; + } + } + } await R.store(bean); io.to(monitor.user_id).emit("heartbeat", bean.toJSON()); - UptimeCacheList.clearCache(monitor.id); + Monitor.sendStats(io, monitor.id, monitor.user_id); new Prometheus(monitor).update(bean, undefined); response.json({ ok: true, }); - - if (Monitor.isImportantForNotification(isFirstBeat, previousStatus, status)) { - await Monitor.sendNotification(isFirstBeat, monitor, bean); - } - } catch (e) { response.status(404).json({ ok: false, @@ -215,9 +229,13 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques try { const requestedMonitorId = parseInt(request.params.id, 10); // if no duration is given, set value to 24 (h) - const requestedDuration = request.params.duration !== undefined ? parseInt(request.params.duration, 10) : 24; + let requestedDuration = request.params.duration !== undefined ? request.params.duration : "24h"; const overrideValue = value && parseFloat(value); + if (/^[0-9]+$/.test(requestedDuration)) { + requestedDuration = `${requestedDuration}h`; + } + let publicMonitor = await R.getRow(` SELECT monitor_group.monitor_id FROM monitor_group, \`group\` WHERE monitor_group.group_id = \`group\`.id @@ -234,10 +252,8 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques badgeValues.message = "N/A"; badgeValues.color = badgeConstants.naColor; } else { - const uptime = overrideValue ?? await Monitor.calcUptime( - requestedDuration, - requestedMonitorId - ); + const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(requestedMonitorId); + const uptime = overrideValue ?? uptimeCalculator.getDataByDuration(requestedDuration).uptime; // limit the displayed uptime percentage to four (two, when displayed as percent) decimal digits const cleanUptime = (uptime * 100).toPrecision(4); @@ -249,7 +265,7 @@ router.get("/api/badge/:id/uptime/:duration?", cache("5 minutes"), async (reques // build a label string. If a custom label is given, override the default one (requestedDuration) badgeValues.label = filterAndJoin([ labelPrefix, - label ?? `Uptime (${requestedDuration}${labelSuffix})`, + label ?? `Uptime (${requestedDuration.slice(0, -1)}${labelSuffix})`, ]); badgeValues.message = filterAndJoin([ prefix, cleanUptime, suffix ]); } @@ -283,19 +299,17 @@ router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request, const requestedMonitorId = parseInt(request.params.id, 10); // Default duration is 24 (h) if not defined in queryParam, limited to 720h (30d) - const requestedDuration = Math.min(request.params.duration ? parseInt(request.params.duration, 10) : 24, 720); + let requestedDuration = request.params.duration !== undefined ? request.params.duration : "24h"; const overrideValue = value && parseFloat(value); - const publicAvgPing = parseInt(await R.getCell(` - SELECT AVG(ping) FROM monitor_group, \`group\`, heartbeat - WHERE monitor_group.group_id = \`group\`.id - AND heartbeat.time > DATETIME('now', ? || ' hours') - AND heartbeat.ping IS NOT NULL - AND public = 1 - AND heartbeat.monitor_id = ? - `, - [ -requestedDuration, requestedMonitorId ] - )); + if (/^[0-9]+$/.test(requestedDuration)) { + requestedDuration = `${requestedDuration}h`; + } + + // Check if monitor is public + + const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(requestedMonitorId); + const publicAvgPing = uptimeCalculator.getDataByDuration(requestedDuration).avgPing; const badgeValues = { style }; @@ -311,7 +325,7 @@ router.get("/api/badge/:id/ping/:duration?", cache("5 minutes"), async (request, // use a given, custom labelColor or use the default badge label color (defined by badge-maker) badgeValues.labelColor = labelColor ?? ""; // build a lable string. If a custom label is given, override the default one (requestedDuration) - badgeValues.label = filterAndJoin([ labelPrefix, label ?? `Avg. Ping (${requestedDuration}${labelSuffix})` ]); + badgeValues.label = filterAndJoin([ labelPrefix, label ?? `Avg. Ping (${requestedDuration.slice(0, -1)}${labelSuffix})` ]); badgeValues.message = filterAndJoin([ prefix, avgPing, suffix ]); } @@ -352,10 +366,12 @@ router.get("/api/badge/:id/avg-response/:duration?", cache("5 minutes"), async ( ); const overrideValue = value && parseFloat(value); + const sqlHourOffset = Database.sqlHourOffset(); + const publicAvgPing = parseInt(await R.getCell(` SELECT AVG(ping) FROM monitor_group, \`group\`, heartbeat WHERE monitor_group.group_id = \`group\`.id - AND heartbeat.time > DATETIME('now', ? || ' hours') + AND heartbeat.time > ${sqlHourOffset} AND heartbeat.ping IS NOT NULL AND public = 1 AND heartbeat.monitor_id = ? @@ -558,4 +574,58 @@ router.get("/api/badge/:id/response", cache("5 minutes"), async (request, respon } }); +/** + * Determines the status of the next beat in the push route handling. + * @param {string} status - The reported new status. + * @param {object} previousHeartbeat - The previous heartbeat object. + * @param {number} maxretries - The maximum number of retries allowed. + * @param {boolean} isUpsideDown - Indicates if the monitor is upside down. + * @param {object} bean - The new heartbeat object. + * @returns {void} + */ +function determineStatus(status, previousHeartbeat, maxretries, isUpsideDown, bean) { + if (isUpsideDown) { + status = flipStatus(status); + } + + if (previousHeartbeat) { + if (previousHeartbeat.status === UP && status === DOWN) { + // Going Down + if ((maxretries > 0) && (previousHeartbeat.retries < maxretries)) { + // Retries available + bean.retries = previousHeartbeat.retries + 1; + bean.status = PENDING; + } else { + // No more retries + bean.retries = 0; + bean.status = DOWN; + } + } else if (previousHeartbeat.status === PENDING && status === DOWN && previousHeartbeat.retries < maxretries) { + // Retries available + bean.retries = previousHeartbeat.retries + 1; + bean.status = PENDING; + } else { + // No more retries or not pending + if (status === DOWN) { + bean.retries = previousHeartbeat.retries + 1; + bean.status = status; + } else { + bean.retries = 0; + bean.status = status; + } + } + } else { + // First beat? + if (status === DOWN && maxretries > 0) { + // Retries available + bean.retries = 1; + bean.status = PENDING; + } else { + // Retires not enabled + bean.retries = 0; + bean.status = status; + } + } +} + module.exports = router; diff --git a/server/routers/status-page-router.js b/server/routers/status-page-router.js index c7a580d876..893f575642 100644 --- a/server/routers/status-page-router.js +++ b/server/routers/status-page-router.js @@ -4,9 +4,9 @@ const { UptimeKumaServer } = require("../uptime-kuma-server"); const StatusPage = require("../model/status_page"); const { allowDevAllOrigin, sendHttpError } = require("../util-server"); const { R } = require("redbean-node"); -const Monitor = require("../model/monitor"); const { badgeConstants } = require("../../src/util"); const { makeBadge } = require("badge-maker"); +const { UptimeCalculator } = require("../uptime-calculator"); let router = express.Router(); @@ -15,9 +15,16 @@ const server = UptimeKumaServer.getInstance(); router.get("/status/:slug", cache("5 minutes"), async (request, response) => { let slug = request.params.slug; + slug = slug.toLowerCase(); await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug); }); +router.get("/status/:slug/rss", cache("5 minutes"), async (request, response) => { + let slug = request.params.slug; + slug = slug.toLowerCase(); + await StatusPage.handleStatusPageRSSResponse(response, slug); +}); + router.get("/status", cache("5 minutes"), async (request, response) => { let slug = "default"; await StatusPage.handleStatusPageResponse(response, server.indexHTML, slug); @@ -32,6 +39,7 @@ router.get("/status-page", cache("5 minutes"), async (request, response) => { router.get("/api/status-page/:slug", cache("5 minutes"), async (request, response) => { allowDevAllOrigin(response); let slug = request.params.slug; + slug = slug.toLowerCase(); try { // Get Status Page @@ -40,16 +48,12 @@ router.get("/api/status-page/:slug", cache("5 minutes"), async (request, respons ]); if (!statusPage) { + sendHttpError(response, "Status Page Not Found"); return null; } let statusPageData = await StatusPage.getStatusPageData(statusPage); - if (!statusPageData) { - sendHttpError(response, "Not Found"); - return; - } - // Response response.json(statusPageData); @@ -68,6 +72,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques let uptimeList = {}; let slug = request.params.slug; + slug = slug.toLowerCase(); let statusPageID = await StatusPage.slugToID(slug); let monitorIDList = await R.getCol(` @@ -92,8 +97,8 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques list = R.convertToBeans("heartbeat", list); heartbeatList[monitorID] = list.reverse().map(row => row.toPublicJSON()); - const type = 24; - uptimeList[`${monitorID}_${type}`] = await Monitor.calcUptime(type, monitorID); + const uptimeCalculator = await UptimeCalculator.getUptimeCalculator(monitorID); + uptimeList[`${monitorID}_24`] = uptimeCalculator.get24Hour().uptime; } response.json({ @@ -110,6 +115,7 @@ router.get("/api/status-page/heartbeat/:slug", cache("1 minutes"), async (reques router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async (request, response) => { allowDevAllOrigin(response); let slug = request.params.slug; + slug = slug.toLowerCase(); try { // Get Status Page @@ -144,7 +150,8 @@ router.get("/api/status-page/:slug/manifest.json", cache("1440 minutes"), async // overall status-page status badge router.get("/api/status-page/:slug/badge", cache("5 minutes"), async (request, response) => { allowDevAllOrigin(response); - const slug = request.params.slug; + let slug = request.params.slug; + slug = slug.toLowerCase(); const statusPageID = await StatusPage.slugToID(slug); const { label, diff --git a/server/server.js b/server/server.js index 3c66bad789..ec5ad49f68 100644 --- a/server/server.js +++ b/server/server.js @@ -19,7 +19,7 @@ const nodeVersion = process.versions.node; // Get the required Node.js version from package.json const requiredNodeVersions = require("../package.json").engines.node; -const bannedNodeVersions = " < 14 || 20.0.* || 20.1.* || 20.2.* || 20.3.* "; +const bannedNodeVersions = " < 18 || 20.0.* || 20.1.* || 20.2.* || 20.3.* "; console.log(`Your Node.js version: ${nodeVersion}`); const semver = require("semver"); @@ -40,7 +40,6 @@ const args = require("args-parser")(process.argv); const { sleep, log, getRandomInt, genSecret, isDev } = require("../src/util"); const config = require("./config"); -log.info("server", "Welcome to Uptime Kuma"); log.debug("server", "Arguments"); log.debug("server", args); @@ -52,17 +51,17 @@ if (!process.env.UPTIME_KUMA_WS_ORIGIN_CHECK) { process.env.UPTIME_KUMA_WS_ORIGIN_CHECK = "cors-like"; } -log.info("server", "Node Env: " + process.env.NODE_ENV); -log.info("server", "Inside Container: " + (process.env.UPTIME_KUMA_IS_CONTAINER === "1")); +log.info("server", "Env: " + process.env.NODE_ENV); +log.debug("server", "Inside Container: " + (process.env.UPTIME_KUMA_IS_CONTAINER === "1")); if (process.env.UPTIME_KUMA_WS_ORIGIN_CHECK === "bypass") { log.warn("server", "WebSocket Origin Check: " + process.env.UPTIME_KUMA_WS_ORIGIN_CHECK); } -log.info("server", "Importing Node libraries"); -const fs = require("fs"); +const checkVersion = require("./check-version"); +log.info("server", "Uptime Kuma Version: " + checkVersion.version); -log.info("server", "Importing 3rd-party libraries"); +log.info("server", "Loading modules"); log.debug("server", "Importing express"); const express = require("express"); @@ -75,8 +74,6 @@ log.debug("server", "Importing http-graceful-shutdown"); const gracefulShutdown = require("http-graceful-shutdown"); log.debug("server", "Importing prometheus-api-metrics"); const prometheusAPIMetrics = require("prometheus-api-metrics"); -log.debug("server", "Importing compare-versions"); -const compareVersions = require("compare-versions"); const { passwordStrength } = require("check-password-strength"); log.debug("server", "Importing 2FA Modules"); @@ -88,22 +85,18 @@ const server = UptimeKumaServer.getInstance(); const io = module.exports.io = server.io; const app = server.app; -log.info("server", "Importing this project modules"); log.debug("server", "Importing Monitor"); const Monitor = require("./model/monitor"); const User = require("./model/user"); log.debug("server", "Importing Settings"); -const { getSettings, setSettings, setting, initJWTSecret, checkLogin, startUnitTest, doubleCheckPassword, startE2eTests, shake256, SHAKE256_LENGTH +const { getSettings, setSettings, setting, initJWTSecret, checkLogin, doubleCheckPassword, shake256, SHAKE256_LENGTH, allowDevAllOrigin, } = require("./util-server"); log.debug("server", "Importing Notification"); const { Notification } = require("./notification"); Notification.init(); -log.debug("server", "Importing Proxy"); -const { Proxy } = require("./proxy"); - log.debug("server", "Importing Database"); const Database = require("./database"); @@ -115,9 +108,6 @@ const { apiAuth } = require("./auth"); const { login } = require("./auth"); const passwordHash = require("./password-hash"); -const checkVersion = require("./check-version"); -log.info("server", "Version: " + checkVersion.version); - const hostname = config.hostname; if (hostname) { @@ -140,16 +130,12 @@ const twoFAVerifyOptions = { * @type {boolean} */ const testMode = !!args["test"] || false; -const e2eTestMode = !!args["e2e"] || false; - -if (config.demoMode) { - log.info("server", "==== Demo Mode ===="); -} // Must be after io instantiation -const { sendNotificationList, sendHeartbeatList, sendImportantHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList } = require("./client"); +const { sendNotificationList, sendHeartbeatList, sendInfo, sendProxyList, sendDockerHostList, sendAPIKeyList, sendRemoteBrowserList, sendMonitorTypeList } = require("./client"); const { statusPageSocketHandler } = require("./socket-handlers/status-page-socket-handler"); -const databaseSocketHandler = require("./socket-handlers/database-socket-handler"); +const { databaseSocketHandler } = require("./socket-handlers/database-socket-handler"); +const { remoteBrowserSocketHandler } = require("./socket-handlers/remote-browser-socket-handler"); const TwoFA = require("./2fa"); const StatusPage = require("./model/status_page"); const { cloudflaredSocketHandler, autoStart: cloudflaredAutoStart, stop: cloudflaredStop } = require("./socket-handlers/cloudflared-socket-handler"); @@ -159,9 +145,11 @@ const { maintenanceSocketHandler } = require("./socket-handlers/maintenance-sock const { apiKeySocketHandler } = require("./socket-handlers/api-key-socket-handler"); const { generalSocketHandler } = require("./socket-handlers/general-socket-handler"); const { Settings } = require("./settings"); -const { CacheableDnsHttpAgent } = require("./cacheable-dns-http-agent"); const apicache = require("./modules/apicache"); const { resetChrome } = require("./monitor-types/real-browser-monitor-type"); +const { EmbeddedMariaDB } = require("./embedded-mariadb"); +const { SetupDatabase } = require("./setup-database"); +const { chartSocketHandler } = require("./socket-handlers/chart-socket-handler"); app.use(express.json()); @@ -181,13 +169,30 @@ app.use(function (req, res, next) { let needSetup = false; (async () => { - Database.init(args); - await initDatabase(testMode); + // Create a data directory + Database.initDataDir(args); + + // Check if is chosen a database type + let setupDatabase = new SetupDatabase(args, server); + if (setupDatabase.isNeedSetup()) { + // Hold here and start a special setup page until user choose a database type + await setupDatabase.start(hostname, port); + } + + // Connect to database + try { + await initDatabase(testMode); + } catch (e) { + log.error("server", "Failed to prepare your database: " + e.message); + process.exit(1); + } + + // Database should be ready now await server.initAfterDatabaseReady(); server.entryPage = await Settings.get("entryPage"); await StatusPage.loadDomainMappingList(); - log.info("server", "Adding route"); + log.debug("server", "Adding route"); // *************************** // Normal Router here @@ -220,6 +225,14 @@ let needSetup = false; } }); + app.get("/setup-database-info", (request, response) => { + allowDevAllOrigin(response); + response.json({ + runningSetup: false, + needSetup: false, + }); + }); + if (isDev) { app.use(express.urlencoded({ extended: true })); app.post("/test-webhook", async (request, response) => { @@ -227,6 +240,42 @@ let needSetup = false; log.debug("test", request.body); response.send("OK"); }); + + app.post("/test-x-www-form-urlencoded", async (request, response) => { + log.debug("test", request.headers); + log.debug("test", request.body); + response.send("OK"); + }); + + const fs = require("fs"); + + app.get("/_e2e/take-sqlite-snapshot", async (request, response) => { + await Database.close(); + try { + fs.cpSync(Database.sqlitePath, `${Database.sqlitePath}.e2e-snapshot`); + } catch (err) { + throw new Error("Unable to copy SQLite DB."); + } + await Database.connect(); + + response.send("Snapshot taken."); + }); + + app.get("/_e2e/restore-sqlite-snapshot", async (request, response) => { + if (!fs.existsSync(`${Database.sqlitePath}.e2e-snapshot`)) { + throw new Error("Snapshot doesn't exist."); + } + + await Database.close(); + try { + fs.cpSync(`${Database.sqlitePath}.e2e-snapshot`, Database.sqlitePath); + } catch (err) { + throw new Error("Unable to copy snapshot file."); + } + await Database.connect(); + + response.send("Snapshot restored."); + }); } // Robots.txt @@ -273,10 +322,10 @@ let needSetup = false; } }); - log.info("server", "Adding socket handler"); + log.debug("server", "Adding socket handler"); io.on("connection", async (socket) => { - sendInfo(socket, true); + await sendInfo(socket, true); if (needSetup) { log.info("server", "Redirect to setup page"); @@ -308,7 +357,7 @@ let needSetup = false; } log.debug("auth", "afterLogin"); - afterLogin(socket, user); + await afterLogin(socket, user); log.debug("auth", "afterLogin ok"); log.info("auth", `Successfully logged in user ${decoded.username}. IP=${clientIP}`); @@ -322,7 +371,8 @@ let needSetup = false; callback({ ok: false, - msg: "The user is inactive or deleted.", + msg: "authUserInactiveOrDeleted", + msgi18n: true, }); } } catch (error) { @@ -332,7 +382,8 @@ let needSetup = false; } callback({ ok: false, - msg: "Invalid token.", + msg: "authInvalidToken", + msgi18n: true, }); } @@ -353,7 +404,7 @@ let needSetup = false; } // Login Rate Limit - if (! await loginRateLimiter.pass(callback)) { + if (!await loginRateLimiter.pass(callback)) { log.info("auth", `Too many failed requests for user ${data.username}. IP=${clientIP}`); return; } @@ -362,7 +413,7 @@ let needSetup = false; if (user) { if (user.twofa_status === 0) { - afterLogin(socket, user); + await afterLogin(socket, user); log.info("auth", `Successfully logged in user ${data.username}. IP=${clientIP}`); @@ -385,7 +436,7 @@ let needSetup = false; let verify = notp.totp.verify(data.token, user.twofa_secret, twoFAVerifyOptions); if (user.twofa_last_token !== data.token && verify) { - afterLogin(socket, user); + await afterLogin(socket, user); await R.exec("UPDATE `user` SET twofa_last_token = ? WHERE id = ? ", [ data.token, @@ -404,7 +455,8 @@ let needSetup = false; callback({ ok: false, - msg: "Invalid Token!", + msg: "authInvalidToken", + msgi18n: true, }); } } @@ -414,7 +466,8 @@ let needSetup = false; callback({ ok: false, - msg: "Incorrect username or password.", + msg: "authIncorrectCreds", + msgi18n: true, }); } @@ -422,7 +475,7 @@ let needSetup = false; socket.on("logout", async (callback) => { // Rate Limit - if (! await loginRateLimiter.pass(callback)) { + if (!await loginRateLimiter.pass(callback)) { return; } @@ -436,7 +489,7 @@ let needSetup = false; socket.on("prepare2FA", async (currentPassword, callback) => { try { - if (! await twoFaRateLimiter.pass(callback)) { + if (!await twoFaRateLimiter.pass(callback)) { return; } @@ -470,7 +523,8 @@ let needSetup = false; } else { callback({ ok: false, - msg: "2FA is already enabled.", + msg: "2faAlreadyEnabled", + msgi18n: true, }); } } catch (error) { @@ -485,7 +539,7 @@ let needSetup = false; const clientIP = await server.getClientIP(socket); try { - if (! await twoFaRateLimiter.pass(callback)) { + if (!await twoFaRateLimiter.pass(callback)) { return; } @@ -500,7 +554,8 @@ let needSetup = false; callback({ ok: true, - msg: "2FA Enabled.", + msg: "2faEnabled", + msgi18n: true, }); } catch (error) { @@ -517,7 +572,7 @@ let needSetup = false; const clientIP = await server.getClientIP(socket); try { - if (! await twoFaRateLimiter.pass(callback)) { + if (!await twoFaRateLimiter.pass(callback)) { return; } @@ -529,7 +584,8 @@ let needSetup = false; callback({ ok: true, - msg: "2FA Disabled.", + msg: "2faDisabled", + msgi18n: true, }); } catch (error) { @@ -561,7 +617,8 @@ let needSetup = false; } else { callback({ ok: false, - msg: "Invalid Token.", + msg: "authInvalidToken", + msgi18n: true, valid: false, }); } @@ -611,7 +668,7 @@ let needSetup = false; throw new Error("Password is too weak. It should contain alphabetic and numeric characters. It must be at least 6 characters in length."); } - if ((await R.count("user")) !== 0) { + if ((await R.knex("user").count("id as count").first()).count !== 0) { throw new Error("Uptime Kuma has been initialized. If you want to run setup again, please delete the database."); } @@ -624,7 +681,8 @@ let needSetup = false; callback({ ok: true, - msg: "Added Successfully.", + msg: "successAdded", + msgi18n: true, }); } catch (e) { @@ -658,6 +716,10 @@ let needSetup = false; monitor.kafkaProducerBrokers = JSON.stringify(monitor.kafkaProducerBrokers); monitor.kafkaProducerSaslOptions = JSON.stringify(monitor.kafkaProducerSaslOptions); + monitor.conditions = JSON.stringify(monitor.conditions); + + monitor.rabbitmqNodes = JSON.stringify(monitor.rabbitmqNodes); + bean.import(monitor); bean.user_id = socket.userID; @@ -667,17 +729,18 @@ let needSetup = false; await updateMonitorNotification(bean.id, notificationIDList); - await server.sendMonitorList(socket); + await server.sendUpdateMonitorIntoList(socket, bean.id); if (monitor.active !== false) { await startMonitor(socket.userID, bean.id); } - log.info("monitor", `Added Monitor: ${monitor.id} User ID: ${socket.userID}`); + log.info("monitor", `Added Monitor: ${bean.id} User ID: ${socket.userID}`); callback({ ok: true, - msg: "Added Successfully.", + msg: "successAdded", + msgi18n: true, monitorID: bean.id, }); @@ -748,6 +811,11 @@ let needSetup = false; bean.game = monitor.game; bean.maxretries = monitor.maxretries; bean.port = parseInt(monitor.port); + + if (isNaN(bean.port)) { + bean.port = null; + } + bean.keyword = monitor.keyword; bean.invertKeyword = monitor.invertKeyword; bean.ignoreTls = monitor.ignoreTls; @@ -766,6 +834,7 @@ let needSetup = false; bean.mqttPassword = monitor.mqttPassword; bean.mqttTopic = monitor.mqttTopic; bean.mqttSuccessMessage = monitor.mqttSuccessMessage; + bean.mqttCheckType = monitor.mqttCheckType; bean.databaseConnectionString = monitor.databaseConnectionString; bean.databaseQuery = monitor.databaseQuery; bean.authMethod = monitor.authMethod; @@ -791,10 +860,20 @@ let needSetup = false; bean.kafkaProducerAllowAutoTopicCreation = monitor.kafkaProducerAllowAutoTopicCreation; bean.kafkaProducerSaslOptions = JSON.stringify(monitor.kafkaProducerSaslOptions); bean.kafkaProducerMessage = monitor.kafkaProducerMessage; + bean.cacheBust = monitor.cacheBust; bean.kafkaProducerSsl = monitor.kafkaProducerSsl; bean.kafkaProducerAllowAutoTopicCreation = monitor.kafkaProducerAllowAutoTopicCreation; bean.gamedigGivenPortOnly = monitor.gamedigGivenPortOnly; + bean.remote_browser = monitor.remote_browser; + bean.snmpVersion = monitor.snmpVersion; + bean.snmpOid = monitor.snmpOid; + bean.jsonPathOperator = monitor.jsonPathOperator; + bean.timeout = monitor.timeout; + bean.rabbitmqNodes = JSON.stringify(monitor.rabbitmqNodes); + bean.rabbitmqUsername = monitor.rabbitmqUsername; + bean.rabbitmqPassword = monitor.rabbitmqPassword; + bean.conditions = JSON.stringify(monitor.conditions); bean.validate(); @@ -806,15 +885,16 @@ let needSetup = false; await updateMonitorNotification(bean.id, monitor.notificationIDList); - if (await bean.isActive()) { + if (await Monitor.isActive(bean.id, bean.active)) { await restartMonitor(socket.userID, bean.id); } - await server.sendMonitorList(socket); + await server.sendUpdateMonitorIntoList(socket, bean.id); callback({ ok: true, msg: "Saved.", + msgi18n: true, monitorID: bean.id, }); @@ -849,14 +929,17 @@ let needSetup = false; log.info("monitor", `Get Monitor: ${monitorID} User ID: ${socket.userID}`); - let bean = await R.findOne("monitor", " id = ? AND user_id = ? ", [ + let monitor = await R.findOne("monitor", " id = ? AND user_id = ? ", [ monitorID, socket.userID, ]); - + const monitorData = [{ id: monitor.id, + active: monitor.active + }]; + const preloadData = await Monitor.preparePreloadData(monitorData); callback({ ok: true, - monitor: await bean.toJSON(), + monitor: monitor.toJSON(preloadData), }); } catch (e) { @@ -877,14 +960,17 @@ let needSetup = false; throw new Error("Invalid period."); } + const sqlHourOffset = Database.sqlHourOffset(); + let list = await R.getAll(` - SELECT * FROM heartbeat - WHERE monitor_id = ? AND - time > DATETIME('now', '-' || ? || ' hours') + SELECT * + FROM heartbeat + WHERE monitor_id = ? + AND time > ${sqlHourOffset} ORDER BY time ASC `, [ monitorID, - period, + -period, ]); callback({ @@ -904,11 +990,12 @@ let needSetup = false; try { checkLogin(socket); await startMonitor(socket.userID, monitorID); - await server.sendMonitorList(socket); + await server.sendUpdateMonitorIntoList(socket, monitorID); callback({ ok: true, - msg: "Resumed Successfully.", + msg: "successResumed", + msgi18n: true, }); } catch (e) { @@ -923,11 +1010,12 @@ let needSetup = false; try { checkLogin(socket); await pauseMonitor(socket.userID, monitorID); - await server.sendMonitorList(socket); + await server.sendUpdateMonitorIntoList(socket, monitorID); callback({ ok: true, - msg: "Paused Successfully.", + msg: "successPaused", + msgi18n: true, }); } catch (e) { @@ -945,7 +1033,7 @@ let needSetup = false; log.info("manage", `Delete Monitor: ${monitorID} User ID: ${socket.userID}`); if (monitorID in server.monitorList) { - server.monitorList[monitorID].stop(); + await server.monitorList[monitorID].stop(); delete server.monitorList[monitorID]; } @@ -965,12 +1053,10 @@ let needSetup = false; callback({ ok: true, - msg: "Deleted Successfully.", + msg: "successDeleted", + msgi18n: true, }); - - await server.sendMonitorList(socket); - // Clear heartbeat list on client - await sendImportantHeartbeatList(socket, monitorID, true, true); + await server.sendDeleteMonitorFromList(socket, monitorID); } catch (e) { callback({ @@ -1029,7 +1115,8 @@ let needSetup = false; if (bean == null) { callback({ ok: false, - msg: "Tag not found", + msg: "tagNotFound", + msgi18n: true, }); return; } @@ -1039,7 +1126,8 @@ let needSetup = false; callback({ ok: true, - msg: "Saved", + msg: "Saved.", + msgi18n: true, tag: await bean.toJSON(), }); @@ -1059,7 +1147,8 @@ let needSetup = false; callback({ ok: true, - msg: "Deleted Successfully.", + msg: "successDeleted", + msgi18n: true, }); } catch (e) { @@ -1082,7 +1171,8 @@ let needSetup = false; callback({ ok: true, - msg: "Added Successfully.", + msg: "successAdded", + msgi18n: true, }); } catch (e) { @@ -1105,7 +1195,8 @@ let needSetup = false; callback({ ok: true, - msg: "Edited Successfully.", + msg: "successEdited", + msgi18n: true, }); } catch (e) { @@ -1128,7 +1219,8 @@ let needSetup = false; callback({ ok: true, - msg: "Deleted Successfully.", + msg: "successDeleted", + msgi18n: true, }); } catch (e) { @@ -1139,11 +1231,77 @@ let needSetup = false; } }); + socket.on("monitorImportantHeartbeatListCount", async (monitorID, callback) => { + try { + checkLogin(socket); + + let count; + if (monitorID == null) { + count = await R.count("heartbeat", "important = 1"); + } else { + count = await R.count("heartbeat", "monitor_id = ? AND important = 1", [ + monitorID, + ]); + } + + callback({ + ok: true, + count: count, + }); + } catch (e) { + callback({ + ok: false, + msg: e.message, + }); + } + }); + + socket.on("monitorImportantHeartbeatListPaged", async (monitorID, offset, count, callback) => { + try { + checkLogin(socket); + + let list; + if (monitorID == null) { + list = await R.find("heartbeat", ` + important = 1 + ORDER BY time DESC + LIMIT ? + OFFSET ? + `, [ + count, + offset, + ]); + } else { + list = await R.find("heartbeat", ` + monitor_id = ? + AND important = 1 + ORDER BY time DESC + LIMIT ? + OFFSET ? + `, [ + monitorID, + count, + offset, + ]); + } + + callback({ + ok: true, + data: list, + }); + } catch (e) { + callback({ + ok: false, + msg: e.message, + }); + } + }); + socket.on("changePassword", async (password, callback) => { try { checkLogin(socket); - if (! password.newPassword) { + if (!password.newPassword) { throw new Error("Invalid new password"); } @@ -1158,7 +1316,9 @@ let needSetup = false; callback({ ok: true, - msg: "Password has been updated successfully.", + token: User.createJWT(user, server.jwtSecret), + msg: "successAuthChangePassword", + msgi18n: true, }); } catch (e) { @@ -1217,8 +1377,6 @@ let needSetup = false; await setSettings("general", data); server.entryPage = data.entryPage; - await CacheableDnsHttpAgent.update(); - // Also need to apply timezone globally if (data.serverTimezone) { await server.setTimezone(data.serverTimezone); @@ -1241,11 +1399,12 @@ let needSetup = false; callback({ ok: true, - msg: "Saved" + msg: "Saved.", + msgi18n: true, }); - sendInfo(socket); - server.sendMaintenanceList(socket); + await sendInfo(socket); + await server.sendMaintenanceList(socket); } catch (e) { callback({ @@ -1265,7 +1424,8 @@ let needSetup = false; callback({ ok: true, - msg: "Saved", + msg: "Saved.", + msgi18n: true, id: notificationBean.id, }); @@ -1286,7 +1446,8 @@ let needSetup = false; callback({ ok: true, - msg: "Deleted", + msg: "successDeleted", + msgi18n: true, }); } catch (e) { @@ -1327,211 +1488,6 @@ let needSetup = false; } }); - socket.on("uploadBackup", async (uploadedJSON, importHandle, callback) => { - try { - checkLogin(socket); - - let backupData = JSON.parse(uploadedJSON); - - log.info("manage", `Importing Backup, User ID: ${socket.userID}, Version: ${backupData.version}`); - - let notificationListData = backupData.notificationList; - let proxyListData = backupData.proxyList; - let monitorListData = backupData.monitorList; - - let version17x = compareVersions.compare(backupData.version, "1.7.0", ">="); - - // If the import option is "overwrite" it'll clear most of the tables, except "settings" and "user" - if (importHandle === "overwrite") { - // Stops every monitor first, so it doesn't execute any heartbeat while importing - for (let id in server.monitorList) { - let monitor = server.monitorList[id]; - await monitor.stop(); - } - await R.exec("DELETE FROM heartbeat"); - await R.exec("DELETE FROM monitor_notification"); - await R.exec("DELETE FROM monitor_tls_info"); - await R.exec("DELETE FROM notification"); - await R.exec("DELETE FROM monitor_tag"); - await R.exec("DELETE FROM tag"); - await R.exec("DELETE FROM monitor"); - await R.exec("DELETE FROM proxy"); - } - - // Only starts importing if the backup file contains at least one notification - if (notificationListData.length >= 1) { - // Get every existing notification name and puts them in one simple string - let notificationNameList = await R.getAll("SELECT name FROM notification"); - let notificationNameListString = JSON.stringify(notificationNameList); - - for (let i = 0; i < notificationListData.length; i++) { - // Only starts importing the notification if the import option is "overwrite", "keep" or "skip" but the notification doesn't exists - if ((importHandle === "skip" && notificationNameListString.includes(notificationListData[i].name) === false) || importHandle === "keep" || importHandle === "overwrite") { - - let notification = JSON.parse(notificationListData[i].config); - await Notification.save(notification, null, socket.userID); - - } - } - } - - // Only starts importing if the backup file contains at least one proxy - if (proxyListData && proxyListData.length >= 1) { - const proxies = await R.findAll("proxy"); - - // Loop over proxy list and save proxies - for (const proxy of proxyListData) { - const exists = proxies.find(item => item.id === proxy.id); - - // Do not process when proxy already exists in import handle is skip and keep - if ([ "skip", "keep" ].includes(importHandle) && !exists) { - return; - } - - // Save proxy as new entry if exists update exists one - await Proxy.save(proxy, exists ? proxy.id : undefined, proxy.userId); - } - } - - // Only starts importing if the backup file contains at least one monitor - if (monitorListData.length >= 1) { - // Get every existing monitor name and puts them in one simple string - let monitorNameList = await R.getAll("SELECT name FROM monitor"); - let monitorNameListString = JSON.stringify(monitorNameList); - - for (let i = 0; i < monitorListData.length; i++) { - // Only starts importing the monitor if the import option is "overwrite", "keep" or "skip" but the notification doesn't exists - if ((importHandle === "skip" && monitorNameListString.includes(monitorListData[i].name) === false) || importHandle === "keep" || importHandle === "overwrite") { - - // Define in here every new variable for monitors which where implemented after the first version of the Import/Export function (1.6.0) - // --- Start --- - - // Define default values - let retryInterval = 0; - let timeout = monitorListData[i].timeout || (monitorListData[i].interval * 0.8); // fallback to old value - - /* - Only replace the default value with the backup file data for the specific version, where it appears the first time - More information about that where "let version" will be defined - */ - if (version17x) { - retryInterval = monitorListData[i].retryInterval; - } - - // --- End --- - - let monitor = { - // Define the new variable from earlier here - name: monitorListData[i].name, - description: monitorListData[i].description, - type: monitorListData[i].type, - url: monitorListData[i].url, - method: monitorListData[i].method || "GET", - body: monitorListData[i].body, - headers: monitorListData[i].headers, - authMethod: monitorListData[i].authMethod, - basic_auth_user: monitorListData[i].basic_auth_user, - basic_auth_pass: monitorListData[i].basic_auth_pass, - authWorkstation: monitorListData[i].authWorkstation, - authDomain: monitorListData[i].authDomain, - timeout, - interval: monitorListData[i].interval, - retryInterval: retryInterval, - resendInterval: monitorListData[i].resendInterval || 0, - hostname: monitorListData[i].hostname, - maxretries: monitorListData[i].maxretries, - port: monitorListData[i].port, - keyword: monitorListData[i].keyword, - invertKeyword: monitorListData[i].invertKeyword, - ignoreTls: monitorListData[i].ignoreTls, - upsideDown: monitorListData[i].upsideDown, - maxredirects: monitorListData[i].maxredirects, - accepted_statuscodes: monitorListData[i].accepted_statuscodes, - dns_resolve_type: monitorListData[i].dns_resolve_type, - dns_resolve_server: monitorListData[i].dns_resolve_server, - notificationIDList: monitorListData[i].notificationIDList, - proxy_id: monitorListData[i].proxy_id || null, - }; - - if (monitorListData[i].pushToken) { - monitor.pushToken = monitorListData[i].pushToken; - } - - let bean = R.dispense("monitor"); - - let notificationIDList = monitor.notificationIDList; - delete monitor.notificationIDList; - - monitor.accepted_statuscodes_json = JSON.stringify(monitor.accepted_statuscodes); - delete monitor.accepted_statuscodes; - - bean.import(monitor); - bean.user_id = socket.userID; - await R.store(bean); - - // Only for backup files with the version 1.7.0 or higher, since there was the tag feature implemented - if (version17x) { - // Only import if the specific monitor has tags assigned - for (const oldTag of monitorListData[i].tags) { - - // Check if tag already exists and get data -> - let tag = await R.findOne("tag", " name = ?", [ - oldTag.name, - ]); - - let tagId; - if (! tag) { - // -> If it doesn't exist, create new tag from backup file - let beanTag = R.dispense("tag"); - beanTag.name = oldTag.name; - beanTag.color = oldTag.color; - await R.store(beanTag); - - tagId = beanTag.id; - } else { - // -> If it already exist, set tagId to value from database - tagId = tag.id; - } - - // Assign the new created tag to the monitor - await R.exec("INSERT INTO monitor_tag (tag_id, monitor_id, value) VALUES (?, ?, ?)", [ - tagId, - bean.id, - oldTag.value, - ]); - - } - } - - await updateMonitorNotification(bean.id, notificationIDList); - - // If monitor was active start it immediately, otherwise pause it - if (monitorListData[i].active === 1) { - await startMonitor(socket.userID, bean.id); - } else { - await pauseMonitor(socket.userID, bean.id); - } - - } - } - - await sendNotificationList(socket); - await server.sendMonitorList(socket); - } - - callback({ - ok: true, - msg: "Backup successfully restored.", - }); - - } catch (e) { - callback({ - ok: false, - msg: e.message, - }); - } - }); - socket.on("clearEvents", async (monitorID, callback) => { try { checkLogin(socket); @@ -1544,8 +1500,6 @@ let needSetup = false; monitorID, ]); - await sendImportantHeartbeatList(socket, monitorID, true, true); - callback({ ok: true, }); @@ -1589,6 +1543,14 @@ let needSetup = false; log.info("manage", `Clear Statistics User ID: ${socket.userID}`); await R.exec("DELETE FROM heartbeat"); + await R.exec("DELETE FROM stat_daily"); + await R.exec("DELETE FROM stat_hourly"); + await R.exec("DELETE FROM stat_minutely"); + + // Restart all monitors to reset the stats + for (let monitorID in server.monitorList) { + await restartMonitor(socket.userID, monitorID); + } callback({ ok: true, @@ -1610,7 +1572,9 @@ let needSetup = false; dockerSocketHandler(socket); maintenanceSocketHandler(socket); apiKeySocketHandler(socket); + remoteBrowserSocketHandler(socket); generalSocketHandler(socket, server); + chartSocketHandler(socket); log.debug("server", "added all socket handlers"); @@ -1621,43 +1585,39 @@ let needSetup = false; log.debug("auth", "check auto login"); if (await setting("disableAuth")) { log.info("auth", "Disabled Auth: auto login to admin"); - afterLogin(socket, await R.findOne("user")); + await afterLogin(socket, await R.findOne("user")); socket.emit("autoLogin"); } else { + socket.emit("loginRequired"); log.debug("auth", "need auth"); } }); - log.info("server", "Init the server"); + log.debug("server", "Init the server"); server.httpServer.once("error", async (err) => { - console.error("Cannot listen: " + err.message); + log.error("server", "Cannot listen: " + err.message); await shutdownFunction(); + process.exit(1); }); - server.start(); + await server.start(); - server.httpServer.listen(port, hostname, () => { + server.httpServer.listen(port, hostname, async () => { if (hostname) { log.info("server", `Listening on ${hostname}:${port}`); } else { log.info("server", `Listening on ${port}`); } - startMonitors(); - checkVersion.startInterval(); + await startMonitors(); - if (testMode) { - startUnitTest(); - } + // Put this here. Start background jobs after the db and server is ready to prevent clear up during db migration. + await initBackgroundJobs(); - if (e2eTestMode) { - startE2eTests(); - } + checkVersion.startInterval(); }); - await initBackgroundJobs(); - // Start cloudflared at the end if configured await cloudflaredAutoStart(cloudflaredToken); @@ -1687,8 +1647,8 @@ async function updateMonitorNotification(monitorID, notificationIDList) { /** * Check if a given user owns a specific monitor - * @param {number} userID - * @param {number} monitorID + * @param {number} userID ID of user to check + * @param {number} monitorID ID of monitor to check * @returns {Promise} * @throws {Error} The specified user does not own the monitor */ @@ -1707,7 +1667,7 @@ async function checkOwner(userID, monitorID) { * Function called after user login * This function is used to send the heartbeat list of a monitor. * @param {Socket} socket Socket.io instance - * @param {Object} user User object + * @param {object} user User object * @returns {Promise} */ async function afterLogin(socket, user) { @@ -1715,28 +1675,26 @@ async function afterLogin(socket, user) { socket.join(user.id); let monitorList = await server.sendMonitorList(socket); - sendInfo(socket); - server.sendMaintenanceList(socket); - sendNotificationList(socket); - sendProxyList(socket); - sendDockerHostList(socket); - sendAPIKeyList(socket); - - await sleep(500); + await Promise.allSettled([ + sendInfo(socket), + server.sendMaintenanceList(socket), + sendNotificationList(socket), + sendProxyList(socket), + sendDockerHostList(socket), + sendAPIKeyList(socket), + sendRemoteBrowserList(socket), + sendMonitorTypeList(socket), + ]); await StatusPage.sendStatusPageList(io, socket); + const monitorPromises = []; for (let monitorID in monitorList) { - await sendHeartbeatList(socket, monitorID); + monitorPromises.push(sendHeartbeatList(socket, monitorID)); + monitorPromises.push(Monitor.sendStats(io, monitorID, user.id)); } - for (let monitorID in monitorList) { - await sendImportantHeartbeatList(socket, monitorID); - } - - for (let monitorID in monitorList) { - await Monitor.sendStats(io, monitorID, user.id); - } + await Promise.all(monitorPromises); // Set server timezone from client browser if not set // It should be run once only @@ -1748,22 +1706,17 @@ async function afterLogin(socket, user) { /** * Initialize the database - * @param {boolean} [testMode=false] Should the connection be + * @param {boolean} testMode Should the connection be * started in test mode? * @returns {Promise} */ async function initDatabase(testMode = false) { - if (! fs.existsSync(Database.path)) { - log.info("server", "Copying Database"); - fs.copyFileSync(Database.templatePath, Database.path); - } - - log.info("server", "Connecting to the Database"); + log.debug("server", "Connecting to the database"); await Database.connect(testMode); - log.info("server", "Connected"); + log.info("server", "Connected to the database"); // Patch the database - await Database.patch(); + await Database.patch(port, hostname); let jwtSecretBean = await R.findOne("setting", " `key` = ? ", [ "jwtSecret", @@ -1774,11 +1727,11 @@ async function initDatabase(testMode = false) { jwtSecretBean = await initJWTSecret(); log.info("server", "Stored JWT secret into database"); } else { - log.info("server", "Load JWT secret from database."); + log.debug("server", "Load JWT secret from database."); } // If there is no record in user table, it is a new Uptime Kuma instance, need to setup - if ((await R.count("user")) === 0) { + if ((await R.knex("user").count("id as count").first()).count === 0) { log.info("server", "No user, need setup"); needSetup = true; } @@ -1807,11 +1760,11 @@ async function startMonitor(userID, monitorID) { ]); if (monitor.id in server.monitorList) { - server.monitorList[monitor.id].stop(); + await server.monitorList[monitor.id].stop(); } server.monitorList[monitor.id] = monitor; - monitor.start(io); + await monitor.start(io); } /** @@ -1841,12 +1794,15 @@ async function pauseMonitor(userID, monitorID) { ]); if (monitorID in server.monitorList) { - server.monitorList[monitorID].stop(); + await server.monitorList[monitorID].stop(); server.monitorList[monitorID].active = 0; } } -/** Resume active monitors */ +/** + * Resume active monitors + * @returns {Promise} + */ async function startMonitors() { let list = await R.find("monitor", " active = 1 "); @@ -1855,7 +1811,11 @@ async function startMonitors() { } for (let monitor of list) { - monitor.start(io); + try { + await monitor.start(io); + } catch (e) { + log.error("monitor", e); + } // Give some delays, so all monitors won't make request at the same moment when just start the server. await sleep(getRandomInt(300, 1000)); } @@ -1876,17 +1836,24 @@ async function shutdownFunction(signal) { log.info("server", "Stopping all monitors"); for (let id in server.monitorList) { let monitor = server.monitorList[id]; - monitor.stop(); + await monitor.stop(); } await sleep(2000); await Database.close(); + if (EmbeddedMariaDB.hasInstance()) { + EmbeddedMariaDB.getInstance().stop(); + } + stopBackgroundJobs(); await cloudflaredStop(); Settings.stopCacheCleaner(); } -/** Final function called before application exits */ +/** + * Final function called before application exits + * @returns {void} + */ function finalFunction() { log.info("server", "Graceful shutdown successful!"); } diff --git a/server/settings.js b/server/settings.js index 285b626b9a..4776c554d7 100644 --- a/server/settings.js +++ b/server/settings.js @@ -96,7 +96,7 @@ class Settings { /** * Get settings based on type * @param {string} type The type of setting - * @returns {Promise} + * @returns {Promise} Settings */ static async getSettings(type) { let list = await R.getAll("SELECT `key`, `value` FROM setting WHERE `type` = ? ", [ @@ -119,7 +119,7 @@ class Settings { /** * Set settings based on type * @param {string} type Type of settings to set - * @param {Object} data Values of settings + * @param {object} data Values of settings * @returns {Promise} */ static async setSettings(type, data) { @@ -150,8 +150,9 @@ class Settings { } /** - * - * @param {string[]} keyList + * Delete selected keys from settings cache + * @param {string[]} keyList Keys to remove + * @returns {void} */ static deleteCache(keyList) { for (let key of keyList) { @@ -159,6 +160,10 @@ class Settings { } } + /** + * Stop the cache cleaner if running + * @returns {void} + */ static stopCacheCleaner() { if (Settings.cacheCleaner) { clearInterval(Settings.cacheCleaner); diff --git a/server/setup-database.js b/server/setup-database.js new file mode 100644 index 0000000000..483f2c9a49 --- /dev/null +++ b/server/setup-database.js @@ -0,0 +1,271 @@ +const express = require("express"); +const { log } = require("../src/util"); +const expressStaticGzip = require("express-static-gzip"); +const fs = require("fs"); +const path = require("path"); +const Database = require("./database"); +const { allowDevAllOrigin } = require("./util-server"); +const mysql = require("mysql2/promise"); + +/** + * A standalone express app that is used to setup a database + * It is used when db-config.json and kuma.db are not found or invalid + * Once it is configured, it will shut down and start the main server + */ +class SetupDatabase { + /** + * Show Setup Page + * @type {boolean} + */ + needSetup = true; + /** + * If the server has finished the setup + * @type {boolean} + * @private + */ + runningSetup = false; + /** + * @inheritDoc + * @type {UptimeKumaServer} + * @private + */ + server; + + /** + * @param {object} args The arguments passed from the command line + * @param {UptimeKumaServer} server the main server instance + */ + constructor(args, server) { + this.server = server; + + // Priority: env > db-config.json + // If env is provided, write it to db-config.json + // If db-config.json is found, check if it is valid + // If db-config.json is not found or invalid, check if kuma.db is found + // If kuma.db is not found, show setup page + + let dbConfig; + + try { + dbConfig = Database.readDBConfig(); + log.debug("setup-database", "db-config.json is found and is valid"); + this.needSetup = false; + + } catch (e) { + log.info("setup-database", "db-config.json is not found or invalid: " + e.message); + + // Check if kuma.db is found (1.X.X users), generate db-config.json + if (fs.existsSync(path.join(Database.dataDir, "kuma.db"))) { + this.needSetup = false; + + log.info("setup-database", "kuma.db is found, generate db-config.json"); + Database.writeDBConfig({ + type: "sqlite", + }); + } else { + this.needSetup = true; + } + dbConfig = {}; + } + + if (process.env.UPTIME_KUMA_DB_TYPE) { + this.needSetup = false; + log.info("setup-database", "UPTIME_KUMA_DB_TYPE is provided by env, try to override db-config.json"); + dbConfig.type = process.env.UPTIME_KUMA_DB_TYPE; + dbConfig.hostname = process.env.UPTIME_KUMA_DB_HOSTNAME; + dbConfig.port = process.env.UPTIME_KUMA_DB_PORT; + dbConfig.dbName = process.env.UPTIME_KUMA_DB_NAME; + dbConfig.username = process.env.UPTIME_KUMA_DB_USERNAME; + dbConfig.password = process.env.UPTIME_KUMA_DB_PASSWORD; + Database.writeDBConfig(dbConfig); + } + + } + + /** + * Show Setup Page + * @returns {boolean} true if the setup page should be shown + */ + isNeedSetup() { + return this.needSetup; + } + + /** + * Check if the embedded MariaDB is enabled + * @returns {boolean} true if the embedded MariaDB is enabled + */ + isEnabledEmbeddedMariaDB() { + return process.env.UPTIME_KUMA_ENABLE_EMBEDDED_MARIADB === "1"; + } + + /** + * Start the setup-database server + * @param {string} hostname where the server is listening + * @param {number} port where the server is listening + * @returns {Promise} + */ + start(hostname, port) { + return new Promise((resolve) => { + const app = express(); + let tempServer; + app.use(express.json()); + + // Disable Keep Alive, otherwise the server will not shutdown, as the client will keep the connection alive + app.use(function (req, res, next) { + res.setHeader("Connection", "close"); + next(); + }); + + app.get("/", async (request, response) => { + response.redirect("/setup-database"); + }); + + app.get("/api/entry-page", async (request, response) => { + allowDevAllOrigin(response); + response.json({ + type: "setup-database", + }); + }); + + app.get("/setup-database-info", (request, response) => { + allowDevAllOrigin(response); + console.log("Request /setup-database-info"); + response.json({ + runningSetup: this.runningSetup, + needSetup: this.needSetup, + isEnabledEmbeddedMariaDB: this.isEnabledEmbeddedMariaDB(), + }); + }); + + app.post("/setup-database", async (request, response) => { + allowDevAllOrigin(response); + + if (this.runningSetup) { + response.status(400).json("Setup is already running"); + return; + } + + this.runningSetup = true; + + let dbConfig = request.body.dbConfig; + + let supportedDBTypes = [ "mariadb", "sqlite" ]; + + if (this.isEnabledEmbeddedMariaDB()) { + supportedDBTypes.push("embedded-mariadb"); + } + + // Validate input + if (typeof dbConfig !== "object") { + response.status(400).json("Invalid dbConfig"); + this.runningSetup = false; + return; + } + + if (!dbConfig.type) { + response.status(400).json("Database Type is required"); + this.runningSetup = false; + return; + } + + if (!supportedDBTypes.includes(dbConfig.type)) { + response.status(400).json("Unsupported Database Type"); + this.runningSetup = false; + return; + } + + // External MariaDB + if (dbConfig.type === "mariadb") { + if (!dbConfig.hostname) { + response.status(400).json("Hostname is required"); + this.runningSetup = false; + return; + } + + if (!dbConfig.port) { + response.status(400).json("Port is required"); + this.runningSetup = false; + return; + } + + if (!dbConfig.dbName) { + response.status(400).json("Database name is required"); + this.runningSetup = false; + return; + } + + if (!dbConfig.username) { + response.status(400).json("Username is required"); + this.runningSetup = false; + return; + } + + if (!dbConfig.password) { + response.status(400).json("Password is required"); + this.runningSetup = false; + return; + } + + // Test connection + try { + const connection = await mysql.createConnection({ + host: dbConfig.hostname, + port: dbConfig.port, + user: dbConfig.username, + password: dbConfig.password, + }); + await connection.execute("SELECT 1"); + connection.end(); + } catch (e) { + response.status(400).json("Cannot connect to the database: " + e.message); + this.runningSetup = false; + return; + } + } + + // Write db-config.json + Database.writeDBConfig(dbConfig); + + response.json({ + ok: true, + }); + + // Shutdown down this express and start the main server + log.info("setup-database", "Database is configured, close the setup-database server and start the main server now."); + if (tempServer) { + tempServer.close(() => { + log.info("setup-database", "The setup-database server is closed"); + resolve(); + }); + } else { + resolve(); + } + + }); + + app.use("/", expressStaticGzip("dist", { + enableBrotli: true, + })); + + app.get("*", async (_request, response) => { + response.send(this.server.indexHTML); + }); + + app.options("*", async (_request, response) => { + allowDevAllOrigin(response); + response.end(); + }); + + tempServer = app.listen(port, hostname, () => { + log.info("setup-database", `Starting Setup Database on ${port}`); + let domain = (hostname) ? hostname : "localhost"; + log.info("setup-database", `Open http://${domain}:${port} in your browser`); + log.info("setup-database", "Waiting for user action..."); + }); + }); + } +} + +module.exports = { + SetupDatabase, +}; diff --git a/server/socket-handlers/api-key-socket-handler.js b/server/socket-handlers/api-key-socket-handler.js index 69b0b60de8..f76b909918 100644 --- a/server/socket-handlers/api-key-socket-handler.js +++ b/server/socket-handlers/api-key-socket-handler.js @@ -9,8 +9,9 @@ const { Settings } = require("../settings"); const { sendAPIKeyList } = require("../client"); /** - * Handlers for Maintenance + * Handlers for API keys * @param {Socket} socket Socket.io instance + * @returns {void} */ module.exports.apiKeySocketHandler = (socket) => { // Add a new api key @@ -37,7 +38,8 @@ module.exports.apiKeySocketHandler = (socket) => { callback({ ok: true, - msg: "Added Successfully.", + msg: "successAdded", + msgi18n: true, key: formattedKey, keyID: bean.id, }); @@ -81,7 +83,8 @@ module.exports.apiKeySocketHandler = (socket) => { callback({ ok: true, - msg: "Deleted Successfully.", + msg: "successDeleted", + msgi18n: true, }); await sendAPIKeyList(socket); @@ -108,7 +111,8 @@ module.exports.apiKeySocketHandler = (socket) => { callback({ ok: true, - msg: "Disabled Successfully.", + msg: "successDisabled", + msgi18n: true, }); await sendAPIKeyList(socket); @@ -135,7 +139,8 @@ module.exports.apiKeySocketHandler = (socket) => { callback({ ok: true, - msg: "Enabled Successfully", + msg: "successEnabled", + msgi18n: true, }); await sendAPIKeyList(socket); diff --git a/server/socket-handlers/chart-socket-handler.js b/server/socket-handlers/chart-socket-handler.js new file mode 100644 index 0000000000..654db0e730 --- /dev/null +++ b/server/socket-handlers/chart-socket-handler.js @@ -0,0 +1,38 @@ +const { checkLogin } = require("../util-server"); +const { UptimeCalculator } = require("../uptime-calculator"); +const { log } = require("../../src/util"); + +module.exports.chartSocketHandler = (socket) => { + socket.on("getMonitorChartData", async (monitorID, period, callback) => { + try { + checkLogin(socket); + + log.debug("monitor", `Get Monitor Chart Data: ${monitorID} User ID: ${socket.userID}`); + + if (period == null) { + throw new Error("Invalid period."); + } + + let uptimeCalculator = await UptimeCalculator.getUptimeCalculator(monitorID); + + let data; + if (period <= 24) { + data = uptimeCalculator.getDataArray(period * 60, "minute"); + } else if (period <= 720) { + data = uptimeCalculator.getDataArray(period, "hour"); + } else { + data = uptimeCalculator.getDataArray(period / 24, "day"); + } + + callback({ + ok: true, + data, + }); + } catch (e) { + callback({ + ok: false, + msg: e.message, + }); + } + }); +}; diff --git a/server/socket-handlers/cloudflared-socket-handler.js b/server/socket-handlers/cloudflared-socket-handler.js index ee58e1ad08..809191fe85 100644 --- a/server/socket-handlers/cloudflared-socket-handler.js +++ b/server/socket-handlers/cloudflared-socket-handler.js @@ -11,6 +11,7 @@ const cloudflared = new CloudflaredTunnel(); * Change running state * @param {string} running Is it running? * @param {string} message Message to pass + * @returns {void} */ cloudflared.change = (running, message) => { io.to("cloudflared").emit(prefix + "running", running); @@ -19,7 +20,8 @@ cloudflared.change = (running, message) => { /** * Emit an error message - * @param {string} errorMessage + * @param {string} errorMessage Error message to send + * @returns {void} */ cloudflared.error = (errorMessage) => { io.to("cloudflared").emit(prefix + "errorMessage", errorMessage); @@ -28,6 +30,7 @@ cloudflared.error = (errorMessage) => { /** * Handler for cloudflared * @param {Socket} socket Socket.io instance + * @returns {void} */ module.exports.cloudflaredSocketHandler = (socket) => { @@ -89,6 +92,7 @@ module.exports.cloudflaredSocketHandler = (socket) => { /** * Automatically start cloudflared * @param {string} token Cloudflared tunnel token + * @returns {Promise} */ module.exports.autoStart = async (token) => { if (!token) { @@ -106,7 +110,10 @@ module.exports.autoStart = async (token) => { } }; -/** Stop cloudflared */ +/** + * Stop cloudflared + * @returns {Promise} + */ module.exports.stop = async () => { log.info("cloudflared", "Stop cloudflared"); if (cloudflared) { diff --git a/server/socket-handlers/database-socket-handler.js b/server/socket-handlers/database-socket-handler.js index 041cbba069..ee2394bf6b 100644 --- a/server/socket-handlers/database-socket-handler.js +++ b/server/socket-handlers/database-socket-handler.js @@ -4,8 +4,9 @@ const Database = require("../database"); /** * Handlers for database * @param {Socket} socket Socket.io instance + * @returns {void} */ -module.exports = (socket) => { +module.exports.databaseSocketHandler = (socket) => { // Post or edit incident socket.on("getDatabaseSize", async (callback) => { @@ -26,7 +27,7 @@ module.exports = (socket) => { socket.on("shrinkDatabase", async (callback) => { try { checkLogin(socket); - Database.shrink(); + await Database.shrink(); callback({ ok: true, }); diff --git a/server/socket-handlers/docker-socket-handler.js b/server/socket-handlers/docker-socket-handler.js index 542f18cef6..95a60bcd30 100644 --- a/server/socket-handlers/docker-socket-handler.js +++ b/server/socket-handlers/docker-socket-handler.js @@ -6,6 +6,7 @@ const { log } = require("../../src/util"); /** * Handlers for docker hosts * @param {Socket} socket Socket.io instance + * @returns {void} */ module.exports.dockerSocketHandler = (socket) => { socket.on("addDockerHost", async (dockerHost, dockerHostID, callback) => { @@ -17,7 +18,8 @@ module.exports.dockerSocketHandler = (socket) => { callback({ ok: true, - msg: "Saved", + msg: "Saved.", + msgi18n: true, id: dockerHostBean.id, }); @@ -38,7 +40,8 @@ module.exports.dockerSocketHandler = (socket) => { callback({ ok: true, - msg: "Deleted", + msg: "successDeleted", + msgi18n: true, }); } catch (e) { diff --git a/server/socket-handlers/general-socket-handler.js b/server/socket-handlers/general-socket-handler.js index b3163c1c12..50dcd946e2 100644 --- a/server/socket-handlers/general-socket-handler.js +++ b/server/socket-handlers/general-socket-handler.js @@ -4,13 +4,15 @@ const { sendInfo } = require("../client"); const { checkLogin } = require("../util-server"); const GameResolver = require("gamedig/lib/GameResolver"); const { testChrome } = require("../monitor-types/real-browser-monitor-type"); +const fs = require("fs"); +const path = require("path"); let gameResolver = new GameResolver(); let gameList = null; /** * Get a game list via GameDig - * @returns {Object[]} list of games supported by GameDig + * @returns {object[]} list of games supported by GameDig */ function getGameList() { if (gameList == null) { @@ -27,8 +29,13 @@ function getGameList() { return gameList; } +/** + * Handler for general events + * @param {Socket} socket Socket.io instance + * @param {UptimeKumaServer} server Uptime Kuma server + * @returns {void} + */ module.exports.generalSocketHandler = (socket, server) => { - socket.on("initServerTimezone", async (timezone) => { try { checkLogin(socket); @@ -63,7 +70,11 @@ module.exports.generalSocketHandler = (socket, server) => { testChrome(executable).then((version) => { callback({ ok: true, - msg: "Found Chromium/Chrome. Version: " + version, + msg: { + key: "foundChromiumVersion", + values: [ version ], + }, + msgi18n: true, }); }).catch((e) => { callback({ @@ -79,6 +90,31 @@ module.exports.generalSocketHandler = (socket, server) => { } }); + socket.on("getPushExample", (language, callback) => { + + try { + let dir = path.join("./extra/push-examples", language); + let files = fs.readdirSync(dir); + + for (let file of files) { + if (file.startsWith("index.")) { + callback({ + ok: true, + code: fs.readFileSync(path.join(dir, file), "utf8"), + }); + return; + } + } + } catch (e) { + + } + + callback({ + ok: false, + msg: "Not found", + }); + }); + // Disconnect all other socket clients of the user socket.on("disconnectOtherSocketClients", async () => { try { diff --git a/server/socket-handlers/maintenance-socket-handler.js b/server/socket-handlers/maintenance-socket-handler.js index ff5bb0fcfc..7de13fe57a 100644 --- a/server/socket-handlers/maintenance-socket-handler.js +++ b/server/socket-handlers/maintenance-socket-handler.js @@ -9,6 +9,7 @@ const server = UptimeKumaServer.getInstance(); /** * Handlers for Maintenance * @param {Socket} socket Socket.io instance + * @returns {void} */ module.exports.maintenanceSocketHandler = (socket) => { // Add a new maintenance @@ -29,7 +30,8 @@ module.exports.maintenanceSocketHandler = (socket) => { callback({ ok: true, - msg: "Added Successfully.", + msg: "successAdded", + msgi18n: true, maintenanceID, }); @@ -60,6 +62,7 @@ module.exports.maintenanceSocketHandler = (socket) => { callback({ ok: true, msg: "Saved.", + msgi18n: true, maintenanceID: bean.id, }); @@ -95,7 +98,8 @@ module.exports.maintenanceSocketHandler = (socket) => { callback({ ok: true, - msg: "Added Successfully.", + msg: "successAdded", + msgi18n: true, }); } catch (e) { @@ -129,7 +133,8 @@ module.exports.maintenanceSocketHandler = (socket) => { callback({ ok: true, - msg: "Added Successfully.", + msg: "successAdded", + msgi18n: true, }); } catch (e) { @@ -248,7 +253,8 @@ module.exports.maintenanceSocketHandler = (socket) => { callback({ ok: true, - msg: "Deleted Successfully.", + msg: "successDeleted", + msgi18n: true, }); await server.sendMaintenanceList(socket); @@ -281,7 +287,8 @@ module.exports.maintenanceSocketHandler = (socket) => { callback({ ok: true, - msg: "Paused Successfully.", + msg: "successPaused", + msgi18n: true, }); await server.sendMaintenanceList(socket); @@ -314,7 +321,8 @@ module.exports.maintenanceSocketHandler = (socket) => { callback({ ok: true, - msg: "Resume Successfully", + msg: "successResumed", + msgi18n: true, }); await server.sendMaintenanceList(socket); diff --git a/server/socket-handlers/proxy-socket-handler.js b/server/socket-handlers/proxy-socket-handler.js index e67a829ff9..9e80371d7e 100644 --- a/server/socket-handlers/proxy-socket-handler.js +++ b/server/socket-handlers/proxy-socket-handler.js @@ -7,6 +7,7 @@ const server = UptimeKumaServer.getInstance(); /** * Handlers for proxy * @param {Socket} socket Socket.io instance + * @returns {void} */ module.exports.proxySocketHandler = (socket) => { socket.on("addProxy", async (proxy, proxyID, callback) => { @@ -23,7 +24,8 @@ module.exports.proxySocketHandler = (socket) => { callback({ ok: true, - msg: "Saved", + msg: "Saved.", + msgi18n: true, id: proxyBean.id, }); @@ -45,7 +47,8 @@ module.exports.proxySocketHandler = (socket) => { callback({ ok: true, - msg: "Deleted", + msg: "successDeleted", + msgi18n: true, }); } catch (e) { diff --git a/server/socket-handlers/remote-browser-socket-handler.js b/server/socket-handlers/remote-browser-socket-handler.js new file mode 100644 index 0000000000..ae53030ec4 --- /dev/null +++ b/server/socket-handlers/remote-browser-socket-handler.js @@ -0,0 +1,82 @@ +const { sendRemoteBrowserList } = require("../client"); +const { checkLogin } = require("../util-server"); +const { RemoteBrowser } = require("../remote-browser"); + +const { log } = require("../../src/util"); +const { testRemoteBrowser } = require("../monitor-types/real-browser-monitor-type"); + +/** + * Handlers for docker hosts + * @param {Socket} socket Socket.io instance + * @returns {void} + */ +module.exports.remoteBrowserSocketHandler = (socket) => { + socket.on("addRemoteBrowser", async (remoteBrowser, remoteBrowserID, callback) => { + try { + checkLogin(socket); + + let remoteBrowserBean = await RemoteBrowser.save(remoteBrowser, remoteBrowserID, socket.userID); + await sendRemoteBrowserList(socket); + + callback({ + ok: true, + msg: "Saved.", + msgi18n: true, + id: remoteBrowserBean.id, + }); + + } catch (e) { + callback({ + ok: false, + msg: e.message, + }); + } + }); + + socket.on("deleteRemoteBrowser", async (dockerHostID, callback) => { + try { + checkLogin(socket); + + await RemoteBrowser.delete(dockerHostID, socket.userID); + await sendRemoteBrowserList(socket); + + callback({ + ok: true, + msg: "successDeleted", + msgi18n: true, + }); + + } catch (e) { + callback({ + ok: false, + msg: e.message, + }); + } + }); + + socket.on("testRemoteBrowser", async (remoteBrowser, callback) => { + try { + checkLogin(socket); + let check = await testRemoteBrowser(remoteBrowser.url); + log.info("remoteBrowser", "Tested remote browser: " + check); + let msg; + + if (check) { + msg = "Connected Successfully."; + } + + callback({ + ok: true, + msg, + }); + + } catch (e) { + log.error("remoteBrowser", e); + + callback({ + ok: false, + msg: e.message, + }); + } + }); +}; diff --git a/server/socket-handlers/status-page-socket-handler.js b/server/socket-handlers/status-page-socket-handler.js index 5f35b8d75d..1114d81fde 100644 --- a/server/socket-handlers/status-page-socket-handler.js +++ b/server/socket-handlers/status-page-socket-handler.js @@ -11,6 +11,7 @@ const { UptimeKumaServer } = require("../uptime-kuma-server"); /** * Socket handlers for status page * @param {Socket} socket Socket.io instance to add listeners on + * @returns {void} */ module.exports.statusPageSocketHandler = (socket) => { @@ -154,6 +155,7 @@ module.exports.statusPageSocketHandler = (socket) => { statusPage.title = config.title; statusPage.description = config.description; statusPage.icon = config.logo; + statusPage.autoRefreshInterval = config.autoRefreshInterval, statusPage.theme = config.theme; //statusPage.published = ; //statusPage.search_engine_index = ; @@ -218,13 +220,17 @@ module.exports.statusPageSocketHandler = (socket) => { // Delete groups that are not in the list log.debug("socket", "Delete groups that are not in the list"); - const slots = groupIDList.map(() => "?").join(","); + if (groupIDList.length === 0) { + await R.exec("DELETE FROM `group` WHERE status_page_id = ?", [ statusPage.id ]); + } else { + const slots = groupIDList.map(() => "?").join(","); - const data = [ - ...groupIDList, - statusPage.id - ]; - await R.exec(`DELETE FROM \`group\` WHERE id NOT IN (${slots}) AND status_page_id = ?`, data); + const data = [ + ...groupIDList, + statusPage.id + ]; + await R.exec(`DELETE FROM \`group\` WHERE id NOT IN (${slots}) AND status_page_id = ?`, data); + } const server = UptimeKumaServer.getInstance(); @@ -279,11 +285,14 @@ module.exports.statusPageSocketHandler = (socket) => { statusPage.title = title; statusPage.theme = "auto"; statusPage.icon = ""; + statusPage.autoRefreshInterval = 300; await R.store(statusPage); callback({ ok: true, - msg: "OK!" + msg: "successAdded", + msgi18n: true, + slug: slug }); } catch (error) { @@ -350,6 +359,8 @@ module.exports.statusPageSocketHandler = (socket) => { * Check slug a-z, 0-9, - only * Regex from: https://stackoverflow.com/questions/22454258/js-regex-string-validation-for-slug * @param {string} slug Slug to test + * @returns {void} + * @throws Slug is not valid */ function checkSlug(slug) { if (typeof slug !== "string") { diff --git a/server/uptime-cache-list.js b/server/uptime-cache-list.js deleted file mode 100644 index d88a9cbf87..0000000000 --- a/server/uptime-cache-list.js +++ /dev/null @@ -1,49 +0,0 @@ -const { log } = require("../src/util"); -class UptimeCacheList { - /** - * list[monitorID][duration] - */ - static list = {}; - - /** - * Get the uptime for a specific period - * @param {number} monitorID - * @param {number} duration - * @return {number} - */ - static getUptime(monitorID, duration) { - if (UptimeCacheList.list[monitorID] && UptimeCacheList.list[monitorID][duration]) { - log.debug("UptimeCacheList", "getUptime: " + monitorID + " " + duration); - return UptimeCacheList.list[monitorID][duration]; - } else { - return null; - } - } - - /** - * Add uptime for specified monitor - * @param {number} monitorID - * @param {number} duration - * @param {number} uptime Uptime to add - */ - static addUptime(monitorID, duration, uptime) { - log.debug("UptimeCacheList", "addUptime: " + monitorID + " " + duration); - if (!UptimeCacheList.list[monitorID]) { - UptimeCacheList.list[monitorID] = {}; - } - UptimeCacheList.list[monitorID][duration] = uptime; - } - - /** - * Clear cache for specified monitor - * @param {number} monitorID - */ - static clearCache(monitorID) { - log.debug("UptimeCacheList", "clearCache: " + monitorID); - delete UptimeCacheList.list[monitorID]; - } -} - -module.exports = { - UptimeCacheList, -}; diff --git a/server/uptime-calculator.js b/server/uptime-calculator.js new file mode 100644 index 0000000000..71d1d458c9 --- /dev/null +++ b/server/uptime-calculator.js @@ -0,0 +1,865 @@ +const dayjs = require("dayjs"); +const { UP, MAINTENANCE, DOWN, PENDING } = require("../src/util"); +const { LimitQueue } = require("./utils/limit-queue"); +const { log } = require("../src/util"); +const { R } = require("redbean-node"); + +/** + * Calculates the uptime of a monitor. + */ +class UptimeCalculator { + /** + * @private + * @type {{string:UptimeCalculator}} + */ + static list = {}; + + /** + * For testing purposes, we can set the current date to a specific date. + * @type {dayjs.Dayjs} + */ + static currentDate = null; + + /** + * monitorID the id of the monitor + * @type {number} + */ + monitorID; + + /** + * Recent 24-hour uptime, each item is a 1-minute interval + * Key: {number} DivisionKey + * @type {LimitQueue} + */ + minutelyUptimeDataList = new LimitQueue(24 * 60); + + /** + * Recent 30-day uptime, each item is a 1-hour interval + * Key: {number} DivisionKey + * @type {LimitQueue} + */ + hourlyUptimeDataList = new LimitQueue(30 * 24); + + /** + * Daily uptime data, + * Key: {number} DailyKey + */ + dailyUptimeDataList = new LimitQueue(365); + + lastUptimeData = null; + lastHourlyUptimeData = null; + lastDailyUptimeData = null; + + lastDailyStatBean = null; + lastHourlyStatBean = null; + lastMinutelyStatBean = null; + + /** + * For migration purposes. + * @type {boolean} + */ + migrationMode = false; + + statMinutelyKeepHour = 24; + statHourlyKeepDay = 30; + + /** + * Get the uptime calculator for a monitor + * Initializes and returns the monitor if it does not exist + * @param {number} monitorID the id of the monitor + * @returns {Promise} UptimeCalculator + */ + static async getUptimeCalculator(monitorID) { + if (!monitorID) { + throw new Error("Monitor ID is required"); + } + + if (!UptimeCalculator.list[monitorID]) { + UptimeCalculator.list[monitorID] = new UptimeCalculator(); + await UptimeCalculator.list[monitorID].init(monitorID); + } + return UptimeCalculator.list[monitorID]; + } + + /** + * Remove a monitor from the list + * @param {number} monitorID the id of the monitor + * @returns {Promise} + */ + static async remove(monitorID) { + delete UptimeCalculator.list[monitorID]; + } + + /** + * + */ + constructor() { + if (process.env.TEST_BACKEND) { + // Override the getCurrentDate() method to return a specific date + // Only for testing + this.getCurrentDate = () => { + if (UptimeCalculator.currentDate) { + return UptimeCalculator.currentDate; + } else { + return dayjs.utc(); + } + }; + } + } + + /** + * Initialize the uptime calculator for a monitor + * @param {number} monitorID the id of the monitor + * @returns {Promise} + */ + async init(monitorID) { + this.monitorID = monitorID; + + let now = this.getCurrentDate(); + + // Load minutely data from database (recent 24 hours only) + let minutelyStatBeans = await R.find("stat_minutely", " monitor_id = ? AND timestamp > ? ORDER BY timestamp", [ + monitorID, + this.getMinutelyKey(now.subtract(24, "hour")), + ]); + + for (let bean of minutelyStatBeans) { + let data = { + up: bean.up, + down: bean.down, + avgPing: bean.ping, + minPing: bean.pingMin, + maxPing: bean.pingMax, + }; + + if (bean.extras != null) { + data = { + ...data, + ...JSON.parse(bean.extras), + }; + } + + let key = bean.timestamp; + this.minutelyUptimeDataList.push(key, data); + } + + // Load hourly data from database (recent 30 days only) + let hourlyStatBeans = await R.find("stat_hourly", " monitor_id = ? AND timestamp > ? ORDER BY timestamp", [ + monitorID, + this.getHourlyKey(now.subtract(30, "day")), + ]); + + for (let bean of hourlyStatBeans) { + let data = { + up: bean.up, + down: bean.down, + avgPing: bean.ping, + minPing: bean.pingMin, + maxPing: bean.pingMax, + }; + + if (bean.extras != null) { + data = { + ...data, + ...JSON.parse(bean.extras), + }; + } + + this.hourlyUptimeDataList.push(bean.timestamp, data); + } + + // Load daily data from database (recent 365 days only) + let dailyStatBeans = await R.find("stat_daily", " monitor_id = ? AND timestamp > ? ORDER BY timestamp", [ + monitorID, + this.getDailyKey(now.subtract(365, "day")), + ]); + + for (let bean of dailyStatBeans) { + let data = { + up: bean.up, + down: bean.down, + avgPing: bean.ping, + minPing: bean.pingMin, + maxPing: bean.pingMax, + }; + + if (bean.extras != null) { + data = { + ...data, + ...JSON.parse(bean.extras), + }; + } + + this.dailyUptimeDataList.push(bean.timestamp, data); + } + } + + /** + * @param {number} status status + * @param {number} ping Ping + * @param {dayjs.Dayjs} date Date (Only for migration) + * @returns {dayjs.Dayjs} date + * @throws {Error} Invalid status + */ + async update(status, ping = 0, date) { + if (!date) { + date = this.getCurrentDate(); + } + + let flatStatus = this.flatStatus(status); + + if (flatStatus === DOWN && ping > 0) { + log.debug("uptime-calc", "The ping is not effective when the status is DOWN"); + } + + let divisionKey = this.getMinutelyKey(date); + let hourlyKey = this.getHourlyKey(date); + let dailyKey = this.getDailyKey(date); + + let minutelyData = this.minutelyUptimeDataList[divisionKey]; + let hourlyData = this.hourlyUptimeDataList[hourlyKey]; + let dailyData = this.dailyUptimeDataList[dailyKey]; + + if (status === MAINTENANCE) { + minutelyData.maintenance = minutelyData.maintenance ? minutelyData.maintenance + 1 : 1; + hourlyData.maintenance = hourlyData.maintenance ? hourlyData.maintenance + 1 : 1; + dailyData.maintenance = dailyData.maintenance ? dailyData.maintenance + 1 : 1; + + } else if (flatStatus === UP) { + minutelyData.up += 1; + hourlyData.up += 1; + dailyData.up += 1; + + // Only UP status can update the ping + if (!isNaN(ping)) { + // Add avg ping + // The first beat of the minute, the ping is the current ping + if (minutelyData.up === 1) { + minutelyData.avgPing = ping; + minutelyData.minPing = ping; + minutelyData.maxPing = ping; + } else { + minutelyData.avgPing = (minutelyData.avgPing * (minutelyData.up - 1) + ping) / minutelyData.up; + minutelyData.minPing = Math.min(minutelyData.minPing, ping); + minutelyData.maxPing = Math.max(minutelyData.maxPing, ping); + } + + // Add avg ping + // The first beat of the hour, the ping is the current ping + if (hourlyData.up === 1) { + hourlyData.avgPing = ping; + hourlyData.minPing = ping; + hourlyData.maxPing = ping; + } else { + hourlyData.avgPing = (hourlyData.avgPing * (hourlyData.up - 1) + ping) / hourlyData.up; + hourlyData.minPing = Math.min(hourlyData.minPing, ping); + hourlyData.maxPing = Math.max(hourlyData.maxPing, ping); + } + + // Add avg ping (daily) + // The first beat of the day, the ping is the current ping + if (dailyData.up === 1) { + dailyData.avgPing = ping; + dailyData.minPing = ping; + dailyData.maxPing = ping; + } else { + dailyData.avgPing = (dailyData.avgPing * (dailyData.up - 1) + ping) / dailyData.up; + dailyData.minPing = Math.min(dailyData.minPing, ping); + dailyData.maxPing = Math.max(dailyData.maxPing, ping); + } + } + + } else if (flatStatus === DOWN) { + minutelyData.down += 1; + hourlyData.down += 1; + dailyData.down += 1; + } + + if (minutelyData !== this.lastUptimeData) { + this.lastUptimeData = minutelyData; + } + + if (hourlyData !== this.lastHourlyUptimeData) { + this.lastHourlyUptimeData = hourlyData; + } + + if (dailyData !== this.lastDailyUptimeData) { + this.lastDailyUptimeData = dailyData; + } + + // Don't store data in test mode + if (process.env.TEST_BACKEND) { + log.debug("uptime-calc", "Skip storing data in test mode"); + return date; + } + + let dailyStatBean = await this.getDailyStatBean(dailyKey); + dailyStatBean.up = dailyData.up; + dailyStatBean.down = dailyData.down; + dailyStatBean.ping = dailyData.avgPing; + dailyStatBean.pingMin = dailyData.minPing; + dailyStatBean.pingMax = dailyData.maxPing; + { + // eslint-disable-next-line no-unused-vars + const { up, down, avgPing, minPing, maxPing, timestamp, ...extras } = dailyData; + if (Object.keys(extras).length > 0) { + dailyStatBean.extras = JSON.stringify(extras); + } + } + await R.store(dailyStatBean); + + let currentDate = this.getCurrentDate(); + + // For migration mode, we don't need to store old hourly and minutely data, but we need 30-day's hourly data + // Run anyway for non-migration mode + if (!this.migrationMode || date.isAfter(currentDate.subtract(this.statHourlyKeepDay, "day"))) { + let hourlyStatBean = await this.getHourlyStatBean(hourlyKey); + hourlyStatBean.up = hourlyData.up; + hourlyStatBean.down = hourlyData.down; + hourlyStatBean.ping = hourlyData.avgPing; + hourlyStatBean.pingMin = hourlyData.minPing; + hourlyStatBean.pingMax = hourlyData.maxPing; + { + // eslint-disable-next-line no-unused-vars + const { up, down, avgPing, minPing, maxPing, timestamp, ...extras } = hourlyData; + if (Object.keys(extras).length > 0) { + hourlyStatBean.extras = JSON.stringify(extras); + } + } + await R.store(hourlyStatBean); + } + + // For migration mode, we don't need to store old hourly and minutely data, but we need 24-hour's minutely data + // Run anyway for non-migration mode + if (!this.migrationMode || date.isAfter(currentDate.subtract(this.statMinutelyKeepHour, "hour"))) { + let minutelyStatBean = await this.getMinutelyStatBean(divisionKey); + minutelyStatBean.up = minutelyData.up; + minutelyStatBean.down = minutelyData.down; + minutelyStatBean.ping = minutelyData.avgPing; + minutelyStatBean.pingMin = minutelyData.minPing; + minutelyStatBean.pingMax = minutelyData.maxPing; + { + // eslint-disable-next-line no-unused-vars + const { up, down, avgPing, minPing, maxPing, timestamp, ...extras } = minutelyData; + if (Object.keys(extras).length > 0) { + minutelyStatBean.extras = JSON.stringify(extras); + } + } + await R.store(minutelyStatBean); + } + + // No need to remove old data in migration mode + if (!this.migrationMode) { + // Remove the old data + // TODO: Improvement: Convert it to a job? + log.debug("uptime-calc", "Remove old data"); + await R.exec("DELETE FROM stat_minutely WHERE monitor_id = ? AND timestamp < ?", [ + this.monitorID, + this.getMinutelyKey(currentDate.subtract(this.statMinutelyKeepHour, "hour")), + ]); + + await R.exec("DELETE FROM stat_hourly WHERE monitor_id = ? AND timestamp < ?", [ + this.monitorID, + this.getHourlyKey(currentDate.subtract(this.statHourlyKeepDay, "day")), + ]); + } + + return date; + } + + /** + * Get the daily stat bean + * @param {number} timestamp milliseconds + * @returns {Promise} stat_daily bean + */ + async getDailyStatBean(timestamp) { + if (this.lastDailyStatBean && this.lastDailyStatBean.timestamp === timestamp) { + return this.lastDailyStatBean; + } + + let bean = await R.findOne("stat_daily", " monitor_id = ? AND timestamp = ?", [ + this.monitorID, + timestamp, + ]); + + if (!bean) { + bean = R.dispense("stat_daily"); + bean.monitor_id = this.monitorID; + bean.timestamp = timestamp; + } + + this.lastDailyStatBean = bean; + return this.lastDailyStatBean; + } + + /** + * Get the hourly stat bean + * @param {number} timestamp milliseconds + * @returns {Promise} stat_hourly bean + */ + async getHourlyStatBean(timestamp) { + if (this.lastHourlyStatBean && this.lastHourlyStatBean.timestamp === timestamp) { + return this.lastHourlyStatBean; + } + + let bean = await R.findOne("stat_hourly", " monitor_id = ? AND timestamp = ?", [ + this.monitorID, + timestamp, + ]); + + if (!bean) { + bean = R.dispense("stat_hourly"); + bean.monitor_id = this.monitorID; + bean.timestamp = timestamp; + } + + this.lastHourlyStatBean = bean; + return this.lastHourlyStatBean; + } + + /** + * Get the minutely stat bean + * @param {number} timestamp milliseconds + * @returns {Promise} stat_minutely bean + */ + async getMinutelyStatBean(timestamp) { + if (this.lastMinutelyStatBean && this.lastMinutelyStatBean.timestamp === timestamp) { + return this.lastMinutelyStatBean; + } + + let bean = await R.findOne("stat_minutely", " monitor_id = ? AND timestamp = ?", [ + this.monitorID, + timestamp, + ]); + + if (!bean) { + bean = R.dispense("stat_minutely"); + bean.monitor_id = this.monitorID; + bean.timestamp = timestamp; + } + + this.lastMinutelyStatBean = bean; + return this.lastMinutelyStatBean; + } + + /** + * Convert timestamp to minutely key + * @param {dayjs.Dayjs} date The heartbeat date + * @returns {number} Timestamp + */ + getMinutelyKey(date) { + // Truncate value to minutes (e.g. 2021-01-01 12:34:56 -> 2021-01-01 12:34:00) + date = date.startOf("minute"); + + // Convert to timestamp in second + let divisionKey = date.unix(); + + if (! (divisionKey in this.minutelyUptimeDataList)) { + this.minutelyUptimeDataList.push(divisionKey, { + up: 0, + down: 0, + avgPing: 0, + minPing: 0, + maxPing: 0, + }); + } + + return divisionKey; + } + + /** + * Convert timestamp to hourly key + * @param {dayjs.Dayjs} date The heartbeat date + * @returns {number} Timestamp + */ + getHourlyKey(date) { + // Truncate value to hours (e.g. 2021-01-01 12:34:56 -> 2021-01-01 12:00:00) + date = date.startOf("hour"); + + // Convert to timestamp in second + let divisionKey = date.unix(); + + if (! (divisionKey in this.hourlyUptimeDataList)) { + this.hourlyUptimeDataList.push(divisionKey, { + up: 0, + down: 0, + avgPing: 0, + minPing: 0, + maxPing: 0, + }); + } + + return divisionKey; + } + + /** + * Convert timestamp to daily key + * @param {dayjs.Dayjs} date The heartbeat date + * @returns {number} Timestamp + */ + getDailyKey(date) { + // Truncate value to start of day (e.g. 2021-01-01 12:34:56 -> 2021-01-01 00:00:00) + // Considering if the user keep changing could affect the calculation, so use UTC time to avoid this problem. + date = date.utc().startOf("day"); + let dailyKey = date.unix(); + + if (!this.dailyUptimeDataList[dailyKey]) { + this.dailyUptimeDataList.push(dailyKey, { + up: 0, + down: 0, + avgPing: 0, + minPing: 0, + maxPing: 0, + }); + } + + return dailyKey; + } + + /** + * Convert timestamp to key + * @param {dayjs.Dayjs} datetime Datetime + * @param {"day" | "hour" | "minute"} type the type of data which is expected to be returned + * @returns {number} Timestamp + * @throws {Error} If the type is invalid + */ + getKey(datetime, type) { + switch (type) { + case "day": + return this.getDailyKey(datetime); + case "hour": + return this.getHourlyKey(datetime); + case "minute": + return this.getMinutelyKey(datetime); + default: + throw new Error("Invalid type"); + } + } + + /** + * Flat status to UP or DOWN + * @param {number} status the status which should be turned into a flat status + * @returns {UP|DOWN|PENDING} The flat status + * @throws {Error} Invalid status + */ + flatStatus(status) { + switch (status) { + case UP: + case MAINTENANCE: + return UP; + case DOWN: + case PENDING: + return DOWN; + } + throw new Error("Invalid status"); + } + + /** + * @param {number} num the number of data points which are expected to be returned + * @param {"day" | "hour" | "minute"} type the type of data which is expected to be returned + * @returns {UptimeDataResult} UptimeDataResult + * @throws {Error} The maximum number of minutes greater than 1440 + */ + getData(num, type = "day") { + + if (type === "hour" && num > 24 * 30) { + throw new Error("The maximum number of hours is 720"); + } + if (type === "minute" && num > 24 * 60) { + throw new Error("The maximum number of minutes is 1440"); + } + if (type === "day" && num > 365) { + throw new Error("The maximum number of days is 365"); + } + // Get the current time period key based on the type + let key = this.getKey(this.getCurrentDate(), type); + + let total = { + up: 0, + down: 0, + }; + + let totalPing = 0; + let endTimestamp; + + // Get the eariest timestamp of the required period based on the type + switch (type) { + case "day": + endTimestamp = key - 86400 * (num - 1); + break; + case "hour": + endTimestamp = key - 3600 * (num - 1); + break; + case "minute": + endTimestamp = key - 60 * (num - 1); + break; + default: + throw new Error("Invalid type"); + } + + // Sum up all data in the specified time range + while (key >= endTimestamp) { + let data; + + switch (type) { + case "day": + data = this.dailyUptimeDataList[key]; + break; + case "hour": + data = this.hourlyUptimeDataList[key]; + break; + case "minute": + data = this.minutelyUptimeDataList[key]; + break; + default: + throw new Error("Invalid type"); + } + + if (data) { + total.up += data.up; + total.down += data.down; + totalPing += data.avgPing * data.up; + } + + // Set key to the previous time period + switch (type) { + case "day": + key -= 86400; + break; + case "hour": + key -= 3600; + break; + case "minute": + key -= 60; + break; + default: + throw new Error("Invalid type"); + } + } + + let uptimeData = new UptimeDataResult(); + + // If there is no data in the previous time ranges, use the last data? + if (total.up === 0 && total.down === 0) { + switch (type) { + case "day": + if (this.lastDailyUptimeData) { + total = this.lastDailyUptimeData; + totalPing = total.avgPing * total.up; + } else { + return uptimeData; + } + break; + case "hour": + if (this.lastHourlyUptimeData) { + total = this.lastHourlyUptimeData; + totalPing = total.avgPing * total.up; + } else { + return uptimeData; + } + break; + case "minute": + if (this.lastUptimeData) { + total = this.lastUptimeData; + totalPing = total.avgPing * total.up; + } else { + return uptimeData; + } + break; + default: + throw new Error("Invalid type"); + } + } + + let avgPing; + + if (total.up === 0) { + avgPing = null; + } else { + avgPing = totalPing / total.up; + } + + if (total.up + total.down === 0) { + uptimeData.uptime = 0; + } else { + uptimeData.uptime = total.up / (total.up + total.down); + } + uptimeData.avgPing = avgPing; + return uptimeData; + } + + /** + * Get data in form of an array + * @param {number} num the number of data points which are expected to be returned + * @param {"day" | "hour" | "minute"} type the type of data which is expected to be returned + * @returns {Array} uptime data + * @throws {Error} The maximum number of minutes greater than 1440 + */ + getDataArray(num, type = "day") { + if (type === "hour" && num > 24 * 30) { + throw new Error("The maximum number of hours is 720"); + } + if (type === "minute" && num > 24 * 60) { + throw new Error("The maximum number of minutes is 1440"); + } + + // Get the current time period key based on the type + let key = this.getKey(this.getCurrentDate(), type); + + let result = []; + + let endTimestamp; + + // Get the eariest timestamp of the required period based on the type + switch (type) { + case "day": + endTimestamp = key - 86400 * (num - 1); + break; + case "hour": + endTimestamp = key - 3600 * (num - 1); + break; + case "minute": + endTimestamp = key - 60 * (num - 1); + break; + default: + throw new Error("Invalid type"); + } + + // Get datapoints in the specified time range + while (key >= endTimestamp) { + let data; + + switch (type) { + case "day": + data = this.dailyUptimeDataList[key]; + break; + case "hour": + data = this.hourlyUptimeDataList[key]; + break; + case "minute": + data = this.minutelyUptimeDataList[key]; + break; + default: + throw new Error("Invalid type"); + } + + if (data) { + data.timestamp = key; + result.push(data); + } + + // Set key to the previous time period + switch (type) { + case "day": + key -= 86400; + break; + case "hour": + key -= 3600; + break; + case "minute": + key -= 60; + break; + default: + throw new Error("Invalid type"); + } + } + + return result; + } + + /** + * Get the uptime data for given duration. + * @param {string} duration A string with a number and a unit (m,h,d,w,M,y), such as 24h, 30d, 1y. + * @returns {UptimeDataResult} UptimeDataResult + * @throws {Error} Invalid duration / Unsupported unit + */ + getDataByDuration(duration) { + const durationNumStr = duration.slice(0, -1); + + if (!/^[0-9]+$/.test(durationNumStr)) { + throw new Error(`Invalid duration: ${duration}`); + } + const num = Number(durationNumStr); + const unit = duration.slice(-1); + + switch (unit) { + case "m": + return this.getData(num, "minute"); + case "h": + return this.getData(num, "hour"); + case "d": + return this.getData(num, "day"); + case "w": + return this.getData(7 * num, "day"); + case "M": + return this.getData(30 * num, "day"); + case "y": + return this.getData(365 * num, "day"); + default: + throw new Error(`Unsupported unit (${unit}) for badge duration ${duration}` + ); + } + } + + /** + * 1440 = 24 * 60mins + * @returns {UptimeDataResult} UptimeDataResult + */ + get24Hour() { + return this.getData(1440, "minute"); + } + + /** + * @returns {UptimeDataResult} UptimeDataResult + */ + get7Day() { + return this.getData(168, "hour"); + } + + /** + * @returns {UptimeDataResult} UptimeDataResult + */ + get30Day() { + return this.getData(30); + } + + /** + * @returns {UptimeDataResult} UptimeDataResult + */ + get1Year() { + return this.getData(365); + } + + /** + * @returns {dayjs.Dayjs} Current datetime in UTC + */ + getCurrentDate() { + return dayjs.utc(); + } + + /** + * For migration purposes. + * @param {boolean} value Migration mode on/off + * @returns {void} + */ + setMigrationMode(value) { + this.migrationMode = value; + } +} + +class UptimeDataResult { + /** + * @type {number} Uptime + */ + uptime = 0; + + /** + * @type {number} Average ping + */ + avgPing = null; +} + +module.exports = { + UptimeCalculator, + UptimeDataResult, +}; diff --git a/server/uptime-kuma-server.js b/server/uptime-kuma-server.js index 5742b29ac8..062f098d7d 100644 --- a/server/uptime-kuma-server.js +++ b/server/uptime-kuma-server.js @@ -7,11 +7,11 @@ const { R } = require("redbean-node"); const { log, isDev } = require("../src/util"); const Database = require("./database"); const util = require("util"); -const { CacheableDnsHttpAgent } = require("./cacheable-dns-http-agent"); const { Settings } = require("./settings"); const dayjs = require("dayjs"); const childProcessAsync = require("promisify-child-process"); const path = require("path"); +const axios = require("axios"); const { isSSL, sslKey, sslCert, sslKeyPassphrase } = require("./config"); // DO NOT IMPORT HERE IF THE MODULES USED `UptimeKumaServer.getInstance()`, put at the bottom of this file instead. @@ -21,7 +21,7 @@ const { isSSL, sslKey, sslCert, sslKeyPassphrase } = require("./config"); */ class UptimeKumaServer { /** - * + * Current server instance * @type {UptimeKumaServer} */ static instance = null; @@ -50,7 +50,6 @@ class UptimeKumaServer { indexHTML = ""; /** - * * @type {{}} */ static monitorTypeList = { @@ -63,6 +62,11 @@ class UptimeKumaServer { */ jwtSecret = null; + /** + * Get the current instance of the server if it exists, otherwise + * create a new instance. + * @returns {UptimeKumaServer} Server instance + */ static getInstance() { if (UptimeKumaServer.instance == null) { UptimeKumaServer.instance = new UptimeKumaServer(); @@ -70,7 +74,16 @@ class UptimeKumaServer { return UptimeKumaServer.instance; } + /** + * + */ constructor() { + // Set axios default user-agent to Uptime-Kuma/version + axios.defaults.headers.common["User-Agent"] = this.getUserAgent(); + + // Set default axios timeout to 5 minutes instead of infinity + axios.defaults.timeout = 300 * 1000; + log.info("server", "Creating express and socket.io instance"); this.app = express(); if (isSSL) { @@ -98,6 +111,11 @@ class UptimeKumaServer { // Set Monitor Types UptimeKumaServer.monitorTypeList["real-browser"] = new RealBrowserMonitorType(); UptimeKumaServer.monitorTypeList["tailscale-ping"] = new TailscalePing(); + UptimeKumaServer.monitorTypeList["dns"] = new DnsMonitorType(); + UptimeKumaServer.monitorTypeList["mqtt"] = new MqttMonitorType(); + UptimeKumaServer.monitorTypeList["snmp"] = new SNMPMonitorType(); + UptimeKumaServer.monitorTypeList["mongodb"] = new MongodbMonitorType(); + UptimeKumaServer.monitorTypeList["rabbitmq"] = new RabbitMqMonitorType(); // Allow all CORS origins (polling) in development let cors = undefined; @@ -161,13 +179,14 @@ class UptimeKumaServer { }); } - /** Initialise app after the database has been set up */ + /** + * Initialise app after the database has been set up + * @returns {Promise} + */ async initAfterDatabaseReady() { // Static this.app.use("/screenshots", express.static(Database.screenshotDir)); - await CacheableDnsHttpAgent.update(); - process.env.TZ = await this.getTimezone(); dayjs.tz.setDefault(process.env.TZ); log.debug("DEBUG", "Timezone: " + process.env.TZ); @@ -178,8 +197,8 @@ class UptimeKumaServer { /** * Send list of monitors to client - * @param {Socket} socket - * @returns {Object} List of monitors + * @param {Socket} socket Socket to send list on + * @returns {Promise} List of monitors */ async sendMonitorList(socket) { let list = await this.getMonitorJSONList(socket.userID); @@ -187,31 +206,63 @@ class UptimeKumaServer { return list; } + /** + * Update Monitor into list + * @param {Socket} socket Socket to send list on + * @param {number} monitorID update or deleted monitor id + * @returns {Promise} + */ + async sendUpdateMonitorIntoList(socket, monitorID) { + let list = await this.getMonitorJSONList(socket.userID, monitorID); + this.io.to(socket.userID).emit("updateMonitorIntoList", list); + } + + /** + * Delete Monitor from list + * @param {Socket} socket Socket to send list on + * @param {number} monitorID update or deleted monitor id + * @returns {Promise} + */ + async sendDeleteMonitorFromList(socket, monitorID) { + this.io.to(socket.userID).emit("deleteMonitorFromList", monitorID); + } + /** * Get a list of monitors for the given user. * @param {string} userID - The ID of the user to get monitors for. - * @returns {Promise} A promise that resolves to an object with monitor IDs as keys and monitor objects as values. + * @param {number} monitorID - The ID of monitor for. + * @returns {Promise} A promise that resolves to an object with monitor IDs as keys and monitor objects as values. * * Generated by Trelent */ - async getMonitorJSONList(userID) { - let result = {}; + async getMonitorJSONList(userID, monitorID = null) { - let monitorList = await R.find("monitor", " user_id = ? ORDER BY weight DESC, name", [ - userID, - ]); + let query = " user_id = ? "; + let queryParams = [ userID ]; - for (let monitor of monitorList) { - result[monitor.id] = await monitor.toJSON(); + if (monitorID) { + query += "AND id = ? "; + queryParams.push(monitorID); } + let monitorList = await R.find("monitor", query + "ORDER BY weight DESC, name", queryParams); + + const monitorData = monitorList.map(monitor => ({ + id: monitor.id, + active: monitor.active, + name: monitor.name, + })); + const preloadData = await Monitor.preparePreloadData(monitorData); + + const result = {}; + monitorList.forEach(monitor => result[monitor.id] = monitor.toJSON(preloadData)); return result; } /** * Send maintenance list to client * @param {Socket} socket Socket.io instance to send to - * @returns {Object} + * @returns {Promise} Maintenance list */ async sendMaintenanceList(socket) { return await this.sendMaintenanceListByUserID(socket.userID); @@ -219,8 +270,8 @@ class UptimeKumaServer { /** * Send list of maintenances to user - * @param {number} userID - * @returns {Object} + * @param {number} userID User to send list to + * @returns {Promise} Maintenance list */ async sendMaintenanceListByUserID(userID) { let list = await this.getMaintenanceJSONList(userID); @@ -231,7 +282,7 @@ class UptimeKumaServer { /** * Get a list of maintenances for the given user. * @param {string} userID - The ID of the user to get maintenances for. - * @returns {Promise} A promise that resolves to an object with maintenance IDs as keys and maintenances objects as values. + * @returns {Promise} A promise that resolves to an object with maintenance IDs as keys and maintenances objects as values. */ async getMaintenanceJSONList(userID) { let result = {}; @@ -243,7 +294,7 @@ class UptimeKumaServer { /** * Load maintenance list and run - * @param userID + * @param {any} userID Unused * @returns {Promise} */ async loadMaintenanceList(userID) { @@ -257,6 +308,11 @@ class UptimeKumaServer { } } + /** + * Retrieve a specific maintenance + * @param {number} maintenanceID ID of maintenance to retrieve + * @returns {(object|null)} Maintenance if it exists + */ getMaintenance(maintenanceID) { if (this.maintenanceList[maintenanceID]) { return this.maintenanceList[maintenanceID]; @@ -268,6 +324,7 @@ class UptimeKumaServer { * Write error to log file * @param {any} error The error to write * @param {boolean} outputToConsole Should the error also be output to console? + * @returns {void} */ static errorLog(error, outputToConsole = true) { const errorLogStream = fs.createWriteStream(path.join(Database.dataDir, "/error.log"), { @@ -292,18 +349,17 @@ class UptimeKumaServer { /** * Get the IP of the client connected to the socket - * @param {Socket} socket - * @returns {Promise} + * @param {Socket} socket Socket to query + * @returns {Promise} IP of client */ getClientIP(socket) { return this.getClientIPwithProxy(socket.client.conn.remoteAddress, socket.client.conn.request.headers); } /** - * - * @param {string} clientIP - * @param {IncomingHttpHeaders} headers - * @returns {Promise} + * @param {string} clientIP Raw client IP + * @param {IncomingHttpHeaders} headers HTTP headers + * @returns {Promise} Client IP with proxy (if trusted) */ async getClientIPwithProxy(clientIP, headers) { if (clientIP === undefined) { @@ -325,7 +381,7 @@ class UptimeKumaServer { * Attempt to get the current server timezone * If this fails, fall back to environment variables and then make a * guess. - * @returns {Promise} + * @returns {Promise} Current timezone */ async getTimezone() { // From process.env.TZ @@ -370,7 +426,7 @@ class UptimeKumaServer { /** * Get the current offset - * @returns {string} + * @returns {string} Time offset */ getTimezoneOffset() { return dayjs().format("Z"); @@ -378,7 +434,9 @@ class UptimeKumaServer { /** * Throw an error if the timezone is invalid - * @param timezone + * @param {string} timezone Timezone to test + * @returns {void} + * @throws The timezone is invalid */ checkTimezone(timezone) { try { @@ -390,7 +448,8 @@ class UptimeKumaServer { /** * Set the current server timezone and environment variables - * @param {string} timezone + * @param {string} timezone Timezone to set + * @returns {Promise} */ async setTimezone(timezone) { this.checkTimezone(timezone); @@ -426,6 +485,7 @@ class UptimeKumaServer { /** * Start all system services (e.g. nscd) * For now, only used in Docker + * @returns {void} */ async startNSCDServices() { if (process.env.UPTIME_KUMA_IS_CONTAINER) { @@ -440,6 +500,7 @@ class UptimeKumaServer { /** * Stop all system services + * @returns {void} */ async stopNSCDServices() { if (process.env.UPTIME_KUMA_IS_CONTAINER) { @@ -452,11 +513,20 @@ class UptimeKumaServer { } } + /** + * Default User-Agent when making HTTP requests + * @returns {string} User-Agent + */ + getUserAgent() { + return "Uptime-Kuma/" + require("../package.json").version; + } + /** * Force connected sockets of a user to refresh and disconnect. * Used for resetting password. - * @param {string} userID - * @param {string?} currentSocketID + * @param {string} userID User ID + * @param {string?} currentSocketID Current socket ID + * @returns {void} */ disconnectAllSocketClients(userID, currentSocketID = undefined) { for (const socket of this.io.sockets.sockets.values()) { @@ -479,3 +549,9 @@ module.exports = { // Must be at the end to avoid circular dependencies const { RealBrowserMonitorType } = require("./monitor-types/real-browser-monitor-type"); const { TailscalePing } = require("./monitor-types/tailscale-ping"); +const { DnsMonitorType } = require("./monitor-types/dns"); +const { MqttMonitorType } = require("./monitor-types/mqtt"); +const { SNMPMonitorType } = require("./monitor-types/snmp"); +const { MongodbMonitorType } = require("./monitor-types/mongodb"); +const { RabbitMqMonitorType } = require("./monitor-types/rabbitmq"); +const Monitor = require("./model/monitor"); diff --git a/server/util-server.js b/server/util-server.js index 37fcc7be5f..5ebc62ac56 100644 --- a/server/util-server.js +++ b/server/util-server.js @@ -4,17 +4,14 @@ const { R } = require("redbean-node"); const { log, genSecret, badgeConstants } = require("../src/util"); const passwordHash = require("./password-hash"); const { Resolver } = require("dns"); -const childProcess = require("child_process"); const iconv = require("iconv-lite"); const chardet = require("chardet"); -const mqtt = require("mqtt"); const chroma = require("chroma-js"); const mssql = require("mssql"); const { Client } = require("pg"); const postgresConParse = require("pg-connection-string").parse; const mysql = require("mysql2"); -const { MongoClient } = require("mongodb"); -const { NtlmClient } = require("axios-ntlm"); +const { NtlmClient } = require("./modules/axios-ntlm/lib/ntlmClient.js"); const { Settings } = require("./settings"); const grpc = require("@grpc/grpc-js"); const protojs = require("protobufjs"); @@ -38,7 +35,7 @@ const crypto = require("crypto"); const isWindows = process.platform === /^win/.test(process.platform); /** * Init or reset JWT secret - * @returns {Promise} + * @returns {Promise} JWT secret */ exports.initJWTSecret = async () => { let jwtSecretBean = await R.findOne("setting", " `key` = ? ", [ @@ -58,7 +55,7 @@ exports.initJWTSecret = async () => { /** * Decodes a jwt and returns the payload portion without verifying the jqt. * @param {string} jwt The input jwt as a string - * @returns {Object} Decoded jwt payload object + * @returns {object} Decoded jwt payload object */ exports.decodeJwt = (jwt) => { return JSON.parse(Buffer.from(jwt.split(".")[1], "base64").toString()); @@ -122,7 +119,7 @@ exports.tcping = function (hostname, port) { /** * Ping the specified machine * @param {string} hostname Hostname / address of machine - * @param {number} [size=56] Size of packet to send + * @param {number} size Size of packet to send * @returns {Promise} Time for ping in ms rounded to nearest integer */ exports.ping = async (hostname, size = 56) => { @@ -130,7 +127,7 @@ exports.ping = async (hostname, size = 56) => { return await exports.pingAsync(hostname, false, size); } catch (e) { // If the host cannot be resolved, try again with ipv6 - console.debug("ping", "IPv6 error message: " + e.message); + log.debug("ping", "IPv6 error message: " + e.message); // As node-ping does not report a specific error for this, try again if it is an empty message with ipv6 no matter what. if (!e.message) { @@ -145,7 +142,7 @@ exports.ping = async (hostname, size = 56) => { * Ping the specified machine * @param {string} hostname Hostname / address of machine to ping * @param {boolean} ipv6 Should IPv6 be used? - * @param {number} [size = 56] Size of ping packet to send + * @param {number} size Size of ping packet to send * @returns {Promise} Time for ping in ms rounded to nearest integer */ exports.pingAsync = function (hostname, ipv6 = false, size = 56) { @@ -172,85 +169,19 @@ exports.pingAsync = function (hostname, ipv6 = false, size = 56) { }); }; -/** - * MQTT Monitor - * @param {string} hostname Hostname / address of machine to test - * @param {string} topic MQTT topic - * @param {string} okMessage Expected result - * @param {Object} [options={}] MQTT options. Contains port, username, - * password and interval (interval defaults to 20) - * @returns {Promise} - */ -exports.mqttAsync = function (hostname, topic, okMessage, options = {}) { - return new Promise((resolve, reject) => { - const { port, username, password, interval = 20 } = options; - - // Adds MQTT protocol to the hostname if not already present - if (!/^(?:http|mqtt|ws)s?:\/\//.test(hostname)) { - hostname = "mqtt://" + hostname; - } - - const timeoutID = setTimeout(() => { - log.debug("mqtt", "MQTT timeout triggered"); - client.end(); - reject(new Error("Timeout")); - }, interval * 1000 * 0.8); - - const mqttUrl = `${hostname}:${port}`; - - log.debug("mqtt", `MQTT connecting to ${mqttUrl}`); - - let client = mqtt.connect(mqttUrl, { - username, - password - }); - - client.on("connect", () => { - log.debug("mqtt", "MQTT connected"); - - try { - log.debug("mqtt", "MQTT subscribe topic"); - client.subscribe(topic); - } catch (e) { - client.end(); - clearTimeout(timeoutID); - reject(new Error("Cannot subscribe topic")); - } - }); - - client.on("error", (error) => { - client.end(); - clearTimeout(timeoutID); - reject(error); - }); - - client.on("message", (messageTopic, message) => { - if (messageTopic === topic) { - client.end(); - clearTimeout(timeoutID); - if (okMessage != null && okMessage !== "" && message.toString() !== okMessage) { - reject(new Error(`Message Mismatch - Topic: ${messageTopic}; Message: ${message.toString()}`)); - } else { - resolve(`Topic: ${messageTopic}; Message: ${message.toString()}`); - } - } - }); - - }); -}; - /** * Monitor Kafka using Producer + * @param {string[]} brokers List of kafka brokers to connect, host and + * port joined by ':' * @param {string} topic Topic name to produce into * @param {string} message Message to produce - * @param {Object} [options={interval = 20, allowAutoTopicCreation = false, ssl = false, clientId = "Uptime-Kuma"}] - * Kafka client options. Contains ssl, clientId, allowAutoTopicCreation and - * interval (interval defaults to 20, allowAutoTopicCreation defaults to false, clientId defaults to "Uptime-Kuma" - * and ssl defaults to false) - * @param {string[]} brokers List of kafka brokers to connect, host and port joined by ':' - * @param {SASLOptions} [saslOptions={}] Options for kafka client Authentication (SASL) (defaults to - * {}) - * @returns {Promise} + * @param {object} options Kafka client options. Contains ssl, clientId, + * allowAutoTopicCreation and interval (interval defaults to 20, + * allowAutoTopicCreation defaults to false, clientId defaults to + * "Uptime-Kuma" and ssl defaults to false) + * @param {SASLOptions} saslOptions Options for kafka client + * Authentication (SASL) (defaults to {}) + * @returns {Promise} Status message */ exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, saslOptions = {}) { return new Promise((resolve, reject) => { @@ -331,9 +262,9 @@ exports.kafkaProducerAsync = function (brokers, topic, message, options = {}, sa /** * Use NTLM Auth for a http request. - * @param {Object} options The http request options - * @param {Object} ntlmOptions The auth options - * @returns {Promise<(string[]|Object[]|Object)>} + * @param {object} options The http request options + * @param {object} ntlmOptions The auth options + * @returns {Promise<(string[] | object[] | object)>} NTLM response */ exports.httpNtlm = function (options, ntlmOptions) { return new Promise((resolve, reject) => { @@ -355,7 +286,7 @@ exports.httpNtlm = function (options, ntlmOptions) { * @param {string} resolverServer The DNS server to use * @param {string} resolverPort Port the DNS server is listening on * @param {string} rrtype The type of record to request - * @returns {Promise<(string[]|Object[]|Object)>} + * @returns {Promise<(string[] | object[] | object)>} DNS response */ exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype) { const resolver = new Resolver(); @@ -388,7 +319,8 @@ exports.dnsResolve = function (hostname, resolverServer, resolverPort, rrtype) { * Run a query on SQL Server * @param {string} connectionString The database connection string * @param {string} query The query to validate the database with - * @returns {Promise<(string[]|Object[]|Object)>} + * @returns {Promise<(string[] | object[] | object)>} Response from + * server */ exports.mssqlQuery = async function (connectionString, query) { let pool; @@ -412,7 +344,8 @@ exports.mssqlQuery = async function (connectionString, query) { * Run a query on Postgres * @param {string} connectionString The database connection string * @param {string} query The query to validate the database with - * @returns {Promise<(string[]|Object[]|Object)>} + * @returns {Promise<(string[] | object[] | object)>} Response from + * server */ exports.postgresQuery = function (connectionString, query) { return new Promise((resolve, reject) => { @@ -470,7 +403,7 @@ exports.postgresQuery = function (connectionString, query) { * @param {string} connectionString The database connection string * @param {string} query The query to validate the database with * @param {?string} password The password to use - * @returns {Promise<(string)>} + * @returns {Promise<(string)>} Response from server */ exports.mysqlQuery = function (connectionString, query, password = undefined) { return new Promise((resolve, reject) => { @@ -503,23 +436,6 @@ exports.mysqlQuery = function (connectionString, query, password = undefined) { }); }; -/** - * Connect to and Ping a MongoDB database - * @param {string} connectionString The database connection string - * @returns {Promise<(string[]|Object[]|Object)>} - */ -exports.mongodbPing = async function (connectionString) { - let client = await MongoClient.connect(connectionString); - let dbPing = await client.db().command({ ping: 1 }); - await client.close(); - - if (dbPing["ok"] === 1) { - return "UP"; - } else { - throw Error("failed"); - } -}; - /** * Query radius server * @param {string} hostname Hostname of radius server @@ -528,9 +444,9 @@ exports.mongodbPing = async function (connectionString) { * @param {string} calledStationId ID of called station * @param {string} callingStationId ID of calling station * @param {string} secret Secret to use - * @param {number} [port=1812] Port to contact radius server on - * @param {number} [timeout=2500] Timeout for connection to use - * @returns {Promise} + * @param {number} port Port to contact radius server on + * @param {number} timeout Timeout for connection to use + * @returns {Promise} Response from server */ exports.radius = function ( hostname, @@ -570,11 +486,16 @@ exports.radius = function ( /** * Redis server ping * @param {string} dsn The redis connection string + * @param {boolean} rejectUnauthorized If false, allows unverified server certificates. + * @returns {Promise} Response from server */ -exports.redisPingAsync = function (dsn) { +exports.redisPingAsync = function (dsn, rejectUnauthorized) { return new Promise((resolve, reject) => { const client = redis.createClient({ - url: dsn + url: dsn, + socket: { + rejectUnauthorized + } }); client.on("error", (err) => { if (client.isOpen) { @@ -611,7 +532,7 @@ exports.setting = async function (key) { }; /** - * Sets the specified setting to specifed value + * Sets the specified setting to specified value * @param {string} key Key of setting to set * @param {any} value Value to set to * @param {?string} type Type of setting @@ -624,7 +545,7 @@ exports.setSetting = async function (key, value, type = null) { /** * Get settings based on type * @param {string} type The type of setting - * @returns {Promise} + * @returns {Promise} Settings of requested type */ exports.getSettings = async function (type) { return await Settings.getSettings(type); @@ -633,7 +554,7 @@ exports.getSettings = async function (type) { /** * Set settings based on type * @param {string} type Type of settings to set - * @param {Object} data Values of settings + * @param {object} data Values of settings * @returns {Promise} */ exports.setSettings = async function (type, data) { @@ -647,7 +568,7 @@ exports.setSettings = async function (type, data) { * Get number of days between two dates * @param {Date} validFrom Start date * @param {Date} validTo End date - * @returns {number} + * @returns {number} Number of days */ const getDaysBetween = (validFrom, validTo) => Math.round(Math.abs(+validFrom - +validTo) / 8.64e7); @@ -656,7 +577,7 @@ const getDaysBetween = (validFrom, validTo) => * Get days remaining from a time range * @param {Date} validFrom Start date * @param {Date} validTo End date - * @returns {number} + * @returns {number} Number of days remaining */ const getDaysRemaining = (validFrom, validTo) => { const daysRemaining = getDaysBetween(validFrom, validTo); @@ -668,8 +589,9 @@ const getDaysRemaining = (validFrom, validTo) => { /** * Fix certificate info for display - * @param {Object} info The chain obtained from getPeerCertificate() - * @returns {Object} An object representing certificate information + * @param {object} info The chain obtained from getPeerCertificate() + * @returns {object} An object representing certificate information + * @throws The certificate chain length exceeded 500. */ const parseCertificateInfo = function (info) { let link = info; @@ -717,7 +639,7 @@ const parseCertificateInfo = function (info) { /** * Check if certificate is valid * @param {tls.TLSSocket} socket TLSSocket, which may or may not be connected - * @returns {Object} Object containing certificate information + * @returns {object} Object containing certificate information */ exports.checkCertificate = function (socket) { let certInfoStartTime = dayjs().valueOf(); @@ -782,7 +704,7 @@ exports.checkStatusCode = function (status, acceptedCodes) { * Get total number of clients in room * @param {Server} io Socket server instance * @param {string} roomName Name of room to check - * @returns {number} + * @returns {number} Total clients in room */ exports.getTotalClientInRoom = (io, roomName) => { @@ -809,7 +731,8 @@ exports.getTotalClientInRoom = (io, roomName) => { /** * Allow CORS all origins if development - * @param {Object} res Response object from axios + * @param {object} res Response object from axios + * @returns {void} */ exports.allowDevAllOrigin = (res) => { if (process.env.NODE_ENV === "development") { @@ -819,16 +742,20 @@ exports.allowDevAllOrigin = (res) => { /** * Allow CORS all origins - * @param {Object} res Response object from axios + * @param {object} res Response object from axios + * @returns {void} */ exports.allowAllOrigin = (res) => { res.header("Access-Control-Allow-Origin", "*"); + res.header("Access-Control-Allow-Methods", "GET, PUT, POST, DELETE, OPTIONS"); res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept"); }; /** * Check if a user is logged in * @param {Socket} socket Socket instance + * @returns {void} + * @throws The user is not logged in */ exports.checkLogin = (socket) => { if (!socket.userID) { @@ -839,8 +766,10 @@ exports.checkLogin = (socket) => { /** * For logged-in users, double-check the password * @param {Socket} socket Socket.io instance - * @param {string} currentPassword - * @returns {Promise} + * @param {string} currentPassword Password to validate + * @returns {Promise} User + * @throws The current password is not a string + * @throws The provided password is not correct */ exports.doubleCheckPassword = async (socket, currentPassword) => { if (typeof currentPassword !== "string") { @@ -858,50 +787,10 @@ exports.doubleCheckPassword = async (socket, currentPassword) => { return user; }; -/** Start Unit tests */ -exports.startUnitTest = async () => { - console.log("Starting unit test..."); - const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm"; - const child = childProcess.spawn(npm, [ "run", "jest-backend" ]); - - child.stdout.on("data", (data) => { - console.log(data.toString()); - }); - - child.stderr.on("data", (data) => { - console.log(data.toString()); - }); - - child.on("close", function (code) { - console.log("Jest exit code: " + code); - process.exit(code); - }); -}; - -/** Start end-to-end tests */ -exports.startE2eTests = async () => { - console.log("Starting unit test..."); - const npm = /^win/.test(process.platform) ? "npm.cmd" : "npm"; - const child = childProcess.spawn(npm, [ "run", "cy:run" ]); - - child.stdout.on("data", (data) => { - console.log(data.toString()); - }); - - child.stderr.on("data", (data) => { - console.log(data.toString()); - }); - - child.on("close", function (code) { - console.log("Jest exit code: " + code); - process.exit(code); - }); -}; - /** * Convert unknown string to UTF8 * @param {Uint8Array} body Buffer - * @returns {string} + * @returns {string} UTF8 string */ exports.convertToUTF8 = (body) => { const guessEncoding = chardet.detect(body); @@ -913,11 +802,10 @@ exports.convertToUTF8 = (body) => { * Returns a color code in hex format based on a given percentage: * 0% => hue = 10 => red * 100% => hue = 90 => green - * * @param {number} percentage float, 0 to 1 - * @param {number} maxHue - * @param {number} minHue, int - * @returns {string}, hex value + * @param {number} maxHue Maximum hue - int + * @param {number} minHue Minimum hue - int + * @returns {string} Color in hex */ exports.percentageToColor = (percentage, maxHue = 90, minHue = 10) => { const hue = percentage * (maxHue - minHue) + minHue; @@ -930,10 +818,9 @@ exports.percentageToColor = (percentage, maxHue = 90, minHue = 10) => { /** * Joins and array of string to one string after filtering out empty values - * - * @param {string[]} parts - * @param {string} connector - * @returns {string} + * @param {string[]} parts Strings to join + * @param {string} connector Separator for joined strings + * @returns {string} Joined strings */ exports.filterAndJoin = (parts, connector = "") => { return parts.filter((part) => !!part && part !== "").join(connector); @@ -941,8 +828,9 @@ exports.filterAndJoin = (parts, connector = "") => { /** * Send an Error response - * @param {Object} res Express response object - * @param {string} [msg=""] Message to send + * @param {object} res Express response object + * @param {string} msg Message to send + * @returns {void} */ module.exports.sendHttpError = (res, msg = "") => { if (msg.includes("SQLITE_BUSY") || msg.includes("SQLITE_LOCKED")) { @@ -963,6 +851,13 @@ module.exports.sendHttpError = (res, msg = "") => { } }; +/** + * Convert timezone of time object + * @param {object} obj Time object to update + * @param {string} timezone New timezone to set + * @param {boolean} timeObjectToUTC Convert time object to UTC + * @returns {object} Time object with updated timezone + */ function timeObjectConvertTimezone(obj, timezone, timeObjectToUTC = true) { let offsetString; @@ -1005,20 +900,20 @@ function timeObjectConvertTimezone(obj, timezone, timeObjectToUTC = true) { } /** - * - * @param {object} obj - * @param {string} timezone - * @returns {object} + * Convert time object to UTC + * @param {object} obj Object to convert + * @param {string} timezone Timezone of time object + * @returns {object} Updated time object */ module.exports.timeObjectToUTC = (obj, timezone = undefined) => { return timeObjectConvertTimezone(obj, timezone, true); }; /** - * - * @param {object} obj - * @param {string} timezone - * @returns {object} + * Convert time object to local time + * @param {object} obj Object to convert + * @param {string} timezone Timezone to convert to + * @returns {object} Updated object */ module.exports.timeObjectToLocal = (obj, timezone = undefined) => { return timeObjectConvertTimezone(obj, timezone, false); @@ -1026,7 +921,8 @@ module.exports.timeObjectToLocal = (obj, timezone = undefined) => { /** * Create gRPC client stib - * @param {Object} options from gRPC client + * @param {object} options from gRPC client + * @returns {Promise} Result of gRPC query */ module.exports.grpcQuery = async (options) => { const { grpcUrl, grpcProtobufData, grpcServiceName, grpcEnableTls, grpcMethod, grpcBody } = options; @@ -1108,10 +1004,9 @@ module.exports.rootCertificatesFingerprints = () => { module.exports.SHAKE256_LENGTH = 16; /** - * - * @param {string} data - * @param {number} len - * @return {string} + * @param {string} data The data to be hashed + * @param {number} len Output length of the hash + * @returns {string} The hashed data in hex format */ module.exports.shake256 = (data, len) => { if (!data) { @@ -1122,6 +1017,16 @@ module.exports.shake256 = (data, len) => { .digest("hex"); }; +/** + * Non await sleep + * Source: https://stackoverflow.com/questions/59099454/is-there-a-way-to-call-sleep-without-await-keyword + * @param {number} n Milliseconds to wait + * @returns {void} + */ +module.exports.wait = (n) => { + Atomics.wait(new Int32Array(new SharedArrayBuffer(4)), 0, 0, n); +}; + // For unit test, export functions if (process.env.TEST_BACKEND) { module.exports.__test = { diff --git a/server/utils/array-with-key.js b/server/utils/array-with-key.js new file mode 100644 index 0000000000..94afc792a1 --- /dev/null +++ b/server/utils/array-with-key.js @@ -0,0 +1,85 @@ +/** + * An object that can be used as an array with a key + * Like PHP's array + * @template K + * @template V + */ +class ArrayWithKey { + /** + * All keys that are stored in the current object + * @type {K[]} + * @private + */ + __stack = []; + + /** + * Push an element to the end of the array + * @param {K} key The key of the element + * @param {V} value The value of the element + * @returns {void} + */ + push(key, value) { + this[key] = value; + this.__stack.push(key); + } + + /** + * Get the last element and remove it from the array + * @returns {V|undefined} The first value, or undefined if there is no element to pop + */ + pop() { + let key = this.__stack.pop(); + let prop = this[key]; + delete this[key]; + return prop; + } + + /** + * Get the last key + * @returns {K|null} The last key, or null if the array is empty + */ + getLastKey() { + if (this.__stack.length === 0) { + return null; + } + return this.__stack[this.__stack.length - 1]; + } + + /** + * Get the first element + * @returns {{key:K,value:V}|null} The first element, or null if the array is empty + */ + shift() { + let key = this.__stack.shift(); + let value = this[key]; + delete this[key]; + return { + key, + value, + }; + } + + /** + * Get the length of the array + * @returns {number} Amount of elements stored + */ + length() { + return this.__stack.length; + } + + /** + * Get the last value + * @returns {V|null} The last element without removing it, or null if the array is empty + */ + last() { + let key = this.getLastKey(); + if (key === null) { + return null; + } + return this[key]; + } +} + +module.exports = { + ArrayWithKey +}; diff --git a/server/utils/knex/lib/dialects/mysql2/schema/mysql2-columncompiler.js b/server/utils/knex/lib/dialects/mysql2/schema/mysql2-columncompiler.js new file mode 100644 index 0000000000..d05a6bc8cd --- /dev/null +++ b/server/utils/knex/lib/dialects/mysql2/schema/mysql2-columncompiler.js @@ -0,0 +1,22 @@ +const ColumnCompilerMySQL = require("knex/lib/dialects/mysql/schema/mysql-columncompiler"); +const { formatDefault } = require("knex/lib/formatter/formatterUtils"); +const { log } = require("../../../../../../../src/util"); + +class KumaColumnCompiler extends ColumnCompilerMySQL { + /** + * Override defaultTo method to handle default value for TEXT fields + * @param {any} value Value + * @returns {string|void} Default value (Don't understand why it can return void or string, but it's the original code, lol) + */ + defaultTo(value) { + if (this.type === "text" && typeof value === "string") { + log.debug("defaultTo", `${this.args[0]}: ${this.type} ${value} ${typeof value}`); + // MySQL 8.0 is required and only if the value is written as an expression: https://dev.mysql.com/doc/refman/8.0/en/data-type-defaults.html + // MariaDB 10.2 is required: https://mariadb.com/kb/en/text/ + return `default (${formatDefault(value, this.type, this.client)})`; + } + return super.defaultTo.apply(this, arguments); + } +} + +module.exports = KumaColumnCompiler; diff --git a/server/utils/limit-queue.js b/server/utils/limit-queue.js new file mode 100644 index 0000000000..9da6d410e5 --- /dev/null +++ b/server/utils/limit-queue.js @@ -0,0 +1,48 @@ +const { ArrayWithKey } = require("./array-with-key"); + +/** + * Limit Queue + * The first element will be removed when the length exceeds the limit + */ +class LimitQueue extends ArrayWithKey { + + /** + * The limit of the queue after which the first element will be removed + * @private + * @type {number} + */ + __limit; + /** + * The callback function when the queue exceeds the limit + * @private + * @callback onExceedCallback + * @param {{key:K,value:V}|nul} item + */ + __onExceed = null; + + /** + * @param {number} limit The limit of the queue after which the first element will be removed + */ + constructor(limit) { + super(); + this.__limit = limit; + } + + /** + * @inheritDoc + */ + push(key, value) { + super.push(key, value); + if (this.length() > this.__limit) { + let item = this.shift(); + if (this.__onExceed) { + this.__onExceed(item); + } + } + } + +} + +module.exports = { + LimitQueue +}; diff --git a/server/utils/simple-migration-server.js b/server/utils/simple-migration-server.js new file mode 100644 index 0000000000..680f8df240 --- /dev/null +++ b/server/utils/simple-migration-server.js @@ -0,0 +1,84 @@ +const express = require("express"); +const http = require("node:http"); +const { log } = require("../../src/util"); + +/** + * SimpleMigrationServer + * For displaying the migration status of the server + * Also, it is used to let Docker healthcheck know the status of the server, as the main server is not started yet, healthcheck will think the server is down incorrectly. + */ +class SimpleMigrationServer { + /** + * Express app instance + * @type {?Express} + */ + app; + + /** + * Server instance + * @type {?Server} + */ + server; + + /** + * Response object + * @type {?Response} + */ + response; + + /** + * Start the server + * @param {number} port Port + * @param {string} hostname Hostname + * @returns {Promise} + */ + start(port, hostname) { + this.app = express(); + this.server = http.createServer(this.app); + + this.app.get("/", (req, res) => { + res.set("Content-Type", "text/plain"); + res.write("Migration is in progress, listening message...\n"); + if (this.response) { + this.response.write("Disconnected\n"); + this.response.end(); + } + this.response = res; + // never ending response + }); + + return new Promise((resolve) => { + this.server.listen(port, hostname, () => { + if (hostname) { + log.info("migration", `Migration server is running on http://${hostname}:${port}`); + } else { + log.info("migration", `Migration server is running on http://localhost:${port}`); + } + resolve(); + }); + }); + } + + /** + * Update the message + * @param {string} msg Message to update + * @returns {void} + */ + update(msg) { + this.response?.write(msg + "\n"); + } + + /** + * Stop the server + * @returns {Promise} + */ + async stop() { + this.response?.write("Finished, please refresh this page.\n"); + this.response?.end(); + await this.server?.close(); + } +} + +module.exports = { + SimpleMigrationServer, +}; diff --git a/src/assets/app.scss b/src/assets/app.scss index 0d3f0454e1..6ddc99decc 100644 --- a/src/assets/app.scss +++ b/src/assets/app.scss @@ -576,6 +576,12 @@ optgroup { outline: none !important; } +.prism-editor__container { + .important { + font-weight: var(--bs-body-font-weight) !important; + } +} + h5.settings-subheading::after { content: ""; display: block; @@ -584,6 +590,20 @@ h5.settings-subheading::after { border-bottom: 1px solid $dark-border-color; } +/* required class */ +.code-editor, .css-editor { + /* we dont use `language-` classes anymore so thats why we need to add background and text color manually */ + + border-radius: 1rem; + padding: 10px 5px; + border: 1px solid #ced4da; + + .dark & { + background: $dark-bg2; + border: 1px solid $dark-border-color; + } +} + $shadow-box-padding: 20px; @@ -599,7 +619,7 @@ $shadow-box-padding: 20px; bottom: 0; margin-left: -$shadow-box-padding; margin-right: -$shadow-box-padding; - z-index: 100; + z-index: 10; background-color: rgba(white, 0.2); backdrop-filter: blur(2px); border-radius: 0 0 10px 10px; @@ -609,6 +629,22 @@ $shadow-box-padding: 20px; } } +@media (max-width: 770px) { + .toast-container { + margin-bottom: 100px !important; + } +} + +@media (max-width: 550px) { + .toast-container { + margin-bottom: 126px !important; + } +} + +.zoom-cursor { + cursor: zoom-in; +} + // Localization @import "localization.scss"; diff --git a/src/assets/vars.scss b/src/assets/vars.scss index e48a6efb61..7250de140e 100644 --- a/src/assets/vars.scss +++ b/src/assets/vars.scss @@ -4,6 +4,7 @@ $warning: #f8a306; $maintenance: #1747f5; $link-color: #111; $border-radius: 50rem; +$secondary-text: #aaa; $highlight: #7ce8a4; $highlight-white: #e7faec; diff --git a/src/components/APIKeyDialog.vue b/src/components/APIKeyDialog.vue index 4bba69fec8..a103cf097f 100644 --- a/src/components/APIKeyDialog.vue +++ b/src/components/APIKeyDialog.vue @@ -92,11 +92,9 @@ + + diff --git a/src/components/EditMonitorConditionGroup.vue b/src/components/EditMonitorConditionGroup.vue new file mode 100644 index 0000000000..910b415083 --- /dev/null +++ b/src/components/EditMonitorConditionGroup.vue @@ -0,0 +1,189 @@ + + + + + diff --git a/src/components/EditMonitorConditions.vue b/src/components/EditMonitorConditions.vue new file mode 100644 index 0000000000..60f7c65899 --- /dev/null +++ b/src/components/EditMonitorConditions.vue @@ -0,0 +1,149 @@ + + + + + diff --git a/src/components/HeartbeatBar.vue b/src/components/HeartbeatBar.vue index 11940c7a9d..429ca9f919 100644 --- a/src/components/HeartbeatBar.vue +++ b/src/components/HeartbeatBar.vue @@ -4,17 +4,23 @@
+ > +
+
-
{{ timeSinceFirstBeat }} ago
+
{{ timeSinceFirstBeat }}
{{ timeSinceLastBeat }}
@@ -47,7 +53,7 @@ export default { beatWidth: 10, beatHeight: 30, hoverScale: 1.5, - beatMargin: 4, + beatHoverAreaPadding: 4, move: false, maxBeat: -1, }; @@ -56,6 +62,7 @@ export default { /** * If heartbeatList is null, get it from $root.heartbeatList + * @returns {object} Heartbeat list */ beatList() { if (this.heartbeatList === null) { @@ -67,8 +74,7 @@ export default { /** * Calculates the amount of beats of padding needed to fill the length of shortBeatList. - * - * @return {number} The amount of beats of padding needed to fill the length of shortBeatList. + * @returns {number} The amount of beats of padding needed to fill the length of shortBeatList. */ numPadding() { if (!this.beatList) { @@ -123,7 +129,7 @@ export default { barStyle() { if (this.move && this.shortBeatList.length > this.maxBeat) { - let width = -(this.beatWidth + this.beatMargin * 2); + let width = -(this.beatWidth + this.beatHoverAreaPadding * 2); return { transition: "all ease-in-out 0.25s", @@ -137,29 +143,33 @@ export default { }, + beatHoverAreaStyle() { + return { + padding: this.beatHoverAreaPadding + "px", + "--hover-scale": this.hoverScale, + }; + }, + beatStyle() { return { width: this.beatWidth + "px", height: this.beatHeight + "px", - margin: this.beatMargin + "px", - "--hover-scale": this.hoverScale, }; }, /** * Returns the style object for positioning the time element. - * @return {Object} The style object containing the CSS properties for positioning the time element. + * @returns {object} The style object containing the CSS properties for positioning the time element. */ timeStyle() { return { - "margin-left": this.numPadding * (this.beatWidth + this.beatMargin * 2) + "px", + "margin-left": this.numPadding * (this.beatWidth + this.beatHoverAreaPadding * 2) + "px", }; }, /** * Calculates the time elapsed since the first valid beat. - * - * @return {string} The time elapsed in minutes or hours. + * @returns {string} The time elapsed in minutes or hours. */ timeSinceFirstBeat() { const firstValidBeat = this.shortBeatList.at(this.numPadding); @@ -173,8 +183,7 @@ export default { /** * Calculates the elapsed time since the last valid beat was registered. - * - * @return {string} The elapsed time in a minutes, hours or "now". + * @returns {string} The elapsed time in a minutes, hours or "now". */ timeSinceLastBeat() { const lastValidBeat = this.shortBeatList.at(-1); @@ -186,11 +195,11 @@ export default { } if (seconds < tolerance) { - return "now"; + return this.$t("now"); } else if (seconds < 60 * 60) { - return (seconds / 60).toFixed(0) + "m ago"; + return this.$t("time ago", [ (seconds / 60).toFixed(0) + "m" ]); } else { - return (seconds / 60 / 60).toFixed(0) + "h ago"; + return this.$t("time ago", [ (seconds / 60 / 60).toFixed(0) + "h" ]); } } }, @@ -221,38 +230,41 @@ export default { if (this.size !== "big") { this.beatWidth = 5; this.beatHeight = 16; - this.beatMargin = 2; + this.beatHoverAreaPadding = 2; } // Suddenly, have an idea how to handle it universally. // If the pixel * ratio != Integer, then it causes render issue, round it to solve it!! const actualWidth = this.beatWidth * window.devicePixelRatio; - const actualMargin = this.beatMargin * window.devicePixelRatio; + const actualHoverAreaPadding = this.beatHoverAreaPadding * window.devicePixelRatio; if (!Number.isInteger(actualWidth)) { this.beatWidth = Math.round(actualWidth) / window.devicePixelRatio; } - if (!Number.isInteger(actualMargin)) { - this.beatMargin = Math.round(actualMargin) / window.devicePixelRatio; + if (!Number.isInteger(actualHoverAreaPadding)) { + this.beatHoverAreaPadding = Math.round(actualHoverAreaPadding) / window.devicePixelRatio; } window.addEventListener("resize", this.resize); this.resize(); }, methods: { - /** Resize the heartbeat bar */ + /** + * Resize the heartbeat bar + * @returns {void} + */ resize() { if (this.$refs.wrap) { - this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatMargin * 2)); + this.maxBeat = Math.floor(this.$refs.wrap.clientWidth / (this.beatWidth + this.beatHoverAreaPadding * 2)); } }, /** * Get the title of the beat. * Used as the hover tooltip on the heartbeat bar. - * @param {Object} beat Beat to get title from - * @returns {string} + * @param {object} beat Beat to get title from + * @returns {string} Beat title */ getBeatTitle(beat) { return `${this.$root.datetime(beat.time)}` + ((beat.msg) ? ` - ${beat.msg}` : ""); @@ -272,31 +284,40 @@ export default { } .hp-bar-big { - .beat { + .beat-hover-area { display: inline-block; - background-color: $primary; - border-radius: $border-radius; - &.empty { - background-color: aliceblue; + &:not(.empty):hover { + transition: all ease-in-out 0.15s; + opacity: 0.8; + transform: scale(var(--hover-scale)); } - &.down { - background-color: $danger; - } + .beat { + background-color: $primary; + border-radius: $border-radius; - &.pending { - background-color: $warning; - } + /* + pointer-events needs to be changed because + tooltip momentarily disappears when crossing between .beat-hover-area and .beat + */ + pointer-events: none; - &.maintenance { - background-color: $maintenance; - } + &.empty { + background-color: aliceblue; + } - &:not(.empty):hover { - transition: all ease-in-out 0.15s; - opacity: 0.8; - transform: scale(var(--hover-scale)); + &.down { + background-color: $danger; + } + + &.pending { + background-color: $warning; + } + + &.maintenance { + background-color: $maintenance; + } } } } @@ -308,7 +329,7 @@ export default { } .word { - color: #aaa; + color: $secondary-text; font-size: 12px; } diff --git a/src/components/HiddenInput.vue b/src/components/HiddenInput.vue index fb86a398cd..85ff88372f 100644 --- a/src/components/HiddenInput.vue +++ b/src/components/HiddenInput.vue @@ -74,11 +74,17 @@ export default { }, methods: { - /** Show users input in plain text */ + /** + * Show users input in plain text + * @returns {void} + */ showInput() { this.visibility = "text"; }, - /** Censor users input */ + /** + * Censor users input + * @returns {void} + */ hideInput() { this.visibility = "password"; }, diff --git a/src/components/Login.vue b/src/components/Login.vue index ec10401841..1f8946f171 100644 --- a/src/components/Login.vue +++ b/src/components/Login.vue @@ -35,7 +35,7 @@ @@ -64,7 +64,10 @@ export default { }, methods: { - /** Submit the user details and attempt to log in */ + /** + * Submit the user details and attempt to log in + * @returns {void} + */ submit() { this.processing = true; diff --git a/src/components/MonitorList.vue b/src/components/MonitorList.vue index 44944ba9b2..a579316b38 100644 --- a/src/components/MonitorList.vue +++ b/src/components/MonitorList.vue @@ -45,7 +45,7 @@ -
+
{{ $t("No Monitors, please") }} {{ $t("add one") }}
@@ -54,11 +54,12 @@ v-for="(item, index) in sortedMonitorList" :key="index" :monitor="item" - :showPathName="filtersActive" :isSelectMode="selectMode" :isSelected="isSelected" :select="select" :deselect="deselect" + :filter-func="filterFunc" + :sort-func="sortFunc" />
@@ -106,6 +107,7 @@ export default { * Improve the sticky appearance of the list by increasing its * height as user scrolls down. * Not used on mobile. + * @returns {object} Style for monitor list */ boxStyle() { if (window.innerWidth > 550) { @@ -122,82 +124,22 @@ export default { /** * Returns a sorted list of monitors based on the applied filters and search text. - * - * @return {Array} The sorted list of monitors. + * @returns {Array} The sorted list of monitors. */ sortedMonitorList() { let result = Object.values(this.$root.monitorList); result = result.filter(monitor => { - // filter by search text - // finds monitor name, tag name or tag value - let searchTextMatch = true; - if (this.searchText !== "") { - const loweredSearchText = this.searchText.toLowerCase(); - searchTextMatch = - monitor.name.toLowerCase().includes(loweredSearchText) - || monitor.tags.find(tag => tag.name.toLowerCase().includes(loweredSearchText) - || tag.value?.toLowerCase().includes(loweredSearchText)); + // The root list does not show children + if (monitor.parent !== null) { + return false; } - - // filter by status - let statusMatch = true; - if (this.filterState.status != null && this.filterState.status.length > 0) { - if (monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[monitor.id]) { - monitor.status = this.$root.lastHeartbeatList[monitor.id].status; - } - statusMatch = this.filterState.status.includes(monitor.status); - } - - // filter by active - let activeMatch = true; - if (this.filterState.active != null && this.filterState.active.length > 0) { - activeMatch = this.filterState.active.includes(monitor.active); - } - - // filter by tags - let tagsMatch = true; - if (this.filterState.tags != null && this.filterState.tags.length > 0) { - tagsMatch = monitor.tags.map(tag => tag.tag_id) // convert to array of tag IDs - .filter(monitorTagId => this.filterState.tags.includes(monitorTagId)) // perform Array Intersaction between filter and monitor's tags - .length > 0; - } - - // Hide children if not filtering - let showChild = true; - if (this.filterState.status == null && this.filterState.active == null && this.filterState.tags == null && this.searchText === "") { - if (monitor.parent !== null) { - showChild = false; - } - } - - return searchTextMatch && statusMatch && activeMatch && tagsMatch && showChild; + return true; }); - // Filter result by active state, weight and alphabetical - result.sort((m1, m2) => { - if (m1.active !== m2.active) { - if (m1.active === false) { - return 1; - } - - if (m2.active === false) { - return -1; - } - } + result = result.filter(this.filterFunc); - if (m1.weight !== m2.weight) { - if (m1.weight > m2.weight) { - return -1; - } - - if (m1.weight < m2.weight) { - return 1; - } - } - - return m1.name.localeCompare(m2.name); - }); + result.sort(this.sortFunc); return result; }, @@ -224,8 +166,7 @@ export default { /** * Determines if any filters are active. - * - * @return {boolean} True if any filter is active, false otherwise. + * @returns {boolean} True if any filter is active, false otherwise. */ filtersActive() { return this.filterState.status != null || this.filterState.active != null || this.filterState.tags != null || this.searchText !== ""; @@ -270,7 +211,10 @@ export default { window.removeEventListener("scroll", this.onScroll); }, methods: { - /** Handle user scroll */ + /** + * Handle user scroll + * @returns {void} + */ onScroll() { if (window.top.scrollY <= 133) { this.windowTop = window.top.scrollY; @@ -286,13 +230,17 @@ export default { monitorURL(id) { return getMonitorRelativeURL(id); }, - /** Clear the search bar */ + /** + * Clear the search bar + * @returns {void} + */ clearSearchText() { this.searchText = ""; }, /** * Update the MonitorList Filter * @param {object} newFilter Object with new filter + * @returns {void} */ updateFilter(newFilter) { this.filterState = newFilter; @@ -300,6 +248,7 @@ export default { /** * Deselect a monitor * @param {number} id ID of monitor + * @returns {void} */ deselect(id) { delete this.selectedMonitors[id]; @@ -307,6 +256,7 @@ export default { /** * Select a monitor * @param {number} id ID of monitor + * @returns {void} */ select(id) { this.selectedMonitors[id] = true; @@ -314,36 +264,127 @@ export default { /** * Determine if monitor is selected * @param {number} id ID of monitor - * @returns {bool} + * @returns {bool} Is the monitor selected? */ isSelected(id) { return id in this.selectedMonitors; }, - /** Disable select mode and reset selection */ + /** + * Disable select mode and reset selection + * @returns {void} + */ cancelSelectMode() { this.selectMode = false; this.selectedMonitors = {}; }, - /** Show dialog to confirm pause */ + /** + * Show dialog to confirm pause + * @returns {void} + */ pauseDialog() { this.$refs.confirmPause.show(); }, - /** Pause each selected monitor */ + /** + * Pause each selected monitor + * @returns {void} + */ pauseSelected() { Object.keys(this.selectedMonitors) .filter(id => this.$root.monitorList[id].active) - .forEach(id => this.$root.getSocket().emit("pauseMonitor", id)); + .forEach(id => this.$root.getSocket().emit("pauseMonitor", id, () => {})); this.cancelSelectMode(); }, - /** Resume each selected monitor */ + /** + * Resume each selected monitor + * @returns {void} + */ resumeSelected() { Object.keys(this.selectedMonitors) .filter(id => !this.$root.monitorList[id].active) - .forEach(id => this.$root.getSocket().emit("resumeMonitor", id)); + .forEach(id => this.$root.getSocket().emit("resumeMonitor", id, () => {})); this.cancelSelectMode(); }, + /** + * Whether a monitor should be displayed based on the filters + * @param {object} monitor Monitor to check + * @returns {boolean} Should the monitor be displayed + */ + filterFunc(monitor) { + // Group monitors bypass filter if at least 1 of children matched + if (monitor.type === "group") { + const children = Object.values(this.$root.monitorList).filter(m => m.parent === monitor.id); + if (children.some((child, index, children) => this.filterFunc(child))) { + return true; + } + } + + // filter by search text + // finds monitor name, tag name or tag value + let searchTextMatch = true; + if (this.searchText !== "") { + const loweredSearchText = this.searchText.toLowerCase(); + searchTextMatch = + monitor.name.toLowerCase().includes(loweredSearchText) + || monitor.tags.find(tag => tag.name.toLowerCase().includes(loweredSearchText) + || tag.value?.toLowerCase().includes(loweredSearchText)); + } + + // filter by status + let statusMatch = true; + if (this.filterState.status != null && this.filterState.status.length > 0) { + if (monitor.id in this.$root.lastHeartbeatList && this.$root.lastHeartbeatList[monitor.id]) { + monitor.status = this.$root.lastHeartbeatList[monitor.id].status; + } + statusMatch = this.filterState.status.includes(monitor.status); + } + + // filter by active + let activeMatch = true; + if (this.filterState.active != null && this.filterState.active.length > 0) { + activeMatch = this.filterState.active.includes(monitor.active); + } + + // filter by tags + let tagsMatch = true; + if (this.filterState.tags != null && this.filterState.tags.length > 0) { + tagsMatch = monitor.tags.map(tag => tag.tag_id) // convert to array of tag IDs + .filter(monitorTagId => this.filterState.tags.includes(monitorTagId)) // perform Array Intersaction between filter and monitor's tags + .length > 0; + } + + return searchTextMatch && statusMatch && activeMatch && tagsMatch; + }, + /** + * Function used in Array.sort to order monitors in a list. + * @param {*} m1 monitor 1 + * @param {*} m2 monitor 2 + * @returns {number} -1, 0 or 1 + */ + sortFunc(m1, m2) { + if (m1.active !== m2.active) { + if (m1.active === false) { + return 1; + } + + if (m2.active === false) { + return -1; + } + } + + if (m1.weight !== m2.weight) { + if (m1.weight > m2.weight) { + return -1; + } + + if (m1.weight < m2.weight) { + return 1; + } + } + + return m1.name.localeCompare(m2.name); + } }, }; @@ -441,5 +482,4 @@ export default { align-items: center; gap: 10px; } - diff --git a/src/components/MonitorListFilter.vue b/src/components/MonitorListFilter.vue index c7598cfddc..330efc9bec 100644 --- a/src/components/MonitorListFilter.vue +++ b/src/components/MonitorListFilter.vue @@ -141,6 +141,11 @@ +
  • + +
  • diff --git a/src/components/MonitorListItem.vue b/src/components/MonitorListItem.vue index 4013b1e380..74ba4835cf 100644 --- a/src/components/MonitorListItem.vue +++ b/src/components/MonitorListItem.vue @@ -20,7 +20,7 @@ - {{ monitorName }} + {{ monitor.name }}
    @@ -43,13 +43,15 @@
    @@ -75,11 +77,6 @@ export default { type: Object, default: null, }, - /** Should the monitor name show it's parent */ - showPathName: { - type: Boolean, - default: false, - }, /** If the user is in select mode */ isSelectMode: { type: Boolean, @@ -105,6 +102,16 @@ export default { type: Function, default: () => {} }, + /** Function to filter child monitors */ + filterFunc: { + type: Function, + default: () => {} + }, + /** Function to sort child monitors */ + sortFunc: { + type: Function, + default: () => {}, + } }, data() { return { @@ -115,32 +122,13 @@ export default { sortedChildMonitorList() { let result = Object.values(this.$root.monitorList); + // Get children result = result.filter(childMonitor => childMonitor.parent === this.monitor.id); - result.sort((m1, m2) => { + // Run filter on children + result = result.filter(this.filterFunc); - if (m1.active !== m2.active) { - if (m1.active === 0) { - return 1; - } - - if (m2.active === 0) { - return -1; - } - } - - if (m1.weight !== m2.weight) { - if (m1.weight > m2.weight) { - return -1; - } - - if (m1.weight < m2.weight) { - return 1; - } - } - - return m1.name.localeCompare(m2.name); - }); + result.sort(this.sortFunc); return result; }, @@ -152,13 +140,6 @@ export default { marginLeft: `${31 * this.depth}px`, }; }, - monitorName() { - if (this.showPathName) { - return this.monitor.pathName; - } else { - return this.monitor.name; - } - } }, watch: { isSelectMode() { @@ -189,7 +170,9 @@ export default { }, methods: { /** - * Changes the collapsed value of the current monitor and saves it to local storage + * Changes the collapsed value of the current monitor and saves + * it to local storage + * @returns {void} */ changeCollapsed() { this.isCollapsed = !this.isCollapsed; @@ -214,6 +197,7 @@ export default { }, /** * Toggle selection of monitor + * @returns {void} */ toggleSelection() { if (this.isSelected(this.monitor.id)) { diff --git a/src/components/MonitorSettingDialog.vue b/src/components/MonitorSettingDialog.vue index d8e9da1a76..e6b2cd1ef4 100644 --- a/src/components/MonitorSettingDialog.vue +++ b/src/components/MonitorSettingDialog.vue @@ -67,8 +67,9 @@ export default { methods: { /** * Setting monitor - * @param {Object} group Data of monitor - * @param {Object} monitor Data of monitor + * @param {object} group Data of monitor + * @param {object} monitor Data of monitor + * @returns {void} */ show(group, monitor) { this.monitor = { @@ -86,6 +87,7 @@ export default { * Toggle the value of sendUrl * @param {number} groupIndex Index of group monitor is member of * @param {number} index Index of monitor within group + * @returns {void} */ toggleLink(groupIndex, index) { this.$root.publicGroupList[groupIndex].monitorList[index].sendUrl = !this.$root.publicGroupList[groupIndex].monitorList[index].sendUrl; @@ -95,10 +97,10 @@ export default { * Should a link to the monitor be shown? * Attempts to guess if a link should be shown based upon if * sendUrl is set and if the URL is default or not. - * @param {Object} monitor Monitor to check - * @param {boolean} [ignoreSendUrl=false] Should the presence of the sendUrl + * @param {object} monitor Monitor to check + * @param {boolean} ignoreSendUrl Should the presence of the sendUrl * property be ignored. This will only work in edit mode. - * @returns {boolean} + * @returns {boolean} Should the link be shown? */ showLink(monitor, ignoreSendUrl = false) { // We must check if there are any elements in monitorList to diff --git a/src/components/NotificationDialog.vue b/src/components/NotificationDialog.vue index f7fce0d318..f6d7280299 100644 --- a/src/components/NotificationDialog.vue +++ b/src/components/NotificationDialog.vue @@ -114,12 +114,18 @@ export default { "AlertNow": "AlertNow", "apprise": this.$t("apprise"), "Bark": "Bark", + "Bitrix24": "Bitrix24", "clicksendsms": "ClickSend SMS", + "CallMeBot": "CallMeBot (WhatsApp, Telegram Call, Facebook Messanger)", "discord": "Discord", + "Elks": "46elks", "GoogleChat": "Google Chat (Google Workspace)", "gorush": "Gorush", "gotify": "Gotify", + "GrafanaOncall": "Grafana Oncall", + "HeiiOnCall": "Heii On-Call", "HomeAssistant": "Home Assistant", + "Keep": "Keep", "Kook": "Kook", "line": "LINE Messenger", "LineNotify": "LINE Notify", @@ -130,6 +136,7 @@ export default { "ntfy": "Ntfy", "octopush": "Octopush", "OneBot": "OneBot", + "Onesender": "Onesender", "Opsgenie": "Opsgenie", "PagerDuty": "PagerDuty", "PagerTree": "PagerTree", @@ -139,18 +146,26 @@ export default { "pushy": "Pushy", "rocket.chat": "Rocket.Chat", "signal": "Signal", + "SIGNL4": "SIGNL4", "slack": "Slack", "squadcast": "SquadCast", "SMSEagle": "SMSEagle", + "SMSPartner": "SMS Partner", "smtp": this.$t("smtp"), "stackfield": "Stackfield", "teams": "Microsoft Teams", "telegram": "Telegram", + "threema": "Threema", "twilio": "Twilio", "Splunk": "Splunk", "webhook": "Webhook", "GoAlert": "GoAlert", - "ZohoCliq": "ZohoCliq" + "ZohoCliq": "ZohoCliq", + "SevenIO": "SevenIO", + "whapi": "WhatsApp (Whapi)", + "gtxmessaging": "GtxMessaging", + "Cellsynt": "Cellsynt", + "SendGrid": "SendGrid" }; // Put notifications here if it's not supported in most regions or its documentation is not in English @@ -167,6 +182,7 @@ export default { "WeCom": "WeCom (企业微信群机器人)", "ServerChan": "ServerChan (Server酱)", "smsc": "SMSC", + "WPush": "WPush(wpush.cn)", }; // Sort by notification name @@ -218,7 +234,10 @@ export default { }, methods: { - /** Show dialog to confirm deletion */ + /** + * Show dialog to confirm deletion + * @returns {void} + */ deleteConfirm() { this.modal.hide(); this.$refs.confirmDelete.show(); @@ -227,6 +246,7 @@ export default { /** * Show settings for specified notification * @param {number} notificationID ID of notification to show + * @returns {void} */ show(notificationID) { if (notificationID) { @@ -250,7 +270,10 @@ export default { this.modal.show(); }, - /** Submit the form to the server */ + /** + * Submit the form to the server + * @returns {void} + */ submit() { this.processing = true; this.$root.getSocket().emit("addNotification", this.notification, this.id, (res) => { @@ -269,7 +292,10 @@ export default { }); }, - /** Test the notification endpoint */ + /** + * Test the notification endpoint + * @returns {void} + */ test() { this.processing = true; this.$root.getSocket().emit("testNotification", this.notification, (res) => { @@ -278,7 +304,10 @@ export default { }); }, - /** Delete the notification endpoint */ + /** + * Delete the notification endpoint + * @returns {void} + */ deleteNotification() { this.processing = true; this.$root.getSocket().emit("deleteNotification", this.id, (res) => { @@ -293,7 +322,8 @@ export default { /** * Get a unique default name for the notification * @param {keyof NotificationFormList} notificationKey - * @return {string} + * Notification to retrieve + * @returns {string} Default name */ getUniqueDefaultName(notificationKey) { diff --git a/src/components/PingChart.vue b/src/components/PingChart.vue index 9502eb84cc..60b0d3c9c1 100644 --- a/src/components/PingChart.vue +++ b/src/components/PingChart.vue @@ -1,16 +1,24 @@ + + diff --git a/src/pages/StatusPage.vue b/src/pages/StatusPage.vue index 121b8622b0..116968282c 100644 --- a/src/pages/StatusPage.vue +++ b/src/pages/StatusPage.vue @@ -1,7 +1,7 @@