diff --git a/compose.yaml b/compose.yaml index 7ccccf4cc..f412c2513 100644 --- a/compose.yaml +++ b/compose.yaml @@ -4,23 +4,25 @@ version: '3.9' services: console-api: image: ${CONSOLE_API_IMAGE} - container_name: console-api - network_mode: host volumes: - ${PWD}/console-config.yaml:/deployments/console-config.yaml:z + ports: + - :8080 environment: CONSOLE_CONFIG_PATH: /deployments/console-config.yaml QUARKUS_KUBERNETES_CLIENT_API_SERVER_URL: ${CONSOLE_API_KUBERNETES_API_SERVER_URL} QUARKUS_KUBERNETES_CLIENT_TRUST_CERTS: "true" QUARKUS_KUBERNETES_CLIENT_TOKEN: ${CONSOLE_API_SERVICE_ACCOUNT_TOKEN} + labels: + io.streamshub.console.container: api console-ui: image: ${CONSOLE_UI_IMAGE} - container_name: console-ui - network_mode: host + ports: + - :3000 environment: - HOSTNAME: localhost - PORT: 3005 NEXTAUTH_SECRET: ${CONSOLE_UI_NEXTAUTH_SECRET} - NEXTAUTH_URL: http://localhost:3005 - BACKEND_URL: http://localhost:8080/ + NEXTAUTH_URL: http://localhost:3000 + BACKEND_URL: http://console-api:8080/ + labels: + io.streamshub.console.container: ui diff --git a/podman-desktop-extension/.dockerignore b/podman-desktop-extension/.dockerignore new file mode 100644 index 000000000..3c3629e64 --- /dev/null +++ b/podman-desktop-extension/.dockerignore @@ -0,0 +1 @@ +node_modules diff --git a/podman-desktop-extension/.editorconfig b/podman-desktop-extension/.editorconfig new file mode 100644 index 000000000..872069e8b --- /dev/null +++ b/podman-desktop-extension/.editorconfig @@ -0,0 +1,18 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# https://github.com/jokeyrhyme/standard-editorconfig + +# top-most EditorConfig file +root = true + +# defaults +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_size = 2 +indent_style = space + +[*.md] +trim_trailing_whitespace = false diff --git a/podman-desktop-extension/.eslintignore b/podman-desktop-extension/.eslintignore new file mode 100644 index 000000000..91d7a7e22 --- /dev/null +++ b/podman-desktop-extension/.eslintignore @@ -0,0 +1,6 @@ +build +*.config.js +__mocks__ +coverage +packages/backend/media/** +tests/ \ No newline at end of file diff --git a/podman-desktop-extension/.eslintrc.json b/podman-desktop-extension/.eslintrc.json new file mode 100644 index 000000000..0b9c60edc --- /dev/null +++ b/podman-desktop-extension/.eslintrc.json @@ -0,0 +1,93 @@ +{ + "root": true, + "env": { + "es2021": true, + "node": true, + "browser": false + }, + "extends": [ + "eslint:recommended", + /** @see https://github.com/typescript-eslint/typescript-eslint/tree/master/packages/eslint-plugin#recommended-configs */ + "plugin:@typescript-eslint/recommended", + "plugin:import/recommended", + "plugin:import/typescript", + "plugin:etc/recommended", + "plugin:sonarjs/recommended" + ], + "parser": "@typescript-eslint/parser", + "parserOptions": { + "ecmaVersion": 12, + "sourceType": "module", + "project": [ + "packages/*/tsconfig.json", + "tests/playwright/tsconfig.json" + ] + }, + "settings": { + "import/resolver": { + "typescript": true, + "node": true, + "eslint-import-resolver-custom-alias": { + "alias": { + "/@": "./src", + "/@gen": "./src-generated" + }, + "extensions": [".ts"], + "packages": ["packages/*"] + } + } + }, + "ignorePatterns": [ + "node_modules/**", + "**/dist/**" + ], + "plugins": ["@typescript-eslint", "sonarjs", "etc", "redundant-undefined", "no-null"], + "rules": { + "eqeqeq": "error", + "@typescript-eslint/no-unused-vars": ["error", { "argsIgnorePattern": "^_" }], + "@typescript-eslint/no-var-requires": "off", + "@typescript-eslint/consistent-type-imports": "error", + "@typescript-eslint/no-explicit-any": "error", + "prefer-promise-reject-errors": "error", + "@typescript-eslint/await-thenable": "error", + "@typescript-eslint/no-floating-promises": "error", + "@typescript-eslint/no-misused-promises": "error", + "@typescript-eslint/prefer-optional-chain": "error", + "@typescript-eslint/prefer-nullish-coalescing": "error", + "no-null/no-null": "error", + + /** + * Having a semicolon helps the optimizer interpret your code correctly. + * This avoids rare errors in optimized code. + * @see https://twitter.com/alex_kozack/status/1364210394328408066 + */ + "semi": [ + "error", + "always" + ], + /** + * This will make the history of changes in the hit a little cleaner + */ + "comma-dangle": [ + "warn", + "always-multiline" + ], + /** + * Just for beauty + */ + "quotes": ["error", "single", { "allowTemplateLiterals": true }], + "import/no-duplicates": "error", + "import/no-unresolved": "off", + "import/default": "off", + "import/no-named-as-default-member": "off", + "import/no-named-as-default": "off", + "sonarjs/cognitive-complexity": "off", + "sonarjs/no-duplicate-string": "off", + "sonarjs/no-empty-collection": "off", + "sonarjs/no-small-switch": "off", + "etc/no-commented-out-code": "error", + "etc/no-deprecated": "off", + "redundant-undefined/redundant-undefined": "error", + "import/no-extraneous-dependencies": "error" + } +} diff --git a/podman-desktop-extension/.gitattributes b/podman-desktop-extension/.gitattributes new file mode 100644 index 000000000..94f480de9 --- /dev/null +++ b/podman-desktop-extension/.gitattributes @@ -0,0 +1 @@ +* text=auto eol=lf \ No newline at end of file diff --git a/podman-desktop-extension/.github/ISSUE_TEMPLATE/bug_report.yml b/podman-desktop-extension/.github/ISSUE_TEMPLATE/bug_report.yml new file mode 100644 index 000000000..5882fbf5c --- /dev/null +++ b/podman-desktop-extension/.github/ISSUE_TEMPLATE/bug_report.yml @@ -0,0 +1,59 @@ +name: Bug 🐞 +description: Report a bug report +labels: [kind/bug 🐞] + +body: + - type: markdown + attributes: + value: | + Before opening a bug report, please search for the behaviour in the existing issues. + + --- + + Thank you for taking the time to file a bug report. To address this bug as fast as possible, we need some information. + + - type: textarea + id: bug-description + attributes: + label: Bug description + description: What happened? + validations: + required: true + + - type: input + id: os + attributes: + label: Operating system + description: "Which operating system are you on? Please provide the version as well. If you are on a Mac, please specify Apple silicon or Intel." + placeholder: "macOS Ventura 13.4 (Arm), Windows 11" + validations: + required: true + + - type: dropdown + id: version + attributes: + label: Version + description: What version of the bootable container extension are you running? + options: + - "next (development version)" + validations: + required: true + + - type: textarea + id: steps + attributes: + label: Steps to reproduce + description: What steps do we need to take to reproduce this error? + + - type: textarea + id: logs + attributes: + label: Relevant log output + description: If applicable, provide relevant log output. + render: shell + + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Add any other context or screenshots here. diff --git a/podman-desktop-extension/.github/ISSUE_TEMPLATE/config.yml b/podman-desktop-extension/.github/ISSUE_TEMPLATE/config.yml new file mode 100644 index 000000000..3ba13e0ce --- /dev/null +++ b/podman-desktop-extension/.github/ISSUE_TEMPLATE/config.yml @@ -0,0 +1 @@ +blank_issues_enabled: false diff --git a/podman-desktop-extension/.github/ISSUE_TEMPLATE/enhancement.yml b/podman-desktop-extension/.github/ISSUE_TEMPLATE/enhancement.yml new file mode 100644 index 000000000..7077e6847 --- /dev/null +++ b/podman-desktop-extension/.github/ISSUE_TEMPLATE/enhancement.yml @@ -0,0 +1,42 @@ +name: Enhancement ✨ +description: Suggest an enhancement to an existing feature +labels: [kind/enhancement ✨] + +body: + - type: markdown + attributes: + value: | + Before opening a new enhancement, please search for potential existing issues. + + --- + + Thank you for taking the time to file an enhancement request, we appreciate and value your time to help the project! + + - type: textarea + id: problem + attributes: + label: Is your enhancement related to a problem? Please describe + description: A clear and concise description of what the problem is. + placeholder: I'm always frustrated when [...] + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Describe the solution you'd like + description: A clear and concise description of what you want to happen. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Describe alternatives you've considered + description: A clear and concise description of any alternative solutions or features you've considered. + + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Add any other context or screenshots here. diff --git a/podman-desktop-extension/.github/ISSUE_TEMPLATE/epic.yml b/podman-desktop-extension/.github/ISSUE_TEMPLATE/epic.yml new file mode 100644 index 000000000..bcc2b903f --- /dev/null +++ b/podman-desktop-extension/.github/ISSUE_TEMPLATE/epic.yml @@ -0,0 +1,25 @@ +name: Epic ⚡ +description: A high-level feature +labels: [kind/epic ⚡] + +body: + - type: markdown + attributes: + value: | + Epics are normally created by the development team, to group a set of related features and plan work across multiple sprints. + The features this epic includes are referenced with the text of the epic. + + - type: textarea + id: domain + attributes: + label: Epic domain + description: A clear and concise description of the feature area or domain that this epic will address. + placeholder: The bootable container extension should support [...] + validations: + required: true + + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Add any other context or screenshots here. diff --git a/podman-desktop-extension/.github/ISSUE_TEMPLATE/feature_request.yml b/podman-desktop-extension/.github/ISSUE_TEMPLATE/feature_request.yml new file mode 100644 index 000000000..37b40cfb9 --- /dev/null +++ b/podman-desktop-extension/.github/ISSUE_TEMPLATE/feature_request.yml @@ -0,0 +1,42 @@ +name: Feature 💡 +description: Suggest an idea for this project +labels: [kind/feature 💡] + +body: + - type: markdown + attributes: + value: | + Before opening a feature request, please search for potential existing issues. + + --- + + Thank you for taking the time to file a feature request, we appreciate and value your time to help the project! + + - type: textarea + id: problem + attributes: + label: Is your feature request related to a problem? Please describe + description: A clear and concise description of what the problem is. + placeholder: I'm always frustrated when [...] + validations: + required: true + + - type: textarea + id: solution + attributes: + label: Describe the solution you'd like + description: A clear and concise description of what you want to happen. + validations: + required: true + + - type: textarea + id: alternatives + attributes: + label: Describe alternatives you've considered + description: A clear and concise description of any alternative solutions or features you've considered. + + - type: textarea + id: additional-context + attributes: + label: Additional context + description: Add any other context or screenshots here. diff --git a/podman-desktop-extension/.github/PULL_REQUEST_TEMPLATE.md b/podman-desktop-extension/.github/PULL_REQUEST_TEMPLATE.md new file mode 100644 index 000000000..7b16bc1ee --- /dev/null +++ b/podman-desktop-extension/.github/PULL_REQUEST_TEMPLATE.md @@ -0,0 +1,15 @@ +### What does this PR do? + +### Screenshot / video of UI + + + +### What issues does this PR fix or reference? + + + +### How to test this PR? + + diff --git a/podman-desktop-extension/.github/dependabot.yml b/podman-desktop-extension/.github/dependabot.yml new file mode 100644 index 000000000..17a7fbc24 --- /dev/null +++ b/podman-desktop-extension/.github/dependabot.yml @@ -0,0 +1,15 @@ +# Set update schedule for GitHub Actions + +version: 2 +updates: + - package-ecosystem: "github-actions" + directory: "/" + schedule: + interval: "daily" + open-pull-requests-limit: 10 + + - package-ecosystem: "npm" + directory: "/" + schedule: + interval: daily + open-pull-requests-limit: 10 diff --git a/podman-desktop-extension/.github/workflows/bootc-e2e-nightly-windows.yaml b/podman-desktop-extension/.github/workflows/bootc-e2e-nightly-windows.yaml new file mode 100644 index 000000000..3a819e9e7 --- /dev/null +++ b/podman-desktop-extension/.github/workflows/bootc-e2e-nightly-windows.yaml @@ -0,0 +1,254 @@ +# +# Copyright (C) 2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +name: Podman Desktop BootC E2E Nightly + +on: + schedule: + - cron: '0 4 * * *' + workflow_dispatch: + inputs: + fork: + default: 'containers' + description: 'Podman Desktop repo fork' + type: string + required: true + branch: + default: 'main' + description: 'Podman Desktop repo branch' + type: string + required: true + ext_repo_options: + default: 'REPO=podman-desktop-extension-bootc,FORK=containers,BRANCH=main' + description: 'Podman Desktop Extension repo, fork and branch' + type: string + required: true + ext_tests: + default: '1' + description: 'Run E2E tests from extension' + type: string + required: true + npm_target: + default: 'test:e2e' + description: 'npm target to run tests' + type: string + required: true + podman_remote_url: + default: 'https://github.com/containers/podman/releases/download/v5.0.3/podman-remote-release-windows_amd64.zip' + description: 'podman remote zip' + type: string + required: true + podman_version: + default: '5.0.3' + description: 'Podman folder version in archive' + type: 'string' + required: true + podman_options: + default: 'INIT=1,START=1,ROOTFUL=1,NETWORKING=0' + description: 'Podman machine configuration options, no spaces' + type: 'string' + required: true + env_vars: + default: 'TEST_PODMAN_MACHINE=true' + description: 'Env. Variables passed into target machine, ie: VAR1=xxx,VAR2=true,VAR3=15,VAR4="Pass me along"' + type: 'string' + required: true + +jobs: + windows: + name: windows-${{ matrix.windows-version }}-${{ matrix.windows-featurepack }} + runs-on: ubuntu-latest + permissions: + contents: read + checks: write + env: + QENVS_VERSION: v0.6.3 + strategy: + fail-fast: false + matrix: + windows-version: ['10','11'] + windows-featurepack: ['22h2-ent', '23h2-ent'] + exclude: + - windows-version: '10' + windows-featurepack: '23h2-ent' + - windows-version: '11' + windows-featurepack: '22h2-ent' + + + steps: + - name: Get Podman version used by Desktop + run: | + version=$(curl https://raw.githubusercontent.com/containers/podman-desktop/main/extensions/podman/src/podman5.json | jq -r '.version') + echo "Default Podman Version from Podman Desktop: ${version}" + echo "PD_PODMAN_VERSION=${version}" >> $GITHUB_ENV + - name: Set the default env. variables + env: + DEFAULT_FORK: 'containers' + DEFAULT_BRANCH: 'main' + DEFAULT_EXT_TESTS: '1' + DEFAULT_NPM_TARGET: 'test:e2e' + DEFAULT_ENV_VARS: 'TEST_PODMAN_MACHINE=true' + DEFAULT_PODMAN_OPTIONS: 'INIT=1,START=1,ROOTFUL=1,NETWORKING=0' + DEFAULT_EXT_REPO_OPTIONS: 'REPO=podman-desktop-extension-bootc,FORK=containers,BRANCH=main' + DEFAULT_VERSION: "${{ env.PD_PODMAN_VERSION || '5.0.3' }}" + DEFAULT_URL: "https://github.com/containers/podman/releases/download/v$DEFAULT_VERSION/podman-remote-release-windows_amd64.zip" + run: | + echo "FORK=${{ github.event.inputs.fork || env.DEFAULT_FORK }}" >> $GITHUB_ENV + echo "BRANCH=${{ github.event.inputs.branch || env.DEFAULT_BRANCH }}" >> $GITHUB_ENV + echo "NPM_TARGET=${{ github.event.inputs.npm_target || env.DEFAULT_NPM_TARGET }}" >> $GITHUB_ENV + echo "ENV_VARS=${{ github.event.inputs.env_vars || env.DEFAULT_ENV_VARS }}" >> $GITHUB_ENV + echo "PODMAN_VERSION=${{ github.event.inputs.podman_version || env.DEFAULT_VERSION }}" >> $GITHUB_ENV + echo "PODMAN_URL=${{ github.event.inputs.podman_remote_url || env.DEFAULT_URL }}" >> $GITHUB_ENV + echo "EXT_TESTS=${{ github.event.inputs.ext_tests || env.DEFAULT_EXT_TESTS }}" >> $GITHUB_ENV + echo "${{ github.event.inputs.podman_options || env.DEFAULT_PODMAN_OPTIONS }}" | awk -F ',' \ + '{for (i=1; i<=NF; i++) {split($i, kv, "="); print "PODMAN_"kv[1]"="kv[2]}}' >> $GITHUB_ENV + echo "${{ github.event.inputs.ext_repo_options || env.DEFAULT_EXT_REPO_OPTIONS }}" | awk -F ',' \ + '{for (i=1; i<=NF; i++) {split($i, kv, "="); print "EXT_"kv[1]"="kv[2]}}' >> $GITHUB_ENV + + - name: Create instance + run: | + # Create instance + podman run -d --name windows-create --rm \ + -v ${PWD}:/workspace:z \ + -e ARM_TENANT_ID=${{ secrets.ARM_TENANT_ID }} \ + -e ARM_SUBSCRIPTION_ID=${{ secrets.ARM_SUBSCRIPTION_ID }} \ + -e ARM_CLIENT_ID=${{ secrets.ARM_CLIENT_ID }} \ + -e ARM_CLIENT_SECRET='${{ secrets.ARM_CLIENT_SECRET }}' \ + quay.io/rhqp/qenvs:${{ env.QENVS_VERSION }} azure \ + windows create \ + --project-name 'windows-desktop' \ + --backed-url 'file:///workspace' \ + --conn-details-output '/workspace' \ + --windows-version '${{ matrix.windows-version }}' \ + --windows-featurepack '${{ matrix.windows-featurepack }}' \ + --vmsize 'Standard_D8s_v4' \ + --tags project=podman-desktop \ + --spot + # Check logs + podman logs -f windows-create + + - name: Check instance system info + run: | + ssh -i id_rsa \ + -o StrictHostKeyChecking=no \ + -o UserKnownHostsFile=/dev/null \ + -o ServerAliveInterval=30 \ + -o ServerAliveCountMax=1200 \ + $(cat username)@$(cat host) "systeminfo" + + - name: Emulate X session + run: | + # use fake rdp to emulate an active x session + podman run -d --name x-session \ + -e RDP_HOST=$(cat host) \ + -e RDP_USER=$(cat username) \ + -e RDP_PASSWORD=$(cat userpassword) \ + quay.io/rhqp/frdp:v0.0.1 + # Wait until the x session has been created + podman wait --condition running x-session + # Check logs for the x session + podman logs x-session + + - name: Download Podman, do not initialize + run: | + podman run --rm -d --name pde2e-podman-run \ + -e TARGET_HOST=$(cat host) \ + -e TARGET_HOST_USERNAME=$(cat username) \ + -e TARGET_HOST_KEY_PATH=/data/id_rsa \ + -e TARGET_FOLDER=pd-e2e \ + -e TARGET_RESULTS=results \ + -e OUTPUT_FOLDER=/data \ + -e DEBUG=true \ + -v $PWD:/data:z \ + quay.io/odockal/pde2e-podman:v0.0.1-windows \ + pd-e2e/podman.ps1 \ + -downloadUrl ${{ env.PODMAN_URL }} \ + -version ${{ env.PODMAN_VERSION }} \ + -targetFolder pd-e2e \ + -resultsFolder results \ + -initialize 0 \ + -rootful 0 \ + -start 0 \ + -installWSL 0 + # check logs + podman logs -f pde2e-podman-run + + - name: Run Podman Desktop Playwright E2E tests + run: | + podman run -d --name pde2e-runner-run \ + -e TARGET_HOST=$(cat host) \ + -e TARGET_HOST_USERNAME=$(cat username) \ + -e TARGET_HOST_KEY_PATH=/data/id_rsa \ + -e TARGET_FOLDER=pd-e2e \ + -e TARGET_RESULTS=results \ + -e OUTPUT_FOLDER=/data \ + -e DEBUG=true \ + -v $PWD:/data:z \ + quay.io/odockal/pde2e-runner:v0.0.1-windows \ + pd-e2e/runner.ps1 \ + -targetFolder pd-e2e \ + -resultsFolder results \ + -podmanPath $(cat results/podman-location.log) \ + -fork ${{ env.FORK }} \ + -branch ${{ env.BRANCH }} \ + -extRepo ${{ env.EXT_REPO }} \ + -extFork ${{ env.EXT_FORK }} \ + -extBranch ${{ env.EXT_BRANCH }} \ + -extTests ${{ env.EXT_TESTS }} \ + -npmTarget ${{ env.NPM_TARGET }} \ + -initialize ${{ env.PODMAN_INIT }} \ + -rootful ${{ env.PODMAN_ROOTFUL }} \ + -start ${{ env.PODMAN_START }} \ + -userNetworking ${{ env.PODMAN_NETWORKING }} \ + -envVars ${{ env.ENV_VARS }} \ + # check logs + podman logs -f pde2e-runner-run + + - name: Destroy instance + if: always() + run: | + # Destroy instance + podman run -d --name windows-destroy --rm \ + -v ${PWD}:/workspace:z \ + -e ARM_TENANT_ID=${{ secrets.ARM_TENANT_ID }} \ + -e ARM_SUBSCRIPTION_ID=${{ secrets.ARM_SUBSCRIPTION_ID }} \ + -e ARM_CLIENT_ID=${{ secrets.ARM_CLIENT_ID }} \ + -e ARM_CLIENT_SECRET='${{ secrets.ARM_CLIENT_SECRET }}' \ + quay.io/rhqp/qenvs:${{ env.QENVS_VERSION }} azure \ + windows destroy \ + --project-name 'windows-desktop' \ + --backed-url 'file:///workspace' + # Check logs + podman logs -f windows-destroy + + - name: Publish Test Report + uses: mikepenz/action-junit-report@v4 + if: always() # always run even if the previous step fails + with: + fail_on_failure: true + include_passed: true + detailed_summary: true + require_tests: true + report_paths: '**/*results.xml' + + - name: Upload test artifacts + uses: actions/upload-artifact@v4 + if: always() + with: + name: results-e2e-${{ matrix.windows-version }}${{ matrix.windows-featurepack }} + path: | + results/* diff --git a/podman-desktop-extension/.github/workflows/build-next.yaml b/podman-desktop-extension/.github/workflows/build-next.yaml new file mode 100644 index 000000000..4769a6946 --- /dev/null +++ b/podman-desktop-extension/.github/workflows/build-next.yaml @@ -0,0 +1,66 @@ +# +# Copyright (C) 2023-2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +name: CI + +on: + push: + branches: + - 'main' + +jobs: + build: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-node@v4 + with: + node-version: 18 + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "dir=$(npx yarn cache dir)" >> ${GITHUB_OUTPUT} + + - uses: actions/cache@v4 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} + run: npx yarn --frozen-lockfile --network-timeout 180000 + + - name: Run Build + run: npx yarn build + + - name: Login to ghcr.io + run: podman login --username ${{ github.repository_owner }} --password ${{ secrets.GITHUB_TOKEN }} ghcr.io + + - name: Publish Image + id: publish-image + run: | + IMAGE_NAME=ghcr.io/${{ github.repository_owner }}/podman-desktop-extension-bootc + IMAGE_NIGHTLY=${IMAGE_NAME}:nightly + IMAGE_SHA=${IMAGE_NAME}:${GITHUB_SHA} + podman build -t $IMAGE_NIGHTLY . + podman push $IMAGE_NIGHTLY + podman tag $IMAGE_NIGHTLY $IMAGE_SHA + podman push $IMAGE_SHA diff --git a/podman-desktop-extension/.github/workflows/e2e-main.yaml b/podman-desktop-extension/.github/workflows/e2e-main.yaml new file mode 100644 index 000000000..4043975ed --- /dev/null +++ b/podman-desktop-extension/.github/workflows/e2e-main.yaml @@ -0,0 +1,130 @@ +# +# Copyright (C) 2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +name: e2e-tests-main + +on: + push: + branches: [main] + + workflow_dispatch: + inputs: + organization: + default: 'containers' + description: 'Organization of the Podman Desktop repository' + type: string + required: true + repositoryName: + default: 'podman-desktop-extension-bootc' + description: 'Podman Desktop Extension BootC repository name' + type: string + required: true + branch: + default: 'main' + description: 'Podman Desktop Extension BootC repo branch' + type: string + required: true + +jobs: + e2e-tests: + name: Run E2E tests + runs-on: ubuntu-24.04 + steps: + - uses: actions/checkout@v4 + if: github.event_name == 'workflow_dispatch' + with: + repository: ${{ github.event.inputs.organization }}/${{ github.event.inputs.repositoryName }} + ref: ${{ github.event.inputs.branch }} + path: ${{ github.event.inputs.repositoryName }} + + - uses: actions/checkout@v4 + if: github.event_name == 'push' + with: + path: podman-desktop-extension-bootc + + # Checkout podman desktop + - uses: actions/checkout@v4 + with: + repository: containers/podman-desktop + ref: main + path: podman-desktop + + - uses: actions/setup-node@v4 + with: + node-version: 20 + + - name: Update podman + run: | + # ubuntu version from kubic repository to install podman we need (v5) + ubuntu_version='23.04' + sudo sh -c "echo 'deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list" + curl -L "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key" | sudo apt-key add - + # install necessary dependencies for criu package which is not part of 23.04 + sudo apt-get install -qq libprotobuf32t64 python3-protobuf libnet1 + # install criu manually from static location + curl -sLO http://cz.archive.ubuntu.com/ubuntu/pool/universe/c/criu/criu_3.16.1-2_amd64.deb && sudo dpkg -i criu_3.16.1-2_amd64.deb + sudo apt-get update -qq + sudo apt-get -qq -y install podman || { echo "Start fallback steps for podman nightly installation from a static mirror" && \ + sudo sh -c "echo 'deb http://ftp.lysator.liu.se/pub/opensuse/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list" && \ + curl -L "http://ftp.lysator.liu.se/pub/opensuse/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key" | sudo apt-key add - && \ + sudo apt-get update && \ + sudo apt-get -y install podman; } + podman version + + - name: Revert unprivileged user namespace restrictions in Ubuntu 24.04 + run: | + # allow unprivileged user namespace + sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + + - name: Build Podman Desktop for E2E tests + working-directory: ./podman-desktop + run: | + yarn --frozen-lockfile + yarn test:e2e:build + + - name: Get yarn cache directory path + working-directory: ./podman-desktop-extension-bootc + id: yarn-cache-dir-path + run: echo "dir=$(yarn cache dir)" >> ${GITHUB_OUTPUT} + + - uses: actions/cache@v4 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Ensure getting current HEAD version of the test framework + working-directory: ./podman-desktop-extension-bootc/tests/playwright + run: yarn add -D @podman-desktop/tests-playwright@next + + - name: Execute yarn in Bootc Extension + working-directory: ./podman-desktop-extension-bootc + run: yarn --frozen-lockfile + + - name: Run All E2E tests + working-directory: ./podman-desktop-extension-bootc + env: + PODMAN_DESKTOP_ARGS: ${{ github.workspace }}/podman-desktop + run: yarn test:e2e + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: e2e-tests + path: ./**/tests/output/ diff --git a/podman-desktop-extension/.github/workflows/pr-check.yaml b/podman-desktop-extension/.github/workflows/pr-check.yaml new file mode 100644 index 000000000..1d0dd9df3 --- /dev/null +++ b/podman-desktop-extension/.github/workflows/pr-check.yaml @@ -0,0 +1,180 @@ +# +# Copyright (C) 2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +name: pr-check + +on: [pull_request] + +jobs: + lint-format-unit: + name: linter, formatter, and tests / ${{ matrix.os }} + runs-on: ${{ matrix.os }} + timeout-minutes: 15 + strategy: + fail-fast: false + matrix: + os: [windows-2022, ubuntu-22.04, macos-14] + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: 18 + + - name: Get yarn cache directory path (Windows) + if: ${{ matrix.os=='windows-2022' }} + id: yarn-cache-dir-path-windows + run: echo "dir=$(yarn cache dir)" >> ${env:GITHUB_OUTPUT} + + - name: Get yarn cache directory path (mac/Linux) + if: ${{ matrix.os=='ubuntu-22.04' || matrix.os=='macos-14' }} + id: yarn-cache-dir-path-unix + run: echo "dir=$(yarn cache dir)" >> ${GITHUB_OUTPUT} + + - uses: actions/cache@v4 + if: ${{ matrix.os=='windows-2022' }} + id: yarn-cache-windows + with: + path: ${{ steps.yarn-cache-dir-path-windows.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - uses: actions/cache@v4 + if: ${{ matrix.os=='ubuntu-22.04' || matrix.os=='macos-14' }} + id: yarn-cache-unix + with: + path: ${{ steps.yarn-cache-dir-path-unix.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Execute yarn + run: yarn --frozen-lockfile --network-timeout 180000 + + - name: Run linter + run: yarn lint:check + + # skip formatter on windows + - name: Run formatter + if: ${{ matrix.os=='ubuntu-22.04' || matrix.os=='macos-14' }} + run: yarn format:check + + - name: Run tests + run: yarn test + + - name: Run typecheck + run: yarn typecheck + + - name: Run svelte check + run: yarn svelte:check + + - name: Run build + run: yarn build + + e2e-tests: + name: e2e tests + runs-on: ubuntu-24.04 + env: + SKIP_INSTALLATION: true + steps: + - uses: actions/checkout@v4 + with: + path: podman-desktop-extension-bootc + - uses: actions/setup-node@v4 + with: + node-version: 20 + + # Checkout podman desktop + - uses: actions/checkout@v4 + with: + repository: containers/podman-desktop + ref: main + path: podman-desktop + + - name: Update podman + run: | + # ubuntu version from kubic repository to install podman we need (v5) + ubuntu_version='23.04' + sudo sh -c "echo 'deb https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list" + curl -L "https://download.opensuse.org/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key" | sudo apt-key add - + # install necessary dependencies for criu package which is not part of 23.04 + sudo apt-get install -qq libprotobuf32t64 python3-protobuf libnet1 + # install criu manually from static location + curl -sLO http://cz.archive.ubuntu.com/ubuntu/pool/universe/c/criu/criu_3.16.1-2_amd64.deb && sudo dpkg -i criu_3.16.1-2_amd64.deb + sudo apt-get update -qq + sudo apt-get -qq -y install podman || { echo "Start fallback steps for podman nightly installation from a static mirror" && \ + sudo sh -c "echo 'deb http://ftp.lysator.liu.se/pub/opensuse/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/ /' > /etc/apt/sources.list.d/devel:kubic:libcontainers:unstable.list" && \ + curl -L "http://ftp.lysator.liu.se/pub/opensuse/repositories/devel:/kubic:/libcontainers:/unstable/xUbuntu_${ubuntu_version}/Release.key" | sudo apt-key add - && \ + sudo apt-get update && \ + sudo apt-get -y install podman; } + podman version + + - name: Revert unprivileged user namespace restrictions in Ubuntu 24.04 + run: | + # allow unprivileged user namespace + sudo sysctl -w kernel.apparmor_restrict_unprivileged_userns=0 + + - name: Build Podman Desktop for E2E tests + working-directory: ./podman-desktop + run: | + yarn --frozen-lockfile + yarn test:e2e:build + + - name: Get yarn cache directory path + working-directory: ./podman-desktop-extension-bootc + id: yarn-cache-dir-path + run: echo "dir=$(yarn cache dir)" >> ${GITHUB_OUTPUT} + + - uses: actions/cache@v4 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Ensure getting current HEAD version of the test framework + working-directory: ./podman-desktop-extension-bootc/tests/playwright + run: yarn add -D @podman-desktop/tests-playwright@next + + - name: Execute yarn in Bootc Extension + working-directory: ./podman-desktop-extension-bootc + run: yarn --frozen-lockfile + + - name: Build bootc extension from container file + working-directory: ./podman-desktop-extension-bootc + run: | + yarn build + podman build -t local_bootc_image ./ + CONTAINER_ID=$(podman create localhost/local_bootc_image --entrypoint "") + podman export $CONTAINER_ID > /tmp/local_bootc_extension.tar + mkdir -p tests/playwright/tests/output/bootc-tests-pd/plugins + tar -xf /tmp/local_bootc_extension.tar -C tests/playwright/tests/output/bootc-tests-pd/plugins/ + + - name: Run All E2E tests + working-directory: ./podman-desktop-extension-bootc + env: + PODMAN_DESKTOP_ARGS: ${{ github.workspace }}/podman-desktop + run: yarn test:e2e + + - uses: actions/upload-artifact@v4 + if: always() + with: + name: e2e-tests + path: ./**/tests/output/ + + diff --git a/podman-desktop-extension/.github/workflows/release.yaml b/podman-desktop-extension/.github/workflows/release.yaml new file mode 100644 index 000000000..46162178e --- /dev/null +++ b/podman-desktop-extension/.github/workflows/release.yaml @@ -0,0 +1,142 @@ +# +# Copyright (C) 2023-2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +name: release + +on: + workflow_dispatch: + inputs: + version: + description: 'Version to release (example: 0.1.0)' + required: true + branch: + description: 'Branch to use for the release' + required: true + default: main +env: + GITHUB_TOKEN: ${{secrets.GITHUB_TOKEN}} + +jobs: + build: + runs-on: ubuntu-22.04 + steps: + - uses: actions/checkout@v4 + with: + ref: ${{ github.event.inputs.branch }} + + - name: Generate tag utilities + id: TAG_UTIL + run: | + TAG_PATTERN=${{ github.event.inputs.version }} + echo "githubTag=v$TAG_PATTERN" >> ${GITHUB_OUTPUT} + echo "bootcExtensionVersion=$TAG_PATTERN" >> ${GITHUB_OUTPUT} + + - name: tag + run: | + git config --local user.name ${{ github.actor }} + git config --local user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com" + + # Add the new version in package.json file + sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.bootcExtensionVersion }}\",#g" package.json + sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.bootcExtensionVersion }}\",#g" packages/backend/package.json + sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${{ steps.TAG_UTIL.outputs.bootcExtensionVersion }}\",#g" packages/frontend/package.json + git add package.json packages/backend/package.json packages/frontend/package.json + + + # commit the changes + git commit -m "chore: 🥁 tagging ${{ steps.TAG_UTIL.outputs.githubTag }} 🥳" + echo "Tagging with ${{ steps.TAG_UTIL.outputs.githubTag }}" + git tag ${{ steps.TAG_UTIL.outputs.githubTag }} + git push origin ${{ steps.TAG_UTIL.outputs.githubTag }} + + - name: Create Release + id: create_release + uses: ncipollo/release-action@v1 + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + with: + tag: ${{ steps.TAG_UTIL.outputs.githubTag }} + name: ${{ steps.TAG_UTIL.outputs.githubTag }} + draft: true + prerelease: true + + - name: Create the PR to bump the version in the main branch (only if we're tagging from main branch) + if: ${{ github.event.inputs.branch == 'main' }} + run: | + git config --local user.name ${{ github.actor }} + git config --local user.email "${{ github.actor_id }}+${{ github.actor }}@users.noreply.github.com" + CURRENT_VERSION=$(echo "${{ steps.TAG_UTIL.outputs.bootcExtensionVersion }}") + tmp=${CURRENT_VERSION%.*} + minor=${tmp#*.} + bumpedVersion=${CURRENT_VERSION%%.*}.$((minor + 1)).0 + bumpedBranchName="bump-to-${bumpedVersion}" + git checkout -b "${bumpedBranchName}" + sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${bumpedVersion}-next\",#g" package.json + sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${bumpedVersion}-next\",#g" packages/backend/package.json + sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${bumpedVersion}-next\",#g" packages/frontend/package.json + git add package.json packages/backend/package.json packages/frontend/package.json + git commit -s --amend -m "chore: bump version to ${bumpedVersion}" + git push origin "${bumpedBranchName}" + echo -e "📢 Bump version to ${bumpedVersion}\n\n${{ steps.TAG_UTIL.outputs.bootcExtensionVersion }} has been released.\n\n Time to switch to the new ${bumpedVersion} version 🥳" > /tmp/pr-title + pullRequestUrl=$(gh pr create --title "chore: 📢 Bump version to ${bumpedVersion}" --body-file /tmp/pr-title --head "${bumpedBranchName}" --base "main") + echo "📢 Pull request created: ${pullRequestUrl}" + echo "➡️ Flag the PR as being ready for review" + gh pr ready "${pullRequestUrl}" + echo "🔅 Mark the PR as being ok to be merged automatically" + gh pr merge "${pullRequestUrl}" --auto --rebase + sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${CURRENT_VERSION}\",#g" package.json + sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${CURRENT_VERSION}\",#g" packages/backend/package.json + sed -i "s#version\":\ \"\(.*\)\",#version\":\ \"${CURRENT_VERSION}\",#g" packages/frontend/package.json + env: + GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} + + - uses: actions/setup-node@v4 + with: + node-version: 18 + + - name: Get yarn cache directory path + id: yarn-cache-dir-path + run: echo "dir=$(npx yarn cache dir)" >> ${GITHUB_OUTPUT} + + - uses: actions/cache@v4 + id: yarn-cache + with: + path: ${{ steps.yarn-cache-dir-path.outputs.dir }} + key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }} + restore-keys: | + ${{ runner.os }}-yarn- + + - name: Execute yarn + if: ${{ steps.cacheNodeModules.outputs.cache-hit != 'true' }} + run: npx yarn --frozen-lockfile --network-timeout 180000 + + - name: Run Build + run: npx yarn build + + - name: Login to ghcr.io + run: podman login --username ${{ github.repository_owner }} --password ${{ secrets.GITHUB_TOKEN }} ghcr.io + + - name: Publish Image + id: publish-image + run: | + IMAGE_NAME=ghcr.io/${{ github.repository_owner }}/podman-desktop-extension-bootc + IMAGE_WITH_TAG=${IMAGE_NAME}:${{ steps.TAG_UTIL.outputs.bootcExtensionVersion }} + IMAGE_LATEST=${IMAGE_NAME}:latest + podman build -t $IMAGE_WITH_TAG . + podman push $IMAGE_WITH_TAG + podman tag $IMAGE_WITH_TAG $IMAGE_LATEST + podman push $IMAGE_LATEST diff --git a/podman-desktop-extension/.gitignore b/podman-desktop-extension/.gitignore new file mode 100644 index 000000000..59820c6c2 --- /dev/null +++ b/podman-desktop-extension/.gitignore @@ -0,0 +1,7 @@ +node_modules +.DS_Store +dist +.eslintcache +**/coverage +.idea +output diff --git a/podman-desktop-extension/.prettierrc b/podman-desktop-extension/.prettierrc new file mode 100644 index 000000000..f237f8b06 --- /dev/null +++ b/podman-desktop-extension/.prettierrc @@ -0,0 +1,12 @@ +{ + "svelteSortOrder" : "options-styles-scripts-markup", + "svelteStrictMode": true, + "svelteAllowShorthand": false, + "svelteIndentScriptAndStyle": false, + "bracketSameLine": true, + "singleQuote": true, + "arrowParens": "avoid", + "printWidth": 120, + "trailingComma": "all", + "plugins": ["prettier-plugin-svelte"] +} diff --git a/podman-desktop-extension/.yarnrc b/podman-desktop-extension/.yarnrc new file mode 100644 index 000000000..123ac74a0 --- /dev/null +++ b/podman-desktop-extension/.yarnrc @@ -0,0 +1 @@ +ignore-engines true diff --git a/podman-desktop-extension/CODEOWNERS b/podman-desktop-extension/CODEOWNERS new file mode 100644 index 000000000..eadd9ffee --- /dev/null +++ b/podman-desktop-extension/CODEOWNERS @@ -0,0 +1,2 @@ +# Default Owners +* @streamshub/ui diff --git a/podman-desktop-extension/CONTRIBUTING.md b/podman-desktop-extension/CONTRIBUTING.md new file mode 100644 index 000000000..22d4a43c8 --- /dev/null +++ b/podman-desktop-extension/CONTRIBUTING.md @@ -0,0 +1,32 @@ +# Contributing + +You can use `yarn watch --extension-folder` from the Podman Desktop directory to automatically rebuild and test the streamshub extension: + +```sh +git clone https://github.com/containers/podman-desktop +git clone https://github.com/containers/podman-desktop-extension-streamshub +cd podman-desktop +yarn watch --extension-folder ../podman-desktop-extension-streamshub/packages/backend +``` + +### Testing & Developing + +Workflow for developing: + +```sh +# Bootc root folder: +yarn watch + +# In a separate terminal in the Podman Desktop folder: +yarn watch --extension-folder ../podman-desktop-extension-streamshub/packages/backend +``` + +Workflow for testing and validation checking before PR submission: + +```sh +# Tests +yarn test + +# Formatting, linting and typecheck +yarn format:fix && yarn lint:fix && yarn typecheck +``` diff --git a/podman-desktop-extension/Containerfile b/podman-desktop-extension/Containerfile new file mode 100644 index 000000000..872d11241 --- /dev/null +++ b/podman-desktop-extension/Containerfile @@ -0,0 +1,34 @@ +# +# Copyright (C) 2024 Red Hat, Inc. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# SPDX-License-Identifier: Apache-2.0 + +FROM scratch as builder +COPY packages/backend/dist/ /extension/dist +COPY packages/backend/package.json /extension/ +COPY packages/backend/media/ /extension/media +COPY LICENSE /extension/ +COPY packages/backend/icon.png /extension/ +COPY packages/backend/bootable.woff2 /extension/ +COPY README.md /extension/ + +FROM scratch + +LABEL org.opencontainers.image.title="Streamshub Extension" \ + org.opencontainers.image.description="Podman Desktop extension for Streamshub, a console to navigate your Strimzi clusters" \ + org.opencontainers.image.vendor="Red Hat" \ + io.podman-desktop.api.version=">= 1.10.0" + +COPY --from=builder /extension /extension diff --git a/podman-desktop-extension/LICENSE b/podman-desktop-extension/LICENSE new file mode 100644 index 000000000..261eeb9e9 --- /dev/null +++ b/podman-desktop-extension/LICENSE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + + 1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + + 2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + + 3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + + 4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + + 5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + + 6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + + 7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + + 8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + + 9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + + END OF TERMS AND CONDITIONS + + APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + + Copyright [yyyy] [name of copyright owner] + + Licensed under the Apache License, Version 2.0 (the "License"); + you may not use this file except in compliance with the License. + You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. diff --git a/podman-desktop-extension/README.md b/podman-desktop-extension/README.md new file mode 100644 index 000000000..e69de29bb diff --git a/podman-desktop-extension/__mocks__/@podman-desktop/api.js b/podman-desktop-extension/__mocks__/@podman-desktop/api.js new file mode 100644 index 000000000..1fb06f662 --- /dev/null +++ b/podman-desktop-extension/__mocks__/@podman-desktop/api.js @@ -0,0 +1,24 @@ +/********************************************************************** + * Copyright (C) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +/** + * Mock the extension API for vitest. + * This file is referenced from vitest.config.js file. + */ +const plugin = {}; +module.exports = plugin; diff --git a/podman-desktop-extension/docs/img/build_container.gif b/podman-desktop-extension/docs/img/build_container.gif new file mode 100644 index 000000000..02197429e Binary files /dev/null and b/podman-desktop-extension/docs/img/build_container.gif differ diff --git a/podman-desktop-extension/docs/img/install_extension.gif b/podman-desktop-extension/docs/img/install_extension.gif new file mode 100644 index 000000000..af1f23a0f Binary files /dev/null and b/podman-desktop-extension/docs/img/install_extension.gif differ diff --git a/podman-desktop-extension/docs/img/launch_vm.gif b/podman-desktop-extension/docs/img/launch_vm.gif new file mode 100644 index 000000000..99c7adcba Binary files /dev/null and b/podman-desktop-extension/docs/img/launch_vm.gif differ diff --git a/podman-desktop-extension/docs/img/logo.png b/podman-desktop-extension/docs/img/logo.png new file mode 100644 index 000000000..80e763f89 Binary files /dev/null and b/podman-desktop-extension/docs/img/logo.png differ diff --git a/podman-desktop-extension/docs/img/preferences.png b/podman-desktop-extension/docs/img/preferences.png new file mode 100644 index 000000000..3733814ca Binary files /dev/null and b/podman-desktop-extension/docs/img/preferences.png differ diff --git a/podman-desktop-extension/docs/img/press_build.gif b/podman-desktop-extension/docs/img/press_build.gif new file mode 100644 index 000000000..8da971f62 Binary files /dev/null and b/podman-desktop-extension/docs/img/press_build.gif differ diff --git a/podman-desktop-extension/docs/img/push_container.gif b/podman-desktop-extension/docs/img/push_container.gif new file mode 100644 index 000000000..198affb37 Binary files /dev/null and b/podman-desktop-extension/docs/img/push_container.gif differ diff --git a/podman-desktop-extension/docs/img/rootful_setup.png b/podman-desktop-extension/docs/img/rootful_setup.png new file mode 100644 index 000000000..04bf90576 Binary files /dev/null and b/podman-desktop-extension/docs/img/rootful_setup.png differ diff --git a/podman-desktop-extension/docs/img/watch_logs.gif b/podman-desktop-extension/docs/img/watch_logs.gif new file mode 100644 index 000000000..d4a8eacd7 Binary files /dev/null and b/podman-desktop-extension/docs/img/watch_logs.gif differ diff --git a/podman-desktop-extension/docs/img/within_container.gif b/podman-desktop-extension/docs/img/within_container.gif new file mode 100644 index 000000000..691d78029 Binary files /dev/null and b/podman-desktop-extension/docs/img/within_container.gif differ diff --git a/podman-desktop-extension/docs/vm_guide.md b/podman-desktop-extension/docs/vm_guide.md new file mode 100644 index 000000000..64fa3522e --- /dev/null +++ b/podman-desktop-extension/docs/vm_guide.md @@ -0,0 +1,126 @@ +# Disk Image Guide + +## Introduction + +Below is information on how you can deploy your image after building. + +There are **many** solutions to deploy a virtual machine image and this document does not encompass all of them. + +## General Solutions + +* `qcow`: QEMU is the primary software that utilizes both the QCOW and QCOW2 formats. These formats allow you to create, manage, and run virtual machines with features like better performance and snapshot capabilities. [QEMU](https://www.qemu.org/). +* `raw`: The raw image format is widely supported across many virtualization tools and cloud server providers. Software like KVM, VMware, and cloud platforms including AWS and Azure can utilize raw images. Libvirt, often used with KVM, also supports raw images extensively. [Libvirt](https://libvirt.org/). +* `iso`: BalenaEtcher is recommended for writing ISO files to storage devices to create bootable media. It's user-friendly and cross-platform. [Download balenaEtcher](https://www.balena.io/etcher/). +* `vmdk`: VMware Workstation and VMware ESXi are two prominent platforms that support the VMDK format. They provide comprehensive tools for running and managing virtual machines. [VMware Workstation](https://www.vmware.com/products/workstation-pro.html), [VMware ESXi](https://www.vmware.com/products/esxi-and-esx.html). +* `ami`: Amazon EC2 uses the AMI format to launch new virtual servers. You can manage AMIs using Amazon's own tools like AWS Management Console. [Amazon EC2](https://aws.amazon.com/ec2/). + +## Recommended Development & Testing + +## Development on macOS (Silicon) + +### ARM64 (qemu) + +[qemu](https://www.qemu.org/) which emulates the architecture. + +**Installation:** + +``` +brew install qemu +``` + +**Usage:** + +**Important note:** Assuming you are running the example application, the command will port forward local port 8080 to 80. This can be changed in the below `qemu` command. + +1. Build a RAW image +2. Run the following command: +```sh +# Change to your VM image location +export DISK_IMAGE=/Users/myusername/bootc/image/disk.raw + +# Run the qemu command +# note the 8080:80 port forwarding +qemu-system-aarch64 \ + -m 8G \ + -M virt \ + -accel hvf \ + -cpu host \ + -smp 4 \ + -serial mon:stdio \ + -nographic \ + -netdev user,id=usernet,hostfwd=tcp::8080-:80 \ + -device virtio-net,netdev=usernet \ + -drive file=/opt/homebrew/share/qemu/edk2-aarch64-code.fd,format=raw,if=pflash,readonly=on \ + -drive file=$DISK_IMAGE,if=virtio,cache=writethrough,format=raw +``` +3. `curl` your local port to check VM access `curl localhost:8080` +4. To exit the terminal, type: `Ctrl+a` then `x` + +### ARM64 (vfkit) + +[vfkit](https://github.com/crc-org/vfkit) which uses the native Apple hypervisor framework. + +NOTE: This will only run NATIVE architecture images. Your image must use the ARM64 output. + +**Installation:** + +``` +brew tap cfergeau/crc +brew install vfkit +``` + +**Usage:** + +1. Build a RAW image +2. Run the following command: +```sh +# Change to your VM image location +export DISK_IMAGE=/Users/myusername/bootc/image/disk.raw + +# Launch VFkit +vfkit --cpus 2 --memory 2048 \ + --bootloader efi,variable-store=./efi-variable-store,create \ + --device virtio-blk,path=$DISK_IMAGE \ + --device virtio-serial,stdio \ + --device virtio-net,nat,mac=72:20:43:d4:38:62 \ + --device virtio-rng \ + --device virtio-input,keyboard \ + --device virtio-input,pointing \ + --device virtio-gpu,width=1920,height=1080 \ + --gui +``` + + +### x86_64 / AMD64 (qemu) + +[qemu](https://www.qemu.org/) which emulates the architecture. + + +**Installation:** + +``` +brew install qemu +``` + +**Usage:** + +**Important note:** Assuming you are running the example application, the command will port forward local port 8080 to 80. This can be changed in the below `qemu` command. + +1. Build a RAW image +2. Run the following command: +```sh +# Change to your VM image location +export DISK_IMAGE=/Users/myusername/bootc/image/disk.raw + +# Run the qemu command +# note the 8080:80 port forwarding +qemu-system-x86_64 \ + -m 8G \ + -cpu Broadwell-v4 \ + -nographic \ + -netdev user,id=usernet,hostfwd=tcp::8080-:80 \ + -device virtio-net,netdev=usernet \ + -snapshot $DISK_IMAGE +``` +3. `curl` your local port to check VM access `curl localhost:8080` +4. To exit the terminal, type: `Ctrl+a` then `x` \ No newline at end of file diff --git a/podman-desktop-extension/package.json b/podman-desktop-extension/package.json new file mode 100644 index 000000000..84e0e0a3f --- /dev/null +++ b/podman-desktop-extension/package.json @@ -0,0 +1,62 @@ +{ + "name": "streamshub", + "displayName": "Streamshub", + "description": "Streamshub helps you navigate and work with your Strimzi clusters", + "version": "0.0.1-next", + "icon": "icon.png", + "publisher": "redhat", + "private": true, + "engines": { + "node": ">=18.12.0", + "npm": ">=8.19.2" + }, + "scripts": { + "build": "concurrently \"yarn --cwd packages/frontend build\" \"yarn --cwd packages/backend build\"", + "watch": "concurrently \"yarn --cwd packages/frontend watch\" \"yarn --cwd packages/backend watch\"", + "format:check": "prettier --check \"**/src/**/*.{ts,svelte}\"", + "format:fix": "prettier --write \"**/src/**/*.{ts,svelte}\"", + "lint:check": "eslint . --ext js,ts,tsx", + "lint:fix": "eslint . --fix --ext js,ts,tsx", + "svelte:check": "svelte-check", + "test:backend": "vitest run -r packages/backend --passWithNoTests --coverage", + "test:frontend": "vitest run -r packages/frontend --passWithNoTests --coverage", + "test:shared": "vitest run -r packages/shared --passWithNoTests --coverage", + "test": "npm run test:backend && npm run test:shared && npm run test:frontend", + "test:e2e": "cd tests/playwright && npm run test:e2e", + "typecheck:shared": "tsc --noEmit --project packages/shared", + "typecheck:frontend": "tsc --noEmit --project packages/frontend", + "typecheck:backend": "tsc --noEmit --project packages/backend", + "typecheck": "npm run typecheck:shared && npm run typecheck:frontend && npm run typecheck:backend" + }, + "devDependencies": { + "@typescript-eslint/eslint-plugin": "^7.12.0", + "@typescript-eslint/parser": "^6.21.0", + "@vitest/coverage-v8": "^1.6.0", + "autoprefixer": "^10.4.17", + "concurrently": "^8.2.2", + "eslint": "^8.56.0", + "eslint-import-resolver-custom-alias": "^1.3.2", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-etc": "^2.0.3", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-no-null": "^1.0.2", + "eslint-plugin-redundant-undefined": "^1.0.0", + "eslint-plugin-sonarjs": "^0.25.1", + "prettier": "^3.3.1", + "prettier-plugin-svelte": "^3.2.4", + "svelte": "^4.2.18", + "svelte-check": "^3.8.0", + "typescript": "5.4.5", + "vite": "^5.2.12", + "vitest": "^1.6.0" + }, + "workspaces": { + "packages": [ + "packages/*", + "tests/*" + ] + }, + "dependencies": { + "js-yaml": "^4.1.0" + } +} diff --git a/podman-desktop-extension/packages/backend/.editorconfig b/podman-desktop-extension/packages/backend/.editorconfig new file mode 100644 index 000000000..872069e8b --- /dev/null +++ b/podman-desktop-extension/packages/backend/.editorconfig @@ -0,0 +1,18 @@ +# EditorConfig is awesome: http://EditorConfig.org + +# https://github.com/jokeyrhyme/standard-editorconfig + +# top-most EditorConfig file +root = true + +# defaults +[*] +charset = utf-8 +end_of_line = lf +insert_final_newline = true +trim_trailing_whitespace = true +indent_size = 2 +indent_style = space + +[*.md] +trim_trailing_whitespace = false diff --git a/podman-desktop-extension/packages/backend/.gitignore b/podman-desktop-extension/packages/backend/.gitignore new file mode 100644 index 000000000..521c523f7 --- /dev/null +++ b/podman-desktop-extension/packages/backend/.gitignore @@ -0,0 +1,6 @@ +node_modules +.DS_Store +dist +.eslintcache +**/coverage +media diff --git a/podman-desktop-extension/packages/backend/bootable.woff2 b/podman-desktop-extension/packages/backend/bootable.woff2 new file mode 100644 index 000000000..2e15668c9 Binary files /dev/null and b/podman-desktop-extension/packages/backend/bootable.woff2 differ diff --git a/podman-desktop-extension/packages/backend/icon.png b/podman-desktop-extension/packages/backend/icon.png new file mode 100644 index 000000000..879addb33 Binary files /dev/null and b/podman-desktop-extension/packages/backend/icon.png differ diff --git a/podman-desktop-extension/packages/backend/package.json b/podman-desktop-extension/packages/backend/package.json new file mode 100644 index 000000000..9de222f7d --- /dev/null +++ b/podman-desktop-extension/packages/backend/package.json @@ -0,0 +1,101 @@ +{ + "name": "streamshub", + "displayName": "Streamshub", + "description": "Streamshub helps you navigate and work with your Strimzi clusters", + "version": "0.0.1-next", + "icon": "icon.png", + "publisher": "redhat", + "license": "Apache-2.0", + "engines": { + "podman-desktop": ">=1.10.0" + }, + "main": "./dist/extension.js", + "contributes": { + "menus": { + "dashboard/image": [ + { + "command": "streamshub.console.open", + "title": "Open Streamshub console", + "when": "streamshub.component in imageLabelKeys", + "icon": "${streamshub-icon}" + } + ] + }, + "commands": [ + { + "command": "streamshub.console.open", + "title": "Build streamshub disk image" + } + ], + "icons": { + "streamshub-icon": { + "description": "streamshub icon", + "default": { + "fontPath": "streamshub.woff2", + "fontCharacter": "\\0041" + } + } + }, + "views": { + "icons/componentsList": [ + { + "when": "io.streamshub.console.container in componentLabelKeys", + "icon": "${streamshub-icon}" + } + ], + "icons/image": [ + { + "when": "io.streamshub.console.container in componentLabelKeys", + "icon": "${streamshub-icon}" + } + ], + "badges/image": [ + { + "when": "io.streamshub.console.container in componentLabelKeys", + "badge": { + "label": "streamshub", + "color": { + "dark": "bg-sky-300", + "light": "bg-sky-300" + } + } + } + ] + } + }, + "scripts": { + "build": "vite build", + "test": "vitest run --coverage", + "test:watch": "vitest watch --coverage", + "format:check": "prettier --check \"src/**/*.ts\"", + "format:fix": "prettier --write \"src/**/*.ts\"", + "lint:check": "eslint . --ext js,ts,tsx", + "lint:fix": "eslint . --fix --ext js,ts,tsx", + "watch": "vite --mode development build -w" + }, + "devDependencies": { + "@podman-desktop/api": "1.10.3", + "@types/node": "^20", + "@typescript-eslint/eslint-plugin": "^7.12.0", + "@typescript-eslint/parser": "^6.16.0", + "@vitest/coverage-v8": "^1.6.0", + "eslint": "^8.56.0", + "eslint-import-resolver-custom-alias": "^1.3.2", + "eslint-import-resolver-typescript": "^3.6.1", + "eslint-plugin-etc": "^2.0.3", + "eslint-plugin-import": "^2.29.1", + "eslint-plugin-no-null": "^1.0.2", + "eslint-plugin-redundant-undefined": "^1.0.0", + "eslint-plugin-sonarjs": "^0.25.1", + "prettier": "^3.3.1", + "typescript": "5.4.5", + "vite": "^5.2.12", + "vitest": "^1.6.0" + }, + "dependencies": { + "@kubernetes/client-node": "^0.21.0", + "@types/js-yaml": "^4.0.9", + "js-yaml": "^4.1.0", + "semver": "^7.6.2" + } +} diff --git a/podman-desktop-extension/packages/backend/src/api-impl.ts b/podman-desktop-extension/packages/backend/src/api-impl.ts new file mode 100644 index 000000000..1560418de --- /dev/null +++ b/podman-desktop-extension/packages/backend/src/api-impl.ts @@ -0,0 +1,358 @@ +/********************************************************************** + * Copyright (C) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import { Messages } from '/@shared/src/messages/Messages'; +import type { + ConsoleCompose, + ConsoleConfig, + KubernetesCluster, + StreamshubConsoleInfo, +} from '/@shared/src/models/streamshub'; +import type { StreamshubApi } from '/@shared/src/StreamshubApi'; +import * as podmanDesktopApi from '@podman-desktop/api'; +import * as fs from 'node:fs/promises'; +import { telemetryLogger } from './extension'; +import { createAndStartConsole, startConsole, stopAndDeleteConsole, stopConsole } from './utils'; + +const CONTAINER_LABEL = 'io.streamshub.console.container'; + +export class StreamshubImpl implements StreamshubApi { + private webview: podmanDesktopApi.Webview; + + constructor( + private readonly extensionContext: podmanDesktopApi.ExtensionContext, + webview: podmanDesktopApi.Webview, + ) { + this.webview = webview; + } + + async listConsoles(): Promise { + console.group('listConsoles'); + const consoles: Record = {}; + const { storagePath } = this.extensionContext; + try { + const containers = await podmanDesktopApi.containerEngine.listContainers(); + + const consoleContainers = containers.filter( + container => + container.Labels['com.docker.compose.project'] !== undefined && + container.Labels[CONTAINER_LABEL] !== undefined, + ); + consoleContainers.forEach(container => { + const project = container.Labels['com.docker.compose.project']; + const workingDir = container.Labels['com.docker.compose.project.working_dir']; + const c: StreamshubConsoleInfo = consoles[project] ?? { + project, + managed: workingDir.startsWith(storagePath), + api: { + ports: [], + baseUrl: '', + }, + ui: { + ports: [], + url: '', + }, + }; + if (container.Labels[CONTAINER_LABEL] === 'api') { + c.api.ports = container.Ports; + c.api.baseUrl = `http://localhost:${c.api.ports.find(p => p.PublicPort)?.PublicPort}`; + c.api.status = + container.State === 'running' ? 'running' : container.State === 'exited' ? 'exited' : 'starting'; + } + if (container.Labels[CONTAINER_LABEL] === 'ui') { + c.ui.ports = container.Ports; + c.ui.url = `http://localhost:${c.ui.ports.find(p => p.PublicPort)?.PublicPort}`; + c.ui.status = + container.State === 'running' ? 'running' : container.State === 'exited' ? 'exited' : 'starting'; + } + console.log(c); + consoles[project] = c; + }); + + try { + (await fs.readdir(storagePath, { withFileTypes: true })) + .filter(f => f.isDirectory()) + .forEach(f => { + const project = f.name; + if (!consoles[project]) { + consoles[project] = { + project, + managed: true, + api: { + ports: [], + baseUrl: '', + status: 'exited', + }, + ui: { + ports: [], + url: '', + status: 'exited', + }, + }; + } + }); + } catch { + console.log('storagePath empty'); + } + console.log({ containers, consoleContainers, consoles }); + } catch (err) { + await podmanDesktopApi.window.showErrorMessage(`Error listing containers: ${err}`); + console.error('Error listing containers: ', err); + } finally { + console.groupEnd(); + } + return Object.values(consoles); + } + + async openLink(link: string): Promise { + console.log('openLink', link); + await podmanDesktopApi.env.openExternal(podmanDesktopApi.Uri.parse(link)); + } + + // Log an event to telemetry + async telemetryLogUsage(eventName: string, data?: Record): Promise { + telemetryLogger.logUsage(eventName, data); + } + + // Log an error to telemetry + async telemetryLogError(eventName: string, data?: Record): Promise { + telemetryLogger.logError(eventName, data); + } + + async createConsole(projectName: string, compose: ConsoleCompose, config: ConsoleConfig): Promise { + const { storagePath } = this.extensionContext; + console.log('createConsole', { projectName, compose, config, storagePath }); + await createAndStartConsole(storagePath, projectName, compose, config); + } + + async startConsole(projectName: string): Promise { + const { storagePath } = this.extensionContext; + console.log('startConsole', { storagePath, projectName }); + await startConsole(storagePath, projectName); + } + + async stopConsole(projectName: string): Promise { + const { storagePath } = this.extensionContext; + console.log('stopConsole', { storagePath, projectName }); + await stopConsole(storagePath, projectName); + } + + async deleteConsole(projectName: string): Promise { + const { storagePath } = this.extensionContext; + console.log('deleteConsole', { storagePath, projectName }); + await stopAndDeleteConsole(storagePath, projectName); + } + + async getKubernetesClusters(): Promise<{ context: string; server: string; clusters: KubernetesCluster[] }> { + console.group('getKubernetesClusters'); + try { + const { stdout: context } = await podmanDesktopApi.process.exec('kubectl', ['config', 'current-context']); + console.log('getKubernetesClusters', { context }); + const server = context === 'minikube' ? await getServerFromMinikube() : await getServerFromKubectl(); + console.log('getKubernetesClusters', { server }); + const { stdout: kafkaCRsText } = await podmanDesktopApi.process.exec('kubectl', [ + 'get', + 'kafkas.kafka.strimzi.io', + '--all-namespaces', + '-o', + 'json', + ]); + console.log('getKubernetesClusters', { kafkaCRsText }); + const kafkaCRs = JSON.parse(kafkaCRsText) as { + items: { + metadata: { + name: string; + namespace: string; + }; + spec: { + kafka: { + listeners: { + authentication?: { + type: string; + }; + tls: true; + name: string; + }[]; + }; + }; + status: { + listeners: { + name: string; + bootstrapServers: string; + }[]; + }; + }[]; + }; + const clusters = await Promise.all( + kafkaCRs.items.map>(async i => { + const jaasConfigurations = await getNamespaceJaasConfigurations(i.metadata.namespace); + const token = await getToken(i.metadata.namespace); + return { + name: i.metadata.name, + namespace: i.metadata.namespace, + listeners: i.status.listeners.map(l => ({ + ...l, + ...(i.spec.kafka.listeners.find(sl => l.name === sl.name) ?? {}), + })), + jaasConfigurations: jaasConfigurations[i.metadata.name], + token, + }; + }), + ); + console.log('getKubernetesClusters', { clusters }); + return { + context, + server, + clusters, + }; + } catch (e) { + console.error(e); + throw e; + } finally { + console.groupEnd(); + } + } + + async containerChanges() { + console.log('containerChanges'); + return this.notify(Messages.MSG_CONTAINERS_UPDATE); + } + + // The API does not allow callbacks through the RPC, so instead + // we send "notify" messages to the frontend to trigger a refresh + // this method is internal and meant to be used by the API implementation + protected async notify(msg: string, body?: unknown): Promise { + await this.webview.postMessage({ + id: msg, + // Must pass in an empty body to satisfy the type system, if it is undefined, this fails. + body: body ?? '', + }); + } +} + +async function getServerFromKubectl() { + const { stdout: serverRaw } = await podmanDesktopApi.process.exec('kubectl', [ + 'config', + 'view', + '--minify', + '-o', + "jsonpath='{.clusters[0].cluster.server}'", + ]); + return serverRaw.replaceAll("'", ''); +} + +async function getServerFromMinikube() { + const { stdout: server } = await podmanDesktopApi.process.exec('minikube', ['ip']); + return `https://${server}:8443`; +} + +async function getToken(namespace: string): Promise { + console.group('getToken'); + try { + const { stdout: tokenRaw } = await podmanDesktopApi.process.exec('kubectl', [ + 'describe', + 'secret', + 'default-token', + '-n', + namespace, + ]); + + const lines = tokenRaw.split('\n').filter(line => line.startsWith('token')); + + // Step 2: cut -f2 -d':' + const fields = lines.map(line => line.split(':')[1]); + + // Step 3: tr -d " " + return fields.map(field => field.replace(/\s/g, '')).join('\n'); + } catch { + const { stdout: token } = await podmanDesktopApi.process.exec('kubectl', [ + 'create', + 'token', + 'console-server', + '-n', + namespace, + `--duration=${365 * 24}h`, + ]); + return token; + } finally { + console.groupEnd(); + } +} + +async function getNamespaceJaasConfigurations(namespace: string): Promise> { + console.group('getNamespaceJaasConfigurations'); + try { + const { stdout: usersRaw } = await podmanDesktopApi.process.exec('kubectl', [ + 'get', + 'kafkausers', + '-n', + namespace, + '-o', + 'json', + ]); + const users = JSON.parse(usersRaw) as { + items: { + metadata: { + labels: { + 'strimzi.io/cluster': string; + }; + }; + status: { + username: string; + secret: string; + }; + }[]; + }; + const usersList = users.items.map(u => u.status.username); + const { stdout: secretsRaw } = await podmanDesktopApi.process.exec('kubectl', [ + 'get', + 'secrets', + '-n', + namespace, + '-o', + 'json', + ...usersList, + ]); + type Secret = { + data: { + 'sasl.jaas.config': string; + }; + metadata: { + name: string; + }; + }; + type Secrets = { + items: Secret[]; + }; + const secretsObj = JSON.parse(secretsRaw) as Secrets | Secret; + const secrets = 'items' in secretsObj ? secretsObj : { items: [secretsObj] }; + console.log('secrets', secrets); + const jaasConfigurations: Record = Object.fromEntries( + users.items.map(u => [ + u.metadata.labels['strimzi.io/cluster'], + secrets.items.filter(s => s.metadata.name === u.status.secret).map(s => atob(s.data['sasl.jaas.config'])), + ]), + ); + return jaasConfigurations; + } catch (e) { + console.error('getNamespaceJaasConfigurations', e); + } finally { + console.groupEnd(); + } + return {}; +} diff --git a/podman-desktop-extension/packages/backend/src/extension.spec.ts b/podman-desktop-extension/packages/backend/src/extension.spec.ts new file mode 100644 index 000000000..c56027fae --- /dev/null +++ b/podman-desktop-extension/packages/backend/src/extension.spec.ts @@ -0,0 +1,176 @@ +/********************************************************************** + * Copyright (C) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import { afterEach, beforeEach, expect, test, vi, describe } from 'vitest'; +import * as podmanDesktopApi from '@podman-desktop/api'; +import { activate, deactivate, openConsolePage } from './extension'; +import * as fs from 'node:fs'; +import os from 'node:os'; + +/// mock console.log +const originalConsoleLog = console.log; + +const mocks = vi.hoisted(() => ({ + logUsageMock: vi.fn(), + logErrorMock: vi.fn(), + consoleLogMock: vi.fn(), + consoleWarnMock: vi.fn(), +})); + +vi.mock('../package.json', () => ({ + engines: { + 'podman-desktop': '>=1.0.0', + }, +})); + +vi.mock('@podman-desktop/api', async () => { + return { + version: '1.8.0', + env: { + createTelemetryLogger: () => ({ + logUsage: mocks.logUsageMock, + logError: mocks.logErrorMock, + }), + }, + commands: { + registerCommand: vi.fn(), + }, + Uri: class { + static joinPath = () => ({ fsPath: '.' }); + }, + window: { + createWebviewPanel: () => ({ + webview: { + html: '', + onDidReceiveMessage: vi.fn(), + postMessage: vi.fn(), + }, + onDidChangeViewState: vi.fn(), + }), + listWebviews: vi.fn().mockReturnValue([{ viewType: 'a' }, { id: 'test', viewType: 'bootc' }, { viewType: 'b' }]), + }, + navigation: { + navigateToWebview: vi.fn(), + }, + fs: { + createFileSystemWatcher: () => ({ + onDidCreate: vi.fn(), + onDidDelete: vi.fn(), + onDidChange: vi.fn(), + }), + }, + }; +}); + +vi.mock('../package.json', () => ({ + engines: { + 'podman-desktop': '>=1.0.0', + }, +})); + +beforeEach(() => { + vi.clearAllMocks(); + console.log = mocks.consoleLogMock; + console.warn = mocks.consoleWarnMock; +}); + +afterEach(() => { + console.log = originalConsoleLog; +}); + +const fakeContext = { + subscriptions: { + push: vi.fn(), + }, + storagePath: os.tmpdir(), +} as unknown as podmanDesktopApi.ExtensionContext; + +test('check activate', async () => { + vi.spyOn(fs.promises, 'readFile').mockImplementation(() => { + return Promise.resolve(''); + }); + await activate(fakeContext); + + expect(mocks.consoleLogMock).toBeCalledWith('starting bootc extension'); + expect(mocks.logUsageMock).toHaveBeenCalled(); +}); + +describe('version checker', () => { + test('incompatible version', async () => { + (podmanDesktopApi.version as string) = '0.7.0'; + await expect(async () => { + await activate(fakeContext); + }).rejects.toThrowError('Extension is not compatible with Podman Desktop version below 1.0.0 (Current 0.7.0).'); + + // expect the error to be logged + expect(mocks.logErrorMock).toBeCalledWith('start.incompatible', { + version: '0.7.0', + message: 'error activating extension on version below 1.0.0', + }); + }); + + test('next version', async () => { + (podmanDesktopApi.version as string) = '1.0.1-next'; + await activate(fakeContext); + + expect(mocks.logErrorMock).not.toHaveBeenCalled(); + }); + + test('nightlies version', async () => { + (podmanDesktopApi.version as string) = 'v0.0.202404030805-3cb4544'; + await activate(fakeContext); + + expect(mocks.logErrorMock).not.toHaveBeenCalled(); + expect(mocks.consoleWarnMock).toHaveBeenCalledWith('nightlies builds are not subject to version verification.'); + }); + + test('invalid version', async () => { + (podmanDesktopApi.version as string | undefined) = undefined; + await expect(async () => { + await activate(fakeContext); + }).rejects.toThrowError('Extension is not compatible with Podman Desktop version below 1.0.0 (Current unknown).'); + + // expect the activate method to be called on the studio class + expect(mocks.logErrorMock).toBeCalledWith('start.incompatible', { + version: 'unknown', + message: 'error activating extension on version below 1.0.0', + }); + }); +}); + +test('check deactivate', async () => { + await deactivate(); + + expect(mocks.consoleLogMock).toBeCalledWith('stopping bootc extension'); +}); + +test('check command triggers webview and redirects', async () => { + const postMessageMock = vi.fn(); + const panel = { + webview: { + postMessage: postMessageMock, + }, + } as unknown as podmanDesktopApi.WebviewPanel; + + const image = { name: 'build', tag: 'latest' }; + + await openConsolePage(panel, image); + + expect(podmanDesktopApi.navigation.navigateToWebview).toHaveBeenCalled(); + expect(postMessageMock).toHaveBeenCalledWith({ body: 'build/latest', id: 'navigate-build' }); +}); diff --git a/podman-desktop-extension/packages/backend/src/extension.ts b/podman-desktop-extension/packages/backend/src/extension.ts new file mode 100644 index 000000000..897db6176 --- /dev/null +++ b/podman-desktop-extension/packages/backend/src/extension.ts @@ -0,0 +1,172 @@ +/********************************************************************** + * Copyright (C) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import { RpcExtension } from '/@shared/src/messages/MessageProxy'; +import { Messages } from '/@shared/src/messages/Messages'; +import type { ExtensionContext, WebviewPanel } from '@podman-desktop/api'; +import * as extensionApi from '@podman-desktop/api'; +import fs from 'node:fs'; +import { coerce, minVersion, satisfies } from 'semver'; +import { engines } from '../package.json'; +import { StreamshubImpl } from './api-impl'; + +export const telemetryLogger = extensionApi.env.createTelemetryLogger(); +let panel: WebviewPanel; + +export async function activate(extensionContext: ExtensionContext): Promise { + console.log('starting streamshub extension'); + + // Ensure version is above the minimum Podman Desktop version required + const version = extensionApi.version ?? 'unknown'; + if (!checkVersion(version)) { + const min = minVersion(engines['podman-desktop']); + telemetryLogger.logError('start.incompatible', { + version: version, + message: `error activating extension on version below ${min?.version}`, + }); + throw new Error( + `Extension is not compatible with Podman Desktop version below ${min?.version} (Current ${version}).`, + ); + } + + telemetryLogger.logUsage('start'); + + if (panel) { + console.log('existing panel, do cleanup'); + panel.dispose(); + } + console.log('creating panel'); + panel = extensionApi.window.createWebviewPanel('streamshub', 'Streamshub', { + localResourceRoots: [extensionApi.Uri.joinPath(extensionContext.extensionUri, 'media')], + }); + extensionContext.subscriptions.push(panel); + + const indexHtmlUri = extensionApi.Uri.joinPath(extensionContext.extensionUri, 'media', 'index.html'); + const indexHtmlPath = indexHtmlUri.fsPath; + let indexHtml = await fs.promises.readFile(indexHtmlPath, 'utf8'); + + // replace links with webView Uri links + // in the content replace src with webview.asWebviewUri + const scriptLink = indexHtml.match(//g); + if (scriptLink) { + scriptLink.forEach(link => { + const src = link.match(/src="(.*?)"/); + if (src) { + const webviewSrc = panel.webview.asWebviewUri( + extensionApi.Uri.joinPath(extensionContext.extensionUri, 'media', src[1]), + ); + indexHtml = indexHtml.replace(src[1], webviewSrc.toString()); + } + }); + } + + // and now replace for css file as well + const cssLink = indexHtml.match(//g); + if (cssLink) { + cssLink.forEach(link => { + const href = link.match(/href="(.*?)"/); + if (href) { + const webviewHref = panel.webview.asWebviewUri( + extensionApi.Uri.joinPath(extensionContext.extensionUri, 'media', href[1]), + ); + indexHtml = indexHtml.replace(href[1], webviewHref.toString()); + } + }); + } + + // Update the html + console.log('updating webview content ' + indexHtml); + panel.webview.html = indexHtml; + + // Register the 'api' for the webview to communicate to the backend + const rpcExtension = new RpcExtension(panel.webview); + const streamshubApi = new StreamshubImpl(extensionContext, panel.webview); + rpcExtension.registerInstance(StreamshubImpl, streamshubApi); + + extensionContext.subscriptions.push( + extensionApi.commands.registerCommand('streamshub.open.console', async image => { + await openConsolePage(panel, image); + }), + ); + + let debounceTimeout: NodeJS.Timeout; + extensionContext.subscriptions.push( + extensionApi.containerEngine.onEvent(() => { + // cancel previous timeout + if (debounceTimeout) { + clearTimeout(debounceTimeout); + } + + // handle it after a while + debounceTimeout = setTimeout(() => { + void streamshubApi.containerChanges(); + }, 100); + }), + ); +} + +function checkVersion(version: string): boolean { + if (!version) { + return false; + } + + const current = coerce(version); + if (!current) { + return false; + } + + if (current.major === 0 && current.minor === 0) { + console.warn('nightlies builds are not subject to version verification.'); + return true; + } + + return satisfies(current, engines['podman-desktop']); +} + +export async function openConsolePage( + panel: extensionApi.WebviewPanel, + image: { name: string; tag: string }, +): Promise { + console.log('openConsolePage'); + // this should use webview reveal function in the future + const webviews = extensionApi.window.listWebviews(); + const bootcWebView = (await webviews).find(webview => webview.viewType === 'bootc'); + + if (!bootcWebView) { + console.error('Could not find bootc webview'); + return; + } + + await extensionApi.navigation.navigateToWebview(bootcWebView.id); + + // if we trigger immediately, the webview hasn't loaded yet and can't redirect + // if we trigger too slow, there's a visible flash as the homepage appears first + await new Promise(r => setTimeout(r, 100)); + + await panel.webview.postMessage({ + id: Messages.MSG_NAVIGATE_CONSOLE, + body: encodeURIComponent(image.name) + '/' + encodeURIComponent(image.tag), + }); +} + +export async function deactivate(): Promise { + console.log('stopping streamshub extension'); + if (panel) { + panel.dispose(); + } +} diff --git a/podman-desktop-extension/packages/backend/src/utils.ts b/podman-desktop-extension/packages/backend/src/utils.ts new file mode 100644 index 000000000..b9fec9b86 --- /dev/null +++ b/podman-desktop-extension/packages/backend/src/utils.ts @@ -0,0 +1,181 @@ +import type { ConsoleCompose, ConsoleConfig } from '/@shared/src/models/streamshub'; +import * as extensionApi from '@podman-desktop/api'; +import crypto from 'crypto'; +import yaml from 'js-yaml'; +import * as fs from 'node:fs/promises'; +import * as os from 'node:os'; +import * as path from 'node:path'; + +const CONSOLE_API_IMAGE = 'streamshub/console-api:latest'; +const CONSOLE_UI_IMAGE = 'streamshub/console-ui:latest'; +const COMPOSEYAML = 'compose.yaml'; +const CONFIGYAML = 'console-config.yaml'; + +function getProjectPath(storagePath: string, projectName: string) { + return path.join(storagePath, projectName); +} + +async function isProjectCreated(projectPath: string) { + console.log('isProjectCreated', { projectPath }); + // Check if the directory exists + try { + // Check if the directory exists + await fs.access(projectPath); + + // List of files to check + const filesToCheck = [COMPOSEYAML, CONFIGYAML]; + + // Check for each file in the directory + for (const fileName of filesToCheck) { + const filePath = path.join(projectPath, fileName); + await fs.access(filePath); + } + + return true; + } catch { + return false; + } +} + +async function createProject(projectPath: string) { + console.log('createProject', projectPath); + await fs.mkdir(projectPath, { recursive: true }); +} + +async function writeConfig(projectPath: string, config: ConsoleConfig) { + console.log('writeConfig', { projectPath, config }); + const configFile = path.join(projectPath, CONFIGYAML); + const configObj = { + kafka: { + clusters: config.clusters, + }, + }; + const yamlString = yaml.dump(configObj); + await fs.writeFile(configFile, yamlString); +} + +async function writeCompose(projectPath: string, compose: ConsoleCompose) { + console.log('writeCompose', { projectPath, compose }); + const composeFile = path.join(projectPath, COMPOSEYAML); + await fs.writeFile( + composeFile, + `--- +version: '3.9' + +services: + console-api: + image: ${compose.consoleApiImage ?? CONSOLE_API_IMAGE} + ports: + - :8080 + volumes: + - ${projectPath}/console-config.yaml:/deployments/console-config.yaml:z + environment: + CONSOLE_CONFIG_PATH: /deployments/console-config.yaml + QUARKUS_KUBERNETES_CLIENT_API_SERVER_URL: ${compose.consoleApiKubernetesApiServerUrl} + QUARKUS_KUBERNETES_CLIENT_TRUST_CERTS: "true" + QUARKUS_KUBERNETES_CLIENT_TOKEN: ${compose.consoleApiServiceAccountToken} + labels: + io.streamshub.console.container: api + + console-ui: + image: ${compose.consoleUiImage ?? CONSOLE_UI_IMAGE} + ports: + - :3000 + environment: + CONSOLE_METRICS_PROMETHEUS_URL: ${''} + NEXTAUTH_SECRET: ${crypto.randomBytes(32).toString('hex')} + NEXTAUTH_URL: http://localhost:3000 + BACKEND_URL: http://console-api:8080/ + labels: + io.streamshub.console.container: ui + + console-registry: + image: quay.io/apicurio/apicurio-registry-mem:2.6.1.Final + ports: + - :8080 + labels: + io.streamshub.console.container: registry + `, + ); +} + +async function composeUp(projectPath: string) { + console.log('composeUp', { projectPath }); + await extensionApi.process.exec(getPodmanCli(), ['compose', 'up'], { + cwd: projectPath, + }); +} + +async function composeDown(projectPath: string) { + console.log('composeDown', { projectPath }); + await extensionApi.process.exec(getPodmanCli(), ['compose', 'down'], { + cwd: projectPath, + }); +} + +async function deleteProject(projectPath: string) { + console.log('deleteProject', { projectPath }); + await fs.rm(projectPath, { recursive: true, force: true }); +} + +export async function createAndStartConsole( + storagePath: string, + projectName: string, + compose: ConsoleCompose, + config: ConsoleConfig, +) { + console.log('createAndStartConsole', { storagePath, projectName, compose, config }); + const projectPath = getProjectPath(storagePath, projectName); + if ((await isProjectCreated(projectPath)) === false) { + console.log("Project doesn't exist, creating"); + await createProject(projectPath); + await writeCompose(projectPath, compose); + await writeConfig(projectPath, config); + } + await composeUp(projectPath); +} + +export async function startConsole(storagePath: string, projectName: string) { + const projectPath = getProjectPath(storagePath, projectName); + await composeUp(projectPath); +} + +export async function stopConsole(storagePath: string, projectName: string) { + const projectPath = getProjectPath(storagePath, projectName); + await composeDown(projectPath); +} + +export async function stopAndDeleteConsole(storagePath: string, projectName: string) { + const projectPath = getProjectPath(storagePath, projectName); + await composeDown(projectPath); + await deleteProject(projectPath); +} + +// Below functions are borrowed from the podman extension +function getPodmanCli(): string { + const customBinaryPath = getCustomBinaryPath(); + if (customBinaryPath) { + return customBinaryPath; + } + + if (isWindows()) { + return 'podman.exe'; + } + return 'podman'; +} + +function getCustomBinaryPath(): string | undefined { + return extensionApi.configuration.getConfiguration('podman').get('binary.path'); +} + +const windows = os.platform() === 'win32'; + +export function isWindows(): boolean { + return windows; +} + +const linux = os.platform() === 'linux'; + +export function isLinux(): boolean { + return linux; +} diff --git a/podman-desktop-extension/packages/backend/tsconfig.json b/podman-desktop-extension/packages/backend/tsconfig.json new file mode 100644 index 000000000..709235852 --- /dev/null +++ b/podman-desktop-extension/packages/backend/tsconfig.json @@ -0,0 +1,32 @@ +{ + "compilerOptions": { + "strict":true, + "target": "esnext", + "module": "esnext", + "moduleResolution": "Node", + "resolveJsonModule": true, + "lib": [ + "ES2017", + "ES2021", + "webworker", + "dom", + ], + "sourceMap": true, + "outDir": "dist", + "allowSyntheticDefaultImports": true, + "skipLibCheck": true, + "types": [ + "node", + ], + "paths": { + "/@shared/*": ["../shared/*"] + } + }, + "include": [ + "src", + "types/*.d.ts", + "../../types/*.d.ts", + "../shared/*.ts", + "../shared/**/*.ts" + ], +} diff --git a/podman-desktop-extension/packages/backend/vite.config.js b/podman-desktop-extension/packages/backend/vite.config.js new file mode 100644 index 000000000..4fccc16c9 --- /dev/null +++ b/podman-desktop-extension/packages/backend/vite.config.js @@ -0,0 +1,60 @@ +/********************************************************************** + * Copyright (C) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import { join } from 'path'; +import { builtinModules } from 'module'; + +const PACKAGE_ROOT = __dirname; + +/** + * @type {import('vite').UserConfig} + * @see https://vitejs.dev/config/ + */ +const config = { + mode: process.env.MODE, + root: PACKAGE_ROOT, + envDir: process.cwd(), + resolve: { + alias: { + '/@/': join(PACKAGE_ROOT, 'src') + '/', + '/@gen/': join(PACKAGE_ROOT, 'src-generated') + '/', + '/@shared/': join(PACKAGE_ROOT, '../shared') + '/', + }, + }, + build: { + sourcemap: 'inline', + target: 'esnext', + outDir: 'dist', + assetsDir: '.', + minify: process.env.MODE === 'production' ? 'esbuild' : false, + lib: { + entry: 'src/extension.ts', + formats: ['cjs'], + }, + rollupOptions: { + external: ['@podman-desktop/api', ...builtinModules.flatMap(p => [p, `node:${p}`])], + output: { + entryFileNames: '[name].js', + }, + }, + emptyOutDir: true, + reportCompressedSize: false, + }, +}; + +export default config; diff --git a/podman-desktop-extension/packages/backend/vitest.config.js b/podman-desktop-extension/packages/backend/vitest.config.js new file mode 100644 index 000000000..b239adc8a --- /dev/null +++ b/podman-desktop-extension/packages/backend/vitest.config.js @@ -0,0 +1,42 @@ +/********************************************************************** + * Copyright (C) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import path from 'node:path'; +import { join } from 'path'; + +const PACKAGE_ROOT = __dirname; + +const config = { + test: { + include: ['**/*.{test,spec}.?(c|m)[jt]s?(x)', '../shared/**/*.{test,spec}.?(c|m)[jt]s?(x)'], + coverage: { + provider: 'v8', + reporter: ['lcov', 'text'], + }, +}, +resolve: { + alias: { + '@podman-desktop/api': path.resolve(__dirname, '__mocks__/@podman-desktop/api.js'), + '/@/': join(PACKAGE_ROOT, 'src') + '/', + '/@gen/': join(PACKAGE_ROOT, 'src-generated') + '/', + '/@shared/': join(PACKAGE_ROOT, '../shared') + '/', + }, + }, +}; + +export default config; diff --git a/podman-desktop-extension/packages/backend/yarn.lock b/podman-desktop-extension/packages/backend/yarn.lock new file mode 100644 index 000000000..2a2d852ab --- /dev/null +++ b/podman-desktop-extension/packages/backend/yarn.lock @@ -0,0 +1,2841 @@ +# THIS IS AN AUTOGENERATED FILE. DO NOT EDIT THIS FILE DIRECTLY. +# yarn lockfile v1 + + +"@aashutoshrathi/word-wrap@^1.2.3": + version "1.2.6" + resolved "https://registry.yarnpkg.com/@aashutoshrathi/word-wrap/-/word-wrap-1.2.6.tgz#bd9154aec9983f77b3a034ecaa015c2e4201f6cf" + integrity sha512-1Yjs2SvM8TflER/OD3cOjhWWOZb58A2t7wpE2S9XfBYTiIl+XFhQG2bjy4Pu1I+EAlCNUzRDYDdFwFYUKvXcIA== + +"@ampproject/remapping@^2.2.1": + version "2.2.1" + resolved "https://registry.yarnpkg.com/@ampproject/remapping/-/remapping-2.2.1.tgz#99e8e11851128b8702cd57c33684f1d0f260b630" + integrity sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg== + dependencies: + "@jridgewell/gen-mapping" "^0.3.0" + "@jridgewell/trace-mapping" "^0.3.9" + +"@babel/helper-string-parser@^7.23.4": + version "7.23.4" + resolved "https://registry.yarnpkg.com/@babel/helper-string-parser/-/helper-string-parser-7.23.4.tgz#9478c707febcbbe1ddb38a3d91a2e054ae622d83" + integrity sha512-803gmbQdqwdf4olxrX4AJyFBV/RTr3rSmOj0rKwesmzlfhYNDEs+/iOcznzpNWlJlIlTJC2QfPFcHB6DlzdVLQ== + +"@babel/helper-validator-identifier@^7.22.20": + version "7.22.20" + resolved "https://registry.yarnpkg.com/@babel/helper-validator-identifier/-/helper-validator-identifier-7.22.20.tgz#c4ae002c61d2879e724581d96665583dbc1dc0e0" + integrity sha512-Y4OZ+ytlatR8AI+8KZfKuL5urKp7qey08ha31L8b3BwewJAoJamTzyvxPR/5D+KkdJCGPq/+8TukHBlY10FX9A== + +"@babel/parser@^7.23.3": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/parser/-/parser-7.23.6.tgz#ba1c9e512bda72a47e285ae42aff9d2a635a9e3b" + integrity sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ== + +"@babel/types@^7.23.3": + version "7.23.6" + resolved "https://registry.yarnpkg.com/@babel/types/-/types-7.23.6.tgz#be33fdb151e1f5a56877d704492c240fc71c7ccd" + integrity sha512-+uarb83brBzPKN38NX1MkB6vb6+mwvR6amUulqAE7ccQw1pEl+bCia9TbdG1lsnFP7lZySvUn37CHyXQdfTwzg== + dependencies: + "@babel/helper-string-parser" "^7.23.4" + "@babel/helper-validator-identifier" "^7.22.20" + to-fast-properties "^2.0.0" + +"@bcoe/v8-coverage@^0.2.3": + version "0.2.3" + resolved "https://registry.yarnpkg.com/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz#75a2e8b51cb758a7553d6804a5932d7aace75c39" + integrity sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw== + +"@esbuild/aix-ppc64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/aix-ppc64/-/aix-ppc64-0.19.10.tgz#fb3922a0183d27446de00cf60d4f7baaadf98d84" + integrity sha512-Q+mk96KJ+FZ30h9fsJl+67IjNJm3x2eX+GBWGmocAKgzp27cowCOOqSdscX80s0SpdFXZnIv/+1xD1EctFx96Q== + +"@esbuild/android-arm64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm64/-/android-arm64-0.19.10.tgz#ef31015416dd79398082409b77aaaa2ade4d531a" + integrity sha512-1X4CClKhDgC3by7k8aOWZeBXQX8dHT5QAMCAQDArCLaYfkppoARvh0fit3X2Qs+MXDngKcHv6XXyQCpY0hkK1Q== + +"@esbuild/android-arm@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/android-arm/-/android-arm-0.19.10.tgz#1c23c7e75473aae9fb323be5d9db225142f47f52" + integrity sha512-7W0bK7qfkw1fc2viBfrtAEkDKHatYfHzr/jKAHNr9BvkYDXPcC6bodtm8AyLJNNuqClLNaeTLuwURt4PRT9d7w== + +"@esbuild/android-x64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/android-x64/-/android-x64-0.19.10.tgz#df6a4e6d6eb8da5595cfce16d4e3f6bc24464707" + integrity sha512-O/nO/g+/7NlitUxETkUv/IvADKuZXyH4BHf/g/7laqKC4i/7whLpB0gvpPc2zpF0q9Q6FXS3TS75QHac9MvVWw== + +"@esbuild/darwin-arm64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-arm64/-/darwin-arm64-0.19.10.tgz#8462a55db07c1b2fad61c8244ce04469ef1043be" + integrity sha512-YSRRs2zOpwypck+6GL3wGXx2gNP7DXzetmo5pHXLrY/VIMsS59yKfjPizQ4lLt5vEI80M41gjm2BxrGZ5U+VMA== + +"@esbuild/darwin-x64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/darwin-x64/-/darwin-x64-0.19.10.tgz#d1de20bfd41bb75b955ba86a6b1004539e8218c1" + integrity sha512-alfGtT+IEICKtNE54hbvPg13xGBe4GkVxyGWtzr+yHO7HIiRJppPDhOKq3zstTcVf8msXb/t4eavW3jCDpMSmA== + +"@esbuild/freebsd-arm64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-arm64/-/freebsd-arm64-0.19.10.tgz#16904879e34c53a2e039d1284695d2db3e664d57" + integrity sha512-dMtk1wc7FSH8CCkE854GyGuNKCewlh+7heYP/sclpOG6Cectzk14qdUIY5CrKDbkA/OczXq9WesqnPl09mj5dg== + +"@esbuild/freebsd-x64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/freebsd-x64/-/freebsd-x64-0.19.10.tgz#8ad9e5ca9786ca3f1ef1411bfd10b08dcd9d4cef" + integrity sha512-G5UPPspryHu1T3uX8WiOEUa6q6OlQh6gNl4CO4Iw5PS+Kg5bVggVFehzXBJY6X6RSOMS8iXDv2330VzaObm4Ag== + +"@esbuild/linux-arm64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm64/-/linux-arm64-0.19.10.tgz#d82cf2c590faece82d28bbf1cfbe36f22ae25bd2" + integrity sha512-QxaouHWZ+2KWEj7cGJmvTIHVALfhpGxo3WLmlYfJ+dA5fJB6lDEIg+oe/0//FuyVHuS3l79/wyBxbHr0NgtxJQ== + +"@esbuild/linux-arm@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/linux-arm/-/linux-arm-0.19.10.tgz#477b8e7c7bcd34369717b04dd9ee6972c84f4029" + integrity sha512-j6gUW5aAaPgD416Hk9FHxn27On28H4eVI9rJ4az7oCGTFW48+LcgNDBN+9f8rKZz7EEowo889CPKyeaD0iw9Kg== + +"@esbuild/linux-ia32@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ia32/-/linux-ia32-0.19.10.tgz#d55ff822cf5b0252a57112f86857ff23be6cab0e" + integrity sha512-4ub1YwXxYjj9h1UIZs2hYbnTZBtenPw5NfXCRgEkGb0b6OJ2gpkMvDqRDYIDRjRdWSe/TBiZltm3Y3Q8SN1xNg== + +"@esbuild/linux-loong64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/linux-loong64/-/linux-loong64-0.19.10.tgz#a9ad057d7e48d6c9f62ff50f6f208e331c4543c7" + integrity sha512-lo3I9k+mbEKoxtoIbM0yC/MZ1i2wM0cIeOejlVdZ3D86LAcFXFRdeuZmh91QJvUTW51bOK5W2BznGNIl4+mDaA== + +"@esbuild/linux-mips64el@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/linux-mips64el/-/linux-mips64el-0.19.10.tgz#b011a96924773d60ebab396fbd7a08de66668179" + integrity sha512-J4gH3zhHNbdZN0Bcr1QUGVNkHTdpijgx5VMxeetSk6ntdt+vR1DqGmHxQYHRmNb77tP6GVvD+K0NyO4xjd7y4A== + +"@esbuild/linux-ppc64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/linux-ppc64/-/linux-ppc64-0.19.10.tgz#5d8b59929c029811e473f2544790ea11d588d4dd" + integrity sha512-tgT/7u+QhV6ge8wFMzaklOY7KqiyitgT1AUHMApau32ZlvTB/+efeCtMk4eXS+uEymYK249JsoiklZN64xt6oQ== + +"@esbuild/linux-riscv64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/linux-riscv64/-/linux-riscv64-0.19.10.tgz#292b06978375b271bd8bc0a554e0822957508d22" + integrity sha512-0f/spw0PfBMZBNqtKe5FLzBDGo0SKZKvMl5PHYQr3+eiSscfJ96XEknCe+JoOayybWUFQbcJTrk946i3j9uYZA== + +"@esbuild/linux-s390x@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/linux-s390x/-/linux-s390x-0.19.10.tgz#d30af63530f8d4fa96930374c9dd0d62bf59e069" + integrity sha512-pZFe0OeskMHzHa9U38g+z8Yx5FNCLFtUnJtQMpwhS+r4S566aK2ci3t4NCP4tjt6d5j5uo4h7tExZMjeKoehAA== + +"@esbuild/linux-x64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/linux-x64/-/linux-x64-0.19.10.tgz#898c72eeb74d9f2fb43acf316125b475548b75ce" + integrity sha512-SpYNEqg/6pZYoc+1zLCjVOYvxfZVZj6w0KROZ3Fje/QrM3nfvT2llI+wmKSrWuX6wmZeTapbarvuNNK/qepSgA== + +"@esbuild/netbsd-x64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/netbsd-x64/-/netbsd-x64-0.19.10.tgz#fd473a5ae261b43eab6dad4dbd5a3155906e6c91" + integrity sha512-ACbZ0vXy9zksNArWlk2c38NdKg25+L9pr/mVaj9SUq6lHZu/35nx2xnQVRGLrC1KKQqJKRIB0q8GspiHI3J80Q== + +"@esbuild/openbsd-x64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/openbsd-x64/-/openbsd-x64-0.19.10.tgz#96eb8992e526717b5272321eaad3e21f3a608e46" + integrity sha512-PxcgvjdSjtgPMiPQrM3pwSaG4kGphP+bLSb+cihuP0LYdZv1epbAIecHVl5sD3npkfYBZ0ZnOjR878I7MdJDFg== + +"@esbuild/sunos-x64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/sunos-x64/-/sunos-x64-0.19.10.tgz#c16ee1c167f903eaaa6acf7372bee42d5a89c9bc" + integrity sha512-ZkIOtrRL8SEJjr+VHjmW0znkPs+oJXhlJbNwfI37rvgeMtk3sxOQevXPXjmAPZPigVTncvFqLMd+uV0IBSEzqA== + +"@esbuild/win32-arm64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/win32-arm64/-/win32-arm64-0.19.10.tgz#7e417d1971dbc7e469b4eceb6a5d1d667b5e3dcc" + integrity sha512-+Sa4oTDbpBfGpl3Hn3XiUe4f8TU2JF7aX8cOfqFYMMjXp6ma6NJDztl5FDG8Ezx0OjwGikIHw+iA54YLDNNVfw== + +"@esbuild/win32-ia32@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/win32-ia32/-/win32-ia32-0.19.10.tgz#2b52dfec6cd061ecb36171c13bae554888b439e5" + integrity sha512-EOGVLK1oWMBXgfttJdPHDTiivYSjX6jDNaATeNOaCOFEVcfMjtbx7WVQwPSE1eIfCp/CaSF2nSrDtzc4I9f8TQ== + +"@esbuild/win32-x64@0.19.10": + version "0.19.10" + resolved "https://registry.yarnpkg.com/@esbuild/win32-x64/-/win32-x64-0.19.10.tgz#bd123a74f243d2f3a1f046447bb9b363ee25d072" + integrity sha512-whqLG6Sc70AbU73fFYvuYzaE4MNMBIlR1Y/IrUeOXFrWHxBEjjbZaQ3IXIQS8wJdAzue2GwYZCjOrgrU1oUHoA== + +"@eslint-community/eslint-utils@^4.2.0", "@eslint-community/eslint-utils@^4.4.0": + version "4.4.0" + resolved "https://registry.yarnpkg.com/@eslint-community/eslint-utils/-/eslint-utils-4.4.0.tgz#a23514e8fb9af1269d5f7788aa556798d61c6b59" + integrity sha512-1/sA4dwrzBAyeUoQ6oxahHKmrZvsnLCg4RfxW3ZFGGmQkSNQPFNLV9CUEFQP1x9EYXHTo5p6xdhZM1Ne9p/AfA== + dependencies: + eslint-visitor-keys "^3.3.0" + +"@eslint-community/regexpp@^4.5.1", "@eslint-community/regexpp@^4.6.1": + version "4.10.0" + resolved "https://registry.yarnpkg.com/@eslint-community/regexpp/-/regexpp-4.10.0.tgz#548f6de556857c8bb73bbee70c35dc82a2e74d63" + integrity sha512-Cu96Sd2By9mCNTx2iyKOmq10v22jUVQv0lQnlGNy16oE9589yE+QADPbrMGCkA51cKZSg3Pu/aTJVTGfL/qjUA== + +"@eslint/eslintrc@^2.1.4": + version "2.1.4" + resolved "https://registry.yarnpkg.com/@eslint/eslintrc/-/eslintrc-2.1.4.tgz#388a269f0f25c1b6adc317b5a2c55714894c70ad" + integrity sha512-269Z39MS6wVJtsoUl10L60WdkhJVdPG24Q4eZTH3nnF6lpvSShEK3wQjDX9JRWAUPvPh7COouPpU9IrqaZFvtQ== + dependencies: + ajv "^6.12.4" + debug "^4.3.2" + espree "^9.6.0" + globals "^13.19.0" + ignore "^5.2.0" + import-fresh "^3.2.1" + js-yaml "^4.1.0" + minimatch "^3.1.2" + strip-json-comments "^3.1.1" + +"@eslint/js@8.56.0": + version "8.56.0" + resolved "https://registry.yarnpkg.com/@eslint/js/-/js-8.56.0.tgz#ef20350fec605a7f7035a01764731b2de0f3782b" + integrity sha512-gMsVel9D7f2HLkBma9VbtzZRehRogVRfbr++f06nL2vnCGCNlzOD+/MUov/F4p8myyAHspEhVobgjpX64q5m6A== + +"@humanwhocodes/config-array@^0.11.13": + version "0.11.13" + resolved "https://registry.yarnpkg.com/@humanwhocodes/config-array/-/config-array-0.11.13.tgz#075dc9684f40a531d9b26b0822153c1e832ee297" + integrity sha512-JSBDMiDKSzQVngfRjOdFXgFfklaXI4K9nLF49Auh21lmBWRLIK3+xTErTWD4KU54pb6coM6ESE7Awz/FNU3zgQ== + dependencies: + "@humanwhocodes/object-schema" "^2.0.1" + debug "^4.1.1" + minimatch "^3.0.5" + +"@humanwhocodes/module-importer@^1.0.1": + version "1.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz#af5b2691a22b44be847b0ca81641c5fb6ad0172c" + integrity sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA== + +"@humanwhocodes/object-schema@^2.0.1": + version "2.0.1" + resolved "https://registry.yarnpkg.com/@humanwhocodes/object-schema/-/object-schema-2.0.1.tgz#e5211452df060fa8522b55c7b3c0c4d1981cb044" + integrity sha512-dvuCeX5fC9dXgJn9t+X5atfmgQAzUOWqS1254Gh0m6i8wKd10ebXkfNKiRK+1GWi/yTvvLDHpoxLr0xxxeslWw== + +"@istanbuljs/schema@^0.1.2": + version "0.1.3" + resolved "https://registry.yarnpkg.com/@istanbuljs/schema/-/schema-0.1.3.tgz#e45e384e4b8ec16bce2fd903af78450f6bf7ec98" + integrity sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA== + +"@jest/schemas@^29.6.3": + version "29.6.3" + resolved "https://registry.yarnpkg.com/@jest/schemas/-/schemas-29.6.3.tgz#430b5ce8a4e0044a7e3819663305a7b3091c8e03" + integrity sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA== + dependencies: + "@sinclair/typebox" "^0.27.8" + +"@jridgewell/gen-mapping@^0.3.0": + version "0.3.3" + resolved "https://registry.yarnpkg.com/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz#7e02e6eb5df901aaedb08514203b096614024098" + integrity sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ== + dependencies: + "@jridgewell/set-array" "^1.0.1" + "@jridgewell/sourcemap-codec" "^1.4.10" + "@jridgewell/trace-mapping" "^0.3.9" + +"@jridgewell/resolve-uri@3.1.0": + version "3.1.0" + resolved "https://registry.yarnpkg.com/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz#2203b118c157721addfe69d47b70465463066d78" + integrity sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w== + +"@jridgewell/set-array@^1.0.1": + version "1.1.2" + resolved "https://registry.yarnpkg.com/@jridgewell/set-array/-/set-array-1.1.2.tgz#7c6cf998d6d20b914c0a55a91ae928ff25965e72" + integrity sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw== + +"@jridgewell/sourcemap-codec@1.4.14": + version "1.4.14" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz#add4c98d341472a289190b424efbdb096991bb24" + integrity sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw== + +"@jridgewell/sourcemap-codec@^1.4.10", "@jridgewell/sourcemap-codec@^1.4.15": + version "1.4.15" + resolved "https://registry.yarnpkg.com/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz#d7c6e6755c78567a951e04ab52ef0fd26de59f32" + integrity sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg== + +"@jridgewell/trace-mapping@^0.3.12", "@jridgewell/trace-mapping@^0.3.9": + version "0.3.18" + resolved "https://registry.yarnpkg.com/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz#25783b2086daf6ff1dcb53c9249ae480e4dd4cd6" + integrity sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA== + dependencies: + "@jridgewell/resolve-uri" "3.1.0" + "@jridgewell/sourcemap-codec" "1.4.14" + +"@nodelib/fs.scandir@2.1.5": + version "2.1.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz#7619c2eb21b25483f6d167548b4cfd5a7488c3d5" + integrity sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g== + dependencies: + "@nodelib/fs.stat" "2.0.5" + run-parallel "^1.1.9" + +"@nodelib/fs.stat@2.0.5", "@nodelib/fs.stat@^2.0.2": + version "2.0.5" + resolved "https://registry.yarnpkg.com/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz#5bd262af94e9d25bd1e71b05deed44876a222e8b" + integrity sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A== + +"@nodelib/fs.walk@^1.2.3", "@nodelib/fs.walk@^1.2.8": + version "1.2.8" + resolved "https://registry.yarnpkg.com/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz#e95737e8bb6746ddedf69c556953494f196fe69a" + integrity sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg== + dependencies: + "@nodelib/fs.scandir" "2.1.5" + fastq "^1.6.0" + +"@phenomnomnominal/tsquery@^5.0.0": + version "5.0.1" + resolved "https://registry.yarnpkg.com/@phenomnomnominal/tsquery/-/tsquery-5.0.1.tgz#a2a5abc89f92c01562a32806655817516653a388" + integrity sha512-3nVv+e2FQwsW8Aw6qTU6f+1rfcJ3hrcnvH/mu9i8YhxO+9sqbOfpL8m6PbET5+xKOlz/VSbp0RoYWYCtIsnmuA== + dependencies: + esquery "^1.4.0" + +"@podman-desktop/api@^1.7.0": + version "1.7.0" + resolved "https://registry.yarnpkg.com/@podman-desktop/api/-/api-1.7.0.tgz#d6bc298ab4c9e552e3ec6f6d459eb9a204951655" + integrity sha512-TCs8DUzi2OLYKD4iWo1I9+otfM/g0UOiBdwiy6VQj4ycp8jIFF/BKc902+z52a5mfxmGMLOEnbNS2Yg3aDv9Kw== + +"@rollup/rollup-android-arm-eabi@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.9.1.tgz#beaf518ee45a196448e294ad3f823d2d4576cf35" + integrity sha512-6vMdBZqtq1dVQ4CWdhFwhKZL6E4L1dV6jUjuBvsavvNJSppzi6dLBbuV+3+IyUREaj9ZFvQefnQm28v4OCXlig== + +"@rollup/rollup-android-arm64@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.9.1.tgz#6f76cfa759c2d0fdb92122ffe28217181a1664eb" + integrity sha512-Jto9Fl3YQ9OLsTDWtLFPtaIMSL2kwGyGoVCmPC8Gxvym9TCZm4Sie+cVeblPO66YZsYH8MhBKDMGZ2NDxuk/XQ== + +"@rollup/rollup-darwin-arm64@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.9.1.tgz#9aaefe33a5481d66322d1c62f368171c03eabe2b" + integrity sha512-LtYcLNM+bhsaKAIGwVkh5IOWhaZhjTfNOkGzGqdHvhiCUVuJDalvDxEdSnhFzAn+g23wgsycmZk1vbnaibZwwA== + +"@rollup/rollup-darwin-x64@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.9.1.tgz#707dcaadcdc6bd3fd6c69f55d9456cd4446306a3" + integrity sha512-KyP/byeXu9V+etKO6Lw3E4tW4QdcnzDG/ake031mg42lob5tN+5qfr+lkcT/SGZaH2PdW4Z1NX9GHEkZ8xV7og== + +"@rollup/rollup-linux-arm-gnueabihf@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.9.1.tgz#7a4dbbd1dd98731d88a55aefcef0ec4c578fa9c7" + integrity sha512-Yqz/Doumf3QTKplwGNrCHe/B2p9xqDghBZSlAY0/hU6ikuDVQuOUIpDP/YcmoT+447tsZTmirmjgG3znvSCR0Q== + +"@rollup/rollup-linux-arm64-gnu@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.9.1.tgz#967ba8e6f68a5f21bd00cd97773dcdd6107e94ed" + integrity sha512-u3XkZVvxcvlAOlQJ3UsD1rFvLWqu4Ef/Ggl40WAVCuogf4S1nJPHh5RTgqYFpCOvuGJ7H5yGHabjFKEZGExk5Q== + +"@rollup/rollup-linux-arm64-musl@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.9.1.tgz#d3a4e1c9f21eef3b9f4e4989f334a519a1341462" + integrity sha512-0XSYN/rfWShW+i+qjZ0phc6vZ7UWI8XWNz4E/l+6edFt+FxoEghrJHjX1EY/kcUGCnZzYYRCl31SNdfOi450Aw== + +"@rollup/rollup-linux-riscv64-gnu@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.9.1.tgz#415c0533bb752164effd05f5613858e8f6779bc9" + integrity sha512-LmYIO65oZVfFt9t6cpYkbC4d5lKHLYv5B4CSHRpnANq0VZUQXGcCPXHzbCXCz4RQnx7jvlYB1ISVNCE/omz5cw== + +"@rollup/rollup-linux-x64-gnu@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.9.1.tgz#0983385dd753a2e0ecaddea7a81dd37fea5114f5" + integrity sha512-kr8rEPQ6ns/Lmr/hiw8sEVj9aa07gh1/tQF2Y5HrNCCEPiCBGnBUt9tVusrcBBiJfIt1yNaXN6r1CCmpbFEDpg== + +"@rollup/rollup-linux-x64-musl@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.9.1.tgz#eb7494ebc5199cbd2e5c38c2b8acbe2603f35e03" + integrity sha512-t4QSR7gN+OEZLG0MiCgPqMWZGwmeHhsM4AkegJ0Kiy6TnJ9vZ8dEIwHw1LcZKhbHxTY32hp9eVCMdR3/I8MGRw== + +"@rollup/rollup-win32-arm64-msvc@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.9.1.tgz#5bebc66e3a7f82d4b9aa9ff448e7fc13a69656e9" + integrity sha512-7XI4ZCBN34cb+BH557FJPmh0kmNz2c25SCQeT9OiFWEgf8+dL6ZwJ8f9RnUIit+j01u07Yvrsuu1rZGxJCc51g== + +"@rollup/rollup-win32-ia32-msvc@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.9.1.tgz#34156ebf8b4de3b20e6497260fe519a30263f8cf" + integrity sha512-yE5c2j1lSWOH5jp+Q0qNL3Mdhr8WuqCNVjc6BxbVfS5cAS6zRmdiw7ktb8GNpDCEUJphILY6KACoFoRtKoqNQg== + +"@rollup/rollup-win32-x64-msvc@4.9.1": + version "4.9.1" + resolved "https://registry.yarnpkg.com/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.9.1.tgz#d146db7a5949e10837b323ce933ed882ac878262" + integrity sha512-PyJsSsafjmIhVgaI1Zdj7m8BB8mMckFah/xbpplObyHfiXzKcI5UOUXRyOdHW7nz4DpMCuzLnF7v5IWHenCwYA== + +"@sinclair/typebox@^0.27.8": + version "0.27.8" + resolved "https://registry.yarnpkg.com/@sinclair/typebox/-/typebox-0.27.8.tgz#6667fac16c436b5434a387a34dedb013198f6e6e" + integrity sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA== + +"@types/istanbul-lib-coverage@^2.0.1": + version "2.0.4" + resolved "https://registry.yarnpkg.com/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz#8467d4b3c087805d63580480890791277ce35c44" + integrity sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g== + +"@types/json-schema@^7.0.12": + version "7.0.15" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.15.tgz#596a1747233694d50f6ad8a7869fcb6f56cf5841" + integrity sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA== + +"@types/json-schema@^7.0.9": + version "7.0.12" + resolved "https://registry.yarnpkg.com/@types/json-schema/-/json-schema-7.0.12.tgz#d70faba7039d5fca54c83c7dbab41051d2b6f6cb" + integrity sha512-Hr5Jfhc9eYOQNPYO5WLDq/n4jqijdHNlDXjuAQkkt+mWdQR+XJToOHrsD4cPaMXpn6KO7y2+wM8AZEs8VpBLVA== + +"@types/json5@^0.0.29": + version "0.0.29" + resolved "https://registry.yarnpkg.com/@types/json5/-/json5-0.0.29.tgz#ee28707ae94e11d2b827bcbe5270bcea7f3e71ee" + integrity sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ== + +"@types/semver@^7.3.12": + version "7.5.0" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.0.tgz#591c1ce3a702c45ee15f47a42ade72c2fd78978a" + integrity sha512-G8hZ6XJiHnuhQKR7ZmysCeJWE08o8T0AXtk5darsCaTVsYZhhgUrq53jizaR2FvsoeCwJhlmwTjkXBY5Pn/ZHw== + +"@types/semver@^7.5.0": + version "7.5.6" + resolved "https://registry.yarnpkg.com/@types/semver/-/semver-7.5.6.tgz#c65b2bfce1bec346582c07724e3f8c1017a20339" + integrity sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A== + +"@types/yargs-parser@*": + version "21.0.0" + resolved "https://registry.yarnpkg.com/@types/yargs-parser/-/yargs-parser-21.0.0.tgz#0c60e537fa790f5f9472ed2776c2b71ec117351b" + integrity sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA== + +"@types/yargs@^17.0.0": + version "17.0.24" + resolved "https://registry.yarnpkg.com/@types/yargs/-/yargs-17.0.24.tgz#b3ef8d50ad4aa6aecf6ddc97c580a00f5aa11902" + integrity sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw== + dependencies: + "@types/yargs-parser" "*" + +"@typescript-eslint/eslint-plugin@^6.16.0": + version "6.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.16.0.tgz#cc29fbd208ea976de3db7feb07755bba0ce8d8bc" + integrity sha512-O5f7Kv5o4dLWQtPX4ywPPa+v9G+1q1x8mz0Kr0pXUtKsevo+gIJHLkGc8RxaZWtP8RrhwhSNIWThnW42K9/0rQ== + dependencies: + "@eslint-community/regexpp" "^4.5.1" + "@typescript-eslint/scope-manager" "6.16.0" + "@typescript-eslint/type-utils" "6.16.0" + "@typescript-eslint/utils" "6.16.0" + "@typescript-eslint/visitor-keys" "6.16.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" + +"@typescript-eslint/experimental-utils@^5.0.0": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/experimental-utils/-/experimental-utils-5.59.9.tgz#e77482a8b70f1a6aa3a1c6a128be4a5e0e6db940" + integrity sha512-eZTK/Ci0QAqNc/q2MqMwI2+QI5ZI9HM12FcfGwbEvKif5ev/CIIYLmrlckvgPrC8XSbl39HtErR5NJiQkRkvWg== + dependencies: + "@typescript-eslint/utils" "5.59.9" + +"@typescript-eslint/parser@^6.16.0": + version "6.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/parser/-/parser-6.16.0.tgz#36f39f63b126aa25af2ad2df13d9891e9fd5b40c" + integrity sha512-H2GM3eUo12HpKZU9njig3DF5zJ58ja6ahj1GoHEHOgQvYxzoFJJEvC1MQ7T2l9Ha+69ZSOn7RTxOdpC/y3ikMw== + dependencies: + "@typescript-eslint/scope-manager" "6.16.0" + "@typescript-eslint/types" "6.16.0" + "@typescript-eslint/typescript-estree" "6.16.0" + "@typescript-eslint/visitor-keys" "6.16.0" + debug "^4.3.4" + +"@typescript-eslint/scope-manager@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-5.59.9.tgz#eadce1f2733389cdb58c49770192c0f95470d2f4" + integrity sha512-8RA+E+w78z1+2dzvK/tGZ2cpGigBZ58VMEHDZtpE1v+LLjzrYGc8mMaTONSxKyEkz3IuXFM0IqYiGHlCsmlZxQ== + dependencies: + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/visitor-keys" "5.59.9" + +"@typescript-eslint/scope-manager@6.16.0": + version "6.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/scope-manager/-/scope-manager-6.16.0.tgz#f3e9a00fbc1d0701356359cd56489c54d9e37168" + integrity sha512-0N7Y9DSPdaBQ3sqSCwlrm9zJwkpOuc6HYm7LpzLAPqBL7dmzAUimr4M29dMkOP/tEwvOCC/Cxo//yOfJD3HUiw== + dependencies: + "@typescript-eslint/types" "6.16.0" + "@typescript-eslint/visitor-keys" "6.16.0" + +"@typescript-eslint/type-utils@6.16.0": + version "6.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/type-utils/-/type-utils-6.16.0.tgz#5f21c3e49e540ad132dc87fc99af463c184d5ed1" + integrity sha512-ThmrEOcARmOnoyQfYkHw/DX2SEYBalVECmoldVuH6qagKROp/jMnfXpAU/pAIWub9c4YTxga+XwgAkoA0pxfmg== + dependencies: + "@typescript-eslint/typescript-estree" "6.16.0" + "@typescript-eslint/utils" "6.16.0" + debug "^4.3.4" + ts-api-utils "^1.0.1" + +"@typescript-eslint/types@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-5.59.9.tgz#3b4e7ae63718ce1b966e0ae620adc4099a6dcc52" + integrity sha512-uW8H5NRgTVneSVTfiCVffBb8AbwWSKg7qcA4Ot3JI3MPCJGsB4Db4BhvAODIIYE5mNj7Q+VJkK7JxmRhk2Lyjw== + +"@typescript-eslint/types@6.16.0": + version "6.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/types/-/types-6.16.0.tgz#a3abe0045737d44d8234708d5ed8fef5d59dc91e" + integrity sha512-hvDFpLEvTJoHutVl87+MG/c5C8I6LOgEx05zExTSJDEVU7hhR3jhV8M5zuggbdFCw98+HhZWPHZeKS97kS3JoQ== + +"@typescript-eslint/typescript-estree@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.9.tgz#6bfea844e468427b5e72034d33c9fffc9557392b" + integrity sha512-pmM0/VQ7kUhd1QyIxgS+aRvMgw+ZljB3eDb+jYyp6d2bC0mQWLzUDF+DLwCTkQ3tlNyVsvZRXjFyV0LkU/aXjA== + dependencies: + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/visitor-keys" "5.59.9" + debug "^4.3.4" + globby "^11.1.0" + is-glob "^4.0.3" + semver "^7.3.7" + tsutils "^3.21.0" + +"@typescript-eslint/typescript-estree@6.16.0": + version "6.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/typescript-estree/-/typescript-estree-6.16.0.tgz#d6e0578e4f593045f0df06c4b3a22bd6f13f2d03" + integrity sha512-VTWZuixh/vr7nih6CfrdpmFNLEnoVBF1skfjdyGnNwXOH1SLeHItGdZDHhhAIzd3ACazyY2Fg76zuzOVTaknGA== + dependencies: + "@typescript-eslint/types" "6.16.0" + "@typescript-eslint/visitor-keys" "6.16.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" + +"@typescript-eslint/utils@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-5.59.9.tgz#adee890107b5ffe02cd46fdaa6c2125fb3c6c7c4" + integrity sha512-1PuMYsju/38I5Ggblaeb98TOoUvjhRvLpLa1DoTOFaLWqaXl/1iQ1eGurTXgBY58NUdtfTXKP5xBq7q9NDaLKg== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@types/json-schema" "^7.0.9" + "@types/semver" "^7.3.12" + "@typescript-eslint/scope-manager" "5.59.9" + "@typescript-eslint/types" "5.59.9" + "@typescript-eslint/typescript-estree" "5.59.9" + eslint-scope "^5.1.1" + semver "^7.3.7" + +"@typescript-eslint/utils@6.16.0", "@typescript-eslint/utils@^6.2.1": + version "6.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/utils/-/utils-6.16.0.tgz#1c291492d34670f9210d2b7fcf6b402bea3134ae" + integrity sha512-T83QPKrBm6n//q9mv7oiSvy/Xq/7Hyw9SzSEhMHJwznEmQayfBM87+oAlkNAMEO7/MjIwKyOHgBJbxB0s7gx2A== + dependencies: + "@eslint-community/eslint-utils" "^4.4.0" + "@types/json-schema" "^7.0.12" + "@types/semver" "^7.5.0" + "@typescript-eslint/scope-manager" "6.16.0" + "@typescript-eslint/types" "6.16.0" + "@typescript-eslint/typescript-estree" "6.16.0" + semver "^7.5.4" + +"@typescript-eslint/visitor-keys@5.59.9": + version "5.59.9" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.9.tgz#9f86ef8e95aca30fb5a705bb7430f95fc58b146d" + integrity sha512-bT7s0td97KMaLwpEBckbzj/YohnvXtqbe2XgqNvTl6RJVakY5mvENOTPvw5u66nljfZxthESpDozs86U+oLY8Q== + dependencies: + "@typescript-eslint/types" "5.59.9" + eslint-visitor-keys "^3.3.0" + +"@typescript-eslint/visitor-keys@6.16.0": + version "6.16.0" + resolved "https://registry.yarnpkg.com/@typescript-eslint/visitor-keys/-/visitor-keys-6.16.0.tgz#d50da18a05d91318ed3e7e8889bda0edc35f3a10" + integrity sha512-QSFQLruk7fhs91a/Ep/LqRdbJCZ1Rq03rqBdKT5Ky17Sz8zRLUksqIe9DW0pKtg/Z35/ztbLQ6qpOCN6rOC11A== + dependencies: + "@typescript-eslint/types" "6.16.0" + eslint-visitor-keys "^3.4.1" + +"@ungap/structured-clone@^1.2.0": + version "1.2.0" + resolved "https://registry.yarnpkg.com/@ungap/structured-clone/-/structured-clone-1.2.0.tgz#756641adb587851b5ccb3e095daf27ae581c8406" + integrity sha512-zuVdFrMJiuCDQUMCzQaD6KL28MjnqqN8XnAqiEq9PNm/hCPTSGfrXCOfwj1ow4LFb/tNymJPwsNbVePc1xFqrQ== + +"@vitest/coverage-v8@^1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@vitest/coverage-v8/-/coverage-v8-1.1.0.tgz#bc0bbb99fcb608f72794701a86302ff3aabbc125" + integrity sha512-kHQRk70vTdXAyQY2C0vKOHPyQD/R6IUzcGdO4vCuyr4alE5Yg1+Sk2jSdjlIrTTXdcNEs+ReWVM09mmSFJpzyQ== + dependencies: + "@ampproject/remapping" "^2.2.1" + "@bcoe/v8-coverage" "^0.2.3" + debug "^4.3.4" + istanbul-lib-coverage "^3.2.2" + istanbul-lib-report "^3.0.1" + istanbul-lib-source-maps "^4.0.1" + istanbul-reports "^3.1.6" + magic-string "^0.30.5" + magicast "^0.3.2" + picocolors "^1.0.0" + std-env "^3.5.0" + test-exclude "^6.0.0" + v8-to-istanbul "^9.2.0" + +"@vitest/expect@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@vitest/expect/-/expect-1.1.0.tgz#f58eef7de090ad65f30bb93ec54fa9f94c9d1d5d" + integrity sha512-9IE2WWkcJo2BR9eqtY5MIo3TPmS50Pnwpm66A6neb2hvk/QSLfPXBz2qdiwUOQkwyFuuXEUj5380CbwfzW4+/w== + dependencies: + "@vitest/spy" "1.1.0" + "@vitest/utils" "1.1.0" + chai "^4.3.10" + +"@vitest/runner@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@vitest/runner/-/runner-1.1.0.tgz#b3bf60f4a78f4324ca09811dd0f87b721a96b534" + integrity sha512-zdNLJ00pm5z/uhbWF6aeIJCGMSyTyWImy3Fcp9piRGvueERFlQFbUwCpzVce79OLm2UHk9iwaMSOaU9jVHgNVw== + dependencies: + "@vitest/utils" "1.1.0" + p-limit "^5.0.0" + pathe "^1.1.1" + +"@vitest/snapshot@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@vitest/snapshot/-/snapshot-1.1.0.tgz#b9924e4303382b43bb2c31061b173e69a6fb3437" + integrity sha512-5O/wyZg09V5qmNmAlUgCBqflvn2ylgsWJRRuPrnHEfDNT6tQpQ8O1isNGgo+VxofISHqz961SG3iVvt3SPK/QQ== + dependencies: + magic-string "^0.30.5" + pathe "^1.1.1" + pretty-format "^29.7.0" + +"@vitest/spy@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@vitest/spy/-/spy-1.1.0.tgz#7f40697e4fc217ac8c3cc89a865d1751b263f561" + integrity sha512-sNOVSU/GE+7+P76qYo+VXdXhXffzWZcYIPQfmkiRxaNCSPiLANvQx5Mx6ZURJ/ndtEkUJEpvKLXqAYTKEY+lTg== + dependencies: + tinyspy "^2.2.0" + +"@vitest/utils@1.1.0": + version "1.1.0" + resolved "https://registry.yarnpkg.com/@vitest/utils/-/utils-1.1.0.tgz#d177a5f41bdb484bbb43c8d73a77ca782df068b5" + integrity sha512-z+s510fKmYz4Y41XhNs3vcuFTFhcij2YF7F8VQfMEYAAUfqQh0Zfg7+w9xdgFGhPf3tX3TicAe+8BDITk6ampQ== + dependencies: + diff-sequences "^29.6.3" + loupe "^2.3.7" + pretty-format "^29.7.0" + +acorn-jsx@^5.3.2: + version "5.3.2" + resolved "https://registry.yarnpkg.com/acorn-jsx/-/acorn-jsx-5.3.2.tgz#7ed5bb55908b3b2f1bc55c6af1653bada7f07937" + integrity sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ== + +acorn-walk@^8.3.0: + version "8.3.1" + resolved "https://registry.yarnpkg.com/acorn-walk/-/acorn-walk-8.3.1.tgz#2f10f5b69329d90ae18c58bf1fa8fccd8b959a43" + integrity sha512-TgUZgYvqZprrl7YldZNoa9OciCAyZR+Ejm9eXzKCmjsF5IKp/wgQ7Z/ZpjpGTIUPwrHQIcYeI8qDh4PsEwxMbw== + +acorn@^8.10.0, acorn@^8.9.0: + version "8.11.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.11.2.tgz#ca0d78b51895be5390a5903c5b3bdcdaf78ae40b" + integrity sha512-nc0Axzp/0FILLEVsm4fNwLCwMttvhEI263QtVPQcbpfZZ3ts0hLsZGOpE6czNlid7CJ9MlyH8reXkpsf3YUY4w== + +acorn@^8.8.2: + version "8.8.2" + resolved "https://registry.yarnpkg.com/acorn/-/acorn-8.8.2.tgz#1b2f25db02af965399b9776b0c2c391276d37c4a" + integrity sha512-xjIYgE8HBrkpd/sJqOGNspf8uHG+NOHGOw6a/Urj8taM2EXfdNAH2oFcPeIFfsv3+kz/mJrS5VuMqbNLjCa2vw== + +ajv@^6.12.4: + version "6.12.6" + resolved "https://registry.yarnpkg.com/ajv/-/ajv-6.12.6.tgz#baf5a62e802b07d977034586f8c3baf5adf26df4" + integrity sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g== + 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" + +ansi-regex@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/ansi-regex/-/ansi-regex-5.0.1.tgz#082cb2c89c9fe8659a311a53bd6a4dc5301db304" + integrity sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ== + +ansi-styles@^4.0.0, ansi-styles@^4.1.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-4.3.0.tgz#edd803628ae71c04c85ae7a0906edad34b648937" + integrity sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg== + dependencies: + color-convert "^2.0.1" + +ansi-styles@^5.0.0: + version "5.2.0" + resolved "https://registry.yarnpkg.com/ansi-styles/-/ansi-styles-5.2.0.tgz#07449690ad45777d1924ac2abb2fc8895dba836b" + integrity sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA== + +argparse@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/argparse/-/argparse-2.0.1.tgz#246f50f3ca78a3240f6c997e8a9bd1eac49e4b38" + integrity sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q== + +array-buffer-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/array-buffer-byte-length/-/array-buffer-byte-length-1.0.0.tgz#fabe8bc193fea865f317fe7807085ee0dee5aead" + integrity sha512-LPuwb2P+NrQw3XhxGc36+XSvuBPopovXYTR9Ew++Du9Yb/bx5AzBfrIsBoj0EZUifjQU+sHL21sseZ3jerWO/A== + dependencies: + call-bind "^1.0.2" + is-array-buffer "^3.0.1" + +array-includes@^3.1.7: + version "3.1.7" + resolved "https://registry.yarnpkg.com/array-includes/-/array-includes-3.1.7.tgz#8cd2e01b26f7a3086cbc87271593fe921c62abda" + integrity sha512-dlcsNBIiWhPkHdOEEKnehA+RNUWDc4UqFtnIXU4uuYDPtA4LDkr7qip2p0VvFAEXNDr0yWZ9PJyIRiGjRLQzwQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-string "^1.0.7" + +array-union@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/array-union/-/array-union-2.1.0.tgz#b798420adbeb1de828d84acd8a2e23d3efe85e8d" + integrity sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw== + +array.prototype.findlastindex@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.3.tgz#b37598438f97b579166940814e2c0493a4f50207" + integrity sha512-LzLoiOMAxvy+Gd3BAq3B7VeIgPdo+Q8hthvKtXybMvRV0jrXfJM/t8mw7nNlpEcVlVUnCnM2KSX4XU5HmpodOA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + get-intrinsic "^1.2.1" + +array.prototype.flat@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz#1476217df8cff17d72ee8f3ba06738db5b387d18" + integrity sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +array.prototype.flatmap@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz#c9a7c6831db8e719d6ce639190146c24bbd3e527" + integrity sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + es-shim-unscopables "^1.0.0" + +arraybuffer.prototype.slice@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.2.tgz#98bd561953e3e74bb34938e77647179dfe6e9f12" + integrity sha512-yMBKppFur/fbHu9/6USUe03bZ4knMYiwFBcyiaXB8Go0qNehwX6inYPzK9U0NeQvGxKthcmHcaR8P5MStSRBAw== + dependencies: + array-buffer-byte-length "^1.0.0" + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + is-array-buffer "^3.0.2" + is-shared-array-buffer "^1.0.2" + +assertion-error@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/assertion-error/-/assertion-error-1.1.0.tgz#e60b6b0e8f301bd97e5375215bda406c85118c0b" + integrity sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw== + +available-typed-arrays@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz#92f95616501069d07d10edb2fc37d3e1c65123b7" + integrity sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw== + +balanced-match@^1.0.0: + version "1.0.2" + resolved "https://registry.yarnpkg.com/balanced-match/-/balanced-match-1.0.2.tgz#e83e3a7e3f300b34cb9d87f615fa0cbf357690ee" + integrity sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw== + +brace-expansion@^1.1.7: + version "1.1.11" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-1.1.11.tgz#3c7fcbf529d87226f3d2f52b966ff5271eb441dd" + integrity sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA== + dependencies: + balanced-match "^1.0.0" + concat-map "0.0.1" + +brace-expansion@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/brace-expansion/-/brace-expansion-2.0.1.tgz#1edc459e0f0c548486ecf9fc99f2221364b9a0ae" + integrity sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA== + dependencies: + balanced-match "^1.0.0" + +braces@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/braces/-/braces-3.0.2.tgz#3454e1a462ee8d599e236df336cd9ea4f8afe107" + integrity sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A== + dependencies: + fill-range "^7.0.1" + +cac@^6.7.14: + version "6.7.14" + resolved "https://registry.yarnpkg.com/cac/-/cac-6.7.14.tgz#804e1e6f506ee363cb0e3ccbb09cad5dd9870959" + integrity sha512-b6Ilus+c3RrdDk+JhLKUAQfzzgLEPy6wcXqS7f/xe1EETvsDP6GORG7SFuOs6cID5YkqchW/LXZbX5bc8j7ZcQ== + +call-bind@^1.0.0, call-bind@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.2.tgz#b1d4e89e688119c3c9a903ad30abb2f6a919be3c" + integrity sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA== + dependencies: + function-bind "^1.1.1" + get-intrinsic "^1.0.2" + +call-bind@^1.0.4, call-bind@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/call-bind/-/call-bind-1.0.5.tgz#6fa2b7845ce0ea49bf4d8b9ef64727a2c2e2e513" + integrity sha512-C3nQxfFZxFRVoJoGKKI8y3MOEo129NQ+FgQ08iye+Mk4zNZZGdjfs06bVTr+DBSlA66Q2VEcMki/cUCP4SercQ== + dependencies: + function-bind "^1.1.2" + get-intrinsic "^1.2.1" + set-function-length "^1.1.1" + +callsites@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/callsites/-/callsites-3.1.0.tgz#b3630abd8943432f54b3f0519238e33cd7df2f73" + integrity sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ== + +chai@^4.3.10: + version "4.3.10" + resolved "https://registry.yarnpkg.com/chai/-/chai-4.3.10.tgz#d784cec635e3b7e2ffb66446a63b4e33bd390384" + integrity sha512-0UXG04VuVbruMUYbJ6JctvH0YnC/4q3/AkT18q4NaITo91CUm0liMS9VqzT9vZhVQ/1eqPanMWjBM+Juhfb/9g== + dependencies: + assertion-error "^1.1.0" + check-error "^1.0.3" + deep-eql "^4.1.3" + get-func-name "^2.0.2" + loupe "^2.3.6" + pathval "^1.1.1" + type-detect "^4.0.8" + +chalk@^4.0.0: + version "4.1.2" + resolved "https://registry.yarnpkg.com/chalk/-/chalk-4.1.2.tgz#aac4e2b7734a740867aeb16bf02aad556a1e7a01" + integrity sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA== + dependencies: + ansi-styles "^4.1.0" + supports-color "^7.1.0" + +check-error@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/check-error/-/check-error-1.0.3.tgz#a6502e4312a7ee969f646e83bb3ddd56281bd694" + integrity sha512-iKEoDYaRmd1mxM90a2OEfWhjsjPpYPuQ+lMYsoxB126+t8fw7ySEO48nmDg5COTjxDI65/Y2OWpeEHk3ZOe8zg== + dependencies: + get-func-name "^2.0.2" + +cliui@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/cliui/-/cliui-8.0.1.tgz#0c04b075db02cbfe60dc8e6cf2f5486b1a3608aa" + integrity sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ== + dependencies: + string-width "^4.2.0" + strip-ansi "^6.0.1" + wrap-ansi "^7.0.0" + +color-convert@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/color-convert/-/color-convert-2.0.1.tgz#72d3a68d598c9bdb3af2ad1e84f21d896abd4de3" + integrity sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ== + dependencies: + color-name "~1.1.4" + +color-name@~1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/color-name/-/color-name-1.1.4.tgz#c2a09a87acbde69543de6f63fa3995c826c536a2" + integrity sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA== + +concat-map@0.0.1: + version "0.0.1" + resolved "https://registry.yarnpkg.com/concat-map/-/concat-map-0.0.1.tgz#d8a96bd77fd68df7793a73036a3ba0d5405d477b" + integrity sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg== + +convert-source-map@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/convert-source-map/-/convert-source-map-2.0.0.tgz#4b560f649fc4e918dd0ab75cf4961e8bc882d82a" + integrity sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg== + +cross-spawn@^7.0.2, cross-spawn@^7.0.3: + version "7.0.3" + resolved "https://registry.yarnpkg.com/cross-spawn/-/cross-spawn-7.0.3.tgz#f73a85b9d5d41d045551c177e2882d4ac85728a6" + integrity sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w== + dependencies: + path-key "^3.1.0" + shebang-command "^2.0.0" + which "^2.0.1" + +debug@^3.2.7: + version "3.2.7" + resolved "https://registry.yarnpkg.com/debug/-/debug-3.2.7.tgz#72580b7e9145fb39b6676f9c5e5fb100b934179a" + integrity sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ== + dependencies: + ms "^2.1.1" + +debug@^4.1.1, debug@^4.3.2, debug@^4.3.4: + version "4.3.4" + resolved "https://registry.yarnpkg.com/debug/-/debug-4.3.4.tgz#1319f6579357f2338d3337d2cdd4914bb5dcc865" + integrity sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ== + dependencies: + ms "2.1.2" + +deep-eql@^4.1.3: + version "4.1.3" + resolved "https://registry.yarnpkg.com/deep-eql/-/deep-eql-4.1.3.tgz#7c7775513092f7df98d8df9996dd085eb668cc6d" + integrity sha512-WaEtAOpRA1MQ0eohqZjpGD8zdI0Ovsm8mmFhaDN8dvDZzyoUMcYDnf5Y6iu7HTXxf8JDS23qWa4a+hKCDyOPzw== + dependencies: + type-detect "^4.0.0" + +deep-is@^0.1.3: + version "0.1.4" + resolved "https://registry.yarnpkg.com/deep-is/-/deep-is-0.1.4.tgz#a6f2dce612fadd2ef1f519b73551f17e85199831" + integrity sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ== + +define-data-property@^1.0.1, define-data-property@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/define-data-property/-/define-data-property-1.1.1.tgz#c35f7cd0ab09883480d12ac5cb213715587800b3" + integrity sha512-E7uGkTzkk1d0ByLeSc6ZsFS79Axg+m1P/VsgYsxHgiuc3tFSj+MjMIwe90FC4lOAZzNBdY7kkO2P2wKdsQ1vgQ== + dependencies: + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +define-properties@^1.1.3, define-properties@^1.1.4, define-properties@^1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/define-properties/-/define-properties-1.2.0.tgz#52988570670c9eacedd8064f4a990f2405849bd5" + integrity sha512-xvqAVKGfT1+UAvPwKTVw/njhdQ8ZhXK4lI0bCIuCMrp2up9nPnaDftrLtmpTazqd1o+UY4zgzU+avtMbDP+ldA== + dependencies: + has-property-descriptors "^1.0.0" + object-keys "^1.1.1" + +diff-sequences@^29.6.3: + version "29.6.3" + resolved "https://registry.yarnpkg.com/diff-sequences/-/diff-sequences-29.6.3.tgz#4deaf894d11407c51efc8418012f9e70b84ea921" + integrity sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q== + +dir-glob@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/dir-glob/-/dir-glob-3.0.1.tgz#56dbf73d992a4a93ba1584f4534063fd2e41717f" + integrity sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA== + dependencies: + path-type "^4.0.0" + +doctrine@^2.1.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-2.1.0.tgz#5cd01fc101621b42c4cd7f5d1a66243716d3f39d" + integrity sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw== + dependencies: + esutils "^2.0.2" + +doctrine@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/doctrine/-/doctrine-3.0.0.tgz#addebead72a6574db783639dc87a121773973961" + integrity sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w== + dependencies: + esutils "^2.0.2" + +emoji-regex@^8.0.0: + version "8.0.0" + resolved "https://registry.yarnpkg.com/emoji-regex/-/emoji-regex-8.0.0.tgz#e818fd69ce5ccfcb404594f842963bf53164cc37" + integrity sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A== + +enhanced-resolve@^5.12.0: + version "5.14.1" + resolved "https://registry.yarnpkg.com/enhanced-resolve/-/enhanced-resolve-5.14.1.tgz#de684b6803724477a4af5d74ccae5de52c25f6b3" + integrity sha512-Vklwq2vDKtl0y/vtwjSesgJ5MYS7Etuk5txS8VdKL4AOS1aUlD96zqIfsOSLQsdv3xgMRbtkWM8eG9XDfKUPow== + dependencies: + graceful-fs "^4.2.4" + tapable "^2.2.0" + +es-abstract@^1.22.1: + version "1.22.3" + resolved "https://registry.yarnpkg.com/es-abstract/-/es-abstract-1.22.3.tgz#48e79f5573198de6dee3589195727f4f74bc4f32" + integrity sha512-eiiY8HQeYfYH2Con2berK+To6GrK2RxbPawDkGq4UiCQQfZHb6wX9qQqkbpPqaxQFcl8d9QzZqo0tGE0VcrdwA== + dependencies: + array-buffer-byte-length "^1.0.0" + arraybuffer.prototype.slice "^1.0.2" + available-typed-arrays "^1.0.5" + call-bind "^1.0.5" + es-set-tostringtag "^2.0.1" + es-to-primitive "^1.2.1" + function.prototype.name "^1.1.6" + get-intrinsic "^1.2.2" + get-symbol-description "^1.0.0" + globalthis "^1.0.3" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + internal-slot "^1.0.5" + is-array-buffer "^3.0.2" + is-callable "^1.2.7" + is-negative-zero "^2.0.2" + is-regex "^1.1.4" + is-shared-array-buffer "^1.0.2" + is-string "^1.0.7" + is-typed-array "^1.1.12" + is-weakref "^1.0.2" + object-inspect "^1.13.1" + object-keys "^1.1.1" + object.assign "^4.1.4" + regexp.prototype.flags "^1.5.1" + safe-array-concat "^1.0.1" + safe-regex-test "^1.0.0" + string.prototype.trim "^1.2.8" + string.prototype.trimend "^1.0.7" + string.prototype.trimstart "^1.0.7" + typed-array-buffer "^1.0.0" + typed-array-byte-length "^1.0.0" + typed-array-byte-offset "^1.0.0" + typed-array-length "^1.0.4" + unbox-primitive "^1.0.2" + which-typed-array "^1.1.13" + +es-set-tostringtag@^2.0.1: + version "2.0.1" + resolved "https://registry.yarnpkg.com/es-set-tostringtag/-/es-set-tostringtag-2.0.1.tgz#338d502f6f674301d710b80c8592de8a15f09cd8" + integrity sha512-g3OMbtlwY3QewlqAiMLI47KywjWZoEytKr8pf6iTC8uJq5bIAH52Z9pnQ8pVL6whrCto53JZDuUIsifGeLorTg== + dependencies: + get-intrinsic "^1.1.3" + has "^1.0.3" + has-tostringtag "^1.0.0" + +es-shim-unscopables@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/es-shim-unscopables/-/es-shim-unscopables-1.0.0.tgz#702e632193201e3edf8713635d083d378e510241" + integrity sha512-Jm6GPcCdC30eMLbZ2x8z2WuRwAws3zTBBKuusffYVUrNj/GVSUAZ+xKMaUpfNDR5IbyNA5LJbaecoUVbmUcB1w== + dependencies: + has "^1.0.3" + +es-to-primitive@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/es-to-primitive/-/es-to-primitive-1.2.1.tgz#e55cd4c9cdc188bcefb03b366c736323fc5c898a" + integrity sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA== + dependencies: + is-callable "^1.1.4" + is-date-object "^1.0.1" + is-symbol "^1.0.2" + +esbuild@^0.19.3: + version "0.19.10" + resolved "https://registry.yarnpkg.com/esbuild/-/esbuild-0.19.10.tgz#55e83e4a6b702e3498b9f872d84bfb4ebcb6d16e" + integrity sha512-S1Y27QGt/snkNYrRcswgRFqZjaTG5a5xM3EQo97uNBnH505pdzSNe/HLBq1v0RO7iK/ngdbhJB6mDAp0OK+iUA== + optionalDependencies: + "@esbuild/aix-ppc64" "0.19.10" + "@esbuild/android-arm" "0.19.10" + "@esbuild/android-arm64" "0.19.10" + "@esbuild/android-x64" "0.19.10" + "@esbuild/darwin-arm64" "0.19.10" + "@esbuild/darwin-x64" "0.19.10" + "@esbuild/freebsd-arm64" "0.19.10" + "@esbuild/freebsd-x64" "0.19.10" + "@esbuild/linux-arm" "0.19.10" + "@esbuild/linux-arm64" "0.19.10" + "@esbuild/linux-ia32" "0.19.10" + "@esbuild/linux-loong64" "0.19.10" + "@esbuild/linux-mips64el" "0.19.10" + "@esbuild/linux-ppc64" "0.19.10" + "@esbuild/linux-riscv64" "0.19.10" + "@esbuild/linux-s390x" "0.19.10" + "@esbuild/linux-x64" "0.19.10" + "@esbuild/netbsd-x64" "0.19.10" + "@esbuild/openbsd-x64" "0.19.10" + "@esbuild/sunos-x64" "0.19.10" + "@esbuild/win32-arm64" "0.19.10" + "@esbuild/win32-ia32" "0.19.10" + "@esbuild/win32-x64" "0.19.10" + +escalade@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/escalade/-/escalade-3.1.1.tgz#d8cfdc7000965c5a0174b4a82eaa5c0552742e40" + integrity sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw== + +escape-string-regexp@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz#14ba83a5d373e3d311e5afca29cf5bfad965bf34" + integrity sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA== + +eslint-etc@^5.1.0: + version "5.2.1" + resolved "https://registry.yarnpkg.com/eslint-etc/-/eslint-etc-5.2.1.tgz#43e2554a347677ebb6386c915f374918f2efcb87" + integrity sha512-lFJBSiIURdqQKq9xJhvSJFyPA+VeTh5xvk24e8pxVL7bwLBtGF60C/KRkLTMrvCZ6DA3kbPuYhLWY0TZMlqTsg== + dependencies: + "@typescript-eslint/experimental-utils" "^5.0.0" + tsutils "^3.17.1" + tsutils-etc "^1.4.1" + +eslint-import-resolver-custom-alias@^1.3.2: + version "1.3.2" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-custom-alias/-/eslint-import-resolver-custom-alias-1.3.2.tgz#e509097e87de7a10b8c205c24644c3eb3fdf03c4" + integrity sha512-wBPcZA2k6/IXaT8FsLMyiyVSG6WVEuaYIAbeKLXeGwr523BmeB9lKAAoLJWSqp3txsnU4gpkgD2x1q6K8k0uDQ== + dependencies: + glob-parent "^6.0.2" + resolve "^1.22.2" + +eslint-import-resolver-node@^0.3.9: + version "0.3.9" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz#d4eaac52b8a2e7c3cd1903eb00f7e053356118ac" + integrity sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g== + dependencies: + debug "^3.2.7" + is-core-module "^2.13.0" + resolve "^1.22.4" + +eslint-import-resolver-typescript@^3.6.1: + version "3.6.1" + resolved "https://registry.yarnpkg.com/eslint-import-resolver-typescript/-/eslint-import-resolver-typescript-3.6.1.tgz#7b983680edd3f1c5bce1a5829ae0bc2d57fe9efa" + integrity sha512-xgdptdoi5W3niYeuQxKmzVDTATvLYqhpwmykwsh7f6HIOStGWEIL9iqZgQDF9u9OEzrRwR8no5q2VT+bjAujTg== + dependencies: + debug "^4.3.4" + enhanced-resolve "^5.12.0" + eslint-module-utils "^2.7.4" + fast-glob "^3.3.1" + get-tsconfig "^4.5.0" + is-core-module "^2.11.0" + is-glob "^4.0.3" + +eslint-module-utils@^2.7.4, eslint-module-utils@^2.8.0: + version "2.8.0" + resolved "https://registry.yarnpkg.com/eslint-module-utils/-/eslint-module-utils-2.8.0.tgz#e439fee65fc33f6bba630ff621efc38ec0375c49" + integrity sha512-aWajIYfsqCKRDgUfjEXNN/JlrzauMuSEy5sbd7WXbtW3EH6A6MpwEh42c7qD+MqQo9QMJ6fWLAeIJynx0g6OAw== + dependencies: + debug "^3.2.7" + +eslint-plugin-etc@^2.0.3: + version "2.0.3" + resolved "https://registry.yarnpkg.com/eslint-plugin-etc/-/eslint-plugin-etc-2.0.3.tgz#befab319413701dfc4afd2bfefa14362f1db74a5" + integrity sha512-o5RS/0YwtjlGKWjhKojgmm82gV1b4NQUuwk9zqjy9/EjxNFKKYCaF+0M7DkYBn44mJ6JYFZw3Ft249dkKuR1ew== + dependencies: + "@phenomnomnominal/tsquery" "^5.0.0" + "@typescript-eslint/experimental-utils" "^5.0.0" + eslint-etc "^5.1.0" + requireindex "~1.2.0" + tslib "^2.0.0" + tsutils "^3.0.0" + +eslint-plugin-import@^2.29.1: + version "2.29.1" + resolved "https://registry.yarnpkg.com/eslint-plugin-import/-/eslint-plugin-import-2.29.1.tgz#d45b37b5ef5901d639c15270d74d46d161150643" + integrity sha512-BbPC0cuExzhiMo4Ff1BTVwHpjjv28C5R+btTOGaCRC7UEz801up0JadwkeSk5Ued6TG34uaczuVuH6qyy5YUxw== + dependencies: + array-includes "^3.1.7" + array.prototype.findlastindex "^1.2.3" + array.prototype.flat "^1.3.2" + array.prototype.flatmap "^1.3.2" + debug "^3.2.7" + doctrine "^2.1.0" + eslint-import-resolver-node "^0.3.9" + eslint-module-utils "^2.8.0" + hasown "^2.0.0" + is-core-module "^2.13.1" + is-glob "^4.0.3" + minimatch "^3.1.2" + object.fromentries "^2.0.7" + object.groupby "^1.0.1" + object.values "^1.1.7" + semver "^6.3.1" + tsconfig-paths "^3.15.0" + +eslint-plugin-no-null@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/eslint-plugin-no-null/-/eslint-plugin-no-null-1.0.2.tgz#1236a812391390a1877ad4007c26e745341c951f" + integrity sha512-uRDiz88zCO/2rzGfgG15DBjNsgwWtWiSo4Ezy7zzajUgpnFIqd1TjepKeRmJZHEfBGu58o2a8S0D7vglvvhkVA== + +eslint-plugin-redundant-undefined@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-redundant-undefined/-/eslint-plugin-redundant-undefined-1.0.0.tgz#b5c851b0f6fcd74fa67c300579b6e59e30b5d131" + integrity sha512-7qdYTBD968jFqd/BSMERF/zNveCl+9xrqC8kRZ9YSKR6bHoufi6HwvZXJwD/Gih7prfsh9F5Q4STGDxpj6zSCg== + dependencies: + "@typescript-eslint/utils" "^6.2.1" + +eslint-plugin-sonarjs@^0.23.0: + version "0.23.0" + resolved "https://registry.yarnpkg.com/eslint-plugin-sonarjs/-/eslint-plugin-sonarjs-0.23.0.tgz#0265bad801ea210951672ee3cafbcf5d456ada96" + integrity sha512-z44T3PBf9W7qQ/aR+NmofOTyg6HLhSEZOPD4zhStqBpLoMp8GYhFksuUBnCxbnf1nfISpKBVkQhiBLFI/F4Wlg== + +eslint-scope@^5.1.1: + version "5.1.1" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-5.1.1.tgz#e786e59a66cb92b3f6c1fb0d508aab174848f48c" + integrity sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw== + dependencies: + esrecurse "^4.3.0" + estraverse "^4.1.1" + +eslint-scope@^7.2.2: + version "7.2.2" + resolved "https://registry.yarnpkg.com/eslint-scope/-/eslint-scope-7.2.2.tgz#deb4f92563390f32006894af62a22dba1c46423f" + integrity sha512-dOt21O7lTMhDM+X9mB4GX+DZrZtCUJPL/wlcTqxyrx5IvO0IYtILdtrQGQp+8n5S0gwSVmOf9NQrjMOgfQZlIg== + dependencies: + esrecurse "^4.3.0" + estraverse "^5.2.0" + +eslint-visitor-keys@^3.3.0, eslint-visitor-keys@^3.4.1: + version "3.4.1" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz#c22c48f48942d08ca824cc526211ae400478a994" + integrity sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA== + +eslint-visitor-keys@^3.4.3: + version "3.4.3" + resolved "https://registry.yarnpkg.com/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz#0cd72fe8550e3c2eae156a96a4dddcd1c8ac5800" + integrity sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag== + +eslint@^8.56.0: + version "8.56.0" + resolved "https://registry.yarnpkg.com/eslint/-/eslint-8.56.0.tgz#4957ce8da409dc0809f99ab07a1b94832ab74b15" + integrity sha512-Go19xM6T9puCOWntie1/P997aXxFsOi37JIHRWI514Hc6ZnaHGKY9xFhrU65RT6CcBEzZoGG1e6Nq+DT04ZtZQ== + dependencies: + "@eslint-community/eslint-utils" "^4.2.0" + "@eslint-community/regexpp" "^4.6.1" + "@eslint/eslintrc" "^2.1.4" + "@eslint/js" "8.56.0" + "@humanwhocodes/config-array" "^0.11.13" + "@humanwhocodes/module-importer" "^1.0.1" + "@nodelib/fs.walk" "^1.2.8" + "@ungap/structured-clone" "^1.2.0" + ajv "^6.12.4" + chalk "^4.0.0" + cross-spawn "^7.0.2" + debug "^4.3.2" + doctrine "^3.0.0" + escape-string-regexp "^4.0.0" + eslint-scope "^7.2.2" + eslint-visitor-keys "^3.4.3" + espree "^9.6.1" + esquery "^1.4.2" + esutils "^2.0.2" + fast-deep-equal "^3.1.3" + file-entry-cache "^6.0.1" + find-up "^5.0.0" + glob-parent "^6.0.2" + globals "^13.19.0" + graphemer "^1.4.0" + ignore "^5.2.0" + imurmurhash "^0.1.4" + is-glob "^4.0.0" + is-path-inside "^3.0.3" + js-yaml "^4.1.0" + json-stable-stringify-without-jsonify "^1.0.1" + levn "^0.4.1" + lodash.merge "^4.6.2" + minimatch "^3.1.2" + natural-compare "^1.4.0" + optionator "^0.9.3" + strip-ansi "^6.0.1" + text-table "^0.2.0" + +espree@^9.6.0, espree@^9.6.1: + version "9.6.1" + resolved "https://registry.yarnpkg.com/espree/-/espree-9.6.1.tgz#a2a17b8e434690a5432f2f8018ce71d331a48c6f" + integrity sha512-oruZaFkjorTpF32kDSI5/75ViwGeZginGGy2NoOSg3Q9bnwlnmDm4HLnkl0RE3n+njDXR037aY1+x58Z/zFdwQ== + dependencies: + acorn "^8.9.0" + acorn-jsx "^5.3.2" + eslint-visitor-keys "^3.4.1" + +esquery@^1.4.0, esquery@^1.4.2: + version "1.5.0" + resolved "https://registry.yarnpkg.com/esquery/-/esquery-1.5.0.tgz#6ce17738de8577694edd7361c57182ac8cb0db0b" + integrity sha512-YQLXUplAwJgCydQ78IMJywZCceoqk1oH01OERdSAJc/7U2AylwjhSCLDEtqwg811idIS/9fIU5GjG73IgjKMVg== + dependencies: + estraverse "^5.1.0" + +esrecurse@^4.3.0: + version "4.3.0" + resolved "https://registry.yarnpkg.com/esrecurse/-/esrecurse-4.3.0.tgz#7ad7964d679abb28bee72cec63758b1c5d2c9921" + integrity sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag== + dependencies: + estraverse "^5.2.0" + +estraverse@^4.1.1: + version "4.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-4.3.0.tgz#398ad3f3c5a24948be7725e83d11a7de28cdbd1d" + integrity sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw== + +estraverse@^5.1.0, estraverse@^5.2.0: + version "5.3.0" + resolved "https://registry.yarnpkg.com/estraverse/-/estraverse-5.3.0.tgz#2eea5290702f26ab8fe5370370ff86c965d21123" + integrity sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA== + +esutils@^2.0.2: + version "2.0.3" + resolved "https://registry.yarnpkg.com/esutils/-/esutils-2.0.3.tgz#74d2eb4de0b8da1293711910d50775b9b710ef64" + integrity sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g== + +execa@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/execa/-/execa-8.0.1.tgz#51f6a5943b580f963c3ca9c6321796db8cc39b8c" + integrity sha512-VyhnebXciFV2DESc+p6B+y0LjSm0krU4OgJN44qFAhBY0TJ+1V61tYD2+wHusZ6F9n5K+vl8k0sTy7PEfV4qpg== + dependencies: + 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" + +fast-deep-equal@^3.1.1, fast-deep-equal@^3.1.3: + version "3.1.3" + resolved "https://registry.yarnpkg.com/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz#3a7d56b559d6cbc3eb512325244e619a65c6c525" + integrity sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q== + +fast-glob@^3.2.9: + version "3.2.12" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.2.12.tgz#7f39ec99c2e6ab030337142da9e0c18f37afae80" + integrity sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w== + 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" + +fast-glob@^3.3.1: + version "3.3.2" + resolved "https://registry.yarnpkg.com/fast-glob/-/fast-glob-3.3.2.tgz#a904501e57cfdd2ffcded45e99a54fef55e46129" + integrity sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow== + 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" + +fast-json-stable-stringify@^2.0.0: + version "2.1.0" + resolved "https://registry.yarnpkg.com/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz#874bf69c6f404c2b5d99c481341399fd55892633" + integrity sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw== + +fast-levenshtein@^2.0.6: + version "2.0.6" + resolved "https://registry.yarnpkg.com/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz#3d8a5c66883a16a30ca8643e851f19baa7797917" + integrity sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw== + +fastq@^1.6.0: + version "1.15.0" + resolved "https://registry.yarnpkg.com/fastq/-/fastq-1.15.0.tgz#d04d07c6a2a68fe4599fea8d2e103a937fae6b3a" + integrity sha512-wBrocU2LCXXa+lWBt8RoIRD89Fi8OdABODa/kEnyeyjS5aZO5/GNvI5sEINADqP/h8M29UHTHUb53sUu5Ihqdw== + dependencies: + reusify "^1.0.4" + +file-entry-cache@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/file-entry-cache/-/file-entry-cache-6.0.1.tgz#211b2dd9659cb0394b073e7323ac3c933d522027" + integrity sha512-7Gps/XWymbLk2QLYK4NzpMOrYjMhdIxXuIvy2QBsLE6ljuodKvdkWs/cpyJJ3CVIVpH0Oi1Hvg1ovbMzLdFBBg== + dependencies: + flat-cache "^3.0.4" + +fill-range@^7.0.1: + version "7.0.1" + resolved "https://registry.yarnpkg.com/fill-range/-/fill-range-7.0.1.tgz#1919a6a7c75fe38b2c7c77e5198535da9acdda40" + integrity sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ== + dependencies: + to-regex-range "^5.0.1" + +find-up@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/find-up/-/find-up-5.0.0.tgz#4c92819ecb7083561e4f4a240a86be5198f536fc" + integrity sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng== + dependencies: + locate-path "^6.0.0" + path-exists "^4.0.0" + +flat-cache@^3.0.4: + version "3.0.4" + resolved "https://registry.yarnpkg.com/flat-cache/-/flat-cache-3.0.4.tgz#61b0338302b2fe9f957dcc32fc2a87f1c3048b11" + integrity sha512-dm9s5Pw7Jc0GvMYbshN6zchCA9RgQlzzEZX3vylR9IqFfS8XciblUXOKfW6SiuJ0e13eDYZoZV5wdrev7P3Nwg== + dependencies: + flatted "^3.1.0" + rimraf "^3.0.2" + +flatted@^3.1.0: + version "3.2.7" + resolved "https://registry.yarnpkg.com/flatted/-/flatted-3.2.7.tgz#609f39207cb614b89d0765b477cb2d437fbf9787" + integrity sha512-5nqDSxl8nn5BSNxyR3n4I6eDmbolI6WT+QqR547RwxQapgjQBmtktdP+HTBb/a/zLsbzERTONyUB5pefh5TtjQ== + +for-each@^0.3.3: + version "0.3.3" + resolved "https://registry.yarnpkg.com/for-each/-/for-each-0.3.3.tgz#69b447e88a0a5d32c3e7084f3f1710034b21376e" + integrity sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw== + dependencies: + is-callable "^1.1.3" + +fs.realpath@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/fs.realpath/-/fs.realpath-1.0.0.tgz#1504ad2523158caa40db4a2787cb01411994ea4f" + integrity sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw== + +fsevents@~2.3.2: + version "2.3.2" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.2.tgz#8a526f78b8fdf4623b709e0b975c52c24c02fd1a" + integrity sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA== + +fsevents@~2.3.3: + version "2.3.3" + resolved "https://registry.yarnpkg.com/fsevents/-/fsevents-2.3.3.tgz#cac6407785d03675a2a5e1a5305c697b347d90d6" + integrity sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw== + +function-bind@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.1.tgz#a56899d3ea3c9bab874bb9773b7c5ede92f4895d" + integrity sha512-yIovAzMX49sF8Yl58fSCWJ5svSLuaibPxXQJFLmBObTuCr0Mf1KiPopGM9NiFjiYBCbfaa2Fh6breQ6ANVTI0A== + +function-bind@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/function-bind/-/function-bind-1.1.2.tgz#2c02d864d97f3ea6c8830c464cbd11ab6eab7a1c" + integrity sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA== + +function.prototype.name@^1.1.6: + version "1.1.6" + resolved "https://registry.yarnpkg.com/function.prototype.name/-/function.prototype.name-1.1.6.tgz#cdf315b7d90ee77a4c6ee216c3c3362da07533fd" + integrity sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + functions-have-names "^1.2.3" + +functions-have-names@^1.2.3: + version "1.2.3" + resolved "https://registry.yarnpkg.com/functions-have-names/-/functions-have-names-1.2.3.tgz#0404fe4ee2ba2f607f0e0ec3c80bae994133b834" + integrity sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ== + +get-caller-file@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/get-caller-file/-/get-caller-file-2.0.5.tgz#4f94412a82db32f36e3b0b9741f8a97feb031f7e" + integrity sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg== + +get-func-name@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.0.tgz#ead774abee72e20409433a066366023dd6887a41" + integrity sha512-Hm0ixYtaSZ/V7C8FJrtZIuBBI+iSgL+1Aq82zSu8VQNB4S3Gk8e7Qs3VwBDJAhmRZcFqkl3tQu36g/Foh5I5ig== + +get-func-name@^2.0.1, get-func-name@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/get-func-name/-/get-func-name-2.0.2.tgz#0d7cf20cd13fda808669ffa88f4ffc7a3943fc41" + integrity sha512-8vXOvuE167CtIc3OyItco7N/dpRtBbYOsPsXCz7X/PMnlGjYjSGuZJgM1Y7mmew7BKf9BqvLX2tnOVy1BBUsxQ== + +get-intrinsic@^1.0.2, get-intrinsic@^1.1.1, get-intrinsic@^1.1.3, get-intrinsic@^1.2.0: + version "1.2.1" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.1.tgz#d295644fed4505fc9cde952c37ee12b477a83d82" + integrity sha512-2DcsyfABl+gVHEfCOaTrWgyt+tb6MSEGmKq+kI5HwLbIYgjgmMcV8KQ41uaKz1xxUcn9tJtgFbQUEVcEbd0FYw== + dependencies: + function-bind "^1.1.1" + has "^1.0.3" + has-proto "^1.0.1" + has-symbols "^1.0.3" + +get-intrinsic@^1.2.1, get-intrinsic@^1.2.2: + version "1.2.2" + resolved "https://registry.yarnpkg.com/get-intrinsic/-/get-intrinsic-1.2.2.tgz#281b7622971123e1ef4b3c90fd7539306da93f3b" + integrity sha512-0gSo4ml/0j98Y3lngkFEot/zhiCeWsbYIlZ+uZOVgzLyLaUw7wxUL+nCTP0XJvJg1AXulJRI3UJi8GsbDuxdGA== + dependencies: + function-bind "^1.1.2" + has-proto "^1.0.1" + has-symbols "^1.0.3" + hasown "^2.0.0" + +get-stream@^8.0.1: + version "8.0.1" + resolved "https://registry.yarnpkg.com/get-stream/-/get-stream-8.0.1.tgz#def9dfd71742cd7754a7761ed43749a27d02eca2" + integrity sha512-VaUJspBffn/LMCJVoMvSAdmscJyS1auj5Zulnn5UoYcY531UWmdwhRWkcGKnGU93m5HSXP9LP2usOryrBtQowA== + +get-symbol-description@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/get-symbol-description/-/get-symbol-description-1.0.0.tgz#7fdb81c900101fbd564dd5f1a30af5aadc1e58d6" + integrity sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.1" + +get-tsconfig@^4.5.0: + version "4.6.0" + resolved "https://registry.yarnpkg.com/get-tsconfig/-/get-tsconfig-4.6.0.tgz#e977690993a42f3e320e932427502a40f7af6d05" + integrity sha512-lgbo68hHTQnFddybKbbs/RDRJnJT5YyGy2kQzVwbq+g67X73i+5MVTval34QxGkOe9X5Ujf1UYpCaphLyltjEg== + dependencies: + resolve-pkg-maps "^1.0.0" + +glob-parent@^5.1.2: + version "5.1.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-5.1.2.tgz#869832c58034fe68a4093c17dc15e8340d8401c4" + integrity sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow== + dependencies: + is-glob "^4.0.1" + +glob-parent@^6.0.2: + version "6.0.2" + resolved "https://registry.yarnpkg.com/glob-parent/-/glob-parent-6.0.2.tgz#6d237d99083950c79290f24c7642a3de9a28f9e3" + integrity sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A== + dependencies: + is-glob "^4.0.3" + +glob@^7.1.3, glob@^7.1.4: + version "7.2.3" + resolved "https://registry.yarnpkg.com/glob/-/glob-7.2.3.tgz#b8df0fb802bbfa8e89bd1d938b4e16578ed44f2b" + integrity sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q== + dependencies: + fs.realpath "^1.0.0" + inflight "^1.0.4" + inherits "2" + minimatch "^3.1.1" + once "^1.3.0" + path-is-absolute "^1.0.0" + +globals@^13.19.0: + version "13.20.0" + resolved "https://registry.yarnpkg.com/globals/-/globals-13.20.0.tgz#ea276a1e508ffd4f1612888f9d1bad1e2717bf82" + integrity sha512-Qg5QtVkCy/kv3FUSlu4ukeZDVf9ee0iXLAUYX13gbR17bnejFTzr4iS9bY7kwCf1NztRNm1t91fjOiyx4CSwPQ== + dependencies: + type-fest "^0.20.2" + +globalthis@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/globalthis/-/globalthis-1.0.3.tgz#5852882a52b80dc301b0660273e1ed082f0b6ccf" + integrity sha512-sFdI5LyBiNTHjRd7cGPWapiHWMOXKyuBNX/cWJ3NfzrZQVa8GI/8cofCl74AOVqq9W5kNmguTIzJ/1s2gyI9wA== + dependencies: + define-properties "^1.1.3" + +globby@^11.1.0: + version "11.1.0" + resolved "https://registry.yarnpkg.com/globby/-/globby-11.1.0.tgz#bd4be98bb042f83d796f7e3811991fbe82a0d34b" + integrity sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g== + 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" + +gopd@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/gopd/-/gopd-1.0.1.tgz#29ff76de69dac7489b7c0918a5788e56477c332c" + integrity sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA== + dependencies: + get-intrinsic "^1.1.3" + +graceful-fs@^4.2.4: + version "4.2.11" + resolved "https://registry.yarnpkg.com/graceful-fs/-/graceful-fs-4.2.11.tgz#4183e4e8bf08bb6e05bbb2f7d2e0c8f712ca40e3" + integrity sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ== + +graphemer@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/graphemer/-/graphemer-1.4.0.tgz#fb2f1d55e0e3a1849aeffc90c4fa0dd53a0e66c6" + integrity sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag== + +has-bigints@^1.0.1, has-bigints@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/has-bigints/-/has-bigints-1.0.2.tgz#0871bd3e3d51626f6ca0966668ba35d5602d6eaa" + integrity sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ== + +has-flag@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/has-flag/-/has-flag-4.0.0.tgz#944771fd9c81c81265c4d6941860da06bb59479b" + integrity sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ== + +has-property-descriptors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-property-descriptors/-/has-property-descriptors-1.0.0.tgz#610708600606d36961ed04c196193b6a607fa861" + integrity sha512-62DVLZGoiEBDHQyqG4w9xCuZ7eJEwNmJRWw2VY84Oedb7WFcA27fiEVe8oUQx9hAUJ4ekurquucTGwsyO1XGdQ== + dependencies: + get-intrinsic "^1.1.1" + +has-proto@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/has-proto/-/has-proto-1.0.1.tgz#1885c1305538958aff469fef37937c22795408e0" + integrity sha512-7qE+iP+O+bgF9clE5+UoBFzE65mlBiVj3tKCrlNQ0Ogwm0BjpT/gK4SlLYDMybDh5I3TCTKnPPa0oMG7JDYrhg== + +has-symbols@^1.0.2, has-symbols@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has-symbols/-/has-symbols-1.0.3.tgz#bb7b2c4349251dce87b125f7bdf874aa7c8b39f8" + integrity sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A== + +has-tostringtag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/has-tostringtag/-/has-tostringtag-1.0.0.tgz#7e133818a7d394734f941e73c3d3f9291e658b25" + integrity sha512-kFjcSNhnlGV1kyoGk7OXKSawH5JOb/LzUc5w9B02hOTO0dfFRjbHQKvg1d6cf3HbeUmtU9VbbV3qzZ2Teh97WQ== + dependencies: + has-symbols "^1.0.2" + +has@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/has/-/has-1.0.3.tgz#722d7cbfc1f6aa8241f16dd814e011e1f41e8796" + integrity sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw== + dependencies: + function-bind "^1.1.1" + +hasown@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/hasown/-/hasown-2.0.0.tgz#f4c513d454a57b7c7e1650778de226b11700546c" + integrity sha512-vUptKVTpIJhcczKBbgnS+RtcuYMB8+oNzPK2/Hp3hanz8JmpATdmmgLgSaadVREkDm+e2giHwY3ZRkyjSIDDFA== + dependencies: + function-bind "^1.1.2" + +html-escaper@^2.0.0: + version "2.0.2" + resolved "https://registry.yarnpkg.com/html-escaper/-/html-escaper-2.0.2.tgz#dfd60027da36a36dfcbe236262c00a5822681453" + integrity sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg== + +human-signals@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/human-signals/-/human-signals-5.0.0.tgz#42665a284f9ae0dade3ba41ebc37eb4b852f3a28" + integrity sha512-AXcZb6vzzrFAUE61HnN4mpLqd/cSIwNQjtNWR0euPm6y0iqx3G4gOXaIDdtdDwZmhwe82LA6+zinmW4UBWVePQ== + +ignore@^5.2.0: + version "5.2.4" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.2.4.tgz#a291c0c6178ff1b960befe47fcdec301674a6324" + integrity sha512-MAb38BcSbH0eHNBxn7ql2NH/kX33OkB3lZ1BNdh7ENeRChHTYsTvWrMubiIAMNS2llXEEgZ1MUOBtXChP3kaFQ== + +ignore@^5.2.4: + version "5.3.0" + resolved "https://registry.yarnpkg.com/ignore/-/ignore-5.3.0.tgz#67418ae40d34d6999c95ff56016759c718c82f78" + integrity sha512-g7dmpshy+gD7mh88OC9NwSGTKoc3kyLAZQRU1mt53Aw/vnvfXnbC+F/7F7QoYVKbV+KNvJx8wArewKy1vXMtlg== + +import-fresh@^3.2.1: + version "3.3.0" + resolved "https://registry.yarnpkg.com/import-fresh/-/import-fresh-3.3.0.tgz#37162c25fcb9ebaa2e6e53d5b4d88ce17d9e0c2b" + integrity sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw== + dependencies: + parent-module "^1.0.0" + resolve-from "^4.0.0" + +imurmurhash@^0.1.4: + version "0.1.4" + resolved "https://registry.yarnpkg.com/imurmurhash/-/imurmurhash-0.1.4.tgz#9218b9b2b928a238b13dc4fb6b6d576f231453ea" + integrity sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA== + +inflight@^1.0.4: + version "1.0.6" + resolved "https://registry.yarnpkg.com/inflight/-/inflight-1.0.6.tgz#49bd6331d7d02d0c09bc910a1075ba8165b56df9" + integrity sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA== + dependencies: + once "^1.3.0" + wrappy "1" + +inherits@2: + version "2.0.4" + resolved "https://registry.yarnpkg.com/inherits/-/inherits-2.0.4.tgz#0fa2c64f932917c3433a0ded55363aae37416b7c" + integrity sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ== + +internal-slot@^1.0.5: + version "1.0.5" + resolved "https://registry.yarnpkg.com/internal-slot/-/internal-slot-1.0.5.tgz#f2a2ee21f668f8627a4667f309dc0f4fb6674986" + integrity sha512-Y+R5hJrzs52QCG2laLn4udYVnxsfny9CpOhNhUvk/SSSVyF6T27FzRbF0sroPidSu3X8oEAkOn2K804mjpt6UQ== + dependencies: + get-intrinsic "^1.2.0" + has "^1.0.3" + side-channel "^1.0.4" + +is-array-buffer@^3.0.1, is-array-buffer@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/is-array-buffer/-/is-array-buffer-3.0.2.tgz#f2653ced8412081638ecb0ebbd0c41c6e0aecbbe" + integrity sha512-y+FyyR/w8vfIRq4eQcM1EYgSTnmHXPqaF+IgzgraytCFq5Xh8lllDVmAZolPJiZttZLeFSINPYMaEJ7/vWUa1w== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.0" + is-typed-array "^1.1.10" + +is-bigint@^1.0.1: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-bigint/-/is-bigint-1.0.4.tgz#08147a1875bc2b32005d41ccd8291dffc6691df3" + integrity sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg== + dependencies: + has-bigints "^1.0.1" + +is-boolean-object@^1.1.0: + version "1.1.2" + resolved "https://registry.yarnpkg.com/is-boolean-object/-/is-boolean-object-1.1.2.tgz#5c6dc200246dd9321ae4b885a114bb1f75f63719" + integrity sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-callable@^1.1.3, is-callable@^1.1.4, is-callable@^1.2.7: + version "1.2.7" + resolved "https://registry.yarnpkg.com/is-callable/-/is-callable-1.2.7.tgz#3bc2a85ea742d9e36205dcacdd72ca1fdc51b055" + integrity sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA== + +is-core-module@^2.11.0: + version "2.12.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.12.1.tgz#0c0b6885b6f80011c71541ce15c8d66cf5a4f9fd" + integrity sha512-Q4ZuBAe2FUsKtyQJoQHlvP8OvBERxO3jEmy1I7hcRXcJBGGHFh/aJBswbXuS9sgrDH2QUO8ilkwNPHvHMd8clg== + dependencies: + has "^1.0.3" + +is-core-module@^2.13.0, is-core-module@^2.13.1: + version "2.13.1" + resolved "https://registry.yarnpkg.com/is-core-module/-/is-core-module-2.13.1.tgz#ad0d7532c6fea9da1ebdc82742d74525c6273384" + integrity sha512-hHrIjvZsftOsvKSn2TRYl63zvxsgE0K+0mYMoH6gD4omR5IWB2KynivBQczo3+wF1cCkjzvptnI9Q0sPU66ilw== + dependencies: + hasown "^2.0.0" + +is-date-object@^1.0.1: + version "1.0.5" + resolved "https://registry.yarnpkg.com/is-date-object/-/is-date-object-1.0.5.tgz#0841d5536e724c25597bf6ea62e1bd38298df31f" + integrity sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ== + dependencies: + has-tostringtag "^1.0.0" + +is-extglob@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/is-extglob/-/is-extglob-2.1.1.tgz#a88c02535791f02ed37c76a1b9ea9773c833f8c2" + integrity sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ== + +is-fullwidth-code-point@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz#f116f8064fe90b3f7844a38997c0b75051269f1d" + integrity sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg== + +is-glob@^4.0.0, is-glob@^4.0.1, is-glob@^4.0.3: + version "4.0.3" + resolved "https://registry.yarnpkg.com/is-glob/-/is-glob-4.0.3.tgz#64f61e42cbbb2eec2071a9dac0b28ba1e65d5084" + integrity sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg== + dependencies: + is-extglob "^2.1.1" + +is-negative-zero@^2.0.2: + version "2.0.2" + resolved "https://registry.yarnpkg.com/is-negative-zero/-/is-negative-zero-2.0.2.tgz#7bf6f03a28003b8b3965de3ac26f664d765f3150" + integrity sha512-dqJvarLawXsFbNDeJW7zAz8ItJ9cd28YufuuFzh0G8pNHjJMnY08Dv7sYX2uF5UpQOwieAeOExEYAWWfu7ZZUA== + +is-number-object@^1.0.4: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-number-object/-/is-number-object-1.0.7.tgz#59d50ada4c45251784e9904f5246c742f07a42fc" + integrity sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ== + dependencies: + has-tostringtag "^1.0.0" + +is-number@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/is-number/-/is-number-7.0.0.tgz#7535345b896734d5f80c4d06c50955527a14f12b" + integrity sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng== + +is-path-inside@^3.0.3: + version "3.0.3" + resolved "https://registry.yarnpkg.com/is-path-inside/-/is-path-inside-3.0.3.tgz#d231362e53a07ff2b0e0ea7fed049161ffd16283" + integrity sha512-Fd4gABb+ycGAmKou8eMftCupSir5lRxqf4aD/vd0cD2qc4HL07OjCeuHMr8Ro4CoMaeCKDB0/ECBOVWjTwUvPQ== + +is-regex@^1.1.4: + version "1.1.4" + resolved "https://registry.yarnpkg.com/is-regex/-/is-regex-1.1.4.tgz#eef5663cd59fa4c0ae339505323df6854bb15958" + integrity sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg== + dependencies: + call-bind "^1.0.2" + has-tostringtag "^1.0.0" + +is-shared-array-buffer@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-shared-array-buffer/-/is-shared-array-buffer-1.0.2.tgz#8f259c573b60b6a32d4058a1a07430c0a7344c79" + integrity sha512-sqN2UDu1/0y6uvXyStCOzyhAjCSlHceFoMKJW8W9EU9cvic/QdsZ0kEU93HEy3IUEFZIiH/3w+AH/UQbPHNdhA== + dependencies: + call-bind "^1.0.2" + +is-stream@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/is-stream/-/is-stream-3.0.0.tgz#e6bfd7aa6bef69f4f472ce9bb681e3e57b4319ac" + integrity sha512-LnQR4bZ9IADDRSkvpqMGvt/tEJWclzklNgSw48V5EAaAeDd6qGvN8ei6k5p0tvxSR171VmGyHuTiAOfxAbr8kA== + +is-string@^1.0.5, is-string@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/is-string/-/is-string-1.0.7.tgz#0dd12bf2006f255bb58f695110eff7491eebc0fd" + integrity sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg== + dependencies: + has-tostringtag "^1.0.0" + +is-symbol@^1.0.2, is-symbol@^1.0.3: + version "1.0.4" + resolved "https://registry.yarnpkg.com/is-symbol/-/is-symbol-1.0.4.tgz#a6dac93b635b063ca6872236de88910a57af139c" + integrity sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg== + dependencies: + has-symbols "^1.0.2" + +is-typed-array@^1.1.10, is-typed-array@^1.1.9: + version "1.1.10" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.10.tgz#36a5b5cb4189b575d1a3e4b08536bfb485801e3f" + integrity sha512-PJqgEHiWZvMpaFZ3uTc8kHPM4+4ADTlDniuQL7cU/UDA0Ql7F70yGfHph3cLNe+c9toaigv+DFzTJKhc2CtO6A== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +is-typed-array@^1.1.12: + version "1.1.12" + resolved "https://registry.yarnpkg.com/is-typed-array/-/is-typed-array-1.1.12.tgz#d0bab5686ef4a76f7a73097b95470ab199c57d4a" + integrity sha512-Z14TF2JNG8Lss5/HMqt0//T9JeHXttXy5pH/DBU4vi98ozO2btxzq9MwYDZYnKwU8nRsz/+GVFVRDq3DkVuSPg== + dependencies: + which-typed-array "^1.1.11" + +is-weakref@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/is-weakref/-/is-weakref-1.0.2.tgz#9529f383a9338205e89765e0392efc2f100f06f2" + integrity sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ== + dependencies: + call-bind "^1.0.2" + +isarray@^2.0.5: + version "2.0.5" + resolved "https://registry.yarnpkg.com/isarray/-/isarray-2.0.5.tgz#8af1e4c1221244cc62459faf38940d4e644a5723" + integrity sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw== + +isexe@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/isexe/-/isexe-2.0.0.tgz#e8fbf374dc556ff8947a10dcb0572d633f2cfa10" + integrity sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw== + +istanbul-lib-coverage@^3.0.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.0.tgz#189e7909d0a39fa5a3dfad5b03f71947770191d3" + integrity sha512-eOeJ5BHCmHYvQK7xt9GkdHuzuCGS1Y6g9Gvnx3Ym33fz/HpLRYxiS0wHNr+m/MBC8B647Xt608vCDEvhl9c6Mw== + +istanbul-lib-coverage@^3.2.2: + version "3.2.2" + resolved "https://registry.yarnpkg.com/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz#2d166c4b0644d43a39f04bf6c2edd1e585f31756" + integrity sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg== + +istanbul-lib-report@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz#7518fe52ea44de372f460a76b5ecda9ffb73d8a6" + integrity sha512-wcdi+uAKzfiGT2abPpKZ0hSU1rGQjUQnLvtY5MpQ7QCTahD3VODhcu4wcfY1YtkGaDD5yuydOLINXsfbus9ROw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^3.0.0" + supports-color "^7.1.0" + +istanbul-lib-report@^3.0.1: + version "3.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz#908305bac9a5bd175ac6a74489eafd0fc2445a7d" + integrity sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw== + dependencies: + istanbul-lib-coverage "^3.0.0" + make-dir "^4.0.0" + supports-color "^7.1.0" + +istanbul-lib-source-maps@^4.0.1: + version "4.0.1" + resolved "https://registry.yarnpkg.com/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz#895f3a709fcfba34c6de5a42939022f3e4358551" + integrity sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw== + dependencies: + debug "^4.1.1" + istanbul-lib-coverage "^3.0.0" + source-map "^0.6.1" + +istanbul-reports@^3.1.6: + version "3.1.6" + resolved "https://registry.yarnpkg.com/istanbul-reports/-/istanbul-reports-3.1.6.tgz#2544bcab4768154281a2f0870471902704ccaa1a" + integrity sha512-TLgnMkKg3iTDsQ9PbPTdpfAK2DzjF9mqUG7RMgcQl8oFjad8ob4laGxv5XV5U9MAfx8D6tSJiUyuAwzLicaxlg== + dependencies: + html-escaper "^2.0.0" + istanbul-lib-report "^3.0.0" + +js-yaml@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/js-yaml/-/js-yaml-4.1.0.tgz#c1fb65f8f5017901cdd2c951864ba18458a10602" + integrity sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA== + dependencies: + argparse "^2.0.1" + +json-schema-traverse@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz#69f6a87d9513ab8bb8fe63bdb0979c448e684660" + integrity sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg== + +json-stable-stringify-without-jsonify@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz#9db7b59496ad3f3cfef30a75142d2d930ad72651" + integrity sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw== + +json5@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/json5/-/json5-1.0.2.tgz#63d98d60f21b313b77c4d6da18bfa69d80e1d593" + integrity sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA== + dependencies: + minimist "^1.2.0" + +jsonc-parser@^3.2.0: + version "3.2.0" + resolved "https://registry.yarnpkg.com/jsonc-parser/-/jsonc-parser-3.2.0.tgz#31ff3f4c2b9793f89c67212627c51c6394f88e76" + integrity sha512-gfFQZrcTc8CnKXp6Y4/CBT3fTc0OVuDofpre4aEeEpSBPV5X5v4+Vmx+8snU7RLPrNHPKSgLxGo9YuQzz20o+w== + +levn@^0.4.1: + version "0.4.1" + resolved "https://registry.yarnpkg.com/levn/-/levn-0.4.1.tgz#ae4562c007473b932a6200d403268dd2fffc6ade" + integrity sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ== + dependencies: + prelude-ls "^1.2.1" + type-check "~0.4.0" + +local-pkg@^0.5.0: + version "0.5.0" + resolved "https://registry.yarnpkg.com/local-pkg/-/local-pkg-0.5.0.tgz#093d25a346bae59a99f80e75f6e9d36d7e8c925c" + integrity sha512-ok6z3qlYyCDS4ZEU27HaU6x/xZa9Whf8jD4ptH5UZTQYZVYeb9bnZ3ojVhiJNLiXK1Hfc0GNbLXcmZ5plLDDBg== + dependencies: + mlly "^1.4.2" + pkg-types "^1.0.3" + +locate-path@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/locate-path/-/locate-path-6.0.0.tgz#55321eb309febbc59c4801d931a72452a681d286" + integrity sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw== + dependencies: + p-locate "^5.0.0" + +lodash.merge@^4.6.2: + version "4.6.2" + resolved "https://registry.yarnpkg.com/lodash.merge/-/lodash.merge-4.6.2.tgz#558aa53b43b661e1925a0afdfa36a9a1085fe57a" + integrity sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ== + +loupe@^2.3.6: + version "2.3.6" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.6.tgz#76e4af498103c532d1ecc9be102036a21f787b53" + integrity sha512-RaPMZKiMy8/JruncMU5Bt6na1eftNoo++R4Y+N2FrxkDVTrGvcyzFTsaGif4QTeKESheMGegbhw6iUAq+5A8zA== + dependencies: + get-func-name "^2.0.0" + +loupe@^2.3.7: + version "2.3.7" + resolved "https://registry.yarnpkg.com/loupe/-/loupe-2.3.7.tgz#6e69b7d4db7d3ab436328013d37d1c8c3540c697" + integrity sha512-zSMINGVYkdpYSOBmLi0D1Uo7JU9nVdQKrHxC8eYlV+9YKK9WePqAlL7lSlorG/U2Fw1w0hTBmaa/jrQ3UbPHtA== + dependencies: + get-func-name "^2.0.1" + +lru-cache@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/lru-cache/-/lru-cache-6.0.0.tgz#6d6fe6570ebd96aaf90fcad1dafa3b2566db3a94" + integrity sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA== + dependencies: + yallist "^4.0.0" + +magic-string@^0.30.5: + version "0.30.5" + resolved "https://registry.yarnpkg.com/magic-string/-/magic-string-0.30.5.tgz#1994d980bd1c8835dc6e78db7cbd4ae4f24746f9" + integrity sha512-7xlpfBaQaP/T6Vh8MO/EqXSW5En6INHEvEXQiuff7Gku0PWjU3uf6w/j9o7O+SpB5fOAkrI5HeoNgwjEO0pFsA== + dependencies: + "@jridgewell/sourcemap-codec" "^1.4.15" + +magicast@^0.3.2: + version "0.3.2" + resolved "https://registry.yarnpkg.com/magicast/-/magicast-0.3.2.tgz#42dcade5573ed8f10f5540f9d04964e21dba9130" + integrity sha512-Fjwkl6a0syt9TFN0JSYpOybxiMCkYNEeOTnOTNRbjphirLakznZXAqrXgj/7GG3D1dvETONNwrBfinvAbpunDg== + dependencies: + "@babel/parser" "^7.23.3" + "@babel/types" "^7.23.3" + source-map-js "^1.0.2" + +make-dir@^3.0.0: + version "3.1.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-3.1.0.tgz#415e967046b3a7f1d185277d84aa58203726a13f" + integrity sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw== + dependencies: + semver "^6.0.0" + +make-dir@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/make-dir/-/make-dir-4.0.0.tgz#c3c2307a771277cd9638305f915c29ae741b614e" + integrity sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw== + dependencies: + semver "^7.5.3" + +merge-stream@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/merge-stream/-/merge-stream-2.0.0.tgz#52823629a14dd00c9770fb6ad47dc6310f2c1f60" + integrity sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w== + +merge2@^1.3.0, merge2@^1.4.1: + version "1.4.1" + resolved "https://registry.yarnpkg.com/merge2/-/merge2-1.4.1.tgz#4368892f885e907455a6fd7dc55c0c9d404990ae" + integrity sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg== + +micromatch@^4.0.4: + version "4.0.5" + resolved "https://registry.yarnpkg.com/micromatch/-/micromatch-4.0.5.tgz#bc8999a7cbbf77cdc89f132f6e467051b49090c6" + integrity sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA== + dependencies: + braces "^3.0.2" + picomatch "^2.3.1" + +mimic-fn@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/mimic-fn/-/mimic-fn-4.0.0.tgz#60a90550d5cb0b239cca65d893b1a53b29871ecc" + integrity sha512-vqiC06CuhBTUdZH+RYl8sFrL096vA45Ok5ISO6sE/Mr1jRbGH4Csnhi8f3wKVl7x8mO4Au7Ir9D3Oyv1VYMFJw== + +minimatch@9.0.3: + version "9.0.3" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-9.0.3.tgz#a6e00c3de44c3a542bfaae70abfc22420a6da825" + integrity sha512-RHiac9mvaRw0x3AYRgDC1CxAP7HTcNrrECeA8YYJeWnpo+2Q5CegtZjaotWTWxDG3UeGA1coE05iH1mPjT/2mg== + dependencies: + brace-expansion "^2.0.1" + +minimatch@^3.0.4, minimatch@^3.0.5, minimatch@^3.1.1, minimatch@^3.1.2: + version "3.1.2" + resolved "https://registry.yarnpkg.com/minimatch/-/minimatch-3.1.2.tgz#19cd194bfd3e428f049a70817c038d89ab4be35b" + integrity sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw== + dependencies: + brace-expansion "^1.1.7" + +minimist@^1.2.0, minimist@^1.2.6: + version "1.2.8" + resolved "https://registry.yarnpkg.com/minimist/-/minimist-1.2.8.tgz#c1a464e7693302e082a075cee0c057741ac4772c" + integrity sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA== + +mlly@^1.2.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.3.0.tgz#3184cb80c6437bda861a9f452ae74e3434ed9cd1" + integrity sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw== + dependencies: + acorn "^8.8.2" + pathe "^1.1.0" + pkg-types "^1.0.3" + ufo "^1.1.2" + +mlly@^1.4.2: + version "1.4.2" + resolved "https://registry.yarnpkg.com/mlly/-/mlly-1.4.2.tgz#7cf406aa319ff6563d25da6b36610a93f2a8007e" + integrity sha512-i/Ykufi2t1EZ6NaPLdfnZk2AX8cs0d+mTzVKuPfqPKPatxLApaBoxJQ9x1/uckXtrS/U5oisPMDkNs0yQTaBRg== + dependencies: + acorn "^8.10.0" + pathe "^1.1.1" + pkg-types "^1.0.3" + ufo "^1.3.0" + +ms@2.1.2: + version "2.1.2" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.2.tgz#d09d1f357b443f493382a8eb3ccd183872ae6009" + integrity sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w== + +ms@^2.1.1: + version "2.1.3" + resolved "https://registry.yarnpkg.com/ms/-/ms-2.1.3.tgz#574c8138ce1d2b5861f0b44579dbadd60c6615b2" + integrity sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA== + +nanoid@^3.3.7: + version "3.3.7" + resolved "https://registry.yarnpkg.com/nanoid/-/nanoid-3.3.7.tgz#d0c301a691bc8d54efa0a2226ccf3fe2fd656bd8" + integrity sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g== + +natural-compare@^1.4.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/natural-compare/-/natural-compare-1.4.0.tgz#4abebfeed7541f2c27acfb29bdbbd15c8d5ba4f7" + integrity sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw== + +npm-run-path@^5.1.0: + version "5.1.0" + resolved "https://registry.yarnpkg.com/npm-run-path/-/npm-run-path-5.1.0.tgz#bc62f7f3f6952d9894bd08944ba011a6ee7b7e00" + integrity sha512-sJOdmRGrY2sjNTRMbSvluQqg+8X7ZK61yvzBEIDhz4f8z1TZFYABsqjjCBd/0PUNE9M6QDgHJXQkGUEm7Q+l9Q== + dependencies: + path-key "^4.0.0" + +object-inspect@^1.13.1: + version "1.13.1" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.13.1.tgz#b96c6109324ccfef6b12216a956ca4dc2ff94bc2" + integrity sha512-5qoj1RUiKOMsCCNLV1CBiPYE10sziTsnmNxkAI/rZhiD63CF7IqdFGC/XzjWjpSgLf0LxXX3bDFIh0E18f6UhQ== + +object-inspect@^1.9.0: + version "1.12.3" + resolved "https://registry.yarnpkg.com/object-inspect/-/object-inspect-1.12.3.tgz#ba62dffd67ee256c8c086dfae69e016cd1f198b9" + integrity sha512-geUvdk7c+eizMNUDkRpW1wJwgfOiOeHbxBR/hLXK1aT6zmVSO0jsQcs7fj6MGw89jC/cjGfLcNOrtMYtGqm81g== + +object-keys@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/object-keys/-/object-keys-1.1.1.tgz#1c47f272df277f3b1daf061677d9c82e2322c60e" + integrity sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA== + +object.assign@^4.1.4: + version "4.1.4" + resolved "https://registry.yarnpkg.com/object.assign/-/object.assign-4.1.4.tgz#9673c7c7c351ab8c4d0b516f4343ebf4dfb7799f" + integrity sha512-1mxKf0e58bvyjSCtKYY4sRe9itRk3PJpquJOjeIkz885CczcI4IvJJDLPS72oowuSh+pBxUFROpX+TU++hxhZQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.1.4" + has-symbols "^1.0.3" + object-keys "^1.1.1" + +object.fromentries@^2.0.7: + version "2.0.7" + resolved "https://registry.yarnpkg.com/object.fromentries/-/object.fromentries-2.0.7.tgz#71e95f441e9a0ea6baf682ecaaf37fa2a8d7e616" + integrity sha512-UPbPHML6sL8PI/mOqPwsH4G6iyXcCGzLin8KvEPenOZN5lpCNBZZQ+V62vdjB1mQHrmqGQt5/OJzemUA+KJmEA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +object.groupby@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/object.groupby/-/object.groupby-1.0.1.tgz#d41d9f3c8d6c778d9cbac86b4ee9f5af103152ee" + integrity sha512-HqaQtqLnp/8Bn4GL16cj+CUYbnpe1bh0TtEaWvybszDG4tgxCJuRpV8VGuvNaI1fAnI4lUJzDG55MXcOH4JZcQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + get-intrinsic "^1.2.1" + +object.values@^1.1.7: + version "1.1.7" + resolved "https://registry.yarnpkg.com/object.values/-/object.values-1.1.7.tgz#617ed13272e7e1071b43973aa1655d9291b8442a" + integrity sha512-aU6xnDFYT3x17e/f0IiiwlGPTy2jzMySGfUB4fq6z7CV8l85CWHDk5ErhyhpfDHhrOMwGFhSQkhMGHaIotA6Ng== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +once@^1.3.0: + version "1.4.0" + resolved "https://registry.yarnpkg.com/once/-/once-1.4.0.tgz#583b1aa775961d4b113ac17d9c50baef9dd76bd1" + integrity sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w== + dependencies: + wrappy "1" + +onetime@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/onetime/-/onetime-6.0.0.tgz#7c24c18ed1fd2e9bca4bd26806a33613c77d34b4" + integrity sha512-1FlR+gjXK7X+AsAHso35MnyN5KqGwJRi/31ft6x0M194ht7S+rWAvd7PHss9xSKMzE0asv1pyIHaJYq+BbacAQ== + dependencies: + mimic-fn "^4.0.0" + +optionator@^0.9.3: + version "0.9.3" + resolved "https://registry.yarnpkg.com/optionator/-/optionator-0.9.3.tgz#007397d44ed1872fdc6ed31360190f81814e2c64" + integrity sha512-JjCoypp+jKn1ttEFExxhetCKeJt9zhAgAve5FXHixTvFDW/5aEktX9bufBKLRRMdU7bNtpLfcGu94B3cdEJgjg== + dependencies: + "@aashutoshrathi/word-wrap" "^1.2.3" + deep-is "^0.1.3" + fast-levenshtein "^2.0.6" + levn "^0.4.1" + prelude-ls "^1.2.1" + type-check "^0.4.0" + +p-limit@^3.0.2: + version "3.1.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-3.1.0.tgz#e1daccbe78d0d1388ca18c64fea38e3e57e3706b" + integrity sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ== + dependencies: + yocto-queue "^0.1.0" + +p-limit@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-limit/-/p-limit-5.0.0.tgz#6946d5b7140b649b7a33a027d89b4c625b3a5985" + integrity sha512-/Eaoq+QyLSiXQ4lyYV23f14mZRQcXnxfHrN0vCai+ak9G0pp9iEQukIIZq5NccEvwRB8PUnZT0KsOoDCINS1qQ== + dependencies: + yocto-queue "^1.0.0" + +p-locate@^5.0.0: + version "5.0.0" + resolved "https://registry.yarnpkg.com/p-locate/-/p-locate-5.0.0.tgz#83c8315c6785005e3bd021839411c9e110e6d834" + integrity sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw== + dependencies: + p-limit "^3.0.2" + +parent-module@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/parent-module/-/parent-module-1.0.1.tgz#691d2709e78c79fae3a156622452d00762caaaa2" + integrity sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g== + dependencies: + callsites "^3.0.0" + +path-exists@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-exists/-/path-exists-4.0.0.tgz#513bdbe2d3b95d7762e8c1137efa195c6c61b5b3" + integrity sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w== + +path-is-absolute@^1.0.0: + version "1.0.1" + resolved "https://registry.yarnpkg.com/path-is-absolute/-/path-is-absolute-1.0.1.tgz#174b9268735534ffbc7ace6bf53a5a9e1b5c5f5f" + integrity sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg== + +path-key@^3.1.0: + version "3.1.1" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-3.1.1.tgz#581f6ade658cbba65a0d3380de7753295054f375" + integrity sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q== + +path-key@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-key/-/path-key-4.0.0.tgz#295588dc3aee64154f877adb9d780b81c554bf18" + integrity sha512-haREypq7xkM7ErfgIyA0z+Bj4AGKlMSdlQE2jvJo6huWD1EdkKYV+G/T4nq0YEF2vgTT8kqMFKo1uHn950r4SQ== + +path-parse@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/path-parse/-/path-parse-1.0.7.tgz#fbc114b60ca42b30d9daf5858e4bd68bbedb6735" + integrity sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw== + +path-type@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/path-type/-/path-type-4.0.0.tgz#84ed01c0a7ba380afe09d90a8c180dcd9d03043b" + integrity sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw== + +pathe@^1.1.0, pathe@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathe/-/pathe-1.1.1.tgz#1dd31d382b974ba69809adc9a7a347e65d84829a" + integrity sha512-d+RQGp0MAYTIaDBIMmOfMwz3E+LOZnxx1HZd5R18mmCZY0QBlK0LDZfPc8FW8Ed2DlvsuE6PRjroDY+wg4+j/Q== + +pathval@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/pathval/-/pathval-1.1.1.tgz#8534e77a77ce7ac5a2512ea21e0fdb8fcf6c3d8d" + integrity sha512-Dp6zGqpTdETdR63lehJYPeIOqpiNBNtc7BpWSLrOje7UaIsE5aY92r/AunQA7rsXvet3lrJ3JnZX29UPTKXyKQ== + +picocolors@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/picocolors/-/picocolors-1.0.0.tgz#cb5bdc74ff3f51892236eaf79d68bc44564ab81c" + integrity sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ== + +picomatch@^2.3.1: + version "2.3.1" + resolved "https://registry.yarnpkg.com/picomatch/-/picomatch-2.3.1.tgz#3ba3833733646d9d3e4995946c1365a67fb07a42" + integrity sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA== + +pkg-types@^1.0.3: + version "1.0.3" + resolved "https://registry.yarnpkg.com/pkg-types/-/pkg-types-1.0.3.tgz#988b42ab19254c01614d13f4f65a2cfc7880f868" + integrity sha512-nN7pYi0AQqJnoLPC9eHFQ8AcyaixBUOwvqc5TDnIKCMEE6I0y8P7OKA7fPexsXGCGxQDl/cmrLAp26LhcwxZ4A== + dependencies: + jsonc-parser "^3.2.0" + mlly "^1.2.0" + pathe "^1.1.0" + +postcss@^8.4.32: + version "8.4.32" + resolved "https://registry.yarnpkg.com/postcss/-/postcss-8.4.32.tgz#1dac6ac51ab19adb21b8b34fd2d93a86440ef6c9" + integrity sha512-D/kj5JNu6oo2EIy+XL/26JEDTlIbB8hw85G8StOE6L74RQAVVP5rej6wxCNqyMbR4RkPfqvezVbPw81Ngd6Kcw== + dependencies: + nanoid "^3.3.7" + picocolors "^1.0.0" + source-map-js "^1.0.2" + +prelude-ls@^1.2.1: + version "1.2.1" + resolved "https://registry.yarnpkg.com/prelude-ls/-/prelude-ls-1.2.1.tgz#debc6489d7a6e6b0e7611888cec880337d316396" + integrity sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g== + +prettier@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/prettier/-/prettier-3.1.1.tgz#6ba9f23165d690b6cbdaa88cb0807278f7019848" + integrity sha512-22UbSzg8luF4UuZtzgiUOfcGM8s4tjBv6dJRT7j275NXsy2jb4aJa4NNveul5x4eqlF1wuhuR2RElK71RvmVaw== + +pretty-format@^29.7.0: + version "29.7.0" + resolved "https://registry.yarnpkg.com/pretty-format/-/pretty-format-29.7.0.tgz#ca42c758310f365bfa71a0bda0a807160b776812" + integrity sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ== + dependencies: + "@jest/schemas" "^29.6.3" + ansi-styles "^5.0.0" + react-is "^18.0.0" + +punycode@^2.1.0: + version "2.3.0" + resolved "https://registry.yarnpkg.com/punycode/-/punycode-2.3.0.tgz#f67fa67c94da8f4d0cfff981aee4118064199b8f" + integrity sha512-rRV+zQD8tVFys26lAGR9WUuS4iUAngJScM+ZRSKtvl5tKeZ2t5bvdNFdNHBW9FWR4guGHlgmsZ1G7BSm2wTbuA== + +queue-microtask@^1.2.2: + version "1.2.3" + resolved "https://registry.yarnpkg.com/queue-microtask/-/queue-microtask-1.2.3.tgz#4929228bbc724dfac43e0efb058caf7b6cfb6243" + integrity sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A== + +react-is@^18.0.0: + version "18.2.0" + resolved "https://registry.yarnpkg.com/react-is/-/react-is-18.2.0.tgz#199431eeaaa2e09f86427efbb4f1473edb47609b" + integrity sha512-xWGDIW6x921xtzPkhiULtthJHoJvBbF3q26fzloPCK0hsvxtPVelvftw3zjbHWSkR2km9Z+4uxbDDK/6Zw9B8w== + +regexp.prototype.flags@^1.5.1: + version "1.5.1" + resolved "https://registry.yarnpkg.com/regexp.prototype.flags/-/regexp.prototype.flags-1.5.1.tgz#90ce989138db209f81492edd734183ce99f9677e" + integrity sha512-sy6TXMN+hnP/wMy+ISxg3krXx7BAtWVO4UouuCN/ziM9UEne0euamVNafDfvC83bRNr95y0V5iijeDQFUNpvrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + set-function-name "^2.0.0" + +require-directory@^2.1.1: + version "2.1.1" + resolved "https://registry.yarnpkg.com/require-directory/-/require-directory-2.1.1.tgz#8c64ad5fd30dab1c976e2344ffe7f792a6a6df42" + integrity sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q== + +requireindex@~1.2.0: + version "1.2.0" + resolved "https://registry.yarnpkg.com/requireindex/-/requireindex-1.2.0.tgz#3463cdb22ee151902635aa6c9535d4de9c2ef1ef" + integrity sha512-L9jEkOi3ASd9PYit2cwRfyppc9NoABujTP8/5gFcbERmo5jUoAKovIC3fsF17pkTnGsrByysqX+Kxd2OTNI1ww== + +resolve-from@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/resolve-from/-/resolve-from-4.0.0.tgz#4abcd852ad32dd7baabfe9b40e00a36db5f392e6" + integrity sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g== + +resolve-pkg-maps@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/resolve-pkg-maps/-/resolve-pkg-maps-1.0.0.tgz#616b3dc2c57056b5588c31cdf4b3d64db133720f" + integrity sha512-seS2Tj26TBVOC2NIc2rOe2y2ZO7efxITtLZcGSOnHHNOQ7CkiUBfw0Iw2ck6xkIhPwLhKNLS8BO+hEpngQlqzw== + +resolve@^1.22.2: + version "1.22.2" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.2.tgz#0ed0943d4e301867955766c9f3e1ae6d01c6845f" + integrity sha512-Sb+mjNHOULsBv818T40qSPeRiuWLyaGMa5ewydRLFimneixmVy2zdivRl+AF6jaYPC8ERxGDmFSiqui6SfPd+g== + dependencies: + is-core-module "^2.11.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +resolve@^1.22.4: + version "1.22.8" + resolved "https://registry.yarnpkg.com/resolve/-/resolve-1.22.8.tgz#b6c87a9f2aa06dfab52e3d70ac8cde321fa5a48d" + integrity sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw== + dependencies: + is-core-module "^2.13.0" + path-parse "^1.0.7" + supports-preserve-symlinks-flag "^1.0.0" + +reusify@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/reusify/-/reusify-1.0.4.tgz#90da382b1e126efc02146e90845a88db12925d76" + integrity sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw== + +rimraf@^3.0.2: + version "3.0.2" + resolved "https://registry.yarnpkg.com/rimraf/-/rimraf-3.0.2.tgz#f1a5402ba6220ad52cc1282bac1ae3aa49fd061a" + integrity sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA== + dependencies: + glob "^7.1.3" + +rollup@^4.2.0: + version "4.9.1" + resolved "https://registry.yarnpkg.com/rollup/-/rollup-4.9.1.tgz#351d6c03e4e6bcd7a0339df3618d2aeeb108b507" + integrity sha512-pgPO9DWzLoW/vIhlSoDByCzcpX92bKEorbgXuZrqxByte3JFk2xSW2JEeAcyLc9Ru9pqcNNW+Ob7ntsk2oT/Xw== + optionalDependencies: + "@rollup/rollup-android-arm-eabi" "4.9.1" + "@rollup/rollup-android-arm64" "4.9.1" + "@rollup/rollup-darwin-arm64" "4.9.1" + "@rollup/rollup-darwin-x64" "4.9.1" + "@rollup/rollup-linux-arm-gnueabihf" "4.9.1" + "@rollup/rollup-linux-arm64-gnu" "4.9.1" + "@rollup/rollup-linux-arm64-musl" "4.9.1" + "@rollup/rollup-linux-riscv64-gnu" "4.9.1" + "@rollup/rollup-linux-x64-gnu" "4.9.1" + "@rollup/rollup-linux-x64-musl" "4.9.1" + "@rollup/rollup-win32-arm64-msvc" "4.9.1" + "@rollup/rollup-win32-ia32-msvc" "4.9.1" + "@rollup/rollup-win32-x64-msvc" "4.9.1" + fsevents "~2.3.2" + +run-parallel@^1.1.9: + version "1.2.0" + resolved "https://registry.yarnpkg.com/run-parallel/-/run-parallel-1.2.0.tgz#66d1368da7bdf921eb9d95bd1a9229e7f21a43ee" + integrity sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA== + dependencies: + queue-microtask "^1.2.2" + +safe-array-concat@^1.0.1: + version "1.0.1" + resolved "https://registry.yarnpkg.com/safe-array-concat/-/safe-array-concat-1.0.1.tgz#91686a63ce3adbea14d61b14c99572a8ff84754c" + integrity sha512-6XbUAseYE2KtOuGueyeobCySj9L4+66Tn6KQMOPQJrAJEowYKW/YR/MGJZl7FdydUdaFu4LYyDZjxf4/Nmo23Q== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + has-symbols "^1.0.3" + isarray "^2.0.5" + +safe-regex-test@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/safe-regex-test/-/safe-regex-test-1.0.0.tgz#793b874d524eb3640d1873aad03596db2d4f2295" + integrity sha512-JBUUzyOgEwXQY1NuPtvcj/qcBDbDmEvWufhlnXZIm75DEHp+afM1r1ujJpJsV/gSM4t59tpDyPi1sd6ZaPFfsA== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.1.3" + is-regex "^1.1.4" + +semver@^6.0.0: + version "6.3.0" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.0.tgz#ee0a64c8af5e8ceea67687b133761e1becbd1d3d" + integrity sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw== + +semver@^6.3.1: + version "6.3.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-6.3.1.tgz#556d2ef8689146e46dcea4bfdd095f3434dffcb4" + integrity sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA== + +semver@^7.3.7: + version "7.5.1" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.1.tgz#c90c4d631cf74720e46b21c1d37ea07edfab91ec" + integrity sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw== + dependencies: + lru-cache "^6.0.0" + +semver@^7.5.3, semver@^7.5.4: + version "7.5.4" + resolved "https://registry.yarnpkg.com/semver/-/semver-7.5.4.tgz#483986ec4ed38e1c6c48c34894a9182dbff68a6e" + integrity sha512-1bCSESV6Pv+i21Hvpxp3Dx+pSD8lIPt8uVjRrxAUt/nbswYc+tK6Y2btiULjd4+fnq15PX+nqQDC7Oft7WkwcA== + dependencies: + lru-cache "^6.0.0" + +set-function-length@^1.1.1: + version "1.1.1" + resolved "https://registry.yarnpkg.com/set-function-length/-/set-function-length-1.1.1.tgz#4bc39fafb0307224a33e106a7d35ca1218d659ed" + integrity sha512-VoaqjbBJKiWtg4yRcKBQ7g7wnGnLV3M8oLvVWwOk2PdYY6PEFegR1vezXR0tw6fZGF9csVakIRjrJiy2veSBFQ== + dependencies: + define-data-property "^1.1.1" + get-intrinsic "^1.2.1" + gopd "^1.0.1" + has-property-descriptors "^1.0.0" + +set-function-name@^2.0.0: + version "2.0.1" + resolved "https://registry.yarnpkg.com/set-function-name/-/set-function-name-2.0.1.tgz#12ce38b7954310b9f61faa12701620a0c882793a" + integrity sha512-tMNCiqYVkXIZgc2Hnoy2IvC/f8ezc5koaRFkCjrpWzGpCd3qbZXPzVy9MAZzK1ch/X0jvSkojys3oqJN0qCmdA== + dependencies: + define-data-property "^1.0.1" + functions-have-names "^1.2.3" + has-property-descriptors "^1.0.0" + +shebang-command@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/shebang-command/-/shebang-command-2.0.0.tgz#ccd0af4f8835fbdc265b82461aaf0c36663f34ea" + integrity sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA== + dependencies: + shebang-regex "^3.0.0" + +shebang-regex@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/shebang-regex/-/shebang-regex-3.0.0.tgz#ae16f1644d873ecad843b0307b143362d4c42172" + integrity sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A== + +side-channel@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/side-channel/-/side-channel-1.0.4.tgz#efce5c8fdc104ee751b25c58d4290011fa5ea2cf" + integrity sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw== + dependencies: + call-bind "^1.0.0" + get-intrinsic "^1.0.2" + object-inspect "^1.9.0" + +siginfo@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/siginfo/-/siginfo-2.0.0.tgz#32e76c70b79724e3bb567cb9d543eb858ccfaf30" + integrity sha512-ybx0WO1/8bSBLEWXZvEd7gMW3Sn3JFlW3TvX1nREbDLRNQNaeNN8WK0meBwPdAaOI7TtRRRJn/Es1zhrrCHu7g== + +signal-exit@^4.1.0: + version "4.1.0" + resolved "https://registry.yarnpkg.com/signal-exit/-/signal-exit-4.1.0.tgz#952188c1cbd546070e2dd20d0f41c0ae0530cb04" + integrity sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw== + +slash@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/slash/-/slash-3.0.0.tgz#6539be870c165adbd5240220dbe361f1bc4d4634" + integrity sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q== + +source-map-js@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/source-map-js/-/source-map-js-1.0.2.tgz#adbc361d9c62df380125e7f161f71c826f1e490c" + integrity sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw== + +source-map@^0.6.1: + version "0.6.1" + resolved "https://registry.yarnpkg.com/source-map/-/source-map-0.6.1.tgz#74722af32e9614e9c287a8d0bbde48b5e2f1a263" + integrity sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g== + +stackback@0.0.2: + version "0.0.2" + resolved "https://registry.yarnpkg.com/stackback/-/stackback-0.0.2.tgz#1ac8a0d9483848d1695e418b6d031a3c3ce68e3b" + integrity sha512-1XMJE5fQo1jGH6Y/7ebnwPOBEkIEnT4QF32d5R1+VXdXveM0IBMJt8zfaxX1P3QhVwrYe+576+jkANtSS2mBbw== + +std-env@^3.5.0: + version "3.7.0" + resolved "https://registry.yarnpkg.com/std-env/-/std-env-3.7.0.tgz#c9f7386ced6ecf13360b6c6c55b8aaa4ef7481d2" + integrity sha512-JPbdCEQLj1w5GilpiHAx3qJvFndqybBysA3qUOnznweH4QbNYUsW/ea8QzSrnh0vNsezMMw5bcVool8lM0gwzg== + +string-width@^4.1.0, string-width@^4.2.0, string-width@^4.2.3: + version "4.2.3" + resolved "https://registry.yarnpkg.com/string-width/-/string-width-4.2.3.tgz#269c7117d27b05ad2e536830a8ec895ef9c6d010" + integrity sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g== + dependencies: + emoji-regex "^8.0.0" + is-fullwidth-code-point "^3.0.0" + strip-ansi "^6.0.1" + +string.prototype.trim@^1.2.8: + version "1.2.8" + resolved "https://registry.yarnpkg.com/string.prototype.trim/-/string.prototype.trim-1.2.8.tgz#f9ac6f8af4bd55ddfa8895e6aea92a96395393bd" + integrity sha512-lfjY4HcixfQXOfaqCvcBuOIapyaroTXhbkfJN3gcB1OtyupngWK4sEET9Knd0cXd28kTUqu/kHoV4HKSJdnjiQ== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimend@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimend/-/string.prototype.trimend-1.0.7.tgz#1bb3afc5008661d73e2dc015cd4853732d6c471e" + integrity sha512-Ni79DqeB72ZFq1uH/L6zJ+DKZTkOtPIHovb3YZHQViE+HDouuU4mBrLOLDn5Dde3RF8qw5qVETEjhu9locMLvA== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +string.prototype.trimstart@^1.0.7: + version "1.0.7" + resolved "https://registry.yarnpkg.com/string.prototype.trimstart/-/string.prototype.trimstart-1.0.7.tgz#d4cdb44b83a4737ffbac2d406e405d43d0184298" + integrity sha512-NGhtDFu3jCEm7B4Fy0DpLewdJQOZcQ0rGbwQ/+stjnrp2i+rlKeCvos9hOIeCmqwratM47OBxY7uFZzjxHXmrg== + dependencies: + call-bind "^1.0.2" + define-properties "^1.2.0" + es-abstract "^1.22.1" + +strip-ansi@^6.0.0, strip-ansi@^6.0.1: + version "6.0.1" + resolved "https://registry.yarnpkg.com/strip-ansi/-/strip-ansi-6.0.1.tgz#9e26c63d30f53443e9489495b2105d37b67a85d9" + integrity sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A== + dependencies: + ansi-regex "^5.0.1" + +strip-bom@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-bom/-/strip-bom-3.0.0.tgz#2334c18e9c759f7bdd56fdef7e9ae3d588e68ed3" + integrity sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA== + +strip-final-newline@^3.0.0: + version "3.0.0" + resolved "https://registry.yarnpkg.com/strip-final-newline/-/strip-final-newline-3.0.0.tgz#52894c313fbff318835280aed60ff71ebf12b8fd" + integrity sha512-dOESqjYr96iWYylGObzd39EuNTa5VJxyvVAEm5Jnh7KGo75V43Hk1odPQkNDyXNmUR6k+gEiDVXnjB8HJ3crXw== + +strip-json-comments@^3.1.1: + version "3.1.1" + resolved "https://registry.yarnpkg.com/strip-json-comments/-/strip-json-comments-3.1.1.tgz#31f1281b3832630434831c310c01cccda8cbe006" + integrity sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig== + +strip-literal@^1.3.0: + version "1.3.0" + resolved "https://registry.yarnpkg.com/strip-literal/-/strip-literal-1.3.0.tgz#db3942c2ec1699e6836ad230090b84bb458e3a07" + integrity sha512-PugKzOsyXpArk0yWmUwqOZecSO0GH0bPoctLcqNDH9J04pVW3lflYE0ujElBGTloevcxF5MofAOZ7C5l2b+wLg== + dependencies: + acorn "^8.10.0" + +supports-color@^7.1.0: + version "7.2.0" + resolved "https://registry.yarnpkg.com/supports-color/-/supports-color-7.2.0.tgz#1b7dcdcb32b8138801b3e478ba6a51caa89648da" + integrity sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw== + dependencies: + has-flag "^4.0.0" + +supports-preserve-symlinks-flag@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz#6eda4bd344a3c94aea376d4cc31bc77311039e09" + integrity sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w== + +tapable@^2.2.0: + version "2.2.1" + resolved "https://registry.yarnpkg.com/tapable/-/tapable-2.2.1.tgz#1967a73ef4060a82f12ab96af86d52fdb76eeca0" + integrity sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ== + +test-exclude@^6.0.0: + version "6.0.0" + resolved "https://registry.yarnpkg.com/test-exclude/-/test-exclude-6.0.0.tgz#04a8698661d805ea6fa293b6cb9e63ac044ef15e" + integrity sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w== + dependencies: + "@istanbuljs/schema" "^0.1.2" + glob "^7.1.4" + minimatch "^3.0.4" + +text-table@^0.2.0: + version "0.2.0" + resolved "https://registry.yarnpkg.com/text-table/-/text-table-0.2.0.tgz#7f5ee823ae805207c00af2df4a84ec3fcfa570b4" + integrity sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw== + +tinybench@^2.5.1: + version "2.5.1" + resolved "https://registry.yarnpkg.com/tinybench/-/tinybench-2.5.1.tgz#3408f6552125e53a5a48adee31261686fd71587e" + integrity sha512-65NKvSuAVDP/n4CqH+a9w2kTlLReS9vhsAP06MWx+/89nMinJyB2icyl58RIcqCmIggpojIGeuJGhjU1aGMBSg== + +tinypool@^0.8.1: + version "0.8.1" + resolved "https://registry.yarnpkg.com/tinypool/-/tinypool-0.8.1.tgz#b6c4e4972ede3e3e5cda74a3da1679303d386b03" + integrity sha512-zBTCK0cCgRROxvs9c0CGK838sPkeokNGdQVUUwHAbynHFlmyJYj825f/oRs528HaIJ97lo0pLIlDUzwN+IorWg== + +tinyspy@^2.2.0: + version "2.2.0" + resolved "https://registry.yarnpkg.com/tinyspy/-/tinyspy-2.2.0.tgz#9dc04b072746520b432f77ea2c2d17933de5d6ce" + integrity sha512-d2eda04AN/cPOR89F7Xv5bK/jrQEhmcLFe6HFldoeO9AJtps+fqEnh486vnT/8y4bw38pSyxDcTCAq+Ks2aJTg== + +to-fast-properties@^2.0.0: + version "2.0.0" + resolved "https://registry.yarnpkg.com/to-fast-properties/-/to-fast-properties-2.0.0.tgz#dc5e698cbd079265bc73e0377681a4e4e83f616e" + integrity sha512-/OaKK0xYrs3DmxRYqL/yDc+FxFUVYhDlXMhRmv3z915w2HF1tnN1omB354j8VUGO/hbRzyD6Y3sA7v7GS/ceog== + +to-regex-range@^5.0.1: + version "5.0.1" + resolved "https://registry.yarnpkg.com/to-regex-range/-/to-regex-range-5.0.1.tgz#1648c44aae7c8d988a326018ed72f5b4dd0392e4" + integrity sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ== + dependencies: + is-number "^7.0.0" + +ts-api-utils@^1.0.1: + version "1.0.3" + resolved "https://registry.yarnpkg.com/ts-api-utils/-/ts-api-utils-1.0.3.tgz#f12c1c781d04427313dbac808f453f050e54a331" + integrity sha512-wNMeqtMz5NtwpT/UZGY5alT+VoKdSsOOP/kqHFcUW1P/VRhH2wJ48+DN2WwUliNbQ976ETwDL0Ifd2VVvgonvg== + +tsconfig-paths@^3.15.0: + version "3.15.0" + resolved "https://registry.yarnpkg.com/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz#5299ec605e55b1abb23ec939ef15edaf483070d4" + integrity sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg== + dependencies: + "@types/json5" "^0.0.29" + json5 "^1.0.2" + minimist "^1.2.6" + strip-bom "^3.0.0" + +tslib@^1.8.1: + version "1.14.1" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-1.14.1.tgz#cf2d38bdc34a134bcaf1091c41f6619e2f672d00" + integrity sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg== + +tslib@^2.0.0: + version "2.5.3" + resolved "https://registry.yarnpkg.com/tslib/-/tslib-2.5.3.tgz#24944ba2d990940e6e982c4bea147aba80209913" + integrity sha512-mSxlJJwl3BMEQCUNnxXBU9jP4JBktcEGhURcPR6VQVlnP0FdDEsIaz0C35dXNGLyRfrATNofF0F5p2KPxQgB+w== + +tsutils-etc@^1.4.1: + version "1.4.2" + resolved "https://registry.yarnpkg.com/tsutils-etc/-/tsutils-etc-1.4.2.tgz#6d6a9f33aa61867d832e4a455b2cebb6b104ebfa" + integrity sha512-2Dn5SxTDOu6YWDNKcx1xu2YUy6PUeKrWZB/x2cQ8vY2+iz3JRembKn/iZ0JLT1ZudGNwQQvtFX9AwvRHbXuPUg== + dependencies: + "@types/yargs" "^17.0.0" + yargs "^17.0.0" + +tsutils@^3.0.0, tsutils@^3.17.1, tsutils@^3.21.0: + version "3.21.0" + resolved "https://registry.yarnpkg.com/tsutils/-/tsutils-3.21.0.tgz#b48717d394cea6c1e096983eed58e9d61715b623" + integrity sha512-mHKK3iUXL+3UF6xL5k0PEhKRUBKPBCv/+RkEOpjRWxxx27KKRBmmA60A9pgOUvMi8GKhRMPEmjBRPzs2W7O1OA== + dependencies: + tslib "^1.8.1" + +type-check@^0.4.0, type-check@~0.4.0: + version "0.4.0" + resolved "https://registry.yarnpkg.com/type-check/-/type-check-0.4.0.tgz#07b8203bfa7056c0657050e3ccd2c37730bab8f1" + integrity sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew== + dependencies: + prelude-ls "^1.2.1" + +type-detect@^4.0.0, type-detect@^4.0.8: + version "4.0.8" + resolved "https://registry.yarnpkg.com/type-detect/-/type-detect-4.0.8.tgz#7646fb5f18871cfbb7749e69bd39a6388eb7450c" + integrity sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g== + +type-fest@^0.20.2: + version "0.20.2" + resolved "https://registry.yarnpkg.com/type-fest/-/type-fest-0.20.2.tgz#1bf207f4b28f91583666cb5fbd327887301cd5f4" + integrity sha512-Ne+eE4r0/iWnpAxD852z3A+N0Bt5RN//NjJwRd2VFHEmrywxf5vsZlh4R6lixl6B+wz/8d+maTSAkN1FIkI3LQ== + +typed-array-buffer@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-buffer/-/typed-array-buffer-1.0.0.tgz#18de3e7ed7974b0a729d3feecb94338d1472cd60" + integrity sha512-Y8KTSIglk9OZEr8zywiIHG/kmQ7KWyjseXs1CbSo8vC42w7hg2HgYTxSWwP0+is7bWDc1H+Fo026CpHFwm8tkw== + dependencies: + call-bind "^1.0.2" + get-intrinsic "^1.2.1" + is-typed-array "^1.1.10" + +typed-array-byte-length@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-length/-/typed-array-byte-length-1.0.0.tgz#d787a24a995711611fb2b87a4052799517b230d0" + integrity sha512-Or/+kvLxNpeQ9DtSydonMxCx+9ZXOswtwJn17SNLvhptaXYDJvkFFP5zbfU/uLmvnBJlI4yrnXRxpdWH/M5tNA== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-byte-offset@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/typed-array-byte-offset/-/typed-array-byte-offset-1.0.0.tgz#cbbe89b51fdef9cd6aaf07ad4707340abbc4ea0b" + integrity sha512-RD97prjEt9EL8YgAgpOkf3O4IF9lhJFr9g0htQkm0rchFp/Vx7LW5Q8fSXXub7BXAODyUQohRMyOc3faCPd0hg== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.2" + for-each "^0.3.3" + has-proto "^1.0.1" + is-typed-array "^1.1.10" + +typed-array-length@^1.0.4: + version "1.0.4" + resolved "https://registry.yarnpkg.com/typed-array-length/-/typed-array-length-1.0.4.tgz#89d83785e5c4098bec72e08b319651f0eac9c1bb" + integrity sha512-KjZypGq+I/H7HI5HlOoGHkWUUGq+Q0TPhQurLbyrVrvnKTBgzLhIJ7j6J/XTQOi0d1RjyZ0wdas8bKs2p0x3Ng== + dependencies: + call-bind "^1.0.2" + for-each "^0.3.3" + is-typed-array "^1.1.9" + +typescript@5.3.3: + version "5.3.3" + resolved "https://registry.yarnpkg.com/typescript/-/typescript-5.3.3.tgz#b3ce6ba258e72e6305ba66f5c9b452aaee3ffe37" + integrity sha512-pXWcraxM0uxAS+tN0AG/BF2TyqmHO014Z070UsJ+pFvYuRSq8KH8DmWpnbXe0pEPDHXZV3FcAbJkijJ5oNEnWw== + +ufo@^1.1.2: + version "1.1.2" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.1.2.tgz#d0d9e0fa09dece0c31ffd57bd363f030a35cfe76" + integrity sha512-TrY6DsjTQQgyS3E3dBaOXf0TpPD8u9FVrVYmKVegJuFw51n/YB9XPt+U6ydzFG5ZIN7+DIjPbNmXoBj9esYhgQ== + +ufo@^1.3.0: + version "1.3.2" + resolved "https://registry.yarnpkg.com/ufo/-/ufo-1.3.2.tgz#c7d719d0628a1c80c006d2240e0d169f6e3c0496" + integrity sha512-o+ORpgGwaYQXgqGDwd+hkS4PuZ3QnmqMMxRuajK/a38L6fTpcE5GPIfrf+L/KemFzfUpeUQc1rRS1iDBozvnFA== + +unbox-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/unbox-primitive/-/unbox-primitive-1.0.2.tgz#29032021057d5e6cdbd08c5129c226dff8ed6f9e" + integrity sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw== + dependencies: + call-bind "^1.0.2" + has-bigints "^1.0.2" + has-symbols "^1.0.3" + which-boxed-primitive "^1.0.2" + +uri-js@^4.2.2: + version "4.4.1" + resolved "https://registry.yarnpkg.com/uri-js/-/uri-js-4.4.1.tgz#9b1a52595225859e55f669d928f88c6c57f2a77e" + integrity sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg== + dependencies: + punycode "^2.1.0" + +v8-to-istanbul@^9.2.0: + version "9.2.0" + resolved "https://registry.yarnpkg.com/v8-to-istanbul/-/v8-to-istanbul-9.2.0.tgz#2ed7644a245cddd83d4e087b9b33b3e62dfd10ad" + integrity sha512-/EH/sDgxU2eGxajKdwLCDmQ4FWq+kpi3uCmBGpw1xJtnAxEjlD8j8PEiGWpCIMIs3ciNAgH0d3TTJiUkYzyZjA== + dependencies: + "@jridgewell/trace-mapping" "^0.3.12" + "@types/istanbul-lib-coverage" "^2.0.1" + convert-source-map "^2.0.0" + +vite-node@1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vite-node/-/vite-node-1.1.0.tgz#0ebcb7398692e378954786dfba28e905e28a76b4" + integrity sha512-jV48DDUxGLEBdHCQvxL1mEh7+naVy+nhUUUaPAZLd3FJgXuxQiewHcfeZebbJ6onDqNGkP4r3MhQ342PRlG81Q== + dependencies: + cac "^6.7.14" + debug "^4.3.4" + pathe "^1.1.1" + picocolors "^1.0.0" + vite "^5.0.0" + +vite@^5.0.0, vite@^5.0.10: + version "5.0.10" + resolved "https://registry.yarnpkg.com/vite/-/vite-5.0.10.tgz#1e13ef5c3cf5aa4eed81f5df6d107b3c3f1f6356" + integrity sha512-2P8J7WWgmc355HUMlFrwofacvr98DAjoE52BfdbwQtyLH06XKwaL/FMnmKM2crF0iX4MpmMKoDlNCB1ok7zHCw== + dependencies: + esbuild "^0.19.3" + postcss "^8.4.32" + rollup "^4.2.0" + optionalDependencies: + fsevents "~2.3.3" + +vitest@^1.1.0: + version "1.1.0" + resolved "https://registry.yarnpkg.com/vitest/-/vitest-1.1.0.tgz#47ba67c564aa137b53b0197d2a992908e7f5b04d" + integrity sha512-oDFiCrw7dd3Jf06HoMtSRARivvyjHJaTxikFxuqJjO76U436PqlVw1uLn7a8OSPrhSfMGVaRakKpA2lePdw79A== + dependencies: + "@vitest/expect" "1.1.0" + "@vitest/runner" "1.1.0" + "@vitest/snapshot" "1.1.0" + "@vitest/spy" "1.1.0" + "@vitest/utils" "1.1.0" + acorn-walk "^8.3.0" + cac "^6.7.14" + chai "^4.3.10" + debug "^4.3.4" + execa "^8.0.1" + local-pkg "^0.5.0" + magic-string "^0.30.5" + pathe "^1.1.1" + picocolors "^1.0.0" + std-env "^3.5.0" + strip-literal "^1.3.0" + tinybench "^2.5.1" + tinypool "^0.8.1" + vite "^5.0.0" + vite-node "1.1.0" + why-is-node-running "^2.2.2" + +which-boxed-primitive@^1.0.2: + version "1.0.2" + resolved "https://registry.yarnpkg.com/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz#13757bc89b209b049fe5d86430e21cf40a89a8e6" + integrity sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg== + dependencies: + is-bigint "^1.0.1" + is-boolean-object "^1.1.0" + is-number-object "^1.0.4" + is-string "^1.0.5" + is-symbol "^1.0.3" + +which-typed-array@^1.1.11, which-typed-array@^1.1.13: + version "1.1.13" + resolved "https://registry.yarnpkg.com/which-typed-array/-/which-typed-array-1.1.13.tgz#870cd5be06ddb616f504e7b039c4c24898184d36" + integrity sha512-P5Nra0qjSncduVPEAr7xhoF5guty49ArDTwzJ/yNuPIbZppyRxFQsRCWrocxIY+CnMVG+qfbU2FmDKyvSGClow== + dependencies: + available-typed-arrays "^1.0.5" + call-bind "^1.0.4" + for-each "^0.3.3" + gopd "^1.0.1" + has-tostringtag "^1.0.0" + +which@^2.0.1: + version "2.0.2" + resolved "https://registry.yarnpkg.com/which/-/which-2.0.2.tgz#7c6a8dd0a636a0327e10b59c9286eee93f3f51b1" + integrity sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA== + dependencies: + isexe "^2.0.0" + +why-is-node-running@^2.2.2: + version "2.2.2" + resolved "https://registry.yarnpkg.com/why-is-node-running/-/why-is-node-running-2.2.2.tgz#4185b2b4699117819e7154594271e7e344c9973e" + integrity sha512-6tSwToZxTOcotxHeA+qGCq1mVzKR3CwcJGmVcY+QE8SHy6TnpFnh8PAvPNHYr7EcuVeG0QSMxtYCuO1ta/G/oA== + dependencies: + siginfo "^2.0.0" + stackback "0.0.2" + +wrap-ansi@^7.0.0: + version "7.0.0" + resolved "https://registry.yarnpkg.com/wrap-ansi/-/wrap-ansi-7.0.0.tgz#67e145cff510a6a6984bdf1152911d69d2eb9e43" + integrity sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q== + dependencies: + ansi-styles "^4.0.0" + string-width "^4.1.0" + strip-ansi "^6.0.0" + +wrappy@1: + version "1.0.2" + resolved "https://registry.yarnpkg.com/wrappy/-/wrappy-1.0.2.tgz#b5243d8f3ec1aa35f1364605bc0d1036e30ab69f" + integrity sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ== + +y18n@^5.0.5: + version "5.0.8" + resolved "https://registry.yarnpkg.com/y18n/-/y18n-5.0.8.tgz#7f4934d0f7ca8c56f95314939ddcd2dd91ce1d55" + integrity sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA== + +yallist@^4.0.0: + version "4.0.0" + resolved "https://registry.yarnpkg.com/yallist/-/yallist-4.0.0.tgz#9bb92790d9c0effec63be73519e11a35019a3a72" + integrity sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A== + +yargs-parser@^21.1.1: + version "21.1.1" + resolved "https://registry.yarnpkg.com/yargs-parser/-/yargs-parser-21.1.1.tgz#9096bceebf990d21bb31fa9516e0ede294a77d35" + integrity sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw== + +yargs@^17.0.0: + version "17.7.2" + resolved "https://registry.yarnpkg.com/yargs/-/yargs-17.7.2.tgz#991df39aca675a192b816e1e0363f9d75d2aa269" + integrity sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w== + dependencies: + cliui "^8.0.1" + escalade "^3.1.1" + get-caller-file "^2.0.5" + require-directory "^2.1.1" + string-width "^4.2.3" + y18n "^5.0.5" + yargs-parser "^21.1.1" + +yocto-queue@^0.1.0: + version "0.1.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-0.1.0.tgz#0294eb3dee05028d31ee1a5fa2c556a6aaf10a1b" + integrity sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q== + +yocto-queue@^1.0.0: + version "1.0.0" + resolved "https://registry.yarnpkg.com/yocto-queue/-/yocto-queue-1.0.0.tgz#7f816433fb2cbc511ec8bf7d263c3b58a1a3c251" + integrity sha512-9bnSc/HEW2uRy67wc+T8UwauLuPJVn28jb+GtJY16iiKWyvmYJRXVT4UamsAEGQfPohgr2q4Tq0sQbQlxTfi1g== diff --git a/podman-desktop-extension/packages/frontend/.eslintignore b/podman-desktop-extension/packages/frontend/.eslintignore new file mode 100644 index 000000000..26caab1b0 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/.eslintignore @@ -0,0 +1,4 @@ +build +*.config.js +__mocks__ +coverage diff --git a/podman-desktop-extension/packages/frontend/.eslintrc.json b/podman-desktop-extension/packages/frontend/.eslintrc.json new file mode 100644 index 000000000..ff7760f6f --- /dev/null +++ b/podman-desktop-extension/packages/frontend/.eslintrc.json @@ -0,0 +1,13 @@ +{ + "env": { + "browser": true, + "node": false + }, + "extends": ["../../.eslintrc.json"], + "rules": { + "@typescript-eslint/no-explicit-any": "off", + "@typescript-eslint/no-floating-promises": "off", + "@typescript-eslint/no-empty-function": "off", + "no-undef": "off" + } +} diff --git a/podman-desktop-extension/packages/frontend/index.html b/podman-desktop-extension/packages/frontend/index.html new file mode 100644 index 000000000..3a5b11759 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/index.html @@ -0,0 +1,12 @@ + + + + + + BootC Extension + + +
+ + + diff --git a/podman-desktop-extension/packages/frontend/package.json b/podman-desktop-extension/packages/frontend/package.json new file mode 100644 index 000000000..f68cffaf2 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/package.json @@ -0,0 +1,57 @@ +{ + "name": "frontend", + "displayName": "frontend UI", + "description": "Frontend UI for the bootc extension", + "version": "1.2.0-next", + "type": "module", + "scripts": { + "preview": "vite preview", + "build": "vite build", + "test": "vitest run --coverage", + "test:watch": "vitest watch --coverage", + "format:check": "prettier --check \"src/**/*.ts\"", + "format:fix": "prettier --write \"src/**/*.{ts,svelte}\"", + "lint:check": "eslint . --ext js,ts,tsx", + "lint:fix": "eslint . --fix --ext js,ts,tsx", + "watch": "vite --mode development build -w" + }, + "dependencies": { + "svelte-preprocess": "^5.1.4", + "tinro": "^0.6.12", + "zod": "^3.23.8" + }, + "devDependencies": { + "@fortawesome/fontawesome-free": "^6.5.1", + "@fortawesome/free-brands-svg-icons": "^6.5.2", + "@fortawesome/free-regular-svg-icons": "^6.5.2", + "@fortawesome/free-solid-svg-icons": "^6.5.2", + "@podman-desktop/ui-svelte": "0.0.202405281806-65d14b4", + "@sveltejs/vite-plugin-svelte": "3.1.1", + "@tailwindcss/typography": "^0.5.13", + "@testing-library/dom": "^10.1.0", + "@testing-library/jest-dom": "^6.4.5", + "@testing-library/svelte": "^5.1.0", + "@testing-library/user-event": "^14.5.1", + "@tsconfig/svelte": "^5.0.4", + "@types/humanize-duration": "^3.27.4", + "@types/node": "^20.14.2", + "@typescript-eslint/eslint-plugin": "^7.12.0", + "@typescript-eslint/parser": "^6.21.0", + "autoprefixer": "^10.4.17", + "filesize": "^10.1.2", + "humanize-duration": "^3.32.1", + "jsdom": "^24.1.0", + "moment": "^2.30.1", + "postcss": "^8.4.35", + "postcss-load-config": "^6.0.1", + "prettier": "^3.3.1", + "prettier-plugin-svelte": "^3.2.4", + "svelte": "^4.2.18", + "svelte-fa": "^4.0.2", + "svelte-markdown": "^0.4.1", + "svelte-preprocess": "^5.1.4", + "tailwindcss": "^3.4.4", + "vite": "^5.2.12", + "vitest": "^1.6.0" + } +} diff --git a/podman-desktop-extension/packages/frontend/postcss.config.cjs b/podman-desktop-extension/packages/frontend/postcss.config.cjs new file mode 100644 index 000000000..e65e3c283 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/postcss.config.cjs @@ -0,0 +1,25 @@ +/********************************************************************** + * Copyright (C) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +module.exports = { + plugins: { + tailwindcss: {}, + 'postcss-import': {}, + autoprefixer: {}, + }, +}; diff --git a/podman-desktop-extension/packages/frontend/src/App.svelte b/podman-desktop-extension/packages/frontend/src/App.svelte new file mode 100644 index 000000000..87decd8b6 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/App.svelte @@ -0,0 +1,55 @@ + + + +
+
+ + + + + + + + + + + + + + + +
+
+
diff --git a/podman-desktop-extension/packages/frontend/src/Clusters.svelte b/podman-desktop-extension/packages/frontend/src/Clusters.svelte new file mode 100644 index 000000000..a3767e7e5 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/Clusters.svelte @@ -0,0 +1,99 @@ + + + + + {#if consoleObj} + + {/if} + + +
+ {#if clusters} + +
+ + {#if clusters.length === 0} + No clusters. + {/if} + {/if} +
+
diff --git a/podman-desktop-extension/packages/frontend/src/Console.svelte b/podman-desktop-extension/packages/frontend/src/Console.svelte new file mode 100644 index 000000000..623e5eb49 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/Console.svelte @@ -0,0 +1,29 @@ + + + + + + + + diff --git a/podman-desktop-extension/packages/frontend/src/ConsoleWizard.svelte b/podman-desktop-extension/packages/frontend/src/ConsoleWizard.svelte new file mode 100644 index 000000000..ea5205fd8 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/ConsoleWizard.svelte @@ -0,0 +1,351 @@ + + + + + + + + + {#if state === 'ready'} +
+ +
+
+ + + +
+

+ This will be used to create a directory on your filesystem in this extension's storage path. +
+
* It must be a unique name. +
* Name must be at least 3 characters long. +
* Only characters and numbers allowed. +

+
+ +
+
+

Kubernetes connection details

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

Strimzi CR details

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

Name of the Strimzi Kafka CR

+
+
+ + + +

Namespace of the Strimzi Kafka CR

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

+ Name of the listener to use for connections from the console +

+
+
+
+
+

Kafka connection properties (optional)

+
+
+ + + +

+ If omitted the bootstrap servers from the Strimzi Kafka CR are used +

+
+
+ + + +
+
+ + + +
+
+ + + +
+
+ +
+
+ +
+
+
+ {:else if state === 'creating'} + + Creating console... + {:else if state === 'created'} + + + + {/if} +
+
diff --git a/podman-desktop-extension/packages/frontend/src/Homepage.svelte b/podman-desktop-extension/packages/frontend/src/Homepage.svelte new file mode 100644 index 000000000..1f59e87c6 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/Homepage.svelte @@ -0,0 +1,93 @@ + + + + + + + +
+ {#if consoles} + +
+ + {#if consoles.length === 0} + + {/if} + {/if} +
+
diff --git a/podman-desktop-extension/packages/frontend/src/Topics.svelte b/podman-desktop-extension/packages/frontend/src/Topics.svelte new file mode 100644 index 000000000..097ffc604 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/Topics.svelte @@ -0,0 +1,126 @@ + + + +
+ {#if topicsTableData} + +
+ + {#if topicsTableData.length === 0} + No topics. + {/if} + {/if} +
+ +
diff --git a/podman-desktop-extension/packages/frontend/src/api/api-common.ts b/podman-desktop-extension/packages/frontend/src/api/api-common.ts new file mode 100644 index 000000000..c94cd1b9e --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/api/api-common.ts @@ -0,0 +1,25 @@ +import { z } from 'zod'; + +export const ApiError = z.object({ + meta: z.object({ type: z.string() }), // z.map(z.string(), z.string()), + id: z.string().optional(), + status: z.string().optional(), + code: z.string().optional(), + title: z.string(), + detail: z.string(), + source: z + .object({ + pointer: z.string(), + parameter: z.string(), + header: z.string(), + }) + .optional(), +}); + +export function filterUndefinedFromObj(obj: Record) { + return Object.fromEntries( + Object.entries(obj).filter( + ([_, value]) => value !== undefined && value !== null, + ), + ); +} diff --git a/podman-desktop-extension/packages/frontend/src/api/api-kafka.ts b/podman-desktop-extension/packages/frontend/src/api/api-kafka.ts new file mode 100644 index 000000000..ba05935bf --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/api/api-kafka.ts @@ -0,0 +1,87 @@ +import { z } from "zod"; + +export const NodeSchema = z.object({ + id: z.number(), + host: z.string(), + port: z.number(), + rack: z.string().optional(), +}); +export type KafkaNode = z.infer; +export const ClusterListSchema = z.object({ + id: z.string(), + type: z.literal("kafkas"), + meta: z.object({ + configured: z.boolean(), + }), + attributes: z.object({ + name: z.string(), + namespace: z.string(), + kafkaVersion: z.string().optional(), + }), +}); +export const ClustersResponseSchema = z.object({ + data: z.array(ClusterListSchema), +}); +export type ClusterList = z.infer; +const ClusterDetailSchema = z.object({ + id: z.string(), + type: z.literal("kafkas"), + attributes: z.object({ + name: z.string(), + namespace: z.string(), + creationTimestamp: z.string(), + status: z.string(), + kafkaVersion: z.string().optional(), + nodes: z.array(NodeSchema), + controller: NodeSchema, + authorizedOperations: z.array(z.string()), + listeners: z.array( + z.object({ + type: z.string(), + bootstrapServers: z.string().nullable(), + authType: z.string().nullable(), + }), + ), + conditions: z.array( + z.object({ + type: z.string().optional(), + status: z.string().optional(), + reason: z.string().optional(), + message: z.string().optional(), + lastTransitionTime: z.string().optional(), + }), + ), + nodePools: z.array(z.string()).optional().nullable(), + }), +}); +export const ClusterResponse = z.object({ + data: ClusterDetailSchema, +}); +export type ClusterDetail = z.infer; + +export const ClusterKpisSchema = z.object({ + broker_state: z.record(z.number()).optional(), + total_topics: z.number().optional(), + total_partitions: z.number().optional(), + underreplicated_topics: z.number().optional(), + replica_count: z.object({ + byNode: z.record(z.number()).optional(), + total: z.number().optional(), + }).optional(), + leader_count: z.object({ + byNode: z.record(z.number()).optional(), + total: z.number().optional(), + }).optional(), + volume_stats_capacity_bytes: z.object({ + byNode: z.record(z.number()).optional(), + total: z.number().optional(), + }).optional(), + volume_stats_used_bytes: z.object({ + byNode: z.record(z.number()).optional(), + total: z.number().optional(), + }).optional(), +}); +export type ClusterKpis = z.infer; + +export const MetricRangeSchema = z.record(z.string(), z.record(z.number()).optional()); +export type MetricRange = z.infer; diff --git a/podman-desktop-extension/packages/frontend/src/api/api-topics.ts b/podman-desktop-extension/packages/frontend/src/api/api-topics.ts new file mode 100644 index 000000000..44ce86a6a --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/api/api-topics.ts @@ -0,0 +1,169 @@ +import { ApiError } from './api-common'; +import { z } from 'zod'; + +export const describeTopicsQuery = encodeURI( + 'fields[topics]=name,status,visibility,partitions,numPartitions,authorizedOperations,configs,totalLeaderLogBytes,consumerGroups', +); +const OffsetSchema = z.object({ + offset: z.number().optional(), + timestamp: z.string().optional(), + leaderEpoch: z.number().optional(), +}); +const PartitionStatusSchema = z.union([ + z.literal('FullyReplicated'), + z.literal('UnderReplicated'), + z.literal('Offline'), +]); +export type PartitionStatus = z.infer; +const PartitionSchema = z.object({ + partition: z.number(), + status: PartitionStatusSchema, + leaderId: z.number().optional(), + replicas: z.array( + z.object({ + nodeId: z.number(), + nodeRack: z.string().optional(), + inSync: z.boolean(), + localStorage: ApiError.or( + z.object({ + size: z.number(), + offsetLag: z.number(), + future: z.boolean(), + }), + ).optional(), + }), + ), + offsets: z + .object({ + earliest: OffsetSchema.optional(), + latest: OffsetSchema.optional(), + maxTimestamp: OffsetSchema.optional(), + timestamp: OffsetSchema.optional(), + }) + .optional() + .nullable(), + leaderLocalStorage: z.number().optional(), +}); +const ConfigSchema = z.object({ + value: z.string(), + source: z.string(), + sensitive: z.boolean(), + readOnly: z.boolean(), + type: z.string(), +}); +const ConfigMapSchema = z.record(z.string(), ConfigSchema); +export type ConfigMap = z.infer; +const NewConfigMapSchema = z.record( + z.string(), + z.object({ + value: z.union([z.string(), z.number(), z.undefined(), z.null()]), + }), +); +export type NewConfigMap = z.infer; +const TopicStatusSchema = z.union([ + z.literal('FullyReplicated'), + z.literal('UnderReplicated'), + z.literal('PartiallyOffline'), + z.literal('Offline'), +]); +export type TopicStatus = z.infer; +const TopicSchema = z.object({ + id: z.string(), + type: z.literal('topics'), + meta: z.object({ + managed: z.boolean().optional(), + }).optional(), + attributes: z.object({ + name: z.string(), + status: TopicStatusSchema, + visibility: z.string(), + partitions: z.array(PartitionSchema).optional(), + numPartitions: z.number().optional(), + authorizedOperations: z.array(z.string()), + configs: ConfigMapSchema, + totalLeaderLogBytes: z.number().optional().nullable(), + }), + relationships: z.object({ + consumerGroups: z.object({ + data: z.array(z.any()), + }), + }), +}); +export const TopicResponse = z.object({ + data: TopicSchema, +}); +export type Topic = z.infer; +const TopicListSchema = z.object({ + id: z.string(), + type: z.literal('topics'), + meta: z.object({ + page: z.object({ + cursor: z.string(), + }), + managed: z.boolean().optional(), + }), + attributes: TopicSchema.shape.attributes.pick({ + name: true, + status: true, + visibility: true, + numPartitions: true, + totalLeaderLogBytes: true, + }), + relationships: z.object({ + consumerGroups: z.object({ + data: z.array(z.any()), + }), + }), +}); +export type TopicList = z.infer; +export const TopicsResponseSchema = z.object({ + meta: z.object({ + page: z.object({ + total: z.number(), + pageNumber: z.number().optional(), + }), + summary: z.object({ + statuses: z.object({ + FullyReplicated: z.number().optional(), + UnderReplicated: z.number().optional(), + PartiallyOffline: z.number().optional(), + Offline: z.number().optional(), + }), + }), + }), + links: z.object({ + first: z.string().nullable(), + prev: z.string().nullable(), + next: z.string().nullable(), + last: z.string().nullable(), + }), + data: z.array(TopicListSchema), +}); +export type TopicsResponse = z.infer; +const TopicCreateResponseSuccessSchema = z.object({ + data: z.object({ + id: z.string(), + }), +}); +export const TopicMutateResponseErrorSchema = z.object({ + errors: z.array( + z.object({ + id: z.string(), + status: z.string(), + code: z.string(), + title: z.string(), + detail: z.string(), + source: z + .object({ + pointer: z.string().optional(), + }) + .optional(), + }), + ), +}); +export const TopicCreateResponseSchema = z.union([ + TopicCreateResponseSuccessSchema, + TopicMutateResponseErrorSchema, +]); +export type TopicMutateError = z.infer; +export type TopicCreateResponse = z.infer; diff --git a/podman-desktop-extension/packages/frontend/src/api/client.ts b/podman-desktop-extension/packages/frontend/src/api/client.ts new file mode 100644 index 000000000..685eb6ddb --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/api/client.ts @@ -0,0 +1,42 @@ +/********************************************************************** + * Copyright (C) 2024 Red Hat, Inc. + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + * SPDX-License-Identifier: Apache-2.0 + ***********************************************************************/ + +import { RpcBrowser } from '/@shared/src/messages/MessageProxy'; +import type { StreamshubApi } from '/@shared/src/StreamshubApi'; + +export interface RouterState { + url: string; +} + +const podmanDesktopApi = acquirePodmanDesktopApi(); +export const rpcBrowser: RpcBrowser = new RpcBrowser(window, podmanDesktopApi); +export const streamshubClient: StreamshubApi = rpcBrowser.getProxy(); + +export const saveRouterState = (state: RouterState) => { + podmanDesktopApi.setState(state); +}; + +const isRouterState = (value: unknown): value is RouterState => { + return typeof value === 'object' && !!value && 'url' in value; +}; + +export const getRouterState = (): RouterState => { + const state = podmanDesktopApi.getState(); + if (isRouterState(state)) return state; + return { url: '/' }; +}; diff --git a/podman-desktop-extension/packages/frontend/src/app.css b/podman-desktop-extension/packages/frontend/src/app.css new file mode 100644 index 000000000..b5c61c956 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/app.css @@ -0,0 +1,3 @@ +@tailwind base; +@tailwind components; +@tailwind utilities; diff --git a/podman-desktop-extension/packages/frontend/src/lib/ClusterNameColumn.svelte b/podman-desktop-extension/packages/frontend/src/lib/ClusterNameColumn.svelte new file mode 100644 index 000000000..c6a6ac1bd --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/ClusterNameColumn.svelte @@ -0,0 +1,19 @@ + + +
+ + {object.attributes.name} + +
diff --git a/podman-desktop-extension/packages/frontend/src/lib/ClusterNamespaceColumn.svelte b/podman-desktop-extension/packages/frontend/src/lib/ClusterNamespaceColumn.svelte new file mode 100644 index 000000000..da16887d6 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/ClusterNamespaceColumn.svelte @@ -0,0 +1,11 @@ + + +
+ {object.attributes.namespace} +
diff --git a/podman-desktop-extension/packages/frontend/src/lib/ClusterVersionColumn.svelte b/podman-desktop-extension/packages/frontend/src/lib/ClusterVersionColumn.svelte new file mode 100644 index 000000000..8e4a21a30 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/ClusterVersionColumn.svelte @@ -0,0 +1,10 @@ + + +
+ {object.attributes.kafkaVersion} +
diff --git a/podman-desktop-extension/packages/frontend/src/lib/ConsoleActions.svelte b/podman-desktop-extension/packages/frontend/src/lib/ConsoleActions.svelte new file mode 100644 index 000000000..a0b325833 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/ConsoleActions.svelte @@ -0,0 +1,54 @@ + + + + +{#if object.managed && showManagedActions} + {#if object.api.status === 'running'} + + {:else} + + {/if} + +{/if} diff --git a/podman-desktop-extension/packages/frontend/src/lib/ConsoleApiStatusColumn.svelte b/podman-desktop-extension/packages/frontend/src/lib/ConsoleApiStatusColumn.svelte new file mode 100644 index 000000000..e902c6cfb --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/ConsoleApiStatusColumn.svelte @@ -0,0 +1,11 @@ + + +
+ {object.api.status} +
diff --git a/podman-desktop-extension/packages/frontend/src/lib/ConsoleColumnActions.svelte b/podman-desktop-extension/packages/frontend/src/lib/ConsoleColumnActions.svelte new file mode 100644 index 000000000..dab6af0cb --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/ConsoleColumnActions.svelte @@ -0,0 +1,8 @@ + + + diff --git a/podman-desktop-extension/packages/frontend/src/lib/ConsoleEmptyScreen.svelte b/podman-desktop-extension/packages/frontend/src/lib/ConsoleEmptyScreen.svelte new file mode 100644 index 000000000..96ac7aef8 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/ConsoleEmptyScreen.svelte @@ -0,0 +1,38 @@ + + +
+
+

Welcome to Streamshub

+ +

+ Streamshub is your entry point to your Apache Kafka™ cluster running on Kubernetes via Strimzi. +

+ +

+ Create your first Streamshub console now. +

+ + + +

+ Want to learn more about Streamshub? Check out the + project documentation +  . +

+
+
diff --git a/podman-desktop-extension/packages/frontend/src/lib/ConsoleProjectColumn.svelte b/podman-desktop-extension/packages/frontend/src/lib/ConsoleProjectColumn.svelte new file mode 100644 index 000000000..861d30e66 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/ConsoleProjectColumn.svelte @@ -0,0 +1,17 @@ + + +
+ {#if object.api.status === 'running' && object.api.ports.filter(p => p.PublicPort !== undefined).length > 0} + + {object.project} + + {:else} + {object.project} + {/if} +
diff --git a/podman-desktop-extension/packages/frontend/src/lib/ConsoleUiStatusColumn.svelte b/podman-desktop-extension/packages/frontend/src/lib/ConsoleUiStatusColumn.svelte new file mode 100644 index 000000000..2938f2f7b --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/ConsoleUiStatusColumn.svelte @@ -0,0 +1,10 @@ + + +
+ {object.ui.status} +
diff --git a/podman-desktop-extension/packages/frontend/src/lib/Link.svelte b/podman-desktop-extension/packages/frontend/src/lib/Link.svelte new file mode 100644 index 000000000..10432045e --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/Link.svelte @@ -0,0 +1,24 @@ + + + + + diff --git a/podman-desktop-extension/packages/frontend/src/lib/Route.svelte b/podman-desktop-extension/packages/frontend/src/lib/Route.svelte new file mode 100644 index 000000000..876607ffe --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/Route.svelte @@ -0,0 +1,46 @@ + + +{#if showContent} + +{/if} diff --git a/podman-desktop-extension/packages/frontend/src/lib/TopicsConsumerGroupsColumn.svelte b/podman-desktop-extension/packages/frontend/src/lib/TopicsConsumerGroupsColumn.svelte new file mode 100644 index 000000000..1f2c45851 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/TopicsConsumerGroupsColumn.svelte @@ -0,0 +1,10 @@ + + +
+ {object.relationships.consumerGroups.data.length} +
diff --git a/podman-desktop-extension/packages/frontend/src/lib/TopicsNameColumn.svelte b/podman-desktop-extension/packages/frontend/src/lib/TopicsNameColumn.svelte new file mode 100644 index 000000000..649616d9e --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/TopicsNameColumn.svelte @@ -0,0 +1,13 @@ + + +
+ + {object.attributes.name} + +
diff --git a/podman-desktop-extension/packages/frontend/src/lib/TopicsPartitionsColumn.svelte b/podman-desktop-extension/packages/frontend/src/lib/TopicsPartitionsColumn.svelte new file mode 100644 index 000000000..dcde3af0d --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/TopicsPartitionsColumn.svelte @@ -0,0 +1,10 @@ + + +
+ {object.attributes.numPartitions} +
diff --git a/podman-desktop-extension/packages/frontend/src/lib/progress/LinearProgress.svelte b/podman-desktop-extension/packages/frontend/src/lib/progress/LinearProgress.svelte new file mode 100644 index 000000000..8f1312f76 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/progress/LinearProgress.svelte @@ -0,0 +1,56 @@ + + + diff --git a/podman-desktop-extension/packages/frontend/src/lib/upstream/DropDownMenuItem.svelte b/podman-desktop-extension/packages/frontend/src/lib/upstream/DropDownMenuItem.svelte new file mode 100644 index 000000000..23372f828 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/upstream/DropDownMenuItem.svelte @@ -0,0 +1,27 @@ + + +{#if !hidden} + +
+ + {#if typeof icon === 'string'} + + {:else} + + {/if} + {#if title}{title}{/if} + +
+{/if} diff --git a/podman-desktop-extension/packages/frontend/src/lib/upstream/FormPage.svelte b/podman-desktop-extension/packages/frontend/src/lib/upstream/FormPage.svelte new file mode 100644 index 000000000..f5c01f687 --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/upstream/FormPage.svelte @@ -0,0 +1,73 @@ + + + + +
+
+
+ {#if showBreadcrumb} +
+ {$lastPage.name} +
>
+ +
{title}
+ + + +
+ {/if} +
+ {#if $$slots.icon} +
+ +
+ {/if} +

{title}

+
+ {#if $$slots.actions} +
+ +
+ {/if} + {#if !showBreadcrumb} + + + + {/if} +
+
+
+
+ {#if inProgress} + + {/if} + {#if $$slots.tabs} +
+ +
+ {/if} +
+ +
+
diff --git a/podman-desktop-extension/packages/frontend/src/lib/upstream/ListItemButtonIcon.svelte b/podman-desktop-extension/packages/frontend/src/lib/upstream/ListItemButtonIcon.svelte new file mode 100644 index 000000000..30026d9fb --- /dev/null +++ b/podman-desktop-extension/packages/frontend/src/lib/upstream/ListItemButtonIcon.svelte @@ -0,0 +1,71 @@ + + + +{#if menu} + +