diff --git a/.github/FUNDING.yml b/.github/FUNDING.yml
new file mode 100644
index 0000000000..a9e4ee246d
--- /dev/null
+++ b/.github/FUNDING.yml
@@ -0,0 +1,3 @@
+# These are supported funding model platforms
+
+github: [dstackai]
diff --git a/.github/ISSUE_TEMPLATE/bug_report.yaml b/.github/ISSUE_TEMPLATE/bug_report.yaml
index ec29747fb6..e9ee5c6415 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.yaml
+++ b/.github/ISSUE_TEMPLATE/bug_report.yaml
@@ -39,4 +39,4 @@ body:
attributes:
label: Additional information
description: |
- Any links, references or screenshots to have more context about the issue.
\ No newline at end of file
+ Any links, references or screenshots to have more context about the issue.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.yaml b/.github/ISSUE_TEMPLATE/feature_request.yaml
index ecd6f89cdc..37457a1d50 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.yaml
+++ b/.github/ISSUE_TEMPLATE/feature_request.yaml
@@ -28,4 +28,4 @@ body:
- 'Yes'
- 'No'
validations:
- required: true
\ No newline at end of file
+ required: true
diff --git a/.github/workflows/build-artifacts.yml b/.github/workflows/build-artifacts.yml
new file mode 100644
index 0000000000..d642a81117
--- /dev/null
+++ b/.github/workflows/build-artifacts.yml
@@ -0,0 +1,254 @@
+name: Build Artifacts
+
+on:
+ workflow_call:
+ inputs:
+ version:
+ type: string
+ required: true
+ staging:
+ type: boolean
+ required: true
+ go-integration-tests:
+ type: boolean
+ required: true
+
+jobs:
+ code-lint:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up uv
+ uses: astral-sh/setup-uv@v5
+ with:
+ python-version: 3.11
+ - run: uv tool install pre-commit
+ - run: pre-commit run -a --show-diff-on-failure
+
+ frontend-build:
+ runs-on: ubuntu-latest
+ defaults:
+ run:
+ working-directory: frontend
+ steps:
+ - uses: actions/checkout@v4
+ - name: Restore cached build
+ id: cache-build
+ uses: actions/cache@v4
+ with:
+ path: frontend/build
+ key: frontend-build-${{ hashFiles('frontend/**') }}
+ restore-keys: |
+ frontend-build-
+ - name: Set up Node
+ if: steps.cache-build.outputs.cache-hit != 'true'
+ uses: actions/setup-node@v4
+ with:
+ node-version: 18
+ - name: Install packages
+ if: steps.cache-build.outputs.cache-hit != 'true'
+ run: npm ci
+ - name: Build dist
+ if: steps.cache-build.outputs.cache-hit != 'true'
+ run: npm run build
+ - name: Upload dist
+ uses: actions/upload-artifact@v4
+ with:
+ name: frontend-build
+ path: frontend/build
+ retention-days: 1
+
+ python-test:
+ needs: [code-lint, frontend-build]
+ runs-on: ${{ matrix.os }}
+ strategy:
+ matrix:
+ os: [macos-latest, ubuntu-latest, windows-latest]
+ python-version: ["3.10", "3.11", "3.12", "3.13"]
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Python ${{ matrix.python-version }}
+ uses: astral-sh/setup-uv@v5
+ with:
+ python-version: ${{ matrix.python-version }}
+ - name: Install dependencies
+ run: uv sync --all-extras
+ - name: Run pyright
+ uses: jakebailey/pyright-action@v3
+ with:
+ pylance-version: latest-release
+ - name: Download frontend build
+ uses: actions/download-artifact@v4
+ with:
+ name: frontend-build
+ path: src/dstack/_internal/server/statics
+ - name: Run pytest on POSIX
+ if: matrix.os != 'windows-latest'
+ # Skip Postgres tests on macos since macos runner doesn't have Docker.
+ run: |
+ RUNPOSTGRES=""
+ if [ "${{ matrix.os }}" != "macos-latest" ]; then
+ RUNPOSTGRES="--runpostgres"
+ fi
+ uv run pytest -n auto src/tests --runui $RUNPOSTGRES
+ - name: Run pytest on Windows
+ if: matrix.os == 'windows-latest'
+ run: |
+ uv run pytest -n auto src/tests --runui --runpostgres
+
+ runner-test:
+ defaults:
+ run:
+ working-directory: runner
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: runner/go.mod
+ cache-dependency-path: runner/go.sum
+ - name: Check if go.mod and go.sum are up-to-date
+ run: go mod tidy -diff
+ - name: Run golangci-lint
+ uses: golangci/golangci-lint-action@v9
+ with:
+ version: v2.6.2 # Should match .pre-commit-config.yaml
+ args: --timeout=20m
+ working-directory: runner
+ - name: Test
+ # Only run slow tests if requested by workflow call inputs.
+ run: |
+ SHORT="-short"
+ if [[ "${{ inputs.go-integration-tests }}" == "true" ]]; then
+ SHORT=""
+ fi
+ go version
+ go fmt $(go list ./... | grep -v /vendor/)
+ go vet $(go list ./... | grep -v /vendor/)
+ go test $SHORT -race $(go list ./... | grep -v /vendor/)
+
+ runner-compile:
+ needs: [runner-test]
+ defaults:
+ run:
+ working-directory: runner
+ env:
+ REPO_NAME: github.com/dstackai/dstack
+ strategy:
+ matrix:
+ include:
+ - { runs-on: "ubuntu-24.04", goos: "linux", goarch: "amd64" }
+ - { runs-on: "ubuntu-24.04-arm", goos: "linux", goarch: "arm64" }
+ runs-on: ${{ matrix.runs-on }}
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up Go
+ uses: actions/setup-go@v5
+ with:
+ go-version-file: runner/go.mod
+ cache-dependency-path: runner/go.sum
+ - name: build
+ env:
+ GOOS: ${{ matrix.goos }}
+ GOARCH: ${{ matrix.goarch }}
+ run: |
+ CGO_ENABLED=0 go build -ldflags "-X 'main.Version=${{ inputs.version }}' -extldflags '-static'" -o dstack-runner-$GOOS-$GOARCH $REPO_NAME/runner/cmd/runner
+ CGO_ENABLED=1 go build -ldflags "-X 'main.Version=${{ inputs.version }}'" -o dstack-shim-$GOOS-$GOARCH $REPO_NAME/runner/cmd/shim
+ - uses: actions/upload-artifact@v4
+ with:
+ name: dstack-runner-${{ matrix.goos }}-${{ matrix.goarch }}
+ path: |
+ runner/dstack-runner-${{ matrix.goos }}-${{ matrix.goarch }}
+ runner/dstack-shim-${{ matrix.goos }}-${{ matrix.goarch }}
+ retention-days: 1
+
+ gateway-build:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up uv
+ uses: astral-sh/setup-uv@v5
+ with:
+ python-version: 3.11
+ - name: Build package
+ working-directory: gateway
+ run: |
+ echo "__version__ = \"${{ inputs.version }}\"" > src/dstack/gateway/version.py
+ # TODO: depend on a specific dstackai/dstack commit for staging builds?
+ if [[ "${{ inputs.staging }}" == "false" ]]; then
+ sed \
+ -i.old \
+ "s|@ https://github.com/dstackai/dstack/archive/refs/heads/master.tar.gz|== ${{ inputs.version }}|" \
+ pyproject.toml
+ diff pyproject.toml pyproject.toml.old > /dev/null && echo "Could not set version" && exit 1
+ fi
+ uv build
+ - uses: actions/upload-artifact@v4
+ with:
+ name: dstack-gateway
+ path: gateway/dist/dstack_gateway-${{ inputs.version }}-py3-none-any.whl
+ retention-days: 1
+
+ python-build:
+ needs: [code-lint, frontend-build]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - name: Set up uv
+ uses: astral-sh/setup-uv@v5
+ with:
+ python-version: 3.11
+ - name: Download frontend build
+ uses: actions/download-artifact@v4
+ with:
+ name: frontend-build
+ path: src/dstack/_internal/server/statics
+ - name: Build dstack Python package
+ # TODO: set __version__ to inputs.version regardless of inputs.staging,
+ # so that staging builds are also tied to a specific runner and gateway version.
+ # May require changing how dstack handles __version__.
+ run: |
+ if [[ "${{ inputs.staging }}" == "true" ]]; then
+ VERSION=0.0.0
+ IS_RELEASE=False
+ else
+ VERSION=${{ inputs.version }}
+ IS_RELEASE=True
+ fi
+ DOCKER_BASE_IMAGE=$(cat src/dstack/version.py | grep "docker_base_image = ")
+ DOCKER_BASE_IMAGE_UBUNTU_VERSION=$(cat src/dstack/version.py | grep "docker_base_image_ubuntu_version = ")
+ VM_BASE_IMAGE=$(cat src/dstack/version.py | grep "vm_base_image = ")
+ echo "__version__ = \"$VERSION\"" > src/dstack/version.py
+ echo "__is_release__ = $IS_RELEASE" >> src/dstack/version.py
+ echo $DOCKER_BASE_IMAGE >> src/dstack/version.py
+ echo $DOCKER_BASE_IMAGE_UBUNTU_VERSION >> src/dstack/version.py
+ echo $VM_BASE_IMAGE >> src/dstack/version.py
+ cp README.md src
+ uv build
+ - uses: actions/upload-artifact@v4
+ with:
+ name: python-build
+ path: dist
+ retention-days: 1
+
+ generate-json-schema:
+ needs: [code-lint]
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: astral-sh/setup-uv@v5
+ with:
+ python-version: 3.11
+ - name: Install dstack
+ run: uv sync
+ - name: Generate json schema
+ run: |
+ mkdir /tmp/json-schemas
+ uv run python -c "from dstack._internal.core.models.configurations import DstackConfiguration; print(DstackConfiguration.schema_json())" > /tmp/json-schemas/configuration.json
+ uv run python -c "from dstack._internal.core.models.profiles import ProfilesConfig; print(ProfilesConfig.schema_json())" > /tmp/json-schemas/profiles.json
+ - uses: actions/upload-artifact@v4
+ with:
+ name: json-schemas
+ path: /tmp/json-schemas
+ retention-days: 1
diff --git a/.github/workflows/build-docs.yml b/.github/workflows/build-docs.yml
new file mode 100644
index 0000000000..6ca99d764a
--- /dev/null
+++ b/.github/workflows/build-docs.yml
@@ -0,0 +1,26 @@
+name: Build Docs
+
+on:
+ workflow_call:
+
+jobs:
+ build-docs:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v4
+ - uses: astral-sh/setup-uv@v5
+ with:
+ python-version: 3.11
+ - name: Install dstack
+ run: |
+ uv sync --extra server
+ - name: Build
+ run: |
+ sudo apt-get update && sudo apt-get install -y libcairo2-dev libfreetype6-dev libffi-dev libjpeg-dev libpng-dev libz-dev
+ uv run mkdocs build -s
+ - uses: actions/upload-artifact@v4
+ with:
+ name: site
+ path: site
+ retention-days: 1
+ include-hidden-files: true
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
index da6af2d686..77e50916c9 100644
--- a/.github/workflows/build.yml
+++ b/.github/workflows/build.yml
@@ -1,217 +1,69 @@
-name: Build
+name: Test Build
on:
push:
branches:
- - 'master'
+ - "master"
paths-ignore:
- - 'docs/**'
- - 'mkdocs.yml'
+ - "mkdocs/**"
+ - "mkdocs.yml"
pull_request:
branches:
- - 'master'
+ - "master"
workflow_dispatch:
inputs:
- intergation-tests:
+ go-integration-tests:
type: boolean
required: true
default: false
+ description: Go integration tests
env:
BUILD_INCREMENT: 150
- PIP_DISABLE_PIP_VERSION_CHECK: on
- PIP_DEFAULT_TIMEOUT: 10
- PIP_PROGRESS_BAR: off
jobs:
- python-lint:
+ compute-version:
runs-on: ubuntu-latest
+ outputs:
+ version: ${{ steps.set-version.outputs.version }}
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
- with:
- python-version: 3.11
- - run: python -m pip install pre-commit
- - run: pre-commit run -a --show-diff-on-failure
-
- python-test:
- needs: [ python-lint ]
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ macos-latest, ubuntu-latest]
- python-version: [ "3.8", "3.9", "3.10", "3.11" ]
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
- - name: Install dependencies
- run: pip install -U '.[all]' -r requirements_dev.txt
- - name: Run pytest
- run: pytest src/tests
-
- update-get-dstack:
- if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
- needs: [ python-test ]
- runs-on: ubuntu-latest
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- steps:
- - name: Install AWS
- run: pip install awscli
- - run: |
- VERSION=$((${{ github.run_number }} + ${{ env.BUILD_INCREMENT }}))
- echo $VERSION | aws s3 cp - s3://get-dstack/stgn-cli/latest-version --acl public-read
-
- runner-test:
- defaults:
- run:
- working-directory: runner
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Set up Go
- uses: actions/setup-go@v5
- with:
- go-version: "1.22"
- - name: Run golangci-lint
- uses: golangci/golangci-lint-action@v6
- with:
- version: v1.58
- args: --timeout=20m
- working-directory: runner
- - name: Test
- # Do not run slow integration tests automatically.
- # Slow tests can be run manually via workflow_dispatch when required.
- run: |
- SHORT="-short"
- if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
- if [[ "${{ github.event.inputs.intergation-tests }}" == "true" ]]; then
- SHORT=""
- fi
- fi
- go version
- go fmt $(go list ./... | grep -v /vendor/)
- go vet $(go list ./... | grep -v /vendor/)
- go test $SHORT -race $(go list ./... | grep -v /vendor/)
-
- runner-compile:
- needs: [runner-test]
- defaults:
- run:
- working-directory: runner
- env:
- REPO_NAME: github.com/dstackai/dstack
- strategy:
- matrix:
- include:
- - { goos: "linux", goarch: "amd64", runson: "ubuntu-latest" }
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Set up Go
- uses: actions/setup-go@v5
- with:
- go-version: "1.22"
- - name: build
- env:
- GOOS: ${{ matrix.goos }}
- GOARCH: ${{ matrix.goarch }}
- ACTIONSOS: ${{ matrix.runson }}
- CGO_ENABLED: 0
+ - id: set-version
run: |
- VERSION=$((${{ github.run_number }} + ${{ env.BUILD_INCREMENT }}))
- go build -ldflags "-X 'main.Version=$VERSION' -extldflags '-static'" -o dstack-runner-$GOOS-$GOARCH $REPO_NAME/runner/cmd/runner
- go build -ldflags "-X 'main.Version=$VERSION' -extldflags '-static'" -o dstack-shim-$GOOS-$GOARCH $REPO_NAME/runner/cmd/shim
- echo $VERSION
- - uses: actions/upload-artifact@v3
- with:
- name: dstack-runner
- path: |
- runner/dstack-runner-${{ matrix.goos }}-${{ matrix.goarch }}
- runner/dstack-shim-${{ matrix.goos }}-${{ matrix.goarch }}
- retention-days: 1
+ echo "version=$((${{ github.run_number }} + ${{ env.BUILD_INCREMENT }}))" >> $GITHUB_OUTPUT
- runner-upload:
+ build-artifacts:
+ needs: [compute-version]
+ uses: ./.github/workflows/build-artifacts.yml
+ with:
+ version: ${{ needs.compute-version.outputs.version }}
+ staging: true
+ # TODO: run integration tests on every 'push' event
+ # https://github.com/dstackai/dstack/issues/3005
+ go-integration-tests: ${{ github.event_name == 'workflow_dispatch' && inputs.go-integration-tests }}
+
+ upload-pre-pypi-artifacts:
+ needs: [compute-version, build-artifacts]
+ # Skip for PRs from forks, where AWS S3 credentials are not available
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
- needs: [runner-compile]
- runs-on: ubuntu-latest
- steps:
- - name: Install AWS
- run: pip install awscli
- - name: Download Runner
- uses: actions/download-artifact@v3
- with:
- name: dstack-runner
- path: runner
- - name: Upload to S3
- working-directory: runner
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- run: |
- VERSION=$((${{ github.run_number }} + ${{ env.BUILD_INCREMENT }}))
- aws s3 cp . "s3://dstack-runner-downloads-stgn/$VERSION/binaries/" --recursive --exclude "*" --include "dstack-*" --acl public-read
- aws s3 cp . "s3://dstack-runner-downloads-stgn/latest/binaries/" --recursive --exclude "*" --include "dstack-*" --acl public-read
-
- generate-json-schema:
+ uses: ./.github/workflows/upload-pre-pypi-artifacts.yml
+ with:
+ version: ${{ needs.compute-version.outputs.version }}
+ staging: true
+ secrets: inherit
+
+ upload-post-pypi-artifacts:
+ needs: [compute-version, build-artifacts]
+ # Skip for PRs from forks, where AWS S3 credentials are not available
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
- needs: [ python-test ]
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-python@v4
- with:
- python-version: 3.11
- - name: Install AWS
- run: pip install awscli
- - name: Install dstack
- run: pip install .
- - name: Generate json schema
- run: |
- python -c "from dstack._internal.core.models.configurations import DstackConfiguration; print(DstackConfiguration.schema_json(indent=2))" > configuration.json
- python -c "from dstack._internal.core.models.profiles import ProfilesConfig; print(ProfilesConfig.schema_json(indent=2))" > profiles.json
- - name: Upload json schema to S3
- run: |
- VERSION=$((${{ github.run_number }} + ${{ env.BUILD_INCREMENT }}))
- aws s3 cp configuration.json "s3://dstack-runner-downloads-stgn/$VERSION/schemas/configuration.json" --acl public-read
- aws s3 cp configuration.json "s3://dstack-runner-downloads-stgn/latest/schemas/configuration.json" --acl public-read
- aws s3 cp profiles.json "s3://dstack-runner-downloads-stgn/$VERSION/schemas/profiles.json" --acl public-read
- aws s3 cp profiles.json "s3://dstack-runner-downloads-stgn/latest/schemas/profiles.json" --acl public-read
+ uses: ./.github/workflows/upload-post-pypi-artifacts.yml
+ with:
+ version: ${{ needs.compute-version.outputs.version }}
+ is-latest-version: true
+ staging: true
+ secrets: inherit
- gateway-build:
+ build-docs:
+ # Skip for PRs from forks, where mkdocs-material-insiders is not available
if: github.event_name != 'pull_request' || github.event.pull_request.head.repo.full_name == github.repository
- runs-on: ubuntu-latest
- defaults:
- run:
- working-directory: gateway
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python 3.11
- uses: actions/setup-python@v5
- with:
- python-version: 3.11
- - name: Install AWS
- run: pip install awscli
- - name: Install dependencies
- run: pip install wheel build
- - name: Compute version
- run: echo VERSION=$((${{ github.run_number }} + ${{ env.BUILD_INCREMENT }})) > $GITHUB_ENV
- - name: Build package
- run: |
- echo "__version__ = \"${{ env.VERSION }}\"" > src/dstack/gateway/version.py
- python -m build .
- - name: Upload to S3
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- run: |
- WHEEL=dstack_gateway-${{ env.VERSION }}-py3-none-any.whl
- aws s3 cp dist/$WHEEL "s3://dstack-gateway-downloads/stgn/$WHEEL"
- echo "${{ env.VERSION }}" | aws s3 cp - "s3://dstack-gateway-downloads/stgn/latest-version"
+ uses: ./.github/workflows/build-docs.yml
+ secrets: inherit
diff --git a/.github/workflows/close-inactive-issues.yml b/.github/workflows/close-inactive-issues.yml
index 9cf2654032..1fcbd24292 100644
--- a/.github/workflows/close-inactive-issues.yml
+++ b/.github/workflows/close-inactive-issues.yml
@@ -1,24 +1,26 @@
name: Close inactive issues
on:
+ workflow_dispatch:
schedule:
- cron: "30 1 * * *"
jobs:
close-issues:
- if: github.repository == 'dstackai/dstack'
runs-on: ubuntu-latest
permissions:
issues: write
pull-requests: write
steps:
- - uses: actions/stale@v5
+ - uses: actions/stale@v9
with:
days-before-issue-stale: 30
days-before-issue-close: 14
stale-issue-label: "stale"
stale-issue-message: "This issue is stale because it has been open for 30 days with no activity."
close-issue-message: "This issue was closed because it has been inactive for 14 days since being marked as stale. Please reopen the issue if it is still relevant."
- close-issue-reason: not_planned
- days-before-pr-stale: -1
- days-before-pr-close: -1
- repo-token: ${{ secrets.GH_TOKEN }}
+ days-before-pr-stale: 14
+ days-before-pr-close: 7
+ stale-pr-label: "stale"
+ stale-pr-message: "This PR is stale because it has been open for 14 days with no activity."
+ close-pr-message: "This PR was closed because it has been inactive for 7 days since being marked as stale. Please reopen the PR if it is still relevant."
+ exempt-issue-labels: no-stale,major
diff --git a/.github/workflows/docker-amd-smi.yml b/.github/workflows/docker-amd-smi.yml
new file mode 100644
index 0000000000..df800fc3c0
--- /dev/null
+++ b/.github/workflows/docker-amd-smi.yml
@@ -0,0 +1,58 @@
+name: Build AMD SMI Docker image
+
+on:
+ workflow_dispatch:
+ inputs:
+ image_name:
+ description: "Docker image name"
+ required: true
+ default: "dstackai/amd-smi"
+ rocm_version:
+ description: "ROCm version"
+ required: true
+ default: "6.4"
+ dstack_revision:
+ description: "Docker image revision"
+ required: true
+ default: 0
+ tag_latest:
+ description: "Update 'latest'"
+ type: boolean
+ default: false
+
+jobs:
+ build-amd-smi:
+ defaults:
+ run:
+ working-directory: docker/amd-smi
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ - name: Login to DockerHub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+ - name: Build and upload to DockerHub
+ run: |
+ IMAGE_NAME=${{ inputs.image_name }}
+ docker buildx build . \
+ --load \
+ --provenance=false \
+ --platform linux/amd64 \
+ --build-arg IMAGE_NAME=${IMAGE_NAME} \
+ --build-arg UBUNTU_VERSION=noble \
+ --build-arg ROCM_VERSION=${{ inputs.rocm_version }} \
+ --build-arg DSTACK_REVISION=${{ inputs.dstack_revision }} \
+ --build-arg BUILD_DATE=$(date --utc --iso-8601=seconds)Z \
+ --tag ${IMAGE_NAME}:latest
+ VERSION=$(docker inspect --format '{{ index .Config.Labels "org.opencontainers.image.version" }}' ${IMAGE_NAME})
+ docker tag ${IMAGE_NAME}:latest ${IMAGE_NAME}:${VERSION}
+ docker push ${IMAGE_NAME}:${VERSION}
+ - name: Tag and push latest
+ if: ${{ inputs.tag_latest }}
+ run: |
+ docker push ${{ inputs.image_name }}:latest
diff --git a/.github/workflows/docker-dind.yml b/.github/workflows/docker-dind.yml
new file mode 100644
index 0000000000..ff03e9dcc5
--- /dev/null
+++ b/.github/workflows/docker-dind.yml
@@ -0,0 +1,46 @@
+name: Build DinD image
+
+on:
+ workflow_dispatch:
+ inputs:
+ image_name:
+ description: "Docker image name"
+ required: true
+ default: "dstackai/dind"
+ dstack_revision:
+ description: "Docker image revision"
+ required: true
+ default: 0
+
+jobs:
+ build-dind:
+ defaults:
+ run:
+ working-directory: docker/dind
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ - name: Login to DockerHub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+ - name: Build and upload to DockerHub
+ run: |
+ IMAGE_NAME=${{ inputs.image_name }}
+ BUILD_DATE=$(date --utc --iso-8601=seconds)Z
+ docker buildx build . \
+ --load \
+ --provenance=false \
+ --platform linux/amd64 \
+ --build-arg IMAGE_NAME=${IMAGE_NAME} \
+ --build-arg DSTACK_REVISION=${{ inputs.dstack_revision }} \
+ --build-arg BUILD_DATE=${BUILD_DATE} \
+ --tag ${IMAGE_NAME}:latest
+ VERSION=$(docker inspect --format '{{ index .Config.Labels "org.opencontainers.image.version" }}' ${IMAGE_NAME})
+ docker tag ${IMAGE_NAME}:latest ${IMAGE_NAME}:${VERSION}
+ docker push ${IMAGE_NAME}:${VERSION}
+ docker push ${IMAGE_NAME}:latest
diff --git a/.github/workflows/docker-tt-smi.yml b/.github/workflows/docker-tt-smi.yml
new file mode 100644
index 0000000000..444266ccdb
--- /dev/null
+++ b/.github/workflows/docker-tt-smi.yml
@@ -0,0 +1,54 @@
+name: Build TT SMI Docker image
+
+on:
+ workflow_dispatch:
+ inputs:
+ image_name:
+ description: "Docker image name"
+ required: true
+ default: "dstackai/tt-smi"
+ tt_smi_version:
+ description: "TT SMI version"
+ required: true
+ default: "3.0.25"
+ tag_latest:
+ description: "Update 'latest'"
+ type: boolean
+ required: true
+ default: false
+
+jobs:
+ build-tt-smi:
+ defaults:
+ run:
+ working-directory: docker/tt-smi
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ - name: Login to DockerHub
+ uses: docker/login-action@v3
+ with:
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+ - name: Build and upload to DockerHub
+ run: |
+ IMAGE_NAME=${{ inputs.image_name }}
+ docker buildx build . \
+ --load \
+ --provenance=false \
+ --platform linux/amd64 \
+ --build-arg IMAGE_NAME=${IMAGE_NAME} \
+ --build-arg TT_SMI_VERSION=${{ inputs.tt_smi_version }} \
+ --build-arg BUILD_DATE=$(date --utc --iso-8601=seconds)Z \
+ --tag ${IMAGE_NAME}:${{ inputs.tt_smi_version }}
+ VERSION=$(docker inspect --format '{{ index .Config.Labels "org.opencontainers.image.version" }}' ${IMAGE_NAME}:${{ inputs.tt_smi_version }})
+ docker tag ${IMAGE_NAME}:${{ inputs.tt_smi_version }} ${IMAGE_NAME}:${VERSION}
+ docker push ${IMAGE_NAME}:${VERSION}
+ - name: Tag and push latest
+ if: ${{ inputs.tag_latest }}
+ run: |
+ docker tag ${{ inputs.image_name }}:${{ inputs.tt_smi_version }} ${{ inputs.image_name }}:latest
+ docker push ${{ inputs.image_name }}:latest
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 34d154134b..c17bf2cd95 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -1,281 +1,55 @@
-name: Build Docker & cloud images
+name: Build Docker images
+run-name: Build Docker images ${{ inputs.image_version }}${{ inputs.staging && ' (staging)' || '' }}
on:
workflow_dispatch:
inputs:
image_version:
- description: "Docker image version"
+ description: "Image version"
required: true
staging:
- description: "Staging build"
+ description: "Build staging images"
type: boolean
default: false
- build_docker:
- description: "Build docker images"
- type: boolean
- default: true
- build_aws:
- description: "Build AWS images"
- type: boolean
- default: true
- build_azure:
- description: "Build Azure images"
- type: boolean
- default: true
- build_gcp:
- description: "Build GCP images"
- type: boolean
- default: true
- build_oci:
- description: "Build OCI images"
- type: boolean
- default: true
- build_nebius:
- description: "Build Nebius images"
- type: boolean
- default: true
env:
- PACKER_VERSION: "1.9.2"
- BUILD_PREFIX: ${{ inputs.staging && format('stgn-{0}-', github.run_number) || '' }} # staging ? prefix : ''
+ BUILD_DOCKER_REPO: ${{ inputs.staging && 'base-stgn' || 'base' }}
jobs:
build-docker:
- if: inputs.build_docker
defaults:
run:
working-directory: docker
- runs-on: ubuntu-latest
- strategy:
- matrix:
- python: [ "3.8", "3.9", "3.10", "3.11", "3.12" ]
- steps:
- - name: Checkout repository
- uses: actions/checkout@v3
- - name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v2
- - name: Login to DockerHub
- uses: docker/login-action@v2
- with:
- username: ${{ secrets.DOCKERHUB_USERNAME }}
- password: ${{ secrets.DOCKERHUB_TOKEN }}
- - name: Set up QEMU
- uses: docker/setup-qemu-action@v2
- - name: Build and upload to DockerHub
- run: |
- docker buildx build --platform linux/amd64 --build-arg PYTHON=${{ matrix.python }} --push --provenance=false --tag dstackai/base:py${{ matrix.python }}-${{ inputs.image_version }}-cuda-12.1 -f base/Dockerfile .
-
- build-aws-images:
- needs: build-docker
- if: always() && inputs.build_aws && (needs.build-docker.result == 'success' || needs.build-docker.result == 'skipped')
- defaults:
- run:
- working-directory: scripts/packer
- runs-on: ubuntu-latest
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ runs-on: dstack-ubuntu-latest-32-cores
strategy:
matrix:
- variant: [ "", "-cuda" ]
+ flavor: ["base", "devel", "devel-efa"]
+ ubuntu_version: ["24"]
steps:
- - uses: actions/checkout@v3
- - name: Download packer
- run: |
- wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- chmod +x packer
- - name: Run packer
- run: |
- ./packer build -var-file=versions.json $PROD_VARS -var image_version=${{ inputs.image_version }} -var build_prefix=$BUILD_PREFIX aws-image${{ matrix.variant }}.json
- env:
- PROD_VARS: ${{ !inputs.staging && '-var-file=aws-vars-prod.json' || '' }} # production ? var-file : ''
-
- build-azure-images:
- needs: build-docker
- if: always() && inputs.build_azure && (needs.build-docker.result == 'success' || needs.build-docker.result == 'skipped')
- defaults:
- run:
- working-directory: scripts/packer
- runs-on: ubuntu-latest
- env:
- AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
- AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
- AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
- AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
- VERSION: ${{ github.run_number }}
- strategy:
- matrix:
- variant: [ "", "-cuda", "-grid" ]
- steps:
- - uses: actions/checkout@v3
- - uses: Azure/login@v1
- name: Log in to az
+ - name: Checkout repository
+ uses: actions/checkout@v4
+ - name: Set up Docker Buildx
+ uses: docker/setup-buildx-action@v3
+ - name: Login to DockerHub
+ uses: docker/login-action@v3
with:
- creds: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}'
- - name: Download packer
- run: |
- wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- chmod +x packer
- - name: Run packer
- run: |
- ./packer build -var-file=versions.json -var image_version=${{ inputs.image_version }} -var build_prefix=$BUILD_PREFIX azure-image${{ matrix.variant }}.json
- - name: Publish azure image
- if: ${{ !inputs.staging }}
- run: |
- IMAGE_DEFINITION=${BUILD_PREFIX}dstack${{ matrix.variant }}-${{ inputs.image_version }}
- IMAGE_NAME=${BUILD_PREFIX}dstack${{ matrix.variant }}-${{ inputs.image_version }}
- ../publish_azure_image.sh $IMAGE_DEFINITION $IMAGE_NAME
-
- build-gcp-images:
- needs: build-docker
- if: always() && inputs.build_gcp && (needs.build-docker.result == 'success' || needs.build-docker.result == 'skipped')
- defaults:
- run:
- working-directory: scripts/packer
- runs-on: ubuntu-latest
- strategy:
- matrix:
- variant: [ "", "-cuda" ]
- permissions:
- contents: 'read'
- id-token: 'write'
- steps:
- - uses: actions/checkout@v3
- - name: 'Authenticate to Google Cloud'
- uses: 'google-github-actions/auth@v1'
- with:
- workload_identity_provider: 'projects/531508670106/locations/global/workloadIdentityPools/github-identity-pool/providers/github-id-provider'
- service_account: 'github-actions@dstack.iam.gserviceaccount.com'
- create_credentials_file: true
- - name: 'Set up Cloud SDK'
- uses: 'google-github-actions/setup-gcloud@v1'
- - name: Download packer
- run: |
- wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- chmod +x packer
- - name: Run packer
- run: |
- ./packer build -var-file=versions.json -var image_version=${{ inputs.image_version }} -var build_prefix=$BUILD_PREFIX gcp-image${{ matrix.variant }}.json
- - name: Publish images
- run: |
- IMAGE_VERSION=${IMAGE_VERSION//./-}
- gcloud compute images add-iam-policy-binding ${BUILD_PREFIX}dstack${{ matrix.variant }}-$IMAGE_VERSION --member='allAuthenticatedUsers' --role='roles/compute.imageUser'
- env:
- IMAGE_VERSION: ${{ inputs.image_version }}
-
- build-oci-images:
- needs: build-docker
- if: always() && inputs.build_oci && (needs.build-docker.result == 'success' || needs.build-docker.result == 'skipped')
- runs-on: ubuntu-latest
- env:
- OCI_COMPARTMENT: ocid1.compartment.oc1..aaaaaaaaxu2uq64unfa2imwkp37icxqv6f7gwp2mczdt2mukuqbkauwqmbtq
- OCI_SUBNET: ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaaewxkaqsmbi2tig5sfw4eexzo3mkb4zrpm4gwvfhqdddnxicxe4fa
- OCI_AVAILABILITY_DOMAIN: kZql:EU-FRANKFURT-1-AD-3
- OCI_REGION: eu-frankfurt-1
- strategy:
- matrix:
- variant: [ "", "-cuda" ]
- steps:
- - uses: actions/checkout@v3
- - name: Setup OCI config
- run: |
- mkdir ~/.oci
- echo "$OCI_KEY_CONTENT" > ~/.oci/key.pem
- echo [DEFAULT] > ~/.oci/config
- echo region=$OCI_REGION >> ~/.oci/config
- echo tenancy=$OCI_TENANCY >> ~/.oci/config
- echo user=$OCI_USER >> ~/.oci/config
- echo fingerprint=$OCI_FINGERPRINT >> ~/.oci/config
- echo key_file=~/.oci/key.pem >> ~/.oci/config
- env:
- OCI_TENANCY: ${{ secrets.OCI_CLI_TENANCY }}
- OCI_USER: ${{ secrets.OCI_CLI_USER }}
- OCI_FINGERPRINT: ${{ secrets.OCI_CLI_FINGERPRINT }}
- OCI_KEY_CONTENT: ${{ secrets.OCI_CLI_KEY_CONTENT }}
- - name: Install packer
- working-directory: scripts/packer
- run: |
- wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- chmod +x packer
- ./packer plugins install github.com/hashicorp/oracle
- - name: Run packer
- working-directory: scripts/packer
- run: |
- ./packer build \
- -var-file=versions.json \
- -var image_version=${{ inputs.image_version }} \
- -var build_prefix=$BUILD_PREFIX \
- -var oci_compartment_ocid=$OCI_COMPARTMENT \
- -var oci_subnet_ocid=$OCI_SUBNET \
- -var oci_availability_domain=$OCI_AVAILABILITY_DOMAIN \
- oci-image${{ matrix.variant }}.json
- - uses: actions/setup-python@v5
- with:
- python-version: '3.12'
- - name: Install dependencies for publishing
- run: |
- pip install .[oci]
- - name: Copy image to target regions
- if: ${{ !inputs.staging }}
- run: |
- python scripts/oci_image_tools.py copy \
- --image ${BUILD_PREFIX}dstack${{ matrix.variant }}-${{ inputs.image_version }} \
- --from $OCI_REGION \
- --compartment $OCI_COMPARTMENT
- - name: Publish image in OCI Marketplace
- if: ${{ !inputs.staging }}
- run: |
- python scripts/oci_image_tools.py publish \
- --image ${BUILD_PREFIX}dstack${{ matrix.variant }}-${{ inputs.image_version }} \
- --compartment $OCI_COMPARTMENT \
- --version ${{ inputs.image_version }} \
- --description "Image for running workloads with dstack - https://dstack.ai/" \
- --os "Ubuntu 22.04" \
- --contact-name dstack \
- --contact-email hello@dstack.ai
-
- build-nebius-images:
- needs: build-docker
- if: always() && inputs.build_nebius && (needs.build-docker.result == 'success' || needs.build-docker.result == 'skipped')
- defaults:
- run:
- working-directory: scripts/packer
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - name: Get Nebius CLI
- run: |
- echo "CLI_VERSION=$CLI_VERSION"
- curl -sSL https://storage.ai.nebius.cloud/ncp/install.sh | bash
- echo "$HOME/nebius-cloud/bin" >> $GITHUB_PATH
- env:
- CLI_VERSION: 0.113.0+Nebius-AI
- - name: Write Nebius credentials
- uses: jsdaniell/create-json@v1.2.2
- with:
- name: "service_account.json"
- json: ${{ secrets.NEBIUS_SERVICE_ACCOUNT }}
- dir: "scripts/packer/"
- - name: Setup Nebius profile
- run: |
- ncp config profile create packer
- ncp config set endpoint api.ai.nebius.cloud:443
- ncp config set service-account-key service_account.json
- rm service_account.json
- - name: Download packer
- run: |
- wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
- chmod +x packer
- ./packer init .
- - name: Run packer (HCL2)
- run: |
- export PKR_VAR_nebius_token=$(ncp iam create-token)
- ./packer build -only yandex.nebius,yandex.nebius-cuda -var image_version=${{ inputs.image_version }} -var build_prefix=$BUILD_PREFIX .
- env:
- PKR_VAR_nebius_folder_id: ${{ secrets.NEBIUS_FOLDER_ID }}
- PKR_VAR_nebius_subnet_id: ${{ secrets.NEBIUS_SUBNET_ID }}
+ username: ${{ secrets.DOCKERHUB_USERNAME }}
+ password: ${{ secrets.DOCKERHUB_TOKEN }}
+ - name: Set up QEMU
+ uses: docker/setup-qemu-action@v3
+ - name: Free up some space
+ run: |
+ df -h /
+ du -hs /usr/share/dotnet
+ rm -rf /usr/share/dotnet
+ df -h /
+ - name: Build and upload to DockerHub
+ run: |
+ docker buildx build \
+ --platform linux/amd64 \
+ --target ${{ matrix.flavor }} \
+ --tag dstackai/${{ env.BUILD_DOCKER_REPO }}:${{ inputs.image_version }}-${{ matrix.flavor }}-ubuntu${{ matrix.ubuntu_version }}.04 \
+ --build-arg UBUNTU_VERSION=${{ matrix.ubuntu_version }} \
+ --provenance=false \
+ --push \
+ -f base/Dockerfile .
diff --git a/.github/workflows/docs.yaml b/.github/workflows/docs.yaml
index 5ec3b892f9..3e0d5f3a75 100644
--- a/.github/workflows/docs.yaml
+++ b/.github/workflows/docs.yaml
@@ -1,37 +1,26 @@
-name: Deploy Docs
+name: Build & Deploy Docs
on:
workflow_dispatch:
- inputs:
- release_tag:
- description: "dstack version"
jobs:
- docs-deploy:
+ build-docs:
+ uses: ./.github/workflows/build-docs.yml
+ secrets: inherit
+
+ deploy-docs:
+ needs: [build-docs]
runs-on: ubuntu-latest
steps:
- uses: actions/checkout@v4
- - uses: actions/setup-python@v4
+ - uses: actions/download-artifact@v4
with:
- python-version: 3.11
- - name: Install dstack
- run: |
- if [ -n "${{ inputs.release_tag }}" ]; then
- pip install "dstack==${{ inputs.release_tag }}"
- else
- pip install -e .
- fi
- - name: Build
- run: |
- pip install pillow cairosvg
- sudo apt-get install -y libcairo2-dev libfreetype6-dev libffi-dev libjpeg-dev libpng-dev libz-dev
- pip install mkdocs-material "mkdocs-material[imaging]" mkdocs-material-extensions mkdocs-redirects mkdocs-gen-files "mkdocstrings[python]" mkdocs-render-swagger-plugin --upgrade
- pip install git+https://${{ secrets.GH_TOKEN }}@github.com/squidfunk/mkdocs-material-insiders.git
- mkdocs build
+ name: site
+ path: site
- name: Deploy
- uses: JamesIves/github-pages-deploy-action@v4
+ uses: JamesIves/github-pages-deploy-action@v4.6.4
with:
repository-name: dstackai/dstackai.github.io
branch: gh-pages
token: ${{ secrets.GH_TOKEN }}
- folder: site
\ No newline at end of file
+ folder: site
diff --git a/.github/workflows/gcp-a3mega-image.yml b/.github/workflows/gcp-a3mega-image.yml
new file mode 100644
index 0000000000..2957671a1b
--- /dev/null
+++ b/.github/workflows/gcp-a3mega-image.yml
@@ -0,0 +1,38 @@
+name: Build GCP A3 Mega VM image
+
+on:
+ - workflow_dispatch
+
+env:
+ PACKER_VERSION: "1.9.2"
+ IMAGE_VERSION: ${{ github.run_number }}
+jobs:
+ build-gcp-images:
+ defaults:
+ run:
+ working-directory: scripts/packer
+ runs-on: ubuntu-latest
+ permissions:
+ contents: 'read'
+ id-token: 'write'
+ steps:
+ - uses: actions/checkout@v4
+ - name: Authenticate to Google Cloud
+ uses: google-github-actions/auth@v2
+ with:
+ workload_identity_provider: 'projects/531508670106/locations/global/workloadIdentityPools/github-identity-pool/providers/github-id-provider'
+ service_account: 'github-actions@dstack.iam.gserviceaccount.com'
+ create_credentials_file: true
+ - name: Set up Cloud SDK
+ uses: google-github-actions/setup-gcloud@v2
+ - name: Download packer
+ run: |
+ wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ chmod +x packer
+ - name: Run packer
+ run: |
+ ./packer build -var image_version=${{ env.IMAGE_VERSION }} gcp-a3mega-image.json
+ - name: Publish image
+ run: |
+ gcloud compute images add-iam-policy-binding dstack-a3mega-${{ env.IMAGE_VERSION }} --member='allAuthenticatedUsers' --role='roles/compute.imageUser'
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index f70ecc1766..0618b00367 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -8,195 +8,109 @@ on:
- "[0-9]+.[0-9]+.[0-9]+"
- "[0-9]+.[0-9]+.[0-9]+.post[0-9]+"
-env:
- BUILD_INCREMENT: 150
- PIP_DISABLE_PIP_VERSION_CHECK: on
- PIP_DEFAULT_TIMEOUT: 10
- PIP_PROGRESS_BAR: off
-
jobs:
- python-lint:
+ compute-version:
runs-on: ubuntu-latest
+ outputs:
+ version: ${{ steps.set-version.outputs.version }}
+ latest: ${{ steps.set-latest.outputs.latest }}
steps:
- - uses: actions/checkout@v4
- - uses: actions/setup-python@v5
+ - name: Set up Python
+ uses: astral-sh/setup-uv@v5
with:
python-version: 3.11
- - run: python -m pip install pre-commit
- - run: pre-commit run -a --show-diff-on-failure
-
- python-test:
- needs: [ python-lint ]
- runs-on: ${{ matrix.os }}
- strategy:
- matrix:
- os: [ macos-latest, ubuntu-latest]
- python-version: [ "3.8", "3.9", "3.10", "3.11" ]
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python ${{ matrix.python-version }}
- uses: actions/setup-python@v5
- with:
- python-version: ${{ matrix.python-version }}
- - name: Install dependencies
- run: pip install -U '.[all]' -r requirements_dev.txt
- - name: Run pytest
- run: pytest src/tests
-
- runner-test:
- defaults:
- run:
- working-directory: runner
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - name: Set up Go
- uses: actions/setup-go@v3
- with:
- go-version: 1.21.1
- - name: golangci-lint
- uses: golangci/golangci-lint-action@v3
- with:
- version: v1.51.2
- args: --issues-exit-code=0 --timeout=20m
- working-directory: runner
- - name: Test
+ # settings to prevent warnings when running uv without a repo checkout
+ enable-cache: false
+ ignore-empty-workdir: true
+ - id: set-version
run: |
- go version
- go fmt $(go list ./... | grep -v /vendor/)
- go vet $(go list ./... | grep -v /vendor/)
- go test -race $(go list ./... | grep -v /vendor/)
-
- runner-compile:
- needs: [runner-test]
- defaults:
- run:
- working-directory: runner
- env:
- REPO_NAME: github.com/dstackai/dstack
- strategy:
- matrix:
- include:
- - { goos: "linux", goarch: "amd64", runson: "ubuntu-latest" }
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v4
- - name: Set up Go
- uses: actions/setup-go@v5
- with:
- go-version: "1.22"
- - name: build
- env:
- GOOS: ${{ matrix.goos }}
- GOARCH: ${{ matrix.goarch }}
- ACTIONSOS: ${{ matrix.runson }}
- CGO_ENABLED: 0
+ echo "version=${GITHUB_REF#refs/tags/}" >> $GITHUB_OUTPUT
+ - id: set-latest
run: |
- VERSION=${GITHUB_REF#refs/tags/}
- go build -ldflags "-X '$REPO_NAME/runner/cmd/runner/version.Version=$VERSION' -extldflags '-static'" -o dstack-runner-$GOOS-$GOARCH $REPO_NAME/runner/cmd/runner
- go build -ldflags "-X '$REPO_NAME/runner/cmd/shim/version.Version=$VERSION' -extldflags '-static'" -o dstack-shim-$GOOS-$GOARCH $REPO_NAME/runner/cmd/shim
- - uses: actions/upload-artifact@v3
- with:
- name: dstack-runner
- path: |
- runner/dstack-runner-${{ matrix.goos }}-${{ matrix.goarch }}
- runner/dstack-shim-${{ matrix.goos }}-${{ matrix.goarch }}
+ uv pip install packaging
+ VERSION=${{ steps.set-version.outputs.version }}
+ LATEST=$(python -c "from packaging import version as pkg_version; print('' if pkg_version.parse('$VERSION').is_prerelease else '1', end='')")
+ echo "latest=$LATEST" >> "$GITHUB_OUTPUT"
- runner-upload:
- needs: [gateway-build, runner-compile]
- runs-on: ubuntu-latest
- steps:
- - name: Install AWS
- run: pip install awscli
- - name: Download Runner
- uses: actions/download-artifact@v3
- with:
- name: dstack-runner
- path: runner
- - name: Upload to S3
- working-directory: runner
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- run: |
- VERSION=${GITHUB_REF#refs/tags/}
- aws s3 cp . "s3://dstack-runner-downloads/$VERSION/binaries/" --recursive --exclude "*" --include "dstack-*" --acl public-read
- aws s3 cp . "s3://dstack-runner-downloads/latest/binaries/" --recursive --exclude "*" --include "dstack-*" --acl public-read
+ build-artifacts:
+ needs: [compute-version]
+ uses: ./.github/workflows/build-artifacts.yml
+ with:
+ version: ${{ needs.compute-version.outputs.version }}
+ staging: false
+ go-integration-tests: false
+
+ upload-pre-pypi-artifacts:
+ needs: [compute-version, build-artifacts]
+ uses: ./.github/workflows/upload-pre-pypi-artifacts.yml
+ with:
+ version: ${{ needs.compute-version.outputs.version }}
+ staging: false
+ secrets: inherit
pypi-upload:
- needs: [ python-test, runner-upload ]
+ needs: [compute-version, upload-pre-pypi-artifacts]
runs-on: ubuntu-latest
- outputs:
- LATEST: ${{ steps.set_latest.outputs.LATEST }}
- name: Set latest variable
steps:
- - uses: actions/checkout@v3
- - name: Set up Python 3.9
- uses: actions/setup-python@v4
+ - name: Set up uv
+ uses: astral-sh/setup-uv@v5
with:
- python-version: 3.9
- - name: Install dependencies
- run: |
- python -m pip install --upgrade pip
- pip install wheel twine packaging
- - name: Set output
- id: set_latest
- run: |
- VERSION=${GITHUB_REF#refs/tags/}
- LATEST=$(python -c "from packaging import version as pkg_version; print('' if pkg_version.parse('$VERSION').is_prerelease else '1', end='')")
- echo "LATEST=$LATEST" >> "$GITHUB_OUTPUT"
- - name: Upload pip package
+ python-version: 3.11
+ # settings to prevent warnings when running uv without a repo checkout
+ enable-cache: false
+ ignore-empty-workdir: true
+ - name: Download Python package
+ uses: actions/download-artifact@v4
+ with:
+ name: python-build
+ path: dist
+ - name: Upload Python package to PyPI
run: |
- VERSION=${GITHUB_REF#refs/tags/}
- BASE_IMAGE=$(cat src/dstack/version.py | grep base_image)
- echo "__version__ = \"$VERSION\"" > src/dstack/version.py
- echo "__is_release__ = True" >> src/dstack/version.py
- echo $BASE_IMAGE >> src/dstack/version.py
- cp README.md src
- python setup.py sdist bdist_wheel -v
- python -m twine upload --repository pypi --username ${{ secrets.PYPI_USERNAME }} --password ${{ secrets.PYPI_PASSWORD }} dist/*
+ uv publish --username ${{ secrets.PYPI_USERNAME }} --password ${{ secrets.PYPI_PASSWORD }}
- update-get-dstack-tag:
- needs: [ pypi-upload ]
- runs-on: ubuntu-latest
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- steps:
- - name: Install AWS
- run: pip install awscli
- - run: |
- VERSION=${GITHUB_REF#refs/tags/}
- echo $VERSION | aws s3 cp - s3://get-dstack/cli/latest-version --acl public-read
+ upload-post-pypi-artifacts:
+ needs: [compute-version, pypi-upload]
+ uses: ./.github/workflows/upload-post-pypi-artifacts.yml
+ with:
+ version: ${{ needs.compute-version.outputs.version }}
+ is-latest-version: ${{ needs.compute-version.outputs.latest == '1' }}
+ staging: false
+ secrets: inherit
server-docker-upload:
- needs: [ pypi-upload ]
+ needs: [compute-version, pypi-upload]
defaults:
run:
working-directory: docker/server
runs-on: ubuntu-latest
steps:
- name: Checkout repository
- uses: actions/checkout@v3
+ uses: actions/checkout@v4
- name: Set up Docker Buildx
- uses: docker/setup-buildx-action@v2
+ uses: docker/setup-buildx-action@v3
- name: Login to DockerHub
- uses: docker/login-action@v2
+ uses: docker/login-action@v3
with:
username: ${{ secrets.DOCKERHUB_USERNAME }}
password: ${{ secrets.DOCKERHUB_TOKEN }}
- name: Set up QEMU
- uses: docker/setup-qemu-action@v2
+ uses: docker/setup-qemu-action@v3
- name: Build and upload to DockerHub
run: |
- VERSION=${GITHUB_REF#refs/tags/}
+ VERSION=${{ needs.compute-version.outputs.version }}
docker buildx build --platform linux/arm64/v8 --build-arg VERSION=$VERSION --push --provenance=false --tag dstackai/dstack:$VERSION-arm64 -f release/Dockerfile .
docker buildx build --platform linux/amd64 --build-arg VERSION=$VERSION --push --provenance=false --tag dstackai/dstack:$VERSION-amd64 -f release/Dockerfile .
+ docker buildx build --platform linux/arm64/v8 --build-arg BASE_IMAGE=dstackai/dstack:$VERSION-arm64 --push --provenance=false --tag dstackai/dstack:nebius-$VERSION-arm64 -f Dockerfile.nebius .
+ docker buildx build --platform linux/amd64 --build-arg BASE_IMAGE=dstackai/dstack:$VERSION-amd64 --push --provenance=false --tag dstackai/dstack:nebius-$VERSION-amd64 -f Dockerfile.nebius .
docker manifest create dstackai/dstack:$VERSION --amend dstackai/dstack:$VERSION-arm64 --amend dstackai/dstack:$VERSION-amd64
docker manifest push dstackai/dstack:$VERSION
- if [ -n "${{ needs.pypi-upload.outputs.LATEST }}" ]; then
+ docker manifest create dstackai/dstack:nebius-$VERSION --amend dstackai/dstack:nebius-$VERSION-arm64 --amend dstackai/dstack:nebius-$VERSION-amd64
+ docker manifest push dstackai/dstack:nebius-$VERSION
+ if [ -n "${{ needs.compute-version.outputs.latest }}" ]; then
docker manifest create dstackai/dstack:latest --amend dstackai/dstack:$VERSION-arm64 --amend dstackai/dstack:$VERSION-amd64
docker manifest push dstackai/dstack:latest
+ docker manifest create dstackai/dstack:nebius-latest --amend dstackai/dstack:nebius-$VERSION-arm64 --amend dstackai/dstack:nebius-$VERSION-amd64
+ docker manifest push dstackai/dstack:nebius-latest
fi
- name: Docker Hub Description
uses: peter-evans/dockerhub-description@v4
@@ -205,62 +119,3 @@ jobs:
password: ${{ secrets.DOCKERHUB_TOKEN }}
repository: dstackai/dstack
readme-filepath: ./docker/server/README.md
-
- generate-json-schema:
- needs: [ pypi-upload ]
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- runs-on: ubuntu-latest
- steps:
- - uses: actions/checkout@v3
- - uses: actions/setup-python@v4
- with:
- python-version: 3.11
- - name: Install AWS
- run: pip install awscli
- - name: Install dstack
- run: pip install .
- - name: Generate json schema
- run: |
- python -c "from dstack._internal.core.models.configurations import DstackConfiguration; print(DstackConfiguration.schema_json(indent=2))" > configuration.json
- python -c "from dstack._internal.core.models.profiles import ProfilesConfig; print(ProfilesConfig.schema_json(indent=2))" > profiles.json
- - name: Upload json schema to S3
- run: |
- VERSION=${GITHUB_REF#refs/tags/}
- aws s3 cp configuration.json "s3://dstack-runner-downloads/$VERSION/schemas/configuration.json" --acl public-read
- aws s3 cp profiles.json "s3://dstack-runner-downloads/$VERSION/schemas/profiles.json" --acl public-read
- if [ -n "${{ needs.pypi-upload.outputs.LATEST }}" ]; then
- aws s3 cp configuration.json "s3://dstack-runner-downloads/latest/schemas/configuration.json" --acl public-read
- aws s3 cp profiles.json "s3://dstack-runner-downloads/latest/schemas/profiles.json" --acl public-read
- fi
-
- gateway-build:
- runs-on: ubuntu-latest
- defaults:
- run:
- working-directory: gateway
- steps:
- - uses: actions/checkout@v4
- - name: Set up Python 3.11
- uses: actions/setup-python@v5
- with:
- python-version: 3.11
- - name: Install AWS
- run: pip install awscli
- - name: Install dependencies
- run: pip install wheel build
- - name: Store version
- run: echo VERSION=${GITHUB_REF#refs/tags/} > $GITHUB_ENV
- - name: Build package
- run: |
- echo "__version__ = \"${{ env.VERSION }}\"" > src/dstack/gateway/version.py
- python -m build .
- - name: Upload to S3
- env:
- AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
- AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
- run: |
- WHEEL=dstack_gateway-${{ env.VERSION }}-py3-none-any.whl
- aws s3 cp dist/$WHEEL "s3://dstack-gateway-downloads/release/$WHEEL"
- echo "${{ env.VERSION }}" | aws s3 cp - "s3://dstack-gateway-downloads/release/latest-version"
diff --git a/.github/workflows/upload-post-pypi-artifacts.yml b/.github/workflows/upload-post-pypi-artifacts.yml
new file mode 100644
index 0000000000..4d9899deda
--- /dev/null
+++ b/.github/workflows/upload-post-pypi-artifacts.yml
@@ -0,0 +1,55 @@
+name: Upload Post-PyPI Artifacts
+
+on:
+ workflow_call:
+ inputs:
+ version:
+ type: string
+ required: true
+ is-latest-version:
+ type: boolean
+ required: true
+ staging:
+ type: boolean
+ required: true
+
+jobs:
+ upload-post-pypi-artifacts:
+ runs-on: ubuntu-latest
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ steps:
+ - uses: astral-sh/setup-uv@v5
+ with:
+ python-version: 3.11
+ # settings to prevent warnings when running uv without a repo checkout
+ enable-cache: false
+ ignore-empty-workdir: true
+ - name: Install AWS
+ run: uv tool install awscli
+ - name: Download JSON schemas
+ uses: actions/download-artifact@v4
+ with:
+ name: json-schemas
+ path: json-schemas
+ - name: Upload JSON schemas to S3
+ working-directory: json-schemas
+ run: |
+ BUCKET=dstack-runner-downloads
+ if [ "${{ inputs.staging }}" = "true" ]; then
+ BUCKET=dstack-runner-downloads-stgn
+ fi
+ aws s3 cp configuration.json "s3://$BUCKET/${{ inputs.version }}/schemas/configuration.json" --acl public-read
+ aws s3 cp profiles.json "s3://$BUCKET/${{ inputs.version }}/schemas/profiles.json" --acl public-read
+ if [ "${{ inputs.is-latest-version }}" = "true" ]; then
+ aws s3 cp configuration.json "s3://$BUCKET/latest/schemas/configuration.json" --acl public-read
+ aws s3 cp profiles.json "s3://$BUCKET/latest/schemas/profiles.json" --acl public-read
+ fi
+ - name: Set latest version in S3
+ run: |
+ CHANNEL=cli
+ if [ "${{ inputs.staging }}" = "true" ]; then
+ CHANNEL=stgn-cli
+ fi
+ echo ${{ inputs.version }} | aws s3 cp - s3://get-dstack/$CHANNEL/latest-version --acl public-read
diff --git a/.github/workflows/upload-pre-pypi-artifacts.yml b/.github/workflows/upload-pre-pypi-artifacts.yml
new file mode 100644
index 0000000000..542f445e2e
--- /dev/null
+++ b/.github/workflows/upload-pre-pypi-artifacts.yml
@@ -0,0 +1,57 @@
+name: Upload Pre-PyPI Artifacts
+
+on:
+ workflow_call:
+ inputs:
+ version:
+ type: string
+ required: true
+ staging:
+ type: boolean
+ required: true
+
+jobs:
+ upload-pre-pypi-artifacts:
+ runs-on: ubuntu-latest
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ steps:
+ - uses: astral-sh/setup-uv@v5
+ with:
+ python-version: 3.11
+ # settings to prevent warnings when running uv without a repo checkout
+ enable-cache: false
+ ignore-empty-workdir: true
+ - name: Install AWS
+ run: uv tool install awscli
+ - name: Download dstack-gateway
+ uses: actions/download-artifact@v4
+ with:
+ name: dstack-gateway
+ path: gateway
+ - name: Upload dstack-gateway to S3
+ working-directory: gateway
+ run: |
+ CHANNEL=release
+ if [ "${{ inputs.staging }}" = "true" ]; then
+ CHANNEL=stgn
+ fi
+ WHEEL=dstack_gateway-${{ inputs.version }}-py3-none-any.whl
+ aws s3 cp $WHEEL "s3://dstack-gateway-downloads/$CHANNEL/$WHEEL"
+ echo "${{ inputs.version }}" | aws s3 cp - "s3://dstack-gateway-downloads/$CHANNEL/latest-version"
+ - name: Download dstack-runner
+ uses: actions/download-artifact@v4
+ with:
+ pattern: dstack-runner-*
+ merge-multiple: true
+ path: runner
+ - name: Upload dstack-runner to S3
+ working-directory: runner
+ run: |
+ BUCKET=dstack-runner-downloads
+ if [ "${{ inputs.staging }}" = "true" ]; then
+ BUCKET=dstack-runner-downloads-stgn
+ fi
+ aws s3 cp . "s3://$BUCKET/${{ inputs.version }}/binaries/" --recursive --exclude "*" --include "dstack-*" --acl public-read
+ aws s3 cp . "s3://$BUCKET/latest/binaries/" --recursive --exclude "*" --include "dstack-*" --acl public-read
diff --git a/.github/workflows/vm-images.yml b/.github/workflows/vm-images.yml
new file mode 100644
index 0000000000..6251fa2027
--- /dev/null
+++ b/.github/workflows/vm-images.yml
@@ -0,0 +1,203 @@
+name: Build VM images
+run-name: Build VM images ${{ inputs.image_version }}${{ inputs.staging && ' (staging)' || '' }}
+
+on:
+ workflow_dispatch:
+ inputs:
+ image_version:
+ description: "Image version"
+ required: true
+ staging:
+ description: "Build staging images"
+ type: boolean
+ default: false
+ build_aws:
+ description: "Build AWS images"
+ type: boolean
+ default: true
+ build_azure:
+ description: "Build Azure images"
+ type: boolean
+ default: true
+ build_gcp:
+ description: "Build GCP images"
+ type: boolean
+ default: true
+ build_oci:
+ description: "Build OCI images"
+ type: boolean
+ default: true
+
+env:
+ PACKER_VERSION: "1.9.2"
+ VM_IMAGE_BUILD_PREFIX: ${{ inputs.staging && format('stgn-{0}-', github.run_number) || '' }} # staging ? prefix : ''
+
+jobs:
+ build-aws-images:
+ if: inputs.build_aws
+ defaults:
+ run:
+ working-directory: scripts/packer
+ runs-on: ubuntu-latest
+ env:
+ AWS_ACCESS_KEY_ID: ${{ secrets.AWS_ACCESS_KEY_ID }}
+ AWS_SECRET_ACCESS_KEY: ${{ secrets.AWS_SECRET_ACCESS_KEY }}
+ strategy:
+ matrix:
+ variant: ["", "-cuda"]
+ steps:
+ - uses: actions/checkout@v4
+ - name: Download packer
+ run: |
+ wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ chmod +x packer
+ - name: Run packer
+ run: |
+ ./packer build -var-file=versions.json $PROD_VARS -var image_version=${{ inputs.image_version }} -var build_prefix=$VM_IMAGE_BUILD_PREFIX aws-image${{ matrix.variant }}.json
+ env:
+ PROD_VARS: ${{ !inputs.staging && '-var-file=aws-vars-prod.json' || '' }} # production ? var-file : ''
+
+ build-azure-images:
+ if: inputs.build_azure
+ defaults:
+ run:
+ working-directory: scripts/packer
+ runs-on: ubuntu-latest
+ env:
+ AZURE_CLIENT_ID: ${{ secrets.AZURE_CLIENT_ID }}
+ AZURE_CLIENT_SECRET: ${{ secrets.AZURE_CLIENT_SECRET }}
+ AZURE_TENANT_ID: ${{ secrets.AZURE_TENANT_ID }}
+ AZURE_SUBSCRIPTION_ID: ${{ secrets.AZURE_SUBSCRIPTION_ID }}
+ VERSION: ${{ github.run_number }}
+ strategy:
+ matrix:
+ variant: ["", "-cuda", "-grid"]
+ steps:
+ - uses: actions/checkout@v4
+ - uses: Azure/login@v2
+ name: Log in to az
+ with:
+ creds: '{"clientId":"${{ secrets.AZURE_CLIENT_ID }}","clientSecret":"${{ secrets.AZURE_CLIENT_SECRET }}","subscriptionId":"${{ secrets.AZURE_SUBSCRIPTION_ID }}","tenantId":"${{ secrets.AZURE_TENANT_ID }}"}'
+ - name: Download packer
+ run: |
+ wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ chmod +x packer
+ - name: Run packer
+ run: |
+ ./packer build -var-file=versions.json -var image_version=${{ inputs.image_version }} -var build_prefix=$VM_IMAGE_BUILD_PREFIX azure-image${{ matrix.variant }}.json
+ - name: Publish azure image
+ if: ${{ !inputs.staging }}
+ run: |
+ IMAGE_DEFINITION=${VM_IMAGE_BUILD_PREFIX}dstack${{ matrix.variant }}-${{ inputs.image_version }}
+ IMAGE_NAME=${VM_IMAGE_BUILD_PREFIX}dstack${{ matrix.variant }}-${{ inputs.image_version }}
+ ../publish_azure_image.sh $IMAGE_DEFINITION $IMAGE_NAME
+
+ build-gcp-images:
+ if: inputs.build_gcp
+ defaults:
+ run:
+ working-directory: scripts/packer
+ runs-on: ubuntu-latest
+ strategy:
+ matrix:
+ variant: ["", "-cuda"]
+ permissions:
+ contents: "read"
+ id-token: "write"
+ steps:
+ - uses: actions/checkout@v4
+ - name: Authenticate to Google Cloud
+ uses: google-github-actions/auth@v2
+ with:
+ workload_identity_provider: "projects/531508670106/locations/global/workloadIdentityPools/github-identity-pool/providers/github-id-provider"
+ service_account: "github-actions@dstack.iam.gserviceaccount.com"
+ create_credentials_file: true
+ - name: Set up Cloud SDK
+ uses: google-github-actions/setup-gcloud@v2
+ - name: Download packer
+ run: |
+ wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ chmod +x packer
+ - name: Run packer
+ run: |
+ ./packer build -var-file=versions.json -var image_version=${{ inputs.image_version }} -var build_prefix=$VM_IMAGE_BUILD_PREFIX gcp-image${{ matrix.variant }}.json
+ - name: Publish images
+ run: |
+ IMAGE_VERSION=${IMAGE_VERSION//./-}
+ gcloud compute images add-iam-policy-binding ${VM_IMAGE_BUILD_PREFIX}dstack${{ matrix.variant }}-$IMAGE_VERSION --member='allAuthenticatedUsers' --role='roles/compute.imageUser'
+ env:
+ IMAGE_VERSION: ${{ inputs.image_version }}
+
+ build-oci-images:
+ if: inputs.build_oci
+ runs-on: ubuntu-latest
+ env:
+ OCI_COMPARTMENT: ocid1.compartment.oc1..aaaaaaaaxu2uq64unfa2imwkp37icxqv6f7gwp2mczdt2mukuqbkauwqmbtq
+ OCI_SUBNET: ocid1.subnet.oc1.eu-frankfurt-1.aaaaaaaaewxkaqsmbi2tig5sfw4eexzo3mkb4zrpm4gwvfhqdddnxicxe4fa
+ OCI_AVAILABILITY_DOMAIN: kZql:EU-FRANKFURT-1-AD-3
+ OCI_REGION: eu-frankfurt-1
+ strategy:
+ matrix:
+ variant: ["", "-cuda"]
+ steps:
+ - uses: actions/checkout@v4
+ - name: Setup OCI config
+ run: |
+ mkdir ~/.oci
+ echo "$OCI_KEY_CONTENT" > ~/.oci/key.pem
+ echo [DEFAULT] > ~/.oci/config
+ echo region=$OCI_REGION >> ~/.oci/config
+ echo tenancy=$OCI_TENANCY >> ~/.oci/config
+ echo user=$OCI_USER >> ~/.oci/config
+ echo fingerprint=$OCI_FINGERPRINT >> ~/.oci/config
+ echo key_file=~/.oci/key.pem >> ~/.oci/config
+ env:
+ OCI_TENANCY: ${{ secrets.OCI_CLI_TENANCY }}
+ OCI_USER: ${{ secrets.OCI_CLI_USER }}
+ OCI_FINGERPRINT: ${{ secrets.OCI_CLI_FINGERPRINT }}
+ OCI_KEY_CONTENT: ${{ secrets.OCI_CLI_KEY_CONTENT }}
+ - name: Install packer
+ working-directory: scripts/packer
+ run: |
+ wget https://releases.hashicorp.com/packer/${{ env.PACKER_VERSION }}/packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ unzip packer_${{ env.PACKER_VERSION }}_linux_amd64.zip
+ chmod +x packer
+ ./packer plugins install github.com/hashicorp/oracle
+ - name: Run packer
+ working-directory: scripts/packer
+ run: |
+ ./packer build \
+ -var-file=versions.json \
+ -var image_version=${{ inputs.image_version }} \
+ -var build_prefix=$VM_IMAGE_BUILD_PREFIX \
+ -var oci_compartment_ocid=$OCI_COMPARTMENT \
+ -var oci_subnet_ocid=$OCI_SUBNET \
+ -var oci_availability_domain=$OCI_AVAILABILITY_DOMAIN \
+ oci-image${{ matrix.variant }}.json
+ - uses: astral-sh/setup-uv@v5
+ with:
+ python-version: "3.12"
+ - name: Install dependencies for publishing
+ run: |
+ uv sync --extra oci
+ - name: Copy image to target regions
+ if: ${{ !inputs.staging }}
+ run: |
+ uv run scripts/oci_image_tools.py copy \
+ --image ${VM_IMAGE_BUILD_PREFIX}dstack${{ matrix.variant }}-${{ inputs.image_version }} \
+ --from $OCI_REGION \
+ --compartment $OCI_COMPARTMENT
+ - name: Publish image in OCI Marketplace
+ if: ${{ !inputs.staging }}
+ run: |
+ uv run scripts/oci_image_tools.py publish \
+ --image ${VM_IMAGE_BUILD_PREFIX}dstack${{ matrix.variant }}-${{ inputs.image_version }} \
+ --compartment $OCI_COMPARTMENT \
+ --version ${{ inputs.image_version }} \
+ --description "Image for running workloads with dstack - https://dstack.ai/" \
+ --os "Ubuntu 22.04" \
+ --contact-name dstack \
+ --contact-email hello@dstack.ai
diff --git a/.gitignore b/.gitignore
index b723429d13..46bc383130 100644
--- a/.gitignore
+++ b/.gitignore
@@ -3,17 +3,30 @@
*.egg-info
dist/
-/venv/
+build/
+venv/
+/site/
/.cache/
.pytest_cache/
.coverage
.idea/
+.fleet
+.vscode
+.aider*
+.local/
+.DS_Store
+.env
+.envrc
+uv.lock
/runner/cmd/shim/shim
/runner/cmd/runner/runner
-build/
-.DS_Store
-.fleet
-.env
\ No newline at end of file
+/src/dstack/_internal/server/statics
+
+profiling_results.html
+
+mkdocs/docs/reference/http/openapi.json
+mkdocs/docs/reference/api/rest/openapi.json
+mkdocs/docs/reference/plugins/rest/rest_plugin_openapi.json
diff --git a/.justfile b/.justfile
new file mode 100644
index 0000000000..efa8c87f61
--- /dev/null
+++ b/.justfile
@@ -0,0 +1,21 @@
+# Root justfile
+#
+# This justfile serves as the main entry point to recipes from different components.
+#
+# Run `just` to see all available commands.
+#
+# Components:
+# * runner/.justfile – Building and uploading dstack runner and shim
+# * frontend/.justfile – Building and running the frontend
+# * mkdocs/.justfile – Building and previewing the docs site
+
+default:
+ @just --list
+
+set allow-duplicate-recipes
+
+import "runner/.justfile"
+
+import "frontend/.justfile"
+
+import "mkdocs/.justfile"
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index 9f49b863ff..c780267f2c 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -1,14 +1,33 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
- rev: v0.4.8
+ rev: v0.12.7 # Should match pyproject.toml
hooks:
- id: ruff
name: ruff common
args: ['--fix']
- id: ruff-format
- repo: https://github.com/golangci/golangci-lint
- rev: v1.58.1
+ rev: v2.6.2 # Should match .github/workflows/build-artifacts.yml
hooks:
- id: golangci-lint-full
- entry: bash -c 'cd runner && golangci-lint run -D depguard --presets import,module,unused "$@"'
+ alias: runner-fix
+ language_version: 1.25.0 # Should match runner/go.mod
+ entry: bash -c 'cd runner && golangci-lint run --fix'
stages: [manual]
+ - id: golangci-lint-full
+ alias: runner-lint
+ language_version: 1.25.0 # Should match runner/go.mod
+ entry: bash -c 'cd runner && golangci-lint run'
+ stages: [manual]
+ - repo: https://github.com/pre-commit/pre-commit-hooks
+ rev: v5.0.0
+ hooks:
+ - id: end-of-file-fixer
+ - repo: local
+ hooks:
+ - id: frontend-pre-commit
+ name: frontend-pre-commit
+ entry: bash -c "cd frontend && npm install && npm run pre-commit"
+ language: system
+ pass_filenames: false
+ files: ^frontend/
diff --git a/AGENTS.md b/AGENTS.md
new file mode 100644
index 0000000000..0bbee7d51c
--- /dev/null
+++ b/AGENTS.md
@@ -0,0 +1,37 @@
+# Repository Guidelines
+
+## Project Structure & Module Organization
+- Core Python package lives in `src/dstack`; internal modules (including server) sit under `_internal`, API surfaces under `api`, and plugin integrations under `plugins`.
+- Tests reside in `src/tests` and mirror package paths; add new suites alongside the code they cover.
+- Frontend lives in `frontend` (React/webpack) and is built into `src/dstack/_internal/server/statics`.
+- Docs sources are in `mkdocs/docs/` with extra contributor notes in `contributing/*.md`.
+
+## Build, Test, and Development Commands
+- Install deps (editable package with extras): `uv sync --all-extras` (uses `.venv` in repo).
+- Run CLI/server from source: `uv run dstack ...` (e.g., `uv run dstack server --port 8000`).
+- Lint/format: `uv run ruff check .` and `uv run ruff format .`.
+- Type check: `uv run pyright -p .`.
+- Test suite: `uv run pytest`.
+- Frontend: from `frontend/` run `npm install`, `npm run build`, then copy `frontend/build` into `src/dstack/_internal/server/statics/`; for dev, `npm run start` with API on port 8000.
+
+## Coding Style & Naming Conventions
+- Python targets 3.10+ with 4-space indentation and max line length of 99 (see `pyproject.toml`; `E501` is ignored but keep lines readable).
+- Imports are sorted via Ruff’s isort settings (`dstack` treated as first-party).
+- Keep primary/public functions before local helper functions in a module section.
+- Roughly keep function definitions in the order they are referenced within a file so call flow stays easy to follow.
+- Prefer early returns over nested `if`/`else` blocks when they make the control flow simpler.
+- Keep private classes, exceptions, and similar implementation-specific types close to the private functions that use them unless they are shared more broadly in the module.
+- Prefer pydantic-style models in `core/models`.
+- Document attributes when the note adds behavior, compatibility, or semantic context that is not obvious from the name and type. Use attribute docstrings without leading newline.
+- Tests use `test_*.py` modules and `test_*` functions; fixtures live near usage.
+
+## Testing Guidelines
+- Default to `uv run pytest`. Use markers from `tests/conftest.py` like `--runpostgres` if need to include specific tests.
+- Group tests for the same unit (function/class) using `Test*` classes that mirror unit's name.
+- Keep tests hermetic (network disabled except localhost per `pytest.ini`); stub cloud calls with mocks.
+
+## Commit & Pull Request Guidelines
+- Commit messages follow the existing style: short, imperative summaries (e.g., “Fix exclude_not_available ignored”); include rationale in the body if needed.
+- For PRs, describe behavior changes and link related issues.
+- Include screenshots or terminal output when touching UX/CLI messages or frontend flows.
+- Always disclose AI Assistance in PRs.
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index f7a694a409..e373738b1b 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -3,7 +3,7 @@
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
-contributors and maintainers pledge to making participation in our project and
+contributors and maintainers pledge to make participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
@@ -11,7 +11,7 @@ appearance, race, religion, or sexual identity and orientation.
## Our Standards
-Examples of behavior that contributes to creating a positive environment
+Examples of behavior that contribute to creating a positive environment
include:
* Using welcoming and inclusive language
@@ -34,12 +34,12 @@ Examples of unacceptable behavior by participants include:
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
-behavior and are expected to take appropriate and fair corrective action in
+behavior, and they are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
-that are not aligned to this Code of Conduct, or to ban temporarily or
+that are not aligned with this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
@@ -58,7 +58,7 @@ Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at hello@dstack.ai. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
-obligated to maintain confidentiality with regard to the reporter of an incident.
+obligated to maintain confidentiality regarding the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
@@ -73,4 +73,4 @@ available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.ht
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
-https://www.contributor-covenant.org/faq
\ No newline at end of file
+https://www.contributor-covenant.org/faq
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 24705478e5..1782025bb6 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -2,6 +2,19 @@
We appreciate your interest in contributing to `dstack`! This document will help you get up to speed with `dstack` codebase and guide you through the contribution process.
+## AI Assistance Notice
+
+If you are using any kind of AI assistance while contributing to `dstack`,
+**this must be disclosed in the pull request**, along with the extent to
+which AI assistance was used.
+As an exception, tab-completions and trivial PRs don't need to be disclosed.
+
+An example disclosure:
+
+> This PR was written primarily by Claude Code.
+
+Failure to disclose this, makes it difficult to determine how much scrutiny to apply to the contribution. Please be respectful to maintainers and disclose AI assistance.
+
## Set up your development environment
Follow [contributing/DEVELOPMENT.md](contributing/DEVELOPMENT.md).
@@ -22,21 +35,40 @@ If you make a non-trivial change to `dstack`, we recommend you learn about `dsta
* Bug fixes that address a clearly defined bug. Include steps to reproduce in the linked issue or the PR.
* New features. Before submitting a feature PR, create an issue with a proposal to discuss it with the core team and other interested parties.
* Minor fixes such as typos.
-* [Examples](examples/README.md).
+* [Examples](examples).
### Before pushing your changes
We use [`ruff`](https://docs.astral.sh/ruff/) to format Python code and to sort Python imports. Before committing your changes, run:
-1. `ruff check --fix`
-2. `ruff format`
+1. `uv run ruff check --fix`
+2. `uv run ruff format`
> There are also helper pre-commits installed for [`ruff`](https://docs.astral.sh/ruff/integrations/#pre-commit) that make commits fail if the code is not formatted or the imports are not sorted. They also change the code as required so that you can review the changes and commit again.
+### Run tests
+
+It's recommended to run tests locally before running them in CI.
+To run Python tests, first ensure you've install dev dependencies as described in [contributing/DEVELOPMENT.md](contributing/DEVELOPMENT.md).
+Then you can do:
+
+```shell
+uv run pytest src/tests
+```
+
+(Optionally) By default, tests run against SQLite.
+Use the `--runpostgres` flag to run the tests against Postgres as well:
+
+```shell
+uv run pytest src/tests --runpostgres
+```
+
## Add a new backend
If you'd like to integrate a new cloud provider to `dstack`, follow [contributing/BACKENDS.md](contributing/BACKENDS.md).
-## Get help
+## What's next
+
+You can find more subject-focused guides in the [contributing](contributing/) directory.
If you have any questions, you can always get help in our [Discord](https://discord.gg/u8SmfwPpMd) community.
diff --git a/README.md b/README.md
index d1d658c32c..b1e616f1b9 100644
--- a/README.md
+++ b/README.md
@@ -1,63 +1,55 @@
-
+
[](https://github.com/dstackai/dstack/commits/)
[](https://github.com/dstackai/dstack/blob/master/LICENSE.md)
-[](https://discord.gg/CBgdrGnZjy)
+[](https://discord.gg/u8SmfwPpMd)
-`dstack` is an open-source container orchestration engine designed for running AI workloads across any cloud or data
-center. It simplifies dev environments, running tasks on clusters, and deployment.
+`dstack` is a unified control plane for GPU provisioning and orchestration that works with any GPU cloud, Kubernetes, or on-prem clusters.
-The supported cloud providers include AWS, GCP, Azure, OCI, Lambda, TensorDock, Vast.ai, RunPod, and CUDO.
-You can also use `dstack` to run workloads on on-prem clusters.
+It streamlines development, training, and inference, and is compatible with any hardware, open-source tools, and frameworks.
-`dstack` natively supports NVIDIA GPU, and Google Cloud TPU accelerator chips.
-
-## Latest news ✨
-
-- [2024/05] [dstack 0.18.4: Google Cloud TPU, and more](https://github.com/dstackai/dstack/releases/tag/0.18.4) (Release)
-- [2024/05] [dstack 0.18.3: OCI, and more](https://github.com/dstackai/dstack/releases/tag/0.18.3) (Release)
-- [2024/05] [dstack 0.18.2: On-prem clusters, private subnets, and more](https://github.com/dstackai/dstack/releases/tag/0.18.2) (Release)
-- [2024/04] [dstack 0.18.0: RunPod, multi-node tasks, and more](https://github.com/dstackai/dstack/releases/tag/0.18.0) (Release)
-- [2024/03] [dstack 0.17.0: Auto-scaling, and other improvements](https://github.com/dstackai/dstack/releases/tag/0.17.0) (Release)
-
-## Installation
+#### Accelerators
-Before using `dstack` through CLI or API, set up a `dstack` server.
+`dstack` supports `NVIDIA`, `AMD`, `Google TPU`, and `Tenstorrent` accelerators out of the box.
-### Install the server
-
-The easiest way to install the server, is via `pip`:
-
-```shell
-pip install "dstack[all]" -U
-```
+## Latest news ✨
+- [2026/04] [dstack 0.20.17: PD disaggregation, Kubernetes volumes](https://github.com/dstackai/dstack/releases/tag/0.20.17)
+- [2026/04] [dstack 0.20.16: Performance, SSH proxy](https://github.com/dstackai/dstack/releases/tag/0.20.16)
+- [2026/03] [dstack 0.20.13: Exports, Templates](https://github.com/dstackai/dstack/releases/tag/0.20.13)
+- [2026/02] [dstack 0.20.12: Crusoe](https://github.com/dstackai/dstack/releases/tag/0.20.12)
+- [2026/02] [dstack 0.20.8: Skills](https://github.com/dstackai/dstack/releases/tag/0.20.8)
+- [2025/12] [dstack 0.20.0: Fleet-first UX, Events, and more](https://github.com/dstackai/dstack/releases/tag/0.20.0)
-### Configure backends
+## How does it work?
-If you have default AWS, GCP, Azure, or OCI credentials on your machine, the `dstack` server will pick them up automatically.
+
+
+
+
-Otherwise, you need to manually specify the cloud credentials in `~/.dstack/server/config.yml`.
+### Launch the server
-See the [server/config.yml reference](https://dstack.ai/docs/reference/server/config.yml.md#examples)
-for details on how to configure backends for all supported cloud providers.
+> Before using `dstack` through CLI or API, set up a `dstack` server. If you already have a running `dstack` server, you only need to [install the CLI](#install-the-cli).
-### Start the server
+To orchestrate compute across GPU clouds or Kubernetes clusters, you need to [configure backends](https://dstack.ai/docs/concepts/backends).
-To start the server, use the `dstack server` command:
+> When using `dstack` with on-prem servers, backend configuration isn’t required. Simply create [SSH fleets](https://dstack.ai/docs/concepts/fleets#ssh-fleets) once the server is up.
-
+The server can be installed on Linux, macOS, and Windows (via WSL 2). It requires Git and
+OpenSSH.
```shell
+$ uv tool install "dstack[all]" -U
$ dstack server
Applying ~/.dstack/server/config.yml...
@@ -66,76 +58,76 @@ The admin token is "bbae0f28-d3dd-4820-bf61-8f4bb40815da"
The server is running at http://127.0.0.1:3000/
```
-
-
-> **Note**
-> It's also possible to run the server via [Docker](https://hub.docker.com/r/dstackai/dstack).
+> For more details on server configuration options, see the
+[Server deployment](https://dstack.ai/docs/guides/server-deployment) guide.
-### CLI & API
+### Install the CLI
-Once the server is up, you can use either `dstack`'s CLI or API to run workloads.
-Below is a live demo of how it works with the CLI.
+
If the CLI is not installed with the server
-### Dev environments
+Once the server is up, you can access it via the `dstack` CLI.
-You specify the required environment and resources, then run it. `dstack` provisions the dev
-environment in the cloud and enables access via your desktop IDE.
+The CLI can be installed on Linux, macOS, and Windows. It requires Git and OpenSSH.
-
-
-### Tasks
-
-Tasks allow for convenient scheduling of any kind of batch jobs, such as training, fine-tuning,
-or data processing, as well as running web applications.
+```shell
+$ uv tool install dstack -U
+```
-Specify the environment and resources, then run it. `dstack` executes the task in the
-cloud, enabling port forwarding to your local machine for convenient access.
+To point the CLI to the `dstack` server, configure it
+with the server address, user token, and project name:
-
+```shell
+$ dstack project add \
+ --name main \
+ --url http://127.0.0.1:3000 \
+ --token bbae0f28-d3dd-4820-bf61-8f4bb40815da
-### Services
+Configuration is updated at ~/.dstack/config.yml
+```
-Services make it very easy to deploy any kind of model or web application as public endpoints.
+
-Use any serving frameworks and specify required resources. `dstack` deploys it in the configured
-backend, handles authorization, and provides an OpenAI-compatible interface if needed.
+### Install agent skills
-
+Install [`dstack` skills](https://skills.sh/dstackai/dstack/dstack) to help AI agents use the CLI and edit configuration files.
-### Pools
+```shell
+$ npx skills add dstackai/dstack
+```
-Pools simplify managing the lifecycle of cloud instances and enable their efficient reuse across runs.
+AI agents like Claude, Codex, and Cursor can now create and manage fleets and submit workloads on your behalf.
-You can have instances provisioned in the cloud automatically, or add them manually, configuring the required resources,
-idle duration, etc.
+### Define configurations
-
+`dstack` supports the following configurations:
+
+* [Fleets](https://dstack.ai/docs/concepts/fleets) — for managing cloud and on-prem clusters
+* [Dev environments](https://dstack.ai/docs/concepts/dev-environments) — for interactive development using a desktop IDE
+* [Tasks](https://dstack.ai/docs/concepts/tasks) — for scheduling jobs (incl. distributed jobs) or running web apps
+* [Services](https://dstack.ai/docs/concepts/services) — for deployment of models and web apps (with auto-scaling and authorization)
+* [Volumes](https://dstack.ai/docs/concepts/volumes) — for managing persisted volumes
-## Examples
+Configuration can be defined as YAML files within your repo.
-Here are some featured examples:
+### Apply configurations
-- [Llama 3](examples/llms/llama3)
-- [Alignment Handbook](examples/fine-tuning/alignment-handbook)
-- [vLLM](examples/deployment/vllm)
-- [Axolotl](examples/fine-tuning/axolotl)
-- [TGI](examples/deployment/tgi)
-- [Ollama](examples/deployment/ollama)
-- [LoRaX](examples/deployment/lorax)
+Apply the configuration via the `dstack apply` CLI command, a programmatic API, or through [AI agent skills](#install-ai-agent-skills).
-Browse [examples](examples) for more examples.
+`dstack` automatically manages provisioning, job queuing, auto-scaling, networking, volumes, run failures,
+out-of-capacity errors, port-forwarding, and more — across clouds and on-prem clusters.
-## More information
+## Useful links
-For additional information and examples, see the following links:
+For additional information, see the following links:
-- [Docs](https://dstack.ai/docs)
-- [Discord](https://discord.gg/u8SmfwPpMd)
+* [Docs](https://dstack.ai/docs)
+* [Examples](https://dstack.ai/examples)
+* [Discord](https://discord.gg/u8SmfwPpMd)
## Contributing
-We welcome contributions to `dstack`!
-To learn more about getting involved in the project, please refer to [CONTRIBUTING.md](CONTRIBUTING.md).
+You're very welcome to contribute to `dstack`.
+Learn more about how to contribute to the project at [CONTRIBUTING.md](CONTRIBUTING.md).
## License
diff --git a/contributing/ARCHITECTURE.md b/contributing/ARCHITECTURE.md
index 4ede39296f..ca14f36245 100644
--- a/contributing/ARCHITECTURE.md
+++ b/contributing/ARCHITECTURE.md
@@ -11,66 +11,43 @@ The `dstack` platform consists of six major components:
* Shim
* Gateway (optional)
-The server provides an HTTP API for submitting runs and managing all of the `dstack` functionality including users,
-projects, backends, repos, secrets, and gateways.
+The server provides an HTTP API for submitting runs and managing all of the `dstack` functionality including users, projects, backends, repos, secrets, and gateways.
-The Python API consists of the low-level and high-level Python API. The low-level Python API is a Python wrapper around
-the server's HTTP API. It's available as `dstack.api.server`. The high-level API provides a more convenient interface to
-work with `dstack` programatically. It's available as `dstack.api`. The `dstack` CLI is implemented on top of the
-high-level API.
+The Python API consists of the low-level and high-level Python API. The low-level Python API is a Python wrapper around the server's HTTP API. It's available as `dstack.api.server`. The high-level API provides a more convenient interface to work with `dstack` programmatically. It's available as `dstack.api`. The `dstack` CLI is implemented on top of the high-level API.
-When the server provisions a cloud instance for a run, it launches a Docker image with the runner inside the image. The
-runner provides an HTTP API that the server uses for submitting the run, uploading the code, fetching logs and so on.
+When the server provisions a cloud instance for a run, it launches a Docker image with the runner inside the image. The runner provides an HTTP API that the server uses for submitting the run, uploading the code, fetching logs and so on.
-The shim may be or may not be present depending on which type of cloud is used. If it's a GPU cloud that provides an API
-for running Docker images, then no shim is required. If it's a traditional cloud that provisions VMs, then the shim is
-started on the VM launch. It pulls and runs the Docker image, controls its execution, and implements any cloud-specific
-functionality such as terminating the instance.
+The shim may be or may not be present depending on which type of cloud is used. If it's a GPU cloud that provides an API for running Docker images, then no shim is required. If it's a traditional cloud that provisions VMs, then the shim is started on the VM launch. It pulls and runs the Docker image, controls its execution, and implements any cloud-specific functionality such as terminating the instance.
-The gateway makes jobs available via a public URL. It works like a reverse proxy that forwards requests to the job
-instance via an SSH tunnel.
+The gateway makes jobs available via a public URL. It works like a reverse proxy that forwards requests to the job instance via an SSH tunnel.
-## Implementation of `dstack run`
+## Implementation of `dstack apply`
-When a user invokes `dstack run`, the CLI first sends the run configuration and other profile parameters to the server
-to get the run plan. The server iterates over configured backends to get all instance offers matching the requirements
-and their availability. If the user is willing to proceed with the offers suggested, the CLI uploads the code from the
-user's machine to the server and submits the run configuration.
+When a user applies a run configuration with `dstack apply`, the CLI sends the run configuration and other profile parameters to the server to get the run plan. The server iterates over configured backends to get all instance offers matching the requirements
+and their availability. If the user is willing to proceed with the offers suggested, the CLI uploads the code from the user's machine to the server and submits the run configuration.
-Note: If a git repository is used, `dstack` only uploads the code diff. The runner then pulls the repository and applies
-the diff to get the copy of the user's files. The `dstack init` command uploads git credentials to the server so that
-the runner can access private repositories.
+Note: If a git repository is used, `dstack` only uploads the code diff. The runner then pulls the repository and applies the diff to get the copy of the user's files. The `dstack init` command uploads git credentials to the server so that the runner can access private repositories.
-The submitted runs are stored in the server database. For each run, the server also creates one or more jobs. (Multiple
-jobs allow for distributed runs.) And for each job, it creates an initial job submission. If one submission fails, the
-server may create new submissions.
+The submitted runs are stored in the server database. For each run, the server also creates one or more jobs. (Multiple jobs allow for distributed runs and multi-replica services.) For each job, it creates a job submission. If a job submission fails, the server may create new submissions.
-A background worker fetches a job submission and iterates over configured backends to provision an instance. It tries
-best offers first until the provisioning succeeds. The instance is instructed to run the shim on the launch. In case
-of "Docker-only" clouds, the docker image is run directly.
+A background worker fetches a job submission and iterates over configured backends to provision an instance. It tries best offers first until the provisioning succeeds. The instance is instructed to run the shim on the launch. In case of "Docker-only" clouds, the docker image is run directly.
-A successfully provisioned job enters the provisioning state. Another background worker processes such jobs. It waits
-for the runner to become available and submits the job.
+A successfully provisioned job enters the provisioning state. Another background worker processes such jobs. It waits for the runner to become available and submits the job.
-Note: The runner HTTP API is not exposed publicly. In order to use it, the server established an SSH connection to the
-instance. The runner HTTP API becomes available via port-forwarding.
+Note: The runner HTTP API is not exposed publicly. In order to use it, the server established an SSH connection to the instance. The runner HTTP API becomes available via port-forwarding.
-After the job is submitted, the job enters the running state. A background worker pings the runner periodically for the
-job status and logs updates.
+After the job is submitted, the job enters the running state. A background worker pings the runner periodically for the job status and logs updates.
-When all job's commands are executed, the runner marks job as done, the container exists, and the shim terminates the
-instance. The job may also be interrupted by `dstack stop` that asks the runner shutdown gracefully. The `--abort` flag
-tells the server to force instance shutdown without notifying the runner, which may be useful if the runner becomes
-unavailable.
+When all job's commands are executed, the runner marks job as done, the container exists, and the shim terminates the instance. The job may also be interrupted by `dstack stop` that asks the runner shutdown gracefully. The `--abort` flag tells the server to force instance shutdown without notifying the runner and waiting for the runner graceful stop.
## Project structure
-The server is a FastAPI app backend by sqlite. The runner and shim are written in Go.
+The server is a FastAPI app backend by SQLite or Postgres. The runner and shim are written in Go.
* `docker/` – Dockefiles for `dstack` images
* `docs/` – source files for mkdocs generated documentation
* `runner/` – source code for the runner and the shim
-* `scripts/` – dev and CI/CD scripts
+* `scripts/` – dev/CI/CD scripts and packer files for building `dstack` cloud VM images.
* `src/` – source code for the `dstack` Python package that includes the server, the CLI and the Python API
* `dstack/`
* `_internal/` – modules hidden from the users of the `dstack` Python API
diff --git a/contributing/AUTOSCALING.md b/contributing/AUTOSCALING.md
index 87e7a5c328..eb5f6e1978 100644
--- a/contributing/AUTOSCALING.md
+++ b/contributing/AUTOSCALING.md
@@ -1,17 +1,22 @@
-dstack features auto-scaling for services published via the gateway. The general flow is:
+# Autoscaling
+
+`dstack` features auto-scaling for services published via the gateway. The general flow is:
- STEP 1: `dstack-gateway` parses nginx `access.log` to collect per-second statistics about requests to the service and request times.
-- STEP 2: `dstack-gateway` aggregates statistics over a 1-minute window.
-- STEP 3: The dstack server pulls all service statistics in the `process_gateways` background task.
-- STEP 4: The `process_runs` background task passes statistics and current replicas to the autoscaler.
-- STEP 5: The autoscaler (configured via the `dstack.yml` file) returns the replica change as an int.
-- STEP 6: `process_runs` calls `scale_run_replicas` to add or remove replicas.
-- STEP 7: `scale_run_replicas` terminates or starts replicas.
- - `SUBMITTED` and `PROVISIONING` replicas get terminated before `RUNNING`.
- - Replicas are terminated by descending `replica_num` and launched by ascending `replica_num`.
+- STEP 2: `dstack-gateway` aggregates statistics over several predefined windows.
+- STEP 3: The server keeps gateway connections alive in the scheduled `process_gateways_connections` task and continuously collects stats from active gateways. This is separate from `GatewayPipeline`, which handles gateway provisioning and deletion.
+- STEP 4: When `RunPipeline` processes a service run, it loads the latest collected gateway stats for that service.
+- STEP 5: The autoscaler (configured via `dstack.yml`) computes the desired replica count for each replica group.
+- STEP 6: `RunPipeline` applies that desired state.
+ - For scale-up, it creates new `SUBMITTED` jobs. `JobSubmittedPipeline` then assigns existing capacity or provisions new capacity for them.
+ - For scale-down, it marks the least-important active replicas as `TERMINATING` with `SCALED_DOWN`. `JobTerminatingPipeline` unregisters and cleans them up.
+- STEP 7: If the service is in rolling deployment, `RunPipeline` handles that in the same active-run processing path.
+ - It allows only a limited surge of replacement replicas.
+ - It delays teardown of old replicas until replacement capacity is available.
+ - It also cleans up replicas that belong to replica groups removed from the configuration.
## RPSAutoscaler
-`RPSAutoscaler` implements simple target tracking scaling. The target value represents requests per second per replica (in a 1-minute window).
+`RPSAutoscaler` implements simple target tracking scaling. The target value represents requests per second per replica (in a configurable window).
-`scale_up_delay` tells how much time has to pass since the last upscale or downscale event before the next upscaling. `scale_down_delay` tells how much time has to pass since the last upscale or downscale event before the next downscaling.
\ No newline at end of file
+`scale_up_delay` tells how much time has to pass since the last upscale or downscale event before the next upscaling. `scale_down_delay` tells how much time has to pass since the last upscale or downscale event before the next downscaling.
diff --git a/contributing/BACKENDS.md b/contributing/BACKENDS.md
index 37d8aae711..0c7ac6a151 100644
--- a/contributing/BACKENDS.md
+++ b/contributing/BACKENDS.md
@@ -4,12 +4,12 @@ The guide below explains the steps required to extend `dstack` with support for
## Overview of the process
-1. Add the cloud provider to [gpuhunt](https://https://github.com/dstackai/gpuhunt)
-2. Integrate the cloud provider into [dstack](https://https://github.com/dstackai/dstack)
+1. Add the cloud provider to [gpuhunt](https://github.com/dstackai/gpuhunt)
+2. Integrate the cloud provider into [dstack](https://github.com/dstackai/dstack)
## 1. Add a cloud provider to dstackai/gpuhunt
-The [gpuhunt](https://https://github.com/dstackai/gpuhunt) project is a utility that `dstack` uses to collect information
+The [gpuhunt](https://github.com/dstackai/gpuhunt) project is a utility that `dstack` uses to collect information
about cloud providers, their supported machine configurations, pricing, etc. This information is later used by `dstack`
for provisioning machines.
@@ -23,169 +23,149 @@ To add a new cloud provider to `gpuhunt`, follow these steps:
git clone https://github.com/dstackai/gpuhunt.git
```
-### 1.2. Create the provider class
+### 1.2. Decide if you will implement an offline or an online provider
-Create the provider class file under `src/gpuhunt/providers`.
+- **Offline providers** offer static machine configurations that are not frequently updated.
+ `gpuhunt` collects offline providers' instance offers on an hourly basis.
+ Examples: `aws`, `gcp`, `azure`, etc.
+- **Online providers** offer dynamic machine configurations that are available at the very moment
+ when you fetch configurations (e.g., GPU marketplaces).
+ `gpuhunt` collects online providers' instance offers each time a `dstack` user provisions a new instance.
+ Examples: `tensordock`, `vastai`, etc.
-Ensure your class...
+### 1.3. Create the provider class
-- Extends the `AbstractProvider` base class.
-- Has the `NAME` property, that will be used as the unique identifier for your provider.
-- Implements the `get` method, that is responsible for fetching the available machine configurations from the cloud provider.
+Create the provider class file under `src/gpuhunt/providers`.
-[//]: # (TODO: Elaborate better on how to use `query_filter` and `balance_resources`)
+Make sure your class extends the [`AbstractProvider`](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/__init__.py)
+base class. See its docstrings for descriptions of the methods that your class should implement.
-Refer to examples: [datacrunch.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/datacrunch.py),
-[aws.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/aws.py),
-[gcp.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/gcp.py),
-[azure.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/azure.py),
-[lambdalabs.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/lambdalabs.py),
-[tensordock.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/tensordock.py),
-[vastai.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/vastai.py).
-
-### 1.3. Register the provider with the catalog
-
-Update the `src/gpuhunt/_internal/catalog.py` file by adding the provider name
-to either `OFFLINE_PROVIDERS` or `ONLINE_PROVIDERS` depending on the type of the provider.
-
-How do I decide which type my provider is?
-
-- `OFFLINE_PROVIDERS` - Use this type if your provider offers static machine configurations that may be collected and
- published on a daily basis. Examples: `aws`, `gcp`, `azure`, etc. These providers offer many machine configurations,
- but they are not updated frequently.
-- `ONLINE_PROVIDERS` - Use this type if your provider offers dynamic machine configurations that are available at the very moment when you fetch configurations (e.g., GPU marketplaces).
- Examples: `tensordock`, `vast`, etc.
-
-### 1.4. Add data quality tests
-
-If the provider is registered via `OFFLINE_PROVIDERS`, you can add data quality tests
-under `src/integrity_tests/`.
-
-Refer to examples: [test_datacrunch.py](https://github.com/dstackai/gpuhunt/blob/main/src/integrity_tests/test_datacrunch.py),
+Refer to examples:
+- Offline providers:
+ [verda.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/verda.py),
+ [aws.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/aws.py),
+ [azure.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/azure.py),
+ [lambdalabs.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/lambdalabs.py).
+- Online providers:
+ [vultr.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/vultr.py)
+ [tensordock.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/tensordock.py),
+ [vastai.py](https://github.com/dstackai/gpuhunt/blob/main/src/gpuhunt/providers/vastai.py).
+
+### 1.4. Register the provider with the catalog
+
+Add your provider in the following places:
+- Either `OFFLINE_PROVIDERS` or `ONLINE_PROVIDERS` in `src/gpuhunt/_internal/catalog.py`.
+- The `python -m gpuhunt` command in `src/gpuhunt/__main__.py`.
+- (offline providers) The CI workflow in `.github/workflows/catalogs.yml`.
+- (online providers) The default catalog in `src/gpuhunt/_internal/default.py`.
+
+### 1.5. Add data quality tests
+
+For offline providers, you can add data quality tests under `src/integrity_tests/`.
+Data quality tests are run after collecting offline catalogs to ensure their integrity.
+
+Refer to examples: [test_verda.py](https://github.com/dstackai/gpuhunt/blob/main/src/integrity_tests/test_verda.py),
[test_gcp.py](https://github.com/dstackai/gpuhunt/blob/main/src/integrity_tests/test_gcp.py).
-> Anything unclear? Ask questions on the [Discord server](https://discord.gg/u8SmfwPpMd).
+### 1.6. Submit a pull request
-Once the cloud provider is added, submit a pull request.
+Once the cloud provider is added, submit a pull request.
+> Anything unclear? Ask questions on the [Discord server](https://discord.gg/u8SmfwPpMd).
## 2. Integrate the cloud provider to dstackai/dstack
-Once the provider is added to `gpuhunt`, we can proceed with implementing
+Once the provider is added to `gpuhunt`, we can proceed with implementing
the corresponding backend with `dstack`. Follow the steps below.
-#### 2.1 Clone the repo
-
-```bash
-git clone https://github.com/dstackai/dstack.git
-```
-
-#### 2.2. Set up the development environment
-
-Follow [DEVELOPMENT.md](DEVELOPMENT.md)`.
-
-#### 2.3. Add dependencies to setup.py
-
-Add any dependencies required by your cloud provider to `setup.py`. Create a separate section with the provider's name for
-these dependencies, and ensure that you update the `all` section to include them as well.
+### 2.1. Determine if you will implement a VM-based or a container-based backend
-#### 2.4. Implement the provider backend
+See the Appendix at the end of this document and make sure the provider meets the outlined requirements.
-##### 2.4.1. Define the backend type
+### 2.2. Set up the development environment
-Add a new enumeration member for your provider to `BackendType` (`src/dstack/_internal/core/models/backends/base.py`).
-Use the name of the provider.
+Follow [DEVELOPMENT.md](DEVELOPMENT.md).
-##### 2.4.2. Create the provider directory
+### 2.3. Add dependencies to setup.py
-Create a new directory under `src/dstack/_internal/core/backends` with the name of the backend type.
+Add any dependencies required by your cloud provider to `setup.py`. Create a separate section with the provider's name for these dependencies, and ensure that you update the `all` section to include them as well.
-##### 2.4.3. Create the backend class
+### 2.4. Add a new backend type
-Under the backend directory you've created, create the `__init__.py` file and define the
-backend class there (should extend `dstack._internal.core.backends.base.Backend`).
+Add a new enumeration member for your provider to `BackendType` ([`src/dstack/_internal/core/models/backends/base.py`](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/models/backends/base.py)).
-Refer to examples:
-[datacrunch](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/datacrunch/__init__.py),
-[aws](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/aws/__init__.py),
-[gcp.py](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/gcp/__init__.py),
-[azure](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/azure/__init__.py), etc.
+### 2.5. Create backend files and classes
-##### 2.4.4. Create the backend compute class
+`dstack` provides a helper script to generate all the necessary files and classes for a new backend.
+To add a new backend named `ExampleXYZ`, you should run:
-Under the backend directory you've created, create the `compute.py` file and define the
-backend compute class there (should extend `dstack._internal.core.backends.base.compute.Compute`).
+```shell
+python scripts/add_backend.py -n ExampleXYZ
+```
-You'll have to implement `get_offers`, `create_instance`, `run_job` and `terminate_instance`.
+It will create an `examplexyz` backend directory under `src/dstack/_internal/core/backends` with the following files:
-The `create_instance` method is required for the pool feature. If you implement the `create_instance` method, you should add the provider name to `BACKENDS_WITH_CREATE_INSTANCE_SUPPORT`. (`src/dstack/_internal/server/services/runs.py`).
+* `backend.py` with the `Backend` class implementation. You typically don't need to modify it.
+* `compute.py` with the `Compute` class implementation. This is the core of the backend that you need to implement.
+* `configurator.py` with the `Configurator` class implementation. It deals with validating and storing backend config. You need to adjust it with custom backend config validation.
+* `models.py` with all the backend config models used by `Backend`, `Compute`, `Configurator` and other parts of `dstack`.
-Refer to examples:
-[datacrunch](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/datacrunch/compute.py),
-[aws](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/aws/compute.py),
-[gcp.py](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/gcp/compute.py),
-[azure](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/azure/compute.py), etc.
+### 2.6. Adjust and register the backend config models
-##### 2.4.5. Create the backend config model class
+Go to `models.py`. It'll contain two config models required for all backends:
-Under the `src/dstack/_internal/core/models/backends` directory, create the file with the name of the backend, and define the
-backend config model classes there.
+* `*BackendConfig` that contains all backend parameters available for user configuration except for creds.
+* `*BackendConfigWithCreds` that contains all backends parameters available for user configuration and also creds.
-[//]: # (TODO: Mention what config model classes are and how they work)
+Adjust generated config models by adding additional config parameters.
+Typically you'd need to only modify the `*BackendConfig` model since other models extend it.
-[//]: # (TODO: Mention what config values class is and how it works)
+Then add these models to `AnyBackendConfig*` unions in [`src/dstack/_internal/core/backends/models.py`](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/models.py).
-Refer to examples:
-[datacrunch](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/models/backends/datacrunch.py),
-[aws](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/models/backends/aws.py),
-[gcp.py](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/models/backends/gcp.py),
-[azure](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/models/backends/azure.py), etc.
+The script also generates `*BackendStoredConfig` that extends `*BackendConfig` to be able to store extra parameters in the DB. By the same logic, it generates `*Config` that extends `*BackendStoredConfig` with creds and uses it as the main `Backend` and `Compute` config instead of using `*BackendConfigWithCreds` directly.
-##### 2.4.6. Create the backend config class
+Refer to examples:
+[verda](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/verda/models.py),
+[aws](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/aws/models.py),
+[gcp](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/gcp/models.py),
+[azure](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/models.py), etc.
-Under the backend directory you've created, create the `config.py` file and define the
-backend config class there (should extend `dstack._internal.core.backends.base.config.BackendConfig`
-and the backend configuration model class defined above).
+### 2.7. Implement the backend compute class
-[//]: # (TODO: Mention what config class is and how it works)
+Go to `compute.py` and implement `Compute` methods.
+Optionally, extend and implement `ComputeWith*` classes to support additional features such as fleets, volumes, gateways, placement groups, etc. For example, extend `ComputeWithCreateInstanceSupport` to support fleets.
Refer to examples:
-[datacrunch](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/datacrunch/config.py),
-[aws](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/aws/config.py),
-[gcp.py](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/gcp/config.py),
-[azure](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/azure/config.py), etc.
-
-##### 2.4.7. Import config model classes
-
-Ensure the config model classes are imported
-into [`src/dstack/_internal/core/models/backends/__init__.py`](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/models/backends/__init__.py).
+[verda](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/verda/compute.py),
+[aws](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/aws/compute.py),
+[gcp](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/gcp/compute.py),
+[azure](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/azure/compute.py), etc.
-[//]: # (TODO: The backend configuration is overly complex and needs simplification: https://github.com/dstackai/dstack/issues/888)
+### 2.8. Implement and register the configurator class
-##### 2.4.8. Create the configurator class
+Go to `configurator.py` and implement custom `Configurator` logic. At minimum, you should implement creds validation.
+You may also need to validate other config parameters if there are any.
-Create the file with the backend name under `src/dstack/_internal/server/services/backends/configurators`(https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/server/services/backends/configurators)
-and define the backend configurator class (must extend `dstack._internal.server.services.backends.configurators.base.Configurator`).
+Refer to examples: [verda](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/verda/configurator.py),
+[aws](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/aws/configurator.py),
+[gcp](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/gcp/configurator.py),
+[azure](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/azure/configurator.py), etc.
-Refer to examples: [datacrunch](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/server/services/backends/configurators/datacrunch.py),
-[aws](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/server/services/backends/configurators/aws.py),
-[gcp.py](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/server/services/backends/configurators/gcp.py),
-[azure](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/server/services/backends/configurators/azure.py), etc.
+Register configurator by appending it to `_CONFIGURATOR_CLASSES` in [`src/dstack/_internal/core/backends/configurators.py`](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/core/backends/configurators.py).
-##### 2.4.9. Create the server config class
+### 2.9. (Optional) Override provisioning timeout
-In [`src/dstack/_internal/server/services/config.py`](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/server/services/config.py),
-define the corresponding server config class (that represents the `~/.dstack/server/config.yml` file),
-and add it to `AnyBackendConfig` (in the same file).
+If instances in the backend take more than 10 minutes to start, override the default provisioning timeout in
+[`src/dstack/_internal/server/background/tasks/common.py`](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/server/background/tasks/common.py).
-##### 2.4.10. Add safe imports
+### 2.10. Document the backend
-In [`src/dstack/_internal/server/services/backends/__init__.py`](https://github.com/dstackai/dstack/blob/master/src/dstack/_internal/server/services/backends/__init__.py),
-add the `try`/`except` block that imports the backend configurator and appends it to `_CONFIGURATOR_CLASSES`.
+Add the backend to the [Concepts->Backends](https://github.com/dstackai/dstack/blob/master/mkdocs/docs/concepts/backends.md
+) page and the [server/comfig.yml](https://github.com/dstackai/dstack/blob/master/mkdocs/docs/reference/server/config.yml.md) reference.
## 3. Appendix
-#### 3.1. Backend compute type
+### 3.1. Backend compute type
`dstack` supports two types of backend compute:
@@ -194,49 +174,47 @@ add the `try`/`except` block that imports the backend configurator and appends i
#### 3.1.1. VM-based backend compute type
-It's when the cloud provider allows provisioning Virtual machines (VMs).
-This is the most flexible backend compute type.
+Used if the cloud provider allows provisioning virtual machines (VMs).
+When `dstack` provisions a VM, it launches the `dstack-shim` agent inside the VM.
+The agent controls the VM and starts Docker containers for users' jobs.
-[//]: # (TODO: Elaborate why it's the most flexible)
+Since `dstack` controls the entire VM, VM-based backends can support more features,
+such as blocks, instance volumes, privileged containers, and reusable instances.
-To support it, `dstack` expects the following from the cloud provider:
+Note, all VM-based backend `Compute`s should sublass the `ComputeWithPrivilegedSupport`
+and `ComputeWithInstanceVolumesSupport` mixins, as the `dstack-shim` agent
+provides these functionalities OOTB.
-- An API for creating and terminating VMs
-- Ubuntu 22.04 LTS
-- NVIDIA CUDA driver 535
-- Docker with NVIDIA runtime
-- OpenSSH server
-- Cloud-init script (preferred)
-- An external IP and public port for SSH
-
-When `dstack` provisions a VM, it launches there `dstack-shim`.
+To support a VM-based backend, `dstack` expects the following:
-[//]: # (TODO: Elaborate on what dstack-shim is and how it works)
+- An API for creating and terminating VMs
+- An external IP and a public port for SSH
+- Cloud-init (preferred)
+- VM images with Ubuntu, OpenSSH, GPU drivers, and Docker with NVIDIA runtime
-The examples of VM-based backends include: `aws`, `azure`, `gcp`, `lambda`, `datacrunch`, `tensordock`, etc.
+For some VM-based backends, the `dstack` team also maintains
+[custom VM images](../scripts/packer/README.md) with the required dependencies
+and `dstack`-specific optimizations.
-[//]: # (TODO: Elaborate on packer scripts)
+Examples of VM-based backends include: `aws`, `azure`, `gcp`, `lambda`, `verda`, etc.
#### 3.1.2. Container-based backend compute type
-It's when the cloud provider allows provisioning only containers.
-This is the most limited backend compute type.
+Used if the cloud provider only allows provisioning containers.
+When `dstack` provisions a container, it launches the `dstack-runner` agent inside the container.
+The agent accepts and runs users' jobs.
-[//]: # (TODO: Elaborate on why it's the most limited)
+Since `dstack` doesn't control the underlying machine, container-based backends don't support some
+`dstack` features, such as blocks, instance volumes, privileged containers, and reusable instances.
-To support it, `dstack` expects the following from the cloud provider:
+To support a container-based backend, `dstack` expects the following:
- An API for creating and terminating containers
-- Docker with NVIDIA runtime
+- Containers properly configured to access GPUs
- An external IP and a public port for SSH
+- A way to specify the Docker image
+- A way to specify credentials for pulling images from private Docker registries
- A way to override the container entrypoint (at least ~2KB)
+- A way to override the container user to root (as in `docker run --user root ...`)
-The examples of container-based backends include: `kubernetes`, `vastai`, etc.
-
-Note: There are two types of compute in dstack:
-
-When `dstack` provisions a VM, it launches there `dstack-runner`.
-
-[//]: # (TODO: Elaborate on what dstack-runner is and how it works)
-
-[//]: # (TODO: Update this guide to incorporate the pool feature)
\ No newline at end of file
+Examples of container-based backends include: `kubernetes`, `vastai`, `runpod`.
diff --git a/contributing/DEVELOPMENT.md b/contributing/DEVELOPMENT.md
index 128c27f03e..b9570c2c60 100644
--- a/contributing/DEVELOPMENT.md
+++ b/contributing/DEVELOPMENT.md
@@ -1,30 +1,54 @@
# Development setup
-## Set up the development environment
-
-### 1. Clone the repo:
- ```
- git clone https://github.com/dstackai/dstack
- cd dstack
- ```
-
-### 2. (Recommended) Create a virtual environment:
- ```
- python3 -m venv venv
- source venv/bin/activate
- ```
-
-### 3. Install `dstack` in editable mode:
- ```
- pip install -e '.[all]'
- ```
-
-### 4. Install dev dependencies:
- ```
- pip install -r requirements_dev.txt
- ```
-
-### 5. (Recommended) Install pre-commits:
- ```
- pre-commit install
- ```
\ No newline at end of file
+## 1. Clone the repo:
+
+```shell
+git clone https://github.com/dstackai/dstack
+cd dstack
+```
+
+## 2. Install uv:
+
+https://docs.astral.sh/uv/getting-started/installation
+
+```shell
+curl -LsSf https://astral.sh/uv/install.sh | sh
+```
+
+## 3. Install `dstack` with all extras and dev dependencies:
+
+```shell
+uv sync --all-extras
+```
+
+`dstack` will be installed into the project's `.venv` in editable mode and can be run with `uv run dstack`.
+
+Alternatively, if you want to manage virtual environments by yourself, you can install `dstack` into the activated virtual environment with `uv sync --all-extras --active`.
+
+## 4. (Recommended) Install pre-commit hooks:
+
+Code formatting and linting can be done automatically on each commit with `pre-commit` hooks:
+
+```shell
+uv run pre-commit install
+```
+
+## 5. (Recommended) Use pyright:
+
+The CI runs `pyright` for type checking `dstack` Python code.
+So we recommend you configure your IDE to use `pyright`/`pylance` with `standard` type checking mode.
+
+You can also install `pyright` and run it from the CLI:
+
+```shell
+uv tool install pyright
+pyright -p .
+```
+
+## 6. Frontend
+
+See [FRONTEND.md](FRONTEND.md) for the details on how to build and develop the frontend.
+
+## 7. Documentation
+
+See [DOCS.md](DOCS.md) for the details on how to preview or build the documentation.
diff --git a/contributing/DOCS.md b/contributing/DOCS.md
new file mode 100644
index 0000000000..663e5c4c77
--- /dev/null
+++ b/contributing/DOCS.md
@@ -0,0 +1,181 @@
+# Documentation setup
+
+## 1. Clone the repo:
+
+```shell
+git clone https://github.com/dstackai/dstack
+cd dstack
+```
+
+## 2. Install uv:
+
+https://docs.astral.sh/uv/getting-started/installation
+
+```shell
+curl -LsSf https://astral.sh/uv/install.sh | sh
+```
+
+## 3. Install `dstack` with all extras and dev dependencies:
+
+> [!WARNING]
+> Building documentation requires `python_version >= 3.11`.
+
+```shell
+uv sync --all-extras
+```
+
+`dstack` will be installed into the project's `.venv` in editable mode.
+
+## 4. (Recommended) Install pre-commit hooks:
+
+Code formatting and linting can be done automatically on each commit with `pre-commit` hooks:
+
+```shell
+uv run pre-commit install
+```
+
+## 5. Preview documentation
+
+To preview the documentation, run the follow command:
+
+```shell
+uv run mkdocs serve --livereload -s
+```
+
+The `--livereload` flag is required to work around live-reload bugs in recent `mkdocs` versions.
+
+If you want to build static files, you can use the following command:
+
+```shell
+uv run mkdocs build -s
+```
+
+## Documentation build system
+
+The documentation uses a custom build system with MkDocs hooks to generate various files dynamically.
+
+### Disable flags
+
+Use these in `.envrc` to disable expensive docs regeneration, especially during `mkdocs serve` auto-reload. Set any of them to disable the corresponding artifact.
+
+```shell
+export DSTACK_DOCS_DISABLE_LLM_TXT=1
+export DSTACK_DOCS_DISABLE_CLI_REFERENCE=1
+export DSTACK_DOCS_DISABLE_YAML_SCHEMAS=1
+export DSTACK_DOCS_DISABLE_OPENAPI_REFERENCE=1
+export DSTACK_DOCS_DISABLE_REST_PLUGIN_SPEC_REFERENCE=1
+```
+
+### Build hooks
+
+The build process is customized via hooks in `scripts/docs/hooks.py`:
+
+#### 1. Schema reference expansion
+
+Files in `docs/reference/**/*.md` can use `#SCHEMA#` placeholders that are expanded with generated schema documentation during the build.
+
+#### 2. llms.txt generation
+
+Two files are generated for LLM consumption:
+
+- **llms.txt**: Structured overview of documentation with titles and descriptions
+ - Generated from mkdocs nav structure
+ - Includes sections: Getting started, Concepts, Guides, Examples
+ - Excludes: Reference section
+ - Configuration: `scripts/docs/gen_llms_files.py` (INCLUDE_SECTIONS, EXCLUDE_SECTIONS)
+
+- **llms-full.txt**: Full concatenation of all pages from llms.txt
+ - Contains complete markdown content of all included pages
+
+The generation logic is in `scripts/docs/gen_llms_files.py` and uses:
+- `site_name`, `site_description`, `site_url` from `mkdocs.yml`
+- Page titles from mkdocs nav structure
+- Page descriptions from markdown frontmatter
+
+**Adding descriptions**: To add descriptions to pages, add YAML frontmatter:
+
+```yaml
+---
+title: Page Title
+description: Short description of what this page covers
+---
+```
+
+For examples, add frontmatter to the page files (e.g., `mkdocs/docs/examples/training/trl.md`).
+
+#### 3. Skills discovery
+
+The build creates `.well-known/skills/` directory structure for skills discovery:
+- Reads `skills/dstack/SKILL.md`
+- Parses name and description from frontmatter
+- Generates `.well-known/skills/index.json`
+- Copies SKILL.md to both `.well-known/skills/dstack/` and site root
+
+#### 4. HTTP API reference
+
+The HTTP API reference is generated from the FastAPI OpenAPI schema:
+
+- `scripts/docs/gen_openapi_reference.py` writes `mkdocs/docs/reference/http/openapi.json`,
+ keeps the per-tag Markdown pages in sync, and updates the generated tag list in the HTTP API
+ index page.
+- Tag pages use `!!swagger openapi.json tag="
"!!`. Keep tag names exactly as they appear
+ in the OpenAPI schema.
+- `scripts/docs/hooks.py` expands the `!!swagger` directive into the Swagger UI container and
+ the hidden operation headings that MkDocs uses for the page table of contents.
+- `mkdocs/assets/javascripts/swagger.js` loads the shared `openapi.json`, filters it by tag on
+ the client, and adapts Swagger UI markup to the docs layout.
+- `mkdocs/assets/stylesheets/swagger.css` contains Swagger-specific styling and should stay
+ scoped under `.dstack-swagger-ui`.
+
+Keep hook logic limited to build-time Markdown/page structure, generated assets, and data
+attributes needed by the client. Small presentation changes belong in `swagger.css`; small
+behavior changes belong in `swagger.js`.
+
+If the HTTP API reference needs deeper structural customization, such as replacing major Swagger
+UI panels, request/response rendering, model rendering, or "try it out" behavior, prefer moving
+toward a dedicated local bundle or custom Swagger UI layout instead of adding more DOM patching.
+That bundle can still use the single generated `openapi.json` and filter by tag on the client, so
+we should not reintroduce per-tag OpenAPI files unless there is a concrete reason.
+
+### File structure
+
+```
+mkdocs/ # docs_dir for the mkdocs site
+├── index.md # Homepage
+├── docs/ # /docs/ URL section
+│ ├── index.md # Getting started
+│ ├── installation.md
+│ ├── quickstart.md
+│ ├── concepts/ # Concept pages
+│ ├── guides/ # How-to guides
+│ ├── reference/ # API reference (schema expansion)
+│ └── examples/ # Example pages (inline source code)
+│ └── training/
+│ └── trl.md # Page content with frontmatter
+├── blog/ # Blog posts
+├── overrides/ # Theme customization
+├── layouts/ # Social card layouts
+└── assets/ # Stylesheets, images, fonts
+
+scripts/docs/
+├── hooks.py # MkDocs build hooks
+├── gen_llms_files.py # llms.txt generation
+├── gen_schema_reference.py # Schema expansion
+└── gen_cli_reference.py # CLI reference generation
+
+skills/
+└── dstack/
+ └── SKILL.md # Skills discovery content
+```
+
+### Testing changes
+
+When modifying the build system:
+
+1. Test local build: `uv run mkdocs build -s`
+2. Check generated files in `site/`:
+ - `site/llms.txt`
+ - `site/llms-full.txt`
+ - `site/.well-known/skills/index.json`
+3. Verify example pages render correctly
+4. Check that descriptions appear in llms.txt
diff --git a/contributing/FRONTEND.md b/contributing/FRONTEND.md
new file mode 100644
index 0000000000..19b623b1d4
--- /dev/null
+++ b/contributing/FRONTEND.md
@@ -0,0 +1,56 @@
+# Frontend development setup
+
+To work with the frontend, switch the current folder to [frontend](../frontend)
+
+```shell
+cd frontend
+```
+
+## Building the frontend
+
+### 1. Install NPM dependencies
+
+Use `npm` to install dependencies:
+
+```shell
+npm install
+```
+
+### 2. Build the frontend
+
+For building the frontend, run:
+
+```shell
+npm run build
+```
+
+### 3. Copy the compiled frontend files
+
+Copy the contents of the `frontend/build` directory to the backend directory (`src/dstack/_internal/server/statics`):
+
+```shell
+cp -r build/ ../src/dstack/_internal/server/statics/
+```
+
+### 4. Run the dstack server
+
+Now, if you've installed `dstack` in editable mode, you can simply run `dstack server`
+and the frontend will be working.
+
+```shell
+dstack server
+```
+
+## Developing the frontend
+
+For frontend development, run a `webpack` dev server:
+
+```shell
+npm run start
+```
+
+The `webpack` dev server expects the API to be running on `http://127.0.0.1:8000`. So ensure to run the API on port `8000`:
+
+```shell
+dstack server --port 8000
+```
diff --git a/contributing/GATEWAY.md b/contributing/GATEWAY.md
deleted file mode 100644
index 29d9ea033b..0000000000
--- a/contributing/GATEWAY.md
+++ /dev/null
@@ -1,72 +0,0 @@
-A dstack gateway is a dedicated instance responsible for publishing user applications to the outer internet via the HTTP protocol. One dstack gateway can serve many services, domains, or projects.
-
-## Gateway creation
-
-Gateways are managed by the dstack server. A gateway is associated with a project and some backend in the project. Users must attach a wildcard domain to the gateway, i.e., all direct subdomains should resolve to the gateway IP address. Since the IP address is unknown during provisioning, dstack doesn't check DNS records.
-
-Provisioning happens as follows:
-1. Launch a non-GPU instance (usually the smallest) with all ports exposed.
-2. Install Nginx, Certbot, and patch configs.
-3. Create blue-green virtual environments.
-4. Install the latest `dstack-gateway` from the S3 bucket.
-5. Run the systemd service `dstack.gateway.service`.
-
-## Gateway update
-
-The `dstack-gateway` has a "blue-green deployment"-like configuration: there are two virtual environments to be swapped on update. The systemd service uses the newly installed package after a restart.
-
-The update process looks like this:
-1. Install the new package to the not-used venv.
-2. Update scripts and systemd service config.
-3. Swap the active venv name in the file `version`.
-4. Restart the systemd service.
-
-The `dstack-gateway` server dumps its internal state to the file `~/dstack/state.json` on termination. It tries to load the state from the same file on start. That allows updating the gateway with published services with minimal downtime.
-
-## Connection between server and gateway
-
-The dstack server keeps a bidirectional tunnel with each GatewayCompute for the whole uptime of the server.
-
-- The tunnel from the server to the gateway is used to manage the gateway: register and unregister services and replicas.
-- The tunnel from the gateway to the server is used to authenticate requests to the gateway based on dstack's tokens.
-
-Authorization responses are cached for 60 seconds. If the server is not responding, the request is denied.
-
-## Nginx
-
-`dstack-gateway` configures an Nginx reverse proxy. Each service or entrypoint configuration is stored as `/etc/nginx/sites-enabled/{port}-{server_name}.conf`. If the Nginx reload fails, `dstack-gateway` rolls back the changes.
-
-`dstack-gateway` enforces HTTPS (except for local traffic). On each service registration a TLS certificate is issued by Let's Encrypt or other configured CA via Certbot.
-
-If there are no replicas, the service configuration always returns 503; otherwise, the upstream with replicas is used. The upstream handles load balancing for us. `dstack-gateway` uses Unix sockets for SSH tunnels to avoid port conflicts between services.
-
-Service authorization is handled with the `localhost:8000/auth` endpoint if needed. `dstack-gateway` may request services without authorization and HTTPS, for example, from the OpenAI interface.
-
-Entrypoint configurations forward requests back to `dstack-gateway`, to a specific module (e.g., OpenAI). Authorization is handled by those modules.
-
-## Gateway registry
-
-The core component of `dstack-gateway` is the services store. It is responsible for:
-
-- Registering a service — assigning a domain, creating an Nginx config.
-- Registering a replica — starting an SSH tunnel, updating Nginx upstream.
-- Unregistering a replica — stopping an SSH tunnel, updating Nginx upstream.
-- Unregistering a service — releasing a domain, removing an Nginx config.
-- Registering an entrypoint — assigning a domain, creating an Nginx config.
-
-To decouple the store from other modules, there is a subscription mechanism. Subscribers will be notified on register service and unregister service.
-
-## OpenAI interface
-
-The OpenAI interface subscribes to `Store` events and emulates the real OpenAI API for chat completion models. It can list running models in the project and redirect requests to the right service.
-
-## Stats Collector
-
-The Stats collector parses nginx `/var/log/nginx/dstack.access.log` to collect basic metrics:
-
-1. Requests per second
-2. Average request processing time
-
-By default, it stores 5 minutes with 1-second resolution frames for each domain. It aggregates these frames in windows of the size 30 seconds, 1 minute, and 5 minutes, before sending to the server.
-
-To increase performance, `StatsCollector` keeps position in file and read only new records. It can detect log rotation and reopen the log file.
\ No newline at end of file
diff --git a/contributing/GPUHUNT.md b/contributing/GPUHUNT.md
index 498584b4ef..33e3150fa1 100644
--- a/contributing/GPUHUNT.md
+++ b/contributing/GPUHUNT.md
@@ -1,3 +1,5 @@
+# gpuhunt
+
[`dstackai/gpuhunt`](https://github.com/dstackai/gpuhunt) is a library developed and used for dstack. It implements the unified interface for fetching offers and prices from different cloud providers.
An offer is a possible configuration. It consists of:
@@ -63,7 +65,7 @@ Some providers offer extreme flexibility in possible configurations, but not all
- Filters out if: outdated family, not supported family
- Queries configuration details to fill CPU, RAM, and GPU information
-### DataCrunch
+### Verda
- Just queries all offers via API
@@ -83,13 +85,23 @@ Some providers offer extreme flexibility in possible configurations, but not all
- Parses Oracle's [Cost Estimator](https://www.oracle.com/cloud/costestimator.html) datasets
- Duplicates each offer in all regions, since prices are the same everywhere and availability is mostly the same
-### Nebius
-
-- Uses hardcoded CPU and GPU platforms configurations
-- Applies SKUs pricing to the platforms
-
### GitHub Actions: collect catalog
The offline catalog is built in GitHub Actions every night. Every offline provider produces a CSV file with offers. Later, those files get compressed into a zip archive and uploaded to the public S3 bucket.
-To ensure data quality, there is a catalog integrity testing step. It uses some simple heuristics to avoid empty catalog files, zero prices, or missing regions.
\ No newline at end of file
+To ensure data quality, there is a catalog integrity testing step. It uses some simple heuristics to avoid empty catalog files, zero prices, or missing regions.
+
+### Backward compatibility
+
+The same `gpuhunt` version can be used by different `dstack` versions.
+Additionally, offline catalogs are produced by the latest `gpuhunt` version, but used by all `dstack` versions.
+
+These mechanisms are used to preserve backward compatibility:
+
+- **`gpuhunt` version**: The interfaces in the `gpuhunt` package preserve backward compatibility
+ within a minor version (`X` in `0.X.Y`).
+- **Offer flags**: If an offer breaks older `dstack` versions, it is marked with a flag in `RawCatalogItem.flags`
+ and the flag is added to the list of supported flags in `dstack`.
+ Older `dstack` versions that don't support this flag will not see the respective offers.
+- **Offline catalog versions**: If a breaking change in the structure or content of an offline catalog is unavoidable,
+ a new version of the catalog can be introduced. Catalog versions are published at `s3://dstack-gpu-pricing/v{N}`.
diff --git a/contributing/LOCKING.md b/contributing/LOCKING.md
new file mode 100644
index 0000000000..c89ad526a4
--- /dev/null
+++ b/contributing/LOCKING.md
@@ -0,0 +1,141 @@
+# Locking
+
+The `dstack` server supports SQLite and Postgres databases with two implementations of resource locking to handle concurrent access:
+
+* In-memory locking for SQLite.
+* DB-level locking for Postgres.
+
+## SQLite locking
+
+SQLite is missing efficient mechanisms to handle concurrent writes (e.g. select for update), so `dstack` implements in-memory resource-level locking. In-memory locking works correctly under the assumption that there is only one server instance (process), which is a `dstack` limitation when using SQLite.
+
+The in-memory locking is implemented via locksets. Locksets are Python sets that store IDs of locked resources. Concurrent access to locksets is guarded with asyncio locks:
+
+```python
+lock, lockset = get_lockset("my_table")
+async with lock:
+ # select resource that is not in lockset
+ lockset.add(resource.id)
+try:
+ process_resource(resource)
+finally:
+ lockset.remove(resource.id)
+```
+
+Locksets are an optimization. One can think of them as per-resource-id locks that allow independent locking of different resources.
+
+## Postgres locking
+
+Postgres resource locking is implemented via standard SELECT FOR UPDATE.
+SQLAlchemy provides `.with_for_update()` that has no effect if SELECT FOR UPDATE is not supported as in SQLite.
+
+There are few places that rely on advisory locks as when generating unique resource names.
+
+## Working with locks
+
+Concurrency is hard. Concurrency with locking is especially hard. Below you'll find common patterns and gotchas when working with locks to make it a bit more manageable.
+
+**A task should acquire locks on resources it modifies**
+
+This is common sense. An alternative could be the inverse: job processing cannot run in parallel with run processing, so job processing takes run lock. This indirection complicates things and is discouraged. In this example, run processing should take job lock instead.
+
+**Start new transaction after acquiring a lock to see other transactions changes in SQLite.**
+
+```python
+select resource ids by names
+lock resource ids
+await session.commit()
+# The next statement will start new transaction
+select ...
+```
+
+> SQLite exhibits Snapshot Isolation. When a read transaction starts, that reader continues to see an unchanging "snapshot" of the database file as it existed at the moment in time when the read transaction started. Any write transactions that commit while the read transaction is active are still invisible to the read transaction, because the reader is seeing a snapshot of database file from a prior moment in time. Source: https://www.sqlite.org/isolation.html
+
+Thus, if a new transaction is not started, you won't see changes that concurrent transactions made before you acquired the lock.
+
+This is not relevant for Postgres since it doesn't rely on in-memory locking (and it also runs on Read Committed isolation level by default).
+
+**Release in-memory locks only after committing changes**
+
+```python
+# Don't do this!
+lock resources
+unlock resources
+do smth else
+await session.commit()
+```
+
+```python
+# Do this!
+lock resources
+await session.commit()
+unlock resources
+```
+
+If a transaction releases a lock before committing changes, the changes may not be visible to another transaction that acquired the lock and relies upon seeing all committed changes.
+
+**Using `joinedload` when selecting `.with_for_update()`**
+
+Using `joinedload` and `.with_for_update()` triggers an error in case of no related rows because `joinedload` produces OUTER LEFT JOIN and SELECT FOR UPDATE cannot be applied to the nullable side of an OUTER JOIN. Here's the options:
+
+* Use `.with_for_update(of=MainModel)`.
+* Select with `selectinload`
+* First select with `.with_for_update()` without loading related attributes and then re-select with `joinedload` without `.with_for_update()`.
+* Use regular `.join()` to lock related resources, but you may get 0 rows if there is no related row to join.
+
+**Always use `.with_for_update(key_share=True)` unless you plan to delete rows or update a primary key column**
+
+If you `SELECT FOR UPDATE` from a table that is referenced in a child table via a foreign key, it can lead to deadlocks if the child table is updated because Postgres will issue a `FOR KEY SHARE` lock on the parent table rows to ensure valid foreign keys. For this reason, you should always do `SELECT FOR NO KEY UPDATE` (.`with_for_update(key_share=True)`) if primary key columns are not modified. `SELECT FOR NO KEY UPDATE` is not blocked by a `FOR KEY SHARE` lock, so no deadlock.
+
+**Lock unique names**
+
+The following pattern can be used to lock a unique name of some resource type:
+
+```python
+lock_namespace = f"fleet_names_{project.name}"
+if get_db().dialect_name == "sqlite":
+ # Start new transaction to see committed changes after lock
+ await session.commit()
+elif get_db().dialect_name == "postgresql":
+ await session.execute(
+ select(func.pg_advisory_xact_lock(string_to_lock_id(lock_namespace)))
+ )
+
+lock, _ = get_locker(get_db().dialect_name).get_lockset(lock_namespace)
+async with lock:
+ # ... select taken names, use a unique name
+ await session.commit()
+```
+
+Note that:
+
+* This pattern works assuming that Postgres is using default isolation level Read Committed. By the time a transaction acquires the advisory lock, all other transactions that can take the name have committed, so their changes can be seen and a unique name is taken.
+* SQLite needs a commit before selecting taken names due to Snapshot Isolation as noted above.
+
+**Use `AsyncExitStack`**
+
+In-memory locking typically requires taking lock for long (until commit).
+Using lock context managers for in-memory locking is often hard because the lock is tied to a block:
+
+```python
+if something:
+ # Can't do this because the lock will be released before commit. How to lock?
+ async with get_locker(get_db().dialect_name).lock_ctx(...):
+ # ...
+# ...
+await session.commit()
+```
+
+Use [`contextlib.AsyncExitStack`](https://docs.python.org/3/library/contextlib.html#contextlib.AsyncExitStack):
+
+```python
+async with AsyncExitStack() as exit_stack:
+ if something:
+ # The lock will be released only on stack exit, so it's ok.
+ await exit_stack.enter_async_context(
+ get_locker(get_db().dialect_name).lock_ctx(...)
+ )
+ # ...
+ # ...
+ await session.commit()
+```
diff --git a/contributing/MIGRATIONS.md b/contributing/MIGRATIONS.md
new file mode 100644
index 0000000000..f494d829d5
--- /dev/null
+++ b/contributing/MIGRATIONS.md
@@ -0,0 +1,75 @@
+# Database migrations
+
+`dstack` uses Alembic to manage database migrations. If you modify any SQLAlchemy
+[models](../src/dstack/_internal/server/models.py) or related data structures,
+generate a new migration with Alembic:
+
+```shell
+cd src/dstack/_internal/server/
+alembic revision -m "" --autogenerate
+```
+
+Then adjust the generated migration if needed.
+
+## Deployment-compatible migrations
+
+The `dstack` server claims to support multi-replica setups with zero-downtime deployments.
+This means DB migrations should not make changes that break old replicas.
+Incompatible changes should be introduced in multiple stages (releases), following
+the [expand and contract pattern](https://www.prisma.io/dataguide/types/relational/expand-and-contract-pattern).
+
+**Note**: If it's impossible to make the migration compatible with older versions, the PR should say so explicitly, so that the change is planned and released with the migration notice.
+
+Below are some common changes and how to make them.
+
+### Removing a column
+
+1. First release:
+ * Stop reading the column. In SQLAlchemy this can be done by setting `deferred=True` on a model field.
+2. Second release:
+ * Drop the column.
+
+### Changing a column
+
+These steps apply to **renaming a column** or **changing the type of a column**
+
+1. First release:
+ * Introduce a new column with the new type.
+ * Write to both the new and the old column.
+2. Second release:
+ * Migrate data from the old column to the new column.
+ * Start reading the new column.
+ * Stop reading the old column.
+ * Stop writing to the old column.
+3. Third release:
+ * Drop the old column.
+
+### Altering multiple tables
+
+Altering a table requires Postgres to [take an ACCESS EXCLUSIVE lock](https://www.postgresql.org/docs/current/sql-altertable.html). (This applies not only to statements that rewrite the tables but also to statements that modify tables metadata.) Altering multiple tables can cause deadlocks due to conflict with read operations since the `dstack` server does not define an order for read operations. Altering multiple tables should be done in separate transactions/migrations.
+
+### Adding indexes
+
+Use `CREATE INDEX CONCURRENTLY` to avoid tacking exclusive lock on the table for a long time.
+For migrations that create multiple indexes, failures can leave the schema in a partial state
+(some indexes already created, some missing). On Postgres, concurrent index creation can also fail
+midway and leave an invalid index object with the same name. Retrying the migration then fails
+with "already exists".
+
+For retry-safe migrations, pre-drop indexes with `if_exists=True` before creating them again:
+
+```python
+with op.get_context().autocommit_block():
+ op.drop_index(
+ "ix_table_col",
+ table_name="table",
+ if_exists=True,
+ postgresql_concurrently=True,
+ )
+ op.create_index(
+ "ix_table_col",
+ "table",
+ ["col"],
+ postgresql_concurrently=True,
+ )
+```
diff --git a/contributing/PIPELINES.md b/contributing/PIPELINES.md
new file mode 100644
index 0000000000..7e01c2465e
--- /dev/null
+++ b/contributing/PIPELINES.md
@@ -0,0 +1,127 @@
+# Pipelines
+
+This document describes how the `dstack` server implements background processing via so-called "pipelines".
+
+*Historical context: `dstack` used to do all background processing via scheduled tasks. A scheduled task would process a specific resource type like volumes or runs by keeping DB transaction open for the entire processing duration and keeping the resource lock with SELECT FOR UPDATE (or in-memory lock on SQLite). This approach didn't scale well because the number of DB connections was a huge bottleneck. Pipelines replaced scheduled tasks: the do all the heavy processing outside of DB transactions and write locks to DB columns.*
+
+## Overview
+
+* Resources are continuously processed in the background by pipelines. A pipeline consists of a fetcher, workers, and a heartbeater.
+* A fetcher selects rows to be processed from the DB, marks them as locked in the DB, and puts them into an in-memory queue.
+* Workers consume rows from the in-memory queue, process the rows, and unlock them.
+* The locking (unlocking) is done by setting (unsetting) `lock_expires_at`, `lock_token`, `lock_owner`.
+* If the replica/pipeline dies, the rows stay locked in the db. Another replica picks up the rows after `lock_expires_at`.
+* `lock_token` prevents stale replica/pipeline to update the rows already picked up by the new replica.
+* `lock_owner` stores the pipeline that's locked the row so that only that pipeline can recover if it's stale.
+* A heartbeater tracks all rows in the pipeline (in the queue or in processing), and updates the lock expiration. This allows setting small `lock_expires_at` and picking up stale rows quickly
+* A fetcher performs the fetch when the queue size goes under a configured lower limit. It has exponential retry delays between empty fetches, thus reducing load on the DB.
+* There is a fetch hint mechanism that services can use to notify the pipelines within the replica – in that case the fetcher stops sleeping and fetches immediately.
+* Each pipeline locks one main resource but may lock related resources as well. It's not necessary to heartbeat related resources if the pipeline ensures no one else can re-lock them. This is typically done via setting and respecting `lock_owner`.
+
+Related notes:
+
+* All write APIs must respect DB-level locks. The endpoints can either try to acquire the lock with a timeout and error or provide an async API by storing the request in the DB.
+
+## Implementation checklist
+
+Brief checklist for implementing a new pipeline:
+
+1. Fetcher locks only rows that are ready for processing:
+`status/time` filters, `lock_expires_at` is empty or expired, and `lock_owner` is empty or equal to the pipeline name. Keep the fetch order stable with `last_processed_at`.
+2. Fetcher takes row locks with `skip_locked` and updates `lock_expires_at`, `lock_token`, `lock_owner` before enqueueing items.
+3. Worker keeps heavy work outside DB sessions. DB sessions should be short and used only for refetch/locking and final apply.
+4. Apply stage updates rows using update maps/update rows, not by relying on mutating detached ORM models.
+5. Main apply update is guarded by `id + lock_token`. If the update affects `0` rows, the item is stale and processing results must not be applied.
+6. Successful apply updates `last_processed_at` and unlocks resources that were locked by this item.
+7. If related lock is unavailable, reset main lock for retry: keep `lock_owner`, clear `lock_token` and `lock_expires_at`, and set `last_processed_at` to now.
+8. Register the pipeline in `PipelineManager` and hint fetch from services after commit via `pipeline_hinter.hint_fetch(Model.__name__)`.
+9. Add minimum tests: fetch eligibility/order, successful unlock path, stale lock token path, and related lock contention retry path.
+
+## Typical worker structure
+
+Most workers are easiest to reason about when `process()` is split into three phases:
+
+1. Load/refetch: open a short DB session, refetch the locked main row by `id + lock_token`, lock any required related rows, and gather any extra data needed for processing.
+2. Process: do the heavy work outside DB sessions and build result objects or update maps instead of mutating detached ORM models.
+3. Apply: open a short DB session, guard the main update by `id + lock_token`, resolve time placeholders, apply related updates, emit events, and unlock rows.
+
+A dedicated context object is often useful for the load step when the worker needs multiple loaded models, related lock metadata, or derived values that should be passed cleanly into processing and apply. For very small pipelines, a direct load -> process -> apply flow may still be clearer.
+
+Workers can share one context type and one apply function across all states even if the processing logic differs by state:
+
+```python
+async def process(item):
+ context = await _load_process_context(item)
+ if context is None:
+ return
+ result = await _process_item(context)
+ await _apply_process_result(item, context, result)
+```
+
+Sometimes state-specific helpers are still the cleanest option, but they can still share a common apply phase if all states write results in the same general shape:
+
+```python
+async def process(item):
+ if item.status == Status.PENDING:
+ context = await _load_pending_context(item)
+ elif item.status == Status.RUNNING:
+ context = await _load_running_context(item)
+ else:
+ return
+ if context is None:
+ return
+ result = await _process_item(context)
+ await _apply_process_result(item, context, result)
+```
+
+If different states have materially different write-side behavior, different apply paths are fine as well. This commonly happens when one state does a normal guarded update while another does delete-or-cleanup work with different related updates:
+
+```python
+async def process(item):
+ if item.to_be_deleted:
+ await _process_to_be_deleted_item(item)
+ elif item.status == Status.SUBMITTED:
+ await _process_submitted_item(item)
+```
+
+It's ok not to force all pipelines into one exact shape.
+
+## Implementation patterns
+
+**Guarded apply by lock token**
+
+When writing processing results, update the main row with a filter by both `id` and `lock_token`. This guarantees that only the worker that still owns the lock can apply its results. If the update affects no rows, treat the item as stale and skip applying other changes (status changes, related updates, events). A stale item means another worker or replica already continued processing.
+
+**Locking related resources before refetch**
+
+If you first refetch a main resource and only after lock the related resources, you need to ensure the worker doesn't get the stale view on related resources or works properly even in this case. It's often more robust to first lock related resources and then refetch the main resource with related resources already locked.
+
+**Locking many related resources**
+
+A pipeline may need to lock a potentially big set of related resource, e.g. fleet pipeline locking all fleet's instances. For this, do one SELECT FOR UPDATE of non-locked instances and one SELECT to see how many instances there are, and check if you managed to lock all of them. If fail to lock, release the main lock and try processing on another fetch iteration. You may keep `lock_owner` on the main resource or set `lock_owner` on locked related resource and make other pipelines respect that to guarantee the eventual locking of all related resources and avoid lock starvation.
+
+**Locking a shared related resource**
+
+Multiple main resources may need to lock the same related resource, e.g. multiple jobs may need to change the shared instance. In this case it's not sufficient to set `lock_owner` on the related resource to the pipeline name because workers processing different main resources can still race with each other. To avoid heartbeating the related resource, you may include main resource id in `lock_owner`, e.g. set `lock_owner = f"{Pipeline.__name__}:{item.id}"`.
+
+**Reset-and-retry when related lock is unavailable**
+
+If a worker cannot lock a required related resource, it should release only the main lock state needed for fast retry: unset `lock_token` and `lock_expires_at`, keep `lock_owner`, and set `last_processed_at` to now. This avoids long waiting and lets the same pipeline retry quickly on the next fetch iteration while other pipelines can still respect ownership intent.
+
+**Dealing with side effects**
+
+If processing has side effects and the apply phase fails due to a lock mismatch, there are several options: a) revert side effects b) make processing idempotent, i.e. next processing iteration detects side effects does not perform duplicating actions c) log side effects as errors and warn user about possible issues such as orphaned instances – as a temporary solution.
+
+**Bulk apply with one consistent current time**
+
+When apply needs to update multiple rows (main + related resources), build update maps/update rows first and resolve current-time placeholders once in the apply transaction using `NOW_PLACEHOLDER` + `resolve_now_placeholders()`. This keeps timestamps consistent across all rows and avoids subtle ordering bugs when the same processing pass writes several `*_at` fields.
+
+## Performance analysis
+
+* Pipeline throughput = workers_num / worker_processing_time. So quick tasks easily give high-throughput pipelines, e.g. 1s task with 20 workers is 1200 tasks/min.
+A slow 30s task gives only 40 tasks/min with the same number of workers. We can increase the number of workers but the peak memory usage will grow proportionally.
+In general, workers should be optimized to be as quick as possible to improve throughput.
+* Processing latency (wait) is close to 0 due to fetch hints if the pipeline is not saturated. In general, latency = queue_size / throughput.
+* In-memory queue maxsize provides a cap on memory usage and recovery time after crashes (number of locked items to retry).
+* Fetcher's DB load is proportional to the number of pipelines and is expected to be negligible. Workers can put a considerable read/write DB load as it's proportional to the number of workers. This can be optimized by batching workers' writes. Workers do processing outside of transactions so DB connections won't be a bottleneck.
+* There is a risk of lock starvation if a worker needs to lock all related resources. This is to be mitigated by 1) related pipelines checking `lock_owner` and skip locking to let the parent pipeline acquire all the locks eventually and 2) do the related resource locking only on paths that require it.
diff --git a/contributing/PROXY.md b/contributing/PROXY.md
new file mode 100644
index 0000000000..6c738e999d
--- /dev/null
+++ b/contributing/PROXY.md
@@ -0,0 +1,207 @@
+# `dstack-proxy`
+
+`dstack-proxy` is a set of `dstack` components responsible for exposing [services](https://dstack.ai/docs/concepts/services/).
+
+- By default, services are published at `dstack` server URL subpaths. The component that handles traffic to such services is called **in-server proxy**. It runs as part of the `dstack` server. It is implemented in `dstack._internal.server.services.proxy`.
+- Users can optionally deploy a **gateway** to handle traffic to their services. The gateway app runs on a dedicated instance. Although it requires additional configuration, it provides higher performance and supports more features than the in-server proxy. It is implemented in `dstack._internal.proxy.gateway`.
+- The in-server proxy and the gateway share some business logic, such as the OpenAI-compatible API and the connection pool implementation. The common details are implemented in `dstack._internal.proxy.lib`.
+
+## Proxy functions and modules
+
+### Reverse proxy
+
+`dstack-proxy` acts as a reverse proxy and load balancer for services.
+
+The in-server proxy uses a custom reverse proxy implementation based on FastAPI and httpx. It routes requests based on the `/proxy/services//` path. It performs load balancing by selecting a random service replica for each forwarded request.
+
+The gateway uses Nginx. It automatically maintains Nginx configs for each service in `/etc/nginx/sites-enabled/*`. Each service is published at a subdomain. Nginx performs load balancing using the round-robin method. Nginx forwards requests directly to service replicas, so traffic does not go through the gateway app.
+
+### HTTPS
+
+The in-server proxy is part of the `dstack` server, so services are only available over HTTPS if the `dstack` server is deployed with HTTPS.
+
+The gateway can enforce HTTPS in the Nginx config. It uses Certbot to obtain TLS certificates from Let's Encrypt or another configured CA when the service is registered, unless the service configuration specifies `https: false`.
+
+### Auth
+
+Unless the service configuration specifies `auth: false`, `dstack-proxy` checks the authorization of incoming requests based on `dstack` user tokens from the `Authorization` header.
+
+The in-server proxy validates the tokens by querying the correct token from the database.
+
+On gateways, Nginx makes a headers-only subrequest to the gateway app to check authorization for each incoming request. The gateway app then makes a request to the `dstack` server to validate the token. Responses from the `dstack` server are cached for 60 seconds. If the `dstack` server does not respond, the incoming request is denied.
+
+### OpenAI-compatible API
+
+The OpenAI interface emulates the real OpenAI API for chat completion models. It can list running models in the project, convert between OpenAI and TGI request formats, and forward requests to the correct service.
+
+The in-server proxy forwards requests directly to service replicas.
+
+```mermaid
+sequenceDiagram
+ User->>dstack server: http(s):///proxy/models//
+ dstack server->>Service replica: http+unix:///path/to/ssh/socket
+```
+
+The gateway uses Nginx to forward requests so they are included in access logs and service stats.
+
+```mermaid
+sequenceDiagram
+ User->>Nginx: http(s)://gateway./
+ Nginx->>Gateway app: http://localhost:8000/api/models//
+ Gateway app->>Nginx: http://./
+ Nginx->>Service replica: http+unix:///path/to/ssh/socket
+```
+
+### Stats collector
+
+`dstack-proxy` collects service usage stats that are then used by the `dstack` server for autoscaling. Stats collection is only supported on gateways and is implemented by reading `/var/log/nginx/dstack.access.log`
+
+### Service connection pool
+
+`dstack-proxy` connects to service replicas via SSH and forwards their service port to a local Unix socket, which is then used by the reverse proxy. All SSH connections are added to a pool and reused between requests.
+
+The in-server proxy opens an SSH connection when it needs to forward the first request to it, so there may be a delay when forwarding the first request.
+
+The gateway opens SSH connections when each replica is registered.
+
+### Communication with the `dstack` server
+
+The in-server proxy is part of the `dstack` server, so no network communication takes place between them.
+
+Gateway-to-server communication happens over an SSH connection that is established by the `dstack` server when it creates a new gateway or starts. The SSH connection includes bidirectional port forwarding, enabling the gateway and the `dstack` server to call each other's APIs:
+
+- The server calls the gateway to register services, fetch stats, etc.
+- The gateway calls the server to validate user tokens.
+
+### Storage
+
+`dstack-proxy` has a set of stored models and a common storage repo interface.
+
+The in-server proxy repo implementation fetches the models from the database. It doesn't write to the database, as all the details about services and replicas are written by the `dstack` server.
+
+The gateway maintains its own in-memory storage repo. A copy of the repo is also stored in `~/dstack/state-v2.json`. The copy is updated on every write operation and is used for data recovery after restarts. The repo is populated when new services and replicas are registered.
+
+## Dependency injection
+
+When a module has to be implemented differently for the in-server proxy and the gateway, `dstack-proxy` uses interfaces with multiple implementations. For example, there are common interfaces for the storage repo and for auth checks. The in-server proxy and the gateway provide their own implementations for both interfaces.
+
+```mermaid
+classDiagram
+ class BaseProxyRepo {
+ <>
+ }
+ BaseProxyRepo <|-- ServerProxyRepo
+ BaseProxyRepo <|-- GatewayProxyRepo
+
+ class BaseProxyAuthProvider {
+ <>
+ }
+ BaseProxyAuthProvider <|-- ServerProxyAuthProvider
+ BaseProxyAuthProvider <|-- GatewayProxyAuthProvider
+```
+
+`dstack-proxy` then uses dependency injection to select the relevant implementation. Both the in-server proxy and the gateway provide an "injector" class that is used to obtain concrete interface implementations.
+
+```mermaid
+classDiagram
+ class ProxyDependencyInjector {
+ <>
+ +get_repo() BaseProxyRepo
+ +get_auth_provider() BaseProxyAuthProvider
+ }
+ class ServerProxyDependencyInjector {
+ +get_repo() ServerProxyRepo
+ +get_auth_provider() ServerProxyAuthProvider
+ }
+ class GatewayDependencyInjector {
+ +get_repo() GatewayProxyRepo
+ +get_auth_provider() GatewayProxyAuthProvider
+ }
+ ProxyDependencyInjector <|-- ServerProxyDependencyInjector
+ ProxyDependencyInjector <|-- GatewayDependencyInjector
+```
+
+An instance of the relevant injector class is stored in the FastAPI global app state and can be accessed from FastAPI path operations. There are helper functions that can be used as FastAPI path operation dependencies to obtain the injector or a module implementation: `get_injector`, `get_proxy_repo`, `get_proxy_auth_provider`, etc.
+
+There are also similar gateway-specific helper functions to obtain gateway-specific module implementations: `get_gateway_proxy_repo` (guaranteed to return the gateway repo, which has more methods than the base repo interface), `get_nginx`, `get_stats_collector`, etc.
+
+## Gateway operations
+
+Gateway instances are managed by the `dstack` server. A gateway is associated with a project and some backend in the project. Gateways can be shared between projects using Exports.
+
+### Creation
+
+Users can create a gateway using the `dstack apply` command. The gateway YAML configuration must specify the gateway's wildcard domain - all direct subdomains should resolve to the gateway IP address. Since the IP address is unknown during provisioning, `dstack` doesn't check DNS records.
+
+Provisioning happens as follows:
+1. Launch a non-GPU instance (usually the smallest) with all ports exposed.
+2. Install Nginx, Certbot, and patch configs.
+3. Create blue-green virtual environments.
+4. Install the latest `dstack-gateway` package from the S3 bucket. `dstack-gateway` is a thin package that depends on the `dstack` package, which contains the actual gateway implementation.
+5. Run the systemd service `dstack.gateway.service`.
+
+### Update
+
+The gateway has a "blue-green deployment"-like configuration: there are two virtual environments to be swapped on update. The systemd service uses the newly installed package after a restart.
+
+The update process looks like this:
+1. Install the new package to the unused venv.
+2. Update scripts and systemd service config.
+3. Swap the active venv name in `~/dstack/version`.
+4. Restart the systemd service.
+
+## Gateway development
+
+The gateway app needs to interact with Nginx and certbot, so running it locally can be challenging. One way to test your code is to upload your development branch to an existing gateway and run the gateway app from source.
+
+1. Run `dstack server` with `DSTACK_SKIP_GATEWAY_UPDATE=1` environment variable. This will prevent `dstack` from updating and starting the standard gateway version on each server restart.
+
+1. Provision a gateway through `dstack`:
+
+ ```shell
+ dstack apply -f my-gateway.dstack.yml
+ ```
+
+1. Save the gateway key to a file:
+
+ ```shell
+ sqlite3 ~/.dstack/server/data/sqlite.db "SELECT ssh_private_key FROM gateway_computes WHERE deleted = 0 AND ip_address = ''" > /tmp/gateway.key
+ chmod 600 /tmp/gateway.key
+ ```
+
+1. Deliver your code to the gateway. For example, clone it from a remote repo:
+
+ ```shell
+ ssh -i /tmp/gateway.key ubuntu@gateway.example "git clone https://github.com/dstackai/dstack.git ~/dstack-repo"
+ ```
+
+ Or push it from your machine:
+
+ ```shell
+ ssh -i /tmp/gateway.key ubuntu@gateway.example "git init ~/dstack-repo"
+ git remote add gateway ubuntu@gateway.example:~/dstack-repo
+ GIT_SSH_COMMAND='ssh -i /tmp/gateway.key' git push gateway branch_name
+ ```
+
+1. Connect to the gateway:
+
+ ```shell
+ ssh -i /tmp/gateway.key ubuntu@gateway.example
+ ```
+
+1. Prepare an environment with your development branch on the gateway:
+
+ ```shell
+ cd ~/dstack-repo
+ git checkout branch_name
+ curl -LsSf https://astral.sh/uv/install.sh | sh
+ source ~/.local/bin/env
+ uv sync --extra gateway
+ ```
+
+1. Stop the gateway service and start your development version from source:
+
+ ```shell
+ sudo systemctl stop dstack.gateway.service
+ uv run uvicorn dstack._internal.proxy.gateway.main:app
+ ```
diff --git a/contributing/RELEASE.md b/contributing/RELEASE.md
new file mode 100644
index 0000000000..f0798082fc
--- /dev/null
+++ b/contributing/RELEASE.md
@@ -0,0 +1,25 @@
+# Release
+
+This is a `dstack` release guide and checklist for core maintainers.
+
+## Checklist
+
+1. Test `master`:
+ 1. Compare changes to the previous release, e.g. [`https://github.com/dstackai/dstack/compare/0.19.39...master`](https://github.com/dstackai/dstack/compare/0.19.39...master).
+ 2. Test that `master` CLI works with the previous server release. PRs that add new model fields can potentially break client backward compatibility.
+ 3. Test that `master` server works with the previous CLI release.
+ 4. Pay special attention to releases with DB migrations. See [MIGRATIONS.md](MIGRATIONS.md).
+ * Ensure migrations work with rolling deployments and do not lock multiple tables.
+ * Test applying migrations while old replicas do active processing.
+ * Test migrations can be retried if they fail. For example, concurrent index may fail and stay in invalid state.
+2. Create a tag, e.g. `git tag 0.19.40`.
+3. Push the tag to trigger the Release `workflow`, i.e. `git push --tags`.
+4. Generate GitHub release notes from the tag. Highlight major features, deprecations, breaking changes.
+5. Install the release build and test once again, e.g. `uv pip install 'dstack[all]==0.19.40' --refresh`.
+6. Release `dstack` Sky and `dstack` Enterprise.
+7. Publish the release notes and make announcements.
+
+## Troubleshooting
+
+* If a release workflow fails due to a release workflow mistake and the release build is not published, commit a fix and update the tag reference: `git tag -d 0.19.40 && git tag 0.19.40 && git push --tags -f`.
+* If a critical bug is found after the release is published, make a new release. In an extreme case, the broken release can be yanked.
diff --git a/contributing/RUNNER-AND-SHIM.md b/contributing/RUNNER-AND-SHIM.md
index e962528b42..747a0745d2 100644
--- a/contributing/RUNNER-AND-SHIM.md
+++ b/contributing/RUNNER-AND-SHIM.md
@@ -1,26 +1,42 @@
-dstack runs the user's configuration as a Docker container. The user can specify their own image name or use the preconfigured dstack image (with Python and CUDA).
+# runner and shim
-`dstack-runner` is a component responsible for setting environment variables and secrets, executing user commands, reporting logs and job status, and terminating the job on signal from the dstack server. `dstack-runner` is cloud-agnostic and runs as an entrypoint of a Docker container.
+`dstack` runs the user's configuration as a Docker container. The user can specify their own image name or use the preconfigured dstack image (with Python and CUDA).
-If the cloud provider has VM capabilities, dstack runs `dstack-shim` on the host to emulate a container-only environment. `dstack-shim` is responsible for pulling Docker images (public or private), configuring Docker containers (mounts, GPU forwarding, entrypoint, etc.), running Docker containers, and terminating the container on signal from the dstack server.
+`dstack-runner` is a component responsible for setting environment variables and secrets, executing user commands, reporting logs and job status, and terminating the job on signal from the `dstack` server. `dstack-runner` is cloud-agnostic and runs as an entrypoint of a Docker container.
+
+If the cloud provider has VM capabilities, `dstack` runs `dstack-shim` on the host to emulate a container-only environment. `dstack-shim` is responsible for pulling Docker images (public or private), configuring Docker containers (mounts, GPU forwarding, entrypoint, etc.), running Docker containers, and terminating the container on signal from the `dstack` server.
## dstack-shim
-`dstack-shim` works in cycles, allowing to run a different container once the job is finished.
+`dstack-shim` works with _tasks_. Essentially, a task is a `dstack-shim`-specific part of `dstack`'s job, namely a Docker container with its associated data. `dstack-shim` is able to process multiple tasks in parallel.
+
+A task is identified by a unique ID assigned by the `dstack` server. A task has a state: a status, allocated resources, data on disk (container, even if stopped, runner logs), etc. `dstack-shim` keeps a task in memory and its data on disk until the `dstack` server requests removal. The `dstack` server should periodically remove old tasks to clean up storage. Currently, the server removes a task right after termination request, but this is subject to change.
+
+A lifecycle of a task is as follows:
+
+- Wait for a task submission from the `dstack` server (image ref, registry credentials if needed, user, resource constraints, network mode, etc.)
+- Allocate GPU resources, find and mount volumes, pull the image
+- Run the container and
+ - either wait for container to exit
+ - or wait for the termination request from the `dstack` server
+- Deallocate GPU resources, unmount volumes
+
+A container is started in either `host` or `bridge` network mode depending on the instance and the job:
-- STEP 1: Wait for Docker image info (+ registry auth credentials if needed) from the dstack server
-- STEP 2: Pull the Docker image
-- STEP 3: Run the container
- - Wait for container exit
- - Or wait for the interruption signal from the dstack server
-- STEP 4: Go to STEP 1
+- If the instance is shared (split into GPU blocks), network mode is set to `bridge` to avoid port conflicts
+- …unless there are multiple jobs in multinode mode — in that case, the instance is never shared (the jobs takes the whole instance), and network mode is set `host`
+
+ **NOTE**: `host` networking mode would allow jobs to use any port at any moment for internal communication. For example, during distributed PyTorch training.
+- If the instance is not shared by multiple jobs (i.e. GPU blocks feature is not used), network mode is `host` to avoid unnecessary overhead
+
+In `bridge` mode, container ports are mapped to ephemeral host ports. `dstack-shim` stores port mapping as a part of task's state. Currently, the default `bridge` network is used for all containers, but this could be changed in the future to improve container isolation.
+
+All communication between the `dstack` server and `dstack-shim` happens via HTTP API through an SSH tunnel. `dstack-shim` doesn't collect logs. Usually, it is run from a `cloud-init` user-data script.
-All communication between the dstack server and `dstack-shim` happens via REST API through an SSH tunnel. `dstack-shim` doesn't collect logs. Usually, it is run from a `cloud-init` user-data script.
The entrypoint for the container:
- Installs `openssh-server`
- Adds project and user public keys to `~/.ssh/authorized_keys`
-- Downloads `dstack-runner` from the public S3 bucket
-- Starts `dstack-runner`
+- Starts `sshd` and `dstack-runner`
## dstack-runner
@@ -30,18 +46,16 @@ The entrypoint for the container:
- STEP 2: Wait for the code (tarball or diff)
- STEP 3: Prepare the repo (clone git repo and apply the diff, or extract the archive)
- STEP 4: Run the commands from the job spec
- - Wait for the commands to exit
- - Serve logs to the dstack server via HTTP
- - Serve real-time logs to the CLI via WebSocket
- - Wait for the signal to terminate the commands
+ - Wait for the commands to exit
+ - Serve logs to the `dstack` server via HTTP
+ - Serve real-time logs to the CLI via WebSocket
+ - Wait for the signal to terminate the commands
- STEP 5: Wait until all logs are read by the server and the CLI. Or exit after a timeout
-All communication between the dstack server and `dstack-runner` happens via REST API through an SSH tunnel. `dstack-runner` collects the job logs and its own logs. Only the job logs are served via WebSocket.
+All communication between the `dstack` server and `dstack-runner` happens via HTTP API through an SSH tunnel. `dstack-runner` collects the job logs and its own logs. Only the job logs are served via WebSocket.
## SSH tunnels
-dstack expects a running SSH server right next to the `dstack-runner`. It provides a secure channel for communication with the runner API and forwarding any ports without listening for `0.0.0.0`. The `dstack-gateway` also uses this SSH server for forwarding requests from public endpoints.
-
-`dstack-shim` must also be running next to the SSH server. The dstack server connects to this SSH server for interacting with both `dstack-shim` and `dstack-runner` since we use `host` networking mode for the Docker container. The CLI uses this SSH server as a jump host because the user wants to connect to the container.
+`dstack` expects a running SSH server right next to the `dstack-runner`. It provides a secure channel for communication with the runner API and forwarding any ports without listening for `0.0.0.0`. The `dstack-gateway` also uses this SSH server for forwarding requests from public endpoints.
-> `host` networking mode would allow jobs to use any port at any moment for internal communication. For example, during distributed PyTorch training.
\ No newline at end of file
+`dstack-shim` must also be running next to the SSH server. The `dstack` server connects to this SSH server for interacting with both `dstack-shim` and `dstack-runner`. The CLI uses this SSH server as a jump host because the user wants to connect to the container.
diff --git a/contributing/RUNS-AND-JOBS.md b/contributing/RUNS-AND-JOBS.md
index 010ed2bd4a..2f00e751be 100644
--- a/contributing/RUNS-AND-JOBS.md
+++ b/contributing/RUNS-AND-JOBS.md
@@ -1,89 +1,87 @@
+# Runs and jobs
+
## Introduction
-Run is the primary unit of workload in dstack. Users can:
-1. Submit a run using `dstack run` or the API.
+Run is the primary unit of workload in `dstack`. Users can:
+
+1. Submit a run using `dstack apply` or the API.
2. Stop a run using `dstack stop` or the API.
-Runs are created from configurations. There are three basic types of configurations:
+Runs are created from run configurations. There are three types of run configurations:
+
1. `dev-environment` — runs a VS Code server.
2. `task` — runs the user's bash script until completion.
-3. `service` — runs the user's bash script and exposes a port through the gateway, making it accessible from the internet via the HTTP protocol.
-
-A run can spawn one or multiple jobs, depending on the configuration. There could be multiple nodes in a cluster (for distributed training), multiple replicas (for load balancing), or both. During the execution, a job runs on an instance, and the instance can run only one job at any given moment.
+3. `service` — runs the user's bash script and exposes a port through [dstack-proxy](PROXY.md).
-If a job fails and the configuration allows retrying, the server will spawn a new job submission for the job.
+A run can spawn one or multiple jobs, depending on the configuration. A task that specifies multiple `nodes` spawns a job for every node (a multi-node task). A service that specifies multiple `replicas` spawns a job for every replica. A job submission is always assigned to one particular instance. If a job fails and the configuration allows retrying, the server creates a new job submission for the job.
## Run's Lifecycle
-- STEP 1: The user submits the run. `services.runs.submit_run` creates jobs with status `SUBMITTED`. Now the run has status `SUBMITTED`.
-- STEP 2: The server periodically pulls unfinished runs and processes them in `background.tasks.process_runs`.
- - If any job is `RUNNING`, the run becomes `RUNNING`.
- - If any job is `PROVISIONING` or `PULLING`, the run becomes `PROVISIONING`.
- - If any job fails and cannot be retried, the run becomes `TERMINATING`, and after processing, `FAILED`.
- - If all jobs are `DONE`, the run becomes `TERMINATING`, and after processing, `DONE`.
- - If any job fails, can be retried, and there is any other active job, the failed job will be resubmitted in-place. The run status is defined by the rules above.
- - If all jobs fail and can be resubmitted, the run becomes `PENDING`.
-- STEP 3: If the run is `TERMINATING`, the server terminates all jobs by setting their status to `TERMINATING` and assigning the proper `JobTerminationReason`.
-- STEP 4: Once all jobs are finished, the run becomes `TERMINATED`, `DONE`, or `FAILED` based on `RunTerminationReason`.
-- STEP 0: If the run is `PENDING`, `background.tasks.process_runs` will resubmit jobs. The run becomes `SUBMITTED` again.
-
-> No one must assign the finished status to the run, except `services.runs.process_terminating_run`. To terminate the run, assign `TERMINATING` status and `RunTerminationReason`.
+- STEP 1: The user submits the run. `services.runs.submit_run` creates jobs with status `SUBMITTED`. The run starts in `SUBMITTED`.
+- STEP 2: `RunPipeline` continuously processes unfinished runs.
+ - For active runs, it derives the run status from the latest job states in priority order:
+ 1. If any non-retryable failure is present, the run becomes `TERMINATING` with the relevant `RunTerminationReason`.
+ 2. If `stop_criteria == MASTER_DONE` and the master job is done, the run becomes `TERMINATING` with `ALL_JOBS_DONE`.
+ 3. Otherwise, if any job is `RUNNING`, the run becomes `RUNNING`.
+ 4. Otherwise, if any job is `PROVISIONING` or `PULLING`, the run becomes `PROVISIONING`.
+ 5. Otherwise, if jobs are still waiting for placement or provisioning, the run stays `SUBMITTED`.
+ 6. Otherwise, if all contributing jobs are `DONE`, the run becomes `TERMINATING` with `ALL_JOBS_DONE`.
+ 7. Otherwise, if no active replicas remain and the run should be retried, the run becomes `PENDING`.
+ - Retryable replica failures are handled before the final transition is applied:
+ - If a replica fails with a retryable reason while other replicas are still active, `RunPipeline` creates a new `SUBMITTED` submission for that replica and terminates the old jobs in that replica.
+ - If all remaining work is retryable, the run ends up in `PENDING`.
+- STEP 3: If the run is `PENDING`, `RunPipeline` processes it in the pending phase.
+ - For retrying runs, it waits for an exponential backoff before resubmitting.
+ - For scheduled runs, it waits until `next_triggered_at`.
+ - For scaled-to-zero services, it can keep the run in `PENDING` until autoscaling wants replicas again.
+ - Once the run is ready to continue, `RunPipeline` creates new `SUBMITTED` jobs and moves the run back to `SUBMITTED`.
+- STEP 4: If the run is `TERMINATING`, `RunPipeline` marks active jobs as `TERMINATING` and assigns the corresponding `JobTerminationReason`.
+- STEP 5: Once all jobs are finished, the terminating phase of `RunPipeline` either:
+ - assigns the final run status (`TERMINATED`, `DONE`, or `FAILED`), or
+ - for scheduled runs that were not stopped or aborted by the user, returns the run to `PENDING` and computes a new `next_triggered_at`.
### Services
-Services' lifecycle has some modifications:
-- During STEP 1, the service is registered on the gateway. If the gateway is not accessible or the domain name is taken, the run submission fails.
-- During STEP 2, downscaled jobs are ignored.
-- During STEP 4, the service is unregistered on the gateway.
-- During STEP 0, the service can stay in `PENDING` status if it was downscaled to zero (WIP).
+
+Services' run lifecycle has some modifications:
+
+- During STEP 1, the service itself is registered on the gateway or the in-server proxy. If the gateway is not accessible or the domain name is taken, submission fails.
+- During STEP 2, active run processing also computes desired replica counts from gateway stats and handles scale-up, scale-down, rolling deployment, and cleanup of removed replica groups.
+- During STEP 2, jobs already marked `SCALED_DOWN` do not contribute to the run status.
+- During STEP 3, a service can stay in `PENDING` when autoscaling currently wants zero replicas.
+- During STEP 5, the terminating phase of `RunPipeline` unregisters the service from the gateway.
### When can the job be retried?
-It's a complicated question and will be elaborated later with multi-node and replica implementation.
-For now, dstack retries only if:
-- The configuration has enabled the retry policy.
-- The job failed because of `NO_CAPACITY`, and the instance was a spot.
+`dstack` retries the run only if:
+
+- The configuration enables `retry`.
+- The job termination reason is covered by `retry.on_events`.
+- The `retry.duration` is not exceeded.
## Job's Lifecycle
- STEP 1: A newly submitted job has status `SUBMITTED`. It is not assigned to any instance yet.
-- STEP 2: `background.tasks.process_submitted_jobs` tries to assign an existing instance or provision a new one.
- - On success, the job becomes `PROVISIONING`.
- - On failure, the job becomes `TERMINATING`, and after processing, `FAILED` because of `NO_CAPACITY`.
-- STEP 3: `background.tasks.process_running_jobs` periodically pulls unfinished jobs and processes them.
- - While `dstack-shim`/`dstack-runner` is not responding, the job stays `PROVISIONING`.
- - Once `dstack-shim` (for VM-featured backends) becomes available, the server submits the docker image name, and the job becomes `PULLING`.
- - Once `dstack-runner` inside a docker container becomes available, the server submits the code and the job spec, and the job becomes `RUNNING`.
- - If `dstack-shim` or `dstack-runner` don't respond for a long time or fail to respond after successful connection and multiple retries, the job becomes `TERMINATING`, and after processing, `FAILED`.
-- STEP 4: `background.tasks.process_running_jobs` processes `RUNNING` jobs, pulling job logs, runner logs, and job status.
- - If the pulled status is `DONE`, the job becomes `TERMINATING`, and after processing, `DONE`.
- - Otherwise, the job becomes `TERMINATING`, and after processing, `FAILED`.
-- STEP 5: `background.tasks.process_terminating_jobs` processes `TERMINATING` jobs.
- - If the job has `remove_at` in the future, nothing happens.
- - Once `remove_at` is in the past, the server stops the container via `dstack-shim` and releases the instance. The job becomes `TERMINATED`, `DONE`, `FAILED`, or `ABORTED` based on `JobTerminationReason`.
-
-> No one must assign the finished status to the job, except `services.jobs.process_terminating_job`. To terminate the job, assign `TERMINATING` status and `JobTerminationReason`.
+- STEP 2: `JobSubmittedPipeline` assigns the job in two phases:
+ - Assignment: claim an existing instance or reserve a *placeholder* `InstanceModel`. Placeholders are `PENDING` instances that reserve an `instance_num` and a `nodes.max` slot. `InstancePipeline` ignores them.
+ - Provisioning: reuse the existing instance, or cloud-provision and promote the placeholder to `PROVISIONING`.
+ - On success, the job becomes `PROVISIONING`.
+ - On failure, the job becomes `TERMINATING`. `JobTerminatingPipeline` later assigns the final failed status.
+- STEP 3: `JobRunningPipeline` processes `PROVISIONING`, `PULLING`, and `RUNNING` jobs.
+ - While `dstack-shim` / `dstack-runner` is not responding, the job stays `PROVISIONING`.
+ - Once `dstack-shim` (for VM-featured backends) becomes available, the pipeline submits the image and the job becomes `PULLING`.
+ - Once `dstack-runner` inside the container becomes available, the pipeline uploads the code and job spec, and the job becomes `RUNNING`.
+ - While the job is `RUNNING`, the pipeline keeps collecting logs and runner status.
+ - If startup, runner communication, or replica registration fails, the job becomes `TERMINATING`.
+- STEP 4: Once the job is actually ready, `JobRunningPipeline` initializes probes.
+- STEP 5: `JobTerminatingPipeline` processes `TERMINATING` jobs.
+ - If the job has `remove_at` in the future, it waits. This gives the job time for a graceful stop.
+ - Once `remove_at` is in the past, it stops the container, detaches volumes, unregisters service replicas if needed, and releases the instance assignment.
+ - If some volumes are not detached yet, the job stays `TERMINATING` and is retried.
+ - When cleanup is complete, the job becomes `TERMINATED`, `DONE`, `FAILED`, or `ABORTED` based on `JobTerminationReason`.
### Services' Jobs
-Services' jobs lifecycle has some modifications:
-- During STEP 3, once the job becomes `RUNNING`, it is registered on the gateway as a replica. If the gateway is not accessible, the job fails.
-- During STEP 5, the job is unregistered on the gateway (WIP).
-
-## Stop a Run
-To stop a run, `services.runs.stop_runs` assigns `TERMINATING` status to the run and executes one iteration of the processing without waiting for the background task.
-## Concurrency
-Since SQLite lacks per-row locking, we use an in-memory locking mechanism to avoid race conditions.
-
-Every lock consists of a lock primitive (`asyncio.Lock`) and a set of locked IDs (`Set[uuid.UUID]`). It follows the rules below:
-- Only the `asyncio.Lock` holder can add an ID to the set.
-- The processing task must remove the corresponding ID from the set; acquiring `asyncio.Lock` is not required.
-
-Runs and jobs are processed by concurrent background tasks. There are locks for runs and jobs:
-- `PROCESSING_RUNS_(LOCK|IDS)`
-- `SUBMITTED_PROCESSING_JOBS_(LOCK|IDS)`
-- `RUNNING_PROCESSING_JOBS_(LOCK|IDS)`
-- `TERMINATING_PROCESSING_JOBS_(LOCK|IDS)`
+Services' jobs lifecycle has some modifications:
-Run processing takes priority over job processing; that's why:
-- Once `run.id` is in `PROCESSING_RUNS_IDS`, any job processing task should not take any job with `job.run_id` in `PROCESSING_RUNS_IDS`.
-- Any run processing task should wait until job processing tasks release all run's job IDs from `*_PROCESSING_JOBS_IDS` sets.
\ No newline at end of file
+- During STEP 3, once the primary job of a replica is `RUNNING` and ready to receive traffic, `JobRunningPipeline` registers that replica on the gateway. If the gateway is not accessible, the job fails with a gateway-related termination reason.
+- During STEP 5, `JobTerminatingPipeline` unregisters the replica from receiving requests before the job is fully cleaned up.
diff --git a/docker/amd-smi/Dockerfile b/docker/amd-smi/Dockerfile
new file mode 100644
index 0000000000..3736f06095
--- /dev/null
+++ b/docker/amd-smi/Dockerfile
@@ -0,0 +1,30 @@
+ARG UBUNTU_VERSION
+
+FROM ubuntu:${UBUNTU_VERSION}
+
+ARG IMAGE_NAME
+ARG UBUNTU_VERSION
+ARG ROCM_VERSION
+ARG DSTACK_REVISION
+ARG BUILD_DATE
+
+ENV PATH="/opt/rocm/bin:${PATH}"
+
+RUN \
+ export DEBIAN_FRONTEND=noninteractive && \
+ apt-get update && \
+ apt-get install -y --no-install-recommends wget ca-certificates && \
+ base_url="https://repo.radeon.com/amdgpu-install/${ROCM_VERSION}/ubuntu/${UBUNTU_VERSION}/" && \
+ deb_name=$(wget -qO- "${base_url}" | grep -Po '(?<=href=")amdgpu-install_[^"]+') && \
+ wget -O amdgpu-install.deb "${base_url}${deb_name}" && \
+ apt-get install -y --no-install-recommends ./amdgpu-install.deb && \
+ rm ./amdgpu-install.deb && \
+ apt-get update && \
+ apt-get install -y amd-smi-lib
+
+ENTRYPOINT ["/opt/rocm/bin/amd-smi"]
+CMD ["--help"]
+
+LABEL org.opencontainers.image.title="${IMAGE_NAME}"
+LABEL org.opencontainers.image.version="${ROCM_VERSION}-${DSTACK_REVISION}"
+LABEL org.opencontainers.image.created="${BUILD_DATE}"
diff --git a/docker/amd-smi/README.md b/docker/amd-smi/README.md
new file mode 100644
index 0000000000..577036d9c4
--- /dev/null
+++ b/docker/amd-smi/README.md
@@ -0,0 +1,9 @@
+# dstack AMD SMI
+
+An Ubuntu-based image with [AMD SMI](https://rocm.docs.amd.com/projects/amdsmi/en/latest/) preinstalled. Suitable for AMD GPU detection.
+
+## Usage
+
+```shell
+docker run --rm --device /dev/kfd --device /dev/dri dstackai/amd-smi static
+```
diff --git a/docker/base/Dockerfile b/docker/base/Dockerfile
index 9e110458bf..6c01f2e94d 100644
--- a/docker/base/Dockerfile
+++ b/docker/base/Dockerfile
@@ -1,30 +1,187 @@
-FROM nvidia/cuda:12.1.0-base-ubuntu20.04
+ARG UBUNTU_VERSION
-ARG PYTHON
-ENV PYTHON=$PYTHON
+# ============================================================================
+# common: shared base for all flavors. Select a flavor with `--target `
+# (base / devel / devel-efa).
+# ============================================================================
+
+FROM nvidia/cuda:12.8.2-base-ubuntu${UBUNTU_VERSION}.04 AS common
+
+# ARGs before FROM must be redeclared to be used after FROM
+ARG UBUNTU_VERSION
+
+ARG _UV_HOME="/opt/uv"
+
+ENV UV_INSTALL_DIR="${_UV_HOME}/bin"
+ENV UV_MANAGED_PYTHON=1
ENV LANG=C.UTF-8 LC_ALL=C.UTF-8
-ENV PIP_ROOT_USER_ACTION=ignore
-
-RUN apt-key adv --fetch-keys https://developer.download.nvidia.com/compute/cuda/repos/ubuntu2004/x86_64/3bf863cc.pub && \
- apt-get update --fix-missing && \
- apt upgrade -y && \
- export DEBIAN_FRONTEND=noninteractive && \
- ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime && \
- apt-get install -y tzdata && \
- dpkg-reconfigure --frontend noninteractive tzdata && \
- apt-get install -y bzip2 ca-certificates curl build-essential git libglib2.0-0 libsm6 libxext6 libxrender1 mercurial openssh-server subversion wget && \
- sed -i "s/.*PasswordAuthentication.*/PasswordAuthentication no/g" /etc/ssh/sshd_config && mkdir /run/sshd && \
- mkdir ~/.ssh && chmod 700 ~/.ssh && touch ~/.ssh/authorized_keys && chmod 600 ~/.ssh/authorized_keys && rm /etc/ssh/ssh_host_*
-
-RUN wget -O Miniforge3.sh "https://github.com/conda-forge/miniforge/releases/latest/download/Miniforge3-$(uname)-$(uname -m).sh" && \
- bash Miniforge3.sh -b -p "/opt/conda" && \
- rm Miniforge3.sh && \
- ln -s /opt/conda/etc/profile.d/conda.sh /etc/profile.d/conda.sh && \
- chmod +x /opt/conda/etc/profile.d/conda.sh && \
- echo ". /opt/conda/etc/profile.d/conda.sh" >> ~/.bashrc && \
- /opt/conda/condabin/conda update conda --all -y && \
- /opt/conda/condabin/conda create --name workflow python=${PYTHON} -y && \
- /opt/conda/condabin/conda config --prepend channels "nvidia/label/cuda-12.1.0" && \
- /opt/conda/condabin/conda config --set always_yes true && \
- /opt/conda/condabin/conda clean --all && \
- echo "conda activate workflow" >> ~/.bashrc
\ No newline at end of file
+
+ENV PATH="${UV_INSTALL_DIR}:${PATH}"
+
+ENV OMPI_MCA_pml=^cm,ucx
+ENV OMPI_MCA_btl=tcp,self
+ENV OMPI_MCA_btl_tcp_if_exclude=lo,docker0
+ENV NCCL_SOCKET_IFNAME=^docker,lo
+
+RUN export DEBIAN_FRONTEND=noninteractive \
+ && apt-get update --fix-missing \
+ && apt-get upgrade -y \
+ && ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime \
+ && apt-get install -y tzdata \
+ && dpkg-reconfigure --frontend noninteractive tzdata \
+ && apt-get install -y bzip2 ca-certificates curl build-essential git libglib2.0-0 libsm6 libxext6 libxrender1 openssh-server wget \
+ libibverbs1 ibverbs-providers ibverbs-utils libibverbs-dev infiniband-diags \
+ # nvidia/cuda ships nvidia's apt singing key in legacy format (/etc/apt/trusted.gpg).
+ # This lead to warnings, so we install cuda-keyring.
+ && wget https://developer.download.nvidia.com/compute/cuda/repos/ubuntu${UBUNTU_VERSION}04/x86_64/cuda-keyring_1.1-1_all.deb \
+ && dpkg -i cuda-keyring_1.1-1_all.deb \
+ && rm cuda-keyring_1.1-1_all.deb \
+ && rm -f /etc/apt/sources.list.d/cuda.list \
+ && sed -i "s/.*PasswordAuthentication.*/PasswordAuthentication no/g" /etc/ssh/sshd_config \
+ && mkdir /run/sshd \
+ && mkdir -p ~/.ssh && chmod 700 ~/.ssh && touch ~/.ssh/authorized_keys \
+ && chmod 600 ~/.ssh/authorized_keys \
+ && rm /etc/ssh/ssh_host_* \
+ # User: UID/GID 1001 because Ubuntu 24.04 ships a default 'ubuntu' user at 1000.
+ && apt-get install -y sudo \
+ && groupadd -g 1001 dstack \
+ && useradd -u 1001 -g 1001 -G sudo -s /bin/bash -m dstack \
+ && echo 'dstack ALL=(ALL) NOPASSWD: ALL' > /etc/sudoers.d/dstack \
+ # Default working dir
+ && mkdir -p /dstack/run \
+ && chmod a+rwx /dstack/run \
+ # Cleanup
+ && rm -rf /var/lib/apt/lists/*
+
+RUN curl -LsSf https://astral.sh/uv/install.sh | INSTALLER_NO_MODIFY_PATH=1 sh \
+ && uv python install --preview --default
+
+# ============================================================================
+# builder: builds NCCL and nccl-tests from source for the base/devel flavors.
+# ============================================================================
+
+FROM nvidia/cuda:12.8.2-base-ubuntu${UBUNTU_VERSION}.04 AS builder
+
+ENV NCCL_HOME=/opt/nccl
+ENV CUDA_HOME=/usr/local/cuda
+ENV OPEN_MPI_PATH=/usr/lib/x86_64-linux-gnu/openmpi
+
+RUN export DEBIAN_FRONTEND=noninteractive \
+ && apt-get update --fix-missing \
+ && apt-get upgrade -y \
+ && ln -fs /usr/share/zoneinfo/America/New_York /etc/localtime \
+ && apt-get install -y tzdata \
+ && dpkg-reconfigure --frontend noninteractive tzdata \
+ && cuda_version=$(echo ${CUDA_VERSION} | awk -F . '{ print $1"-"$2 }') \
+ && apt-get install -y --no-install-recommends \
+ cuda-libraries-dev-${cuda_version} \
+ cuda-nvcc-${cuda_version} \
+ libhwloc-dev \
+ autoconf \
+ automake \
+ libtool \
+ libopenmpi-dev \
+ git \
+ curl \
+ python3 \
+ build-essential
+
+ARG NCCL_VERSION=2.26.2-1
+
+RUN cd /tmp \
+ && git clone https://github.com/NVIDIA/nccl.git -b v${NCCL_VERSION} \
+ && cd nccl \
+ && make -j$(nproc) src.build BUILDDIR=${NCCL_HOME}
+
+RUN cd /opt \
+ && git clone https://github.com/NVIDIA/nccl-tests \
+ && cd nccl-tests \
+ && make -j$(nproc) \
+ MPI=1 \
+ MPI_HOME=${OPEN_MPI_PATH} \
+ CUDA_HOME=${CUDA_HOME} \
+ NCCL_HOME=${NCCL_HOME}
+
+# ============================================================================
+# base: common + NCCL (from builder) + OpenMPI.
+# ============================================================================
+
+FROM common AS base
+
+ENV NCCL_HOME=/opt/nccl
+
+COPY --from=builder ${NCCL_HOME} ${NCCL_HOME}
+COPY --from=builder /opt/nccl-tests/build /opt/nccl-tests/build
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends openmpi-bin \
+ && rm -rf /var/lib/apt/lists/* \
+ && echo "${NCCL_HOME}/lib" >> /etc/ld.so.conf.d/nccl.conf \
+ && ldconfig
+
+WORKDIR /dstack/run
+
+# ============================================================================
+# devel: base + CUDA development libraries and NVCC.
+# ============================================================================
+
+FROM base AS devel
+
+RUN cuda_version=$(echo ${CUDA_VERSION} | awk -F . '{ print $1"-"$2 }') \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends \
+ cuda-libraries-dev-${cuda_version} \
+ cuda-nvcc-${cuda_version} \
+ libhwloc-dev \
+ && rm -rf /var/lib/apt/lists/*
+
+WORKDIR /dstack/run
+
+# ============================================================================
+# devel-efa: common + CUDA dev libraries + AWS EFA + EFA-aware NCCL.
+# ============================================================================
+
+FROM common AS devel-efa
+
+ENV NCCL_HOME=/usr/local
+ENV CUDA_HOME=/usr/local/cuda
+ENV LIBFABRIC_PATH=/opt/amazon/efa
+ENV OPEN_MPI_PATH=/opt/amazon/openmpi
+ENV PATH="${LIBFABRIC_PATH}/bin:${OPEN_MPI_PATH}/bin:${PATH}"
+ENV LD_LIBRARY_PATH="${OPEN_MPI_PATH}/lib:${LD_LIBRARY_PATH}"
+
+RUN cuda_version=$(echo ${CUDA_VERSION} | awk -F . '{ print $1"-"$2 }') \
+ && apt-get update \
+ && apt-get install -y --no-install-recommends \
+ cuda-libraries-dev-${cuda_version} \
+ cuda-nvcc-${cuda_version} \
+ && rm -rf /var/lib/apt/lists/*
+
+ARG EFA_VERSION=1.48.0
+
+RUN cd /tmp \
+ && apt-get update \
+ && curl -O https://s3-us-west-2.amazonaws.com/aws-efa-installer/aws-efa-installer-${EFA_VERSION}.tar.gz \
+ && tar -xf aws-efa-installer-${EFA_VERSION}.tar.gz \
+ && cd aws-efa-installer \
+ && ./efa_installer.sh -y --skip-kmod -g \
+ && rm -rf /tmp/aws-efa-installer /var/lib/apt/lists/*
+
+ARG NCCL_VERSION=2.27.7-1
+
+RUN cd /tmp \
+ && git clone https://github.com/NVIDIA/nccl.git -b v${NCCL_VERSION} \
+ && cd nccl \
+ && make -j$(nproc) src.build BUILDDIR=${NCCL_HOME} \
+ && rm -rf /tmp/nccl
+
+RUN cd /opt \
+ && git clone https://github.com/NVIDIA/nccl-tests \
+ && cd nccl-tests \
+ && make -j$(nproc) \
+ MPI=1 \
+ MPI_HOME=${OPEN_MPI_PATH} \
+ CUDA_HOME=${CUDA_HOME} \
+ NCCL_HOME=${NCCL_HOME}
+
+WORKDIR /dstack/run
diff --git a/docker/base/README.md b/docker/base/README.md
index 3bbbafa732..5246cbc40b 100644
--- a/docker/base/README.md
+++ b/docker/base/README.md
@@ -1 +1,19 @@
-Image for `dstack` runner instances.
+# dstack base images
+
+Base images for `dstack` runner instances. A single multi-stage `Dockerfile`
+produces all flavors; select one with `docker build --target `:
+
+- **base** — CUDA 12.8, Python (uv-managed), NCCL 2.26.2-1 + NCCL Tests, Open MPI.
+- **devel** — `base` plus the CUDA development libraries and NVCC.
+- **devel-efa** — `base` plus CUDA dev libraries, AWS EFA Installer 1.48.0
+ (Libfabric + Open MPI + AWS OFI NCCL 1.19.0), and an EFA-aware NCCL 2.27.7-1
+ build + NCCL Tests.
+
+Build args: `UBUNTU_VERSION` (e.g. `24`).
+
+Example:
+
+```bash
+docker build --target devel-efa --build-arg UBUNTU_VERSION=24 \
+ -t dstackai/base:local-devel-efa-ubuntu24.04 -f base/Dockerfile .
+```
diff --git a/docker/dind/Dockerfile b/docker/dind/Dockerfile
new file mode 100644
index 0000000000..d41042d187
--- /dev/null
+++ b/docker/dind/Dockerfile
@@ -0,0 +1,24 @@
+# Keep BASE_VERSION (base image tag) and BASE_SHA256 in sync
+ARG BASE_VERSION=24.04-20240827003913
+ARG BASE_SHA256=c9812aad4dbb79d800e5aecdfe41b66ffe47b73f0c070b5143c5acdcd6643ba1
+
+FROM ghcr.io/ehfd/nvidia-dind@sha256:${BASE_SHA256}
+
+ARG IMAGE_NAME
+ARG BASE_VERSION
+ARG DSTACK_REVISION
+ARG BUILD_DATE
+
+COPY start-dockerd /usr/local/bin/
+
+RUN \
+ chmod 755 /usr/local/bin/start-dockerd && \
+ rm /usr/local/bin/entrypoint.sh && \
+ sed -i -e '/nodaemon/d' -e '/program:entrypoint/,/^[[:space:]]*$/d' /etc/supervisord.conf
+
+ENTRYPOINT []
+CMD ["/usr/local/bin/start-dockerd", "-v", "-l"]
+
+LABEL org.opencontainers.image.title="${IMAGE_NAME}"
+LABEL org.opencontainers.image.version="${BASE_VERSION}-${DSTACK_REVISION}"
+LABEL org.opencontainers.image.created="${BUILD_DATE}"
diff --git a/docker/dind/README.md b/docker/dind/README.md
new file mode 100644
index 0000000000..7e0f378a20
--- /dev/null
+++ b/docker/dind/README.md
@@ -0,0 +1,34 @@
+# dstack DinD
+
+An [NVIDIA Docker in Docker](https://github.com/ehfd/nvidia-dind) image tailored for use with `dstack`
+
+## Usage
+
+```yaml
+type: service
+
+name: dind
+
+image: dstackai/dind
+privileged: true
+
+port: 3000
+auth: false
+
+commands:
+ # start docker daemon
+ - start-dockerd
+ # list stored images
+ - docker image ls
+ # run docker with nvidia gpu example (nvidia-smi)
+ - docker run --rm --gpus all debian nvidia-smi
+ # run docker compose example (gitea+postgres)
+ - git clone --depth 1 https://github.com/docker/awesome-compose.git
+ - cd awesome-compose/gitea-postgres
+ - docker compose up
+
+# preserve docker data root between runs (including volumes and image store)
+volumes:
+ - name: dind-volume
+ path: /var/lib/docker
+```
diff --git a/docker/dind/start-dockerd b/docker/dind/start-dockerd
new file mode 100755
index 0000000000..8a4abb3c0b
--- /dev/null
+++ b/docker/dind/start-dockerd
@@ -0,0 +1,201 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+# constants
+
+SUPERVISORD_LOG='/tmp/supervisord.log'
+DOCKERD_LOG='/tmp/dockerd.log'
+DEFAULT_TIMEOUT=60
+
+ERR_INSUFFICIENT_PRIVILEGES=101
+ERR_DOCKERD_FAILED=102
+ERR_INVALID_ARGS=103
+ERR_SUPERVISORD_FAILED=104
+
+# options
+
+verbose=false
+quiet=false
+logs=false
+timeout=${DEFAULT_TIMEOUT}
+
+# functions
+
+is_true() {
+ [[ ${1} = true ]]
+}
+
+is_verbose() {
+ is_true ${verbose}
+}
+
+is_quiet() {
+ is_true ${quiet}
+}
+
+say() {
+ echo "${@}" >&2
+}
+
+say_verbose() {
+ if is_verbose; then
+ say "${@}"
+ fi
+}
+
+check_privileged_mode_or_die() {
+ mkdir /mnt/_tmp
+ if ! mount -t tmpfs none /mnt/_tmp 2> /dev/null; then
+ say 'docker privileged mode required'
+ rm -r /mnt/_tmp
+ exit ${ERR_INSUFFICIENT_PRIVILEGES}
+ fi
+ umount /mnt/_tmp
+ rm -r /mnt/_tmp
+}
+
+start_restart_dockerd() {
+ if supervisorctl pid > /dev/null; then
+ say_verbose "restarting dockerd"
+ supervisorctl stop dockerd > /dev/null
+ if [[ -f ${DOCKERD_LOG} ]]; then
+ rm ${DOCKERD_LOG}
+ fi
+ supervisorctl start dockerd > /dev/null
+ echo 'restarted'
+ else
+ local ctl_status=${?}
+ # LSBInitExitStatuses.NOT_RUNNING = 7
+ if [[ ${ctl_status} -eq 7 ]]; then
+ say_verbose "starting dockerd"
+ supervisord -c /etc/supervisord.conf
+ echo 'started'
+ else
+ say "supervisorctl exited with status ${ctl_status}"
+ if ! is_quiet && [[ -f ${SUPERVISORD_LOG} ]]; then
+ cat ${SUPERVISORD_LOG} >&2
+ fi
+ exit ${ERR_SUPERVISORD_FAILED}
+ fi
+ fi
+}
+
+move_processes_to_separate_cgroup() {
+ # Move processes to a separate cgroup to prevent the root cgroup from becoming
+ # threaded -- "Once you have a threaded controller you can not create cgroups
+ # below it that reference non-threaded controllers like the memory controller".
+ # "A domain cgroup is turned into a threaded domain when [...] threaded controllers
+ # are enabled in the “cgroup.subtree_control” file while there are processes
+ # in the cgroup."
+ # Fixes "cannot enter cgroupv2 "/sys/fs/cgroup/docker" with domain controllers --
+ # it is in threaded mode" when starting containers with resource constraints,
+ # see https://github.com/dstackai/dstack/issues/1854
+ # Based on https://github.com/moby/moby/blob/65cfcc2/hack/dind#L59 and
+ # https://github.com/earthly/earthly/blob/08b0d1f/buildkitd/dockerd-wrapper.sh#L63
+ if [[ -f /sys/fs/cgroup/cgroup.controllers ]]; then
+ local group=/sys/fs/cgroup/dind
+ mkdir -p ${group}
+ xargs -rn1 < /sys/fs/cgroup/cgroup.procs > ${group}/cgroup.procs || true
+ fi
+}
+
+wait_dockerd_started() {
+ local counter=1
+ while true; do
+ if grep -qs 'API listen on' ${DOCKERD_LOG}; then
+ return 0
+ fi
+ if [[ ${counter} -gt ${timeout} ]]; then
+ break
+ fi
+ say_verbose "waiting for dockerd to start (${counter}/${timeout})"
+ ((counter++))
+ sleep 1
+ done
+ return 1
+}
+
+stop_dockerd_and_die() {
+ supervisorctl stop dockerd > /dev/null
+ say 'failed to start dockerd'
+ if ! is_quiet; then
+ cat ${DOCKERD_LOG} >&2
+ fi
+ exit ${ERR_DOCKERD_FAILED}
+}
+
+usage() {
+ echo 'usage: start-dockerd [-v|-q] [-l] [-t SECONDS]'
+ echo ' -v, --verbose get more output, mutually exclusive with -q'
+ echo ' -q, --quiet get less output, mutually exclusive with -v'
+ echo ' -l, --logs follow dockerd log output'
+ echo ' -t, --timeout SECONDS wait for dockerd to start the specified amount'
+ echo ' of seconds before failing with error, '
+ echo " ${DEFAULT_TIMEOUT} seconds by default"
+}
+
+# main
+
+check_privileged_mode_or_die
+
+while [[ ${#} -gt 0 ]]; do
+ option=${1}
+ shift
+ case ${option} in
+ --verbose|-v)
+ verbose=true
+ ;;
+ --quiet|-q)
+ quiet=true
+ ;;
+ --logs|-l)
+ logs=true
+ ;;
+ --timeout|-t)
+ if [[ ${#} -eq 0 ]]; then
+ say "${option}: value expected"
+ exit ${ERR_INVALID_ARGS}
+ fi
+ timeout=${1}
+ shift
+ # single brackets are intentional, compare to:
+ # set -u; [[ "foo" -gt 0 ]]
+ # bash: foo: unbound variable
+ if ! [ "${timeout}" -gt 0 ] 2> /dev/null; then
+ say "${option}: invalid value"
+ exit ${ERR_INVALID_ARGS}
+ fi
+ ;;
+ --help|-h)
+ usage
+ exit 0
+ ;;
+ *)
+ say "${option}: invalid option"
+ usage
+ exit ${ERR_INVALID_ARGS}
+ ;;
+ esac
+done
+
+if is_verbose && is_quiet; then
+ say '--verbose and --quiet are mutually exclusive'
+ exit ${ERR_INVALID_ARGS}
+fi
+
+event=$(start_restart_dockerd)
+if ! wait_dockerd_started; then
+ stop_dockerd_and_die
+fi
+
+if [[ ${event} = 'started' ]]; then
+ move_processes_to_separate_cgroup
+fi
+
+if ! is_quiet; then
+ say "dockerd ${event}"
+fi
+
+if is_true ${logs}; then
+ tail -f ${DOCKERD_LOG}
+fi
diff --git a/docker/server/Dockerfile.nebius b/docker/server/Dockerfile.nebius
new file mode 100644
index 0000000000..d449d8833b
--- /dev/null
+++ b/docker/server/Dockerfile.nebius
@@ -0,0 +1,5 @@
+ARG BASE_IMAGE
+
+FROM ${BASE_IMAGE}
+
+RUN curl -sSL https://storage.eu-north1.nebius.cloud/cli/install.sh | bash
diff --git a/docker/server/README.md b/docker/server/README.md
index 1e3f278b81..2c91a4e152 100644
--- a/docker/server/README.md
+++ b/docker/server/README.md
@@ -1,24 +1,12 @@
-`dstack` is an open-source engine that automates infrastructure provisioning on any cloud — for development, training, and deployment of AI models.
+`dstack` is a streamlined alternative to Kubernetes, specifically designed for AI. It simplifies container orchestration
+for AI workloads both in the cloud and on-prem, speeding up the development, training, and deployment of AI models.
-## Configure backends
-
-To let `dstack` run workloads in your cloud account(s), you need to configure cloud credentials
-in `~/.dstack/server/config.yml` under the `backends` property of the respective project.
-
-Example:
+`dstack` supports `NVIDIA GPU`, `AMD GPU`, and `Google Cloud TPU` out of the box.
-```yaml
-projects:
-- name: main
- backends:
- - type: aws
- creds:
- type: access_key
- access_key: AIZKISCVKUKO5AAKLAEH
- secret_key: QSbmpqJIUBn1V5U3pyM9S6lwwiu8/fOJ2dgfwFdW
-```
+## Configure backends
-For further backend configuration details, refer to [Installation](https://dstack.ai/docs/installation/).
+To use `dstack` with your own cloud accounts, create the `~/.dstack/server/config.yml` file and
+[configure backends](https://dstack.ai/docs/reference/server/config.yml).
## Start the server
@@ -31,74 +19,58 @@ The dstack server is running at http://0.0.0.0:3000
The admin user token is 'bbae0f28-d3dd-4820-bf61-8f4bb40815da'
```
-## Set up the CLI
+For more details on server configuration options, see the
+[server deployment](https://dstack.ai/docs/guides/server-deployment.md) guide.
-The client is configured via `~/.dstack/config.yml` with the server address, user token, and
-the project name.
+### Run with PostgreSQL and the SSH proxy
-To configure this, use the `dstack config` command:
+In production, the `dstack` server is usually run with
+[PostgreSQL](https://dstack.ai/docs/guides/server-deployment#postgresql) instead of the default
+SQLite, and with the [SSH proxy](https://dstack.ai/docs/guides/server-deployment#ssh-proxy). The
+[`docker-compose.yml`](https://github.com/dstackai/dstack/blob/master/docker/server/docker-compose.yml)
+runs that combination locally, so you can try or test a production-like server on your own machine.
+A full production deployment would also configure external
+[logs storage](https://dstack.ai/docs/guides/server-deployment#logs-storage) and
+[file storage](https://dstack.ai/docs/guides/server-deployment#file-storage).
```shell
-dstack config --project main --server http://0.0.0.0:3000 --token bbae0f28-d3dd-4820-bf61-8f4bb40815da
+docker compose -f docker/server/docker-compose.yml up
```
-This will update `~/.dstack/config.yml` allowing the CLI and API to connect to the server by default.
-
-## Environment variables
-
-Here's the list of environment variables which you can override:
-
-- `DSTACK_SERVER_DIR` – (Optional) The path to the directory where the `dstack` server stores the state. Defaults to `/root/.dstack/server`.
-- `DSTACK_DATABASE_URL` – (Optional) The database URL to use instead of default SQLite. Currently `dstack` supports Postgres. Example: `postgresql+asyncpg://myuser:mypassword@localhost:5432/mydatabase`.
-- `DSTACK_SERVER_ADMIN_TOKEN` – (Optional) The default token of the `admin` user. By default, it's generated randomly
- at the first startup.
-
-## Persist state
-
-By default, `dstack` stores its state in `~/.dstack/server/data` using SQLite.
-To use a database, set the `DSTACK_DATABASE_URL` environment variable (see below).
-
-### Replicate SQLite state via Litestream
+This starts PostgreSQL, the `dstack` server at `http://localhost:3000`, and the SSH proxy at
+`localhost:30022`. The admin token is printed to the logs (`docker compose logs server`).
-If not using `DSTACK_DATABASE_URL`, you can still replicate the state to cloud object storage using Litestream. To do
-this, you need to set the following environment variables.
+To access the server from the CLI, add it as a project with `dstack project add`, using the
+admin token from the logs (see [Set up the CLI](#set-up-the-cli) below).
-- `LITESTREAM_REPLICA_URL` - The url of the cloud object storage.
- Examples: `s3:///`, `gcs:///`, `abs://@/`, etc.
-
-#### AWS S3
-
-To persist state into an AWS S3 bucket, provide the following environment variables:
-
-- `AWS_ACCESS_KEY_ID` - The AWS access key ID
-- `AWS_SECRET_ACCESS_KEY` - The AWS secret access key
-
-#### GCP Storage
-
-To persist state into an AWS S3 bucket, provide one of the following environment variables:
-
-- `GOOGLE_APPLICATION_CREDENTIALS` - The path to the GCP service account key JSON file
-- `GOOGLE_APPLICATION_CREDENTIALS_JSON` - The GCP service account key JSON
-
-#### Azure Blob Storage
-
-To persist state into an Azure blog storage, provide the following environment variable.
+## Set up the CLI
-- `LITESTREAM_AZURE_ACCOUNT_KEY` - The Azure storage account key
+To point the CLI to the `dstack` server, configure it
+with the server address, user token, and project name:
-More [details](https://litestream.io/guides/) on options for configuring replication.
+```shell
+$ pip install dstack
+$ dstack project add --name main \
+ --url http://127.0.0.1:3000 \
+ --token bbae0f28-d3dd-4820-bf61-8f4bb40815da
+
+Configuration is updated at ~/.dstack/config.yml
+```
-_**️Note:** The use of Litestream requires that only one instance of the `dstack` server is running at a time._
+## Create SSH fleets
+
+If you want the `dstack` server to run containers on your on-prem servers,
+use [fleets](https://dstack.ai/docs/concepts/fleets#ssh-fleets).
## More information
For additional information and examples, see the following links:
-* [Docs](https://dstack.ai/docs/)
-* [Examples](https://github.com/dstackai/dstack/tree/master/examples)
+* [Docs](https://dstack.ai/docs)
+* [Examples](https://dstack.ai/examples)
* [Changelog](https://github.com/dstackai/dstack/releases)
* [Discord](https://discord.gg/u8SmfwPpMd)
## License
-[Mozilla Public License 2.0](https://github.com/dstackai/dstack/blob/master/LICENSE.md)
\ No newline at end of file
+[Mozilla Public License 2.0](https://github.com/dstackai/dstack/blob/master/LICENSE.md)
diff --git a/docker/server/docker-compose.yml b/docker/server/docker-compose.yml
new file mode 100644
index 0000000000..529271059c
--- /dev/null
+++ b/docker/server/docker-compose.yml
@@ -0,0 +1,73 @@
+name: dstack
+
+services:
+ postgres:
+ image: postgres:16
+ restart: unless-stopped
+ environment:
+ POSTGRES_USER: ${DSTACK_POSTGRES_USER:-dstack}
+ POSTGRES_PASSWORD: ${DSTACK_POSTGRES_PASSWORD:-dstack}
+ POSTGRES_DB: ${DSTACK_POSTGRES_DB:-dstack}
+ volumes:
+ - postgres-data:/var/lib/postgresql/data
+ healthcheck:
+ test: ["CMD-SHELL", "pg_isready -U $$POSTGRES_USER -d $$POSTGRES_DB"]
+ interval: 5s
+ timeout: 5s
+ retries: 10
+
+ server:
+ image: dstackai/dstack:latest # multi-arch — no platform override needed
+ restart: unless-stopped
+ depends_on:
+ postgres:
+ condition: service_healthy
+ environment:
+ DSTACK_DATABASE_URL: postgresql+asyncpg://${DSTACK_POSTGRES_USER:-dstack}:${DSTACK_POSTGRES_PASSWORD:-dstack}@postgres:5432/${DSTACK_POSTGRES_DB:-dstack}
+ DSTACK_SERVER_LOG_FORMAT: rich # human-readable console logs (image defaults to json)
+ # Shared secret between the server and the SSH proxy. The default works locally;
+ # override with a real secret for non-local deployments.
+ DSTACK_SSHPROXY_API_TOKEN: ${DSTACK_SSHPROXY_API_TOKEN:-dstack-sshproxy-token}
+ # Address clients use to reach the SSH proxy. `localhost:30022` is correct for a
+ # client on the same host; use a publicly reachable address for multi-host setups.
+ DSTACK_SERVER_SSHPROXY_ADDRESS: localhost:30022
+ volumes:
+ - server-data:/root/.dstack/server # config.yml + run logs (Postgres holds the rest)
+ ports:
+ - "3000:3000"
+
+ # One-shot init: generates the SSH proxy's host key into a shared volume so no manual
+ # ssh-keygen is needed. The proxy refuses to start without a host key.
+ sshproxy-keygen:
+ image: alpine:3
+ command:
+ - sh
+ - -c
+ - |
+ apk add --no-cache openssh-keygen >/dev/null
+ [ -f /keys/host_key ] || ssh-keygen -t ed25519 -f /keys/host_key -N "" -C dstack-sshproxy
+ volumes:
+ - sshproxy-keys:/keys
+
+ sshproxy:
+ image: dstackai/sshproxy:latest
+ platform: linux/amd64 # image is amd64-only; emulated on Apple Silicon
+ restart: unless-stopped
+ depends_on:
+ sshproxy-keygen:
+ condition: service_completed_successfully
+ server:
+ condition: service_started
+ environment:
+ DSTACK_SSHPROXY_API_URL: http://server:3000
+ DSTACK_SSHPROXY_API_TOKEN: ${DSTACK_SSHPROXY_API_TOKEN:-dstack-sshproxy-token}
+ command: ["--host-key", "/keys/host_key"]
+ volumes:
+ - sshproxy-keys:/keys
+ ports:
+ - "30022:30022"
+
+volumes:
+ postgres-data:
+ server-data:
+ sshproxy-keys:
diff --git a/docker/server/entrypoint.sh b/docker/server/entrypoint.sh
index c326937916..8cd67fd260 100644
--- a/docker/server/entrypoint.sh
+++ b/docker/server/entrypoint.sh
@@ -7,9 +7,15 @@ if [ -n "${GOOGLE_APPLICATION_CREDENTIALS_JSON}" ]; then
echo "${GOOGLE_APPLICATION_CREDENTIALS_JSON}" > "${GOOGLE_APPLICATION_CREDENTIALS_DIR}/application_default_credentials.json"
fi
+DB_PATH="${HOME}/.dstack/server/data/sqlite.db"
+mkdir -p "$(dirname "$DB_PATH")"
if [[ -z "${LITESTREAM_REPLICA_URL}" ]]; then
- dstack server --host 0.0.0.0
+ exec dstack server --host 0.0.0.0
else
- litestream restore -if-replica-exists -o ${HOME}/.dstack/server/data/sqlite.db ${LITESTREAM_REPLICA_URL}
- litestream replicate -exec "dstack server --host 0.0.0.0" ${HOME}/.dstack/server/data/sqlite.db ${LITESTREAM_REPLICA_URL}
+ if [[ ! -f "$DB_PATH" ]]; then
+ echo "Starting db restore"
+ litestream restore -if-replica-exists -o "$DB_PATH" "$LITESTREAM_REPLICA_URL"
+ echo "Finished db restore"
+ fi
+ exec litestream replicate -exec "dstack server --host 0.0.0.0" "$DB_PATH" "$LITESTREAM_REPLICA_URL"
fi
diff --git a/docker/server/release/Dockerfile b/docker/server/release/Dockerfile
index fff4b7a57e..a88439d61e 100644
--- a/docker/server/release/Dockerfile
+++ b/docker/server/release/Dockerfile
@@ -9,19 +9,24 @@ WORKDIR /dstack-server
RUN apt-get update && apt-get install -y \
curl \
- software-properties-common \
git \
+ sqlite3 \
+ tini \
&& rm -rf /var/lib/apt/lists/*
-RUN if [ $(uname -m) = "aarch64" ]; then ARCH="arm64"; else ARCH="amd64"; fi && \
- curl https://github.com/benbjohnson/litestream/releases/download/v0.3.9/litestream-v0.3.9-linux-$ARCH.deb -O -L && \
- dpkg -i litestream-v0.3.9-linux-$ARCH.deb
+RUN if [ $(uname -m) = "aarch64" ]; then ARCH="arm64"; else ARCH="x86_64"; fi && \
+ curl https://github.com/benbjohnson/litestream/releases/download/v0.5.9/litestream-0.5.9-linux-$ARCH.deb -O -L && \
+ dpkg -i litestream-0.5.9-linux-$ARCH.deb
-RUN pip install "dstack[all]==$VERSION" --progress-bar off
+ADD https://astral.sh/uv/install.sh /uv-installer.sh
+RUN sh /uv-installer.sh && rm /uv-installer.sh
+ENV PATH="/root/.local/bin/:$PATH"
+
+RUN uv tool install "dstack[all]==$VERSION"
COPY entrypoint.sh entrypoint.sh
RUN chmod 777 entrypoint.sh
EXPOSE 3000
-ENTRYPOINT ["./entrypoint.sh"]
+ENTRYPOINT ["/usr/bin/tini", "--", "./entrypoint.sh"]
diff --git a/docker/server/stgn/Dockerfile b/docker/server/stgn/Dockerfile
index e9e410aa98..b2c4f96370 100644
--- a/docker/server/stgn/Dockerfile
+++ b/docker/server/stgn/Dockerfile
@@ -7,21 +7,26 @@ WORKDIR /dstack-server
RUN apt-get update && apt-get install -y \
curl \
- software-properties-common \
git \
+ sqlite3 \
+ tini \
&& rm -rf /var/lib/apt/lists/*
-RUN if [ $(uname -m) = "aarch64" ]; then ARCH="arm64"; else ARCH="amd64"; fi && \
- curl https://github.com/benbjohnson/litestream/releases/download/v0.3.9/litestream-v0.3.9-linux-$ARCH.deb -O -L && \
- dpkg -i litestream-v0.3.9-linux-$ARCH.deb
+RUN if [ $(uname -m) = "aarch64" ]; then ARCH="arm64"; else ARCH="x86_64"; fi && \
+ curl https://github.com/benbjohnson/litestream/releases/download/v0.5.9/litestream-0.5.9-linux-$ARCH.deb -O -L && \
+ dpkg -i litestream-0.5.9-linux-$ARCH.deb
+ADD https://astral.sh/uv/install.sh /uv-installer.sh
+RUN sh /uv-installer.sh && rm /uv-installer.sh
+ENV PATH="/root/.local/bin/:$PATH"
+
+COPY pyproject.toml uv.lock README.md ./
COPY src src
-COPY setup.py README.md ./
-RUN pip install '.[all]'
+RUN uv sync --extra all
COPY docker/server/entrypoint.sh entrypoint.sh
RUN chmod 777 entrypoint.sh
EXPOSE 3000
-ENTRYPOINT ["./entrypoint.sh"]
+ENTRYPOINT ["/usr/bin/tini", "--", "./entrypoint.sh"]
diff --git a/docker/tt-smi/Dockerfile b/docker/tt-smi/Dockerfile
new file mode 100644
index 0000000000..da190db313
--- /dev/null
+++ b/docker/tt-smi/Dockerfile
@@ -0,0 +1,23 @@
+FROM ubuntu:22.04
+
+ARG IMAGE_NAME
+ARG TT_SMI_VERSION
+ARG BUILD_DATE
+
+ENV PATH="/root/.cargo/bin:${PATH}"
+
+RUN \
+ apt-get update && \
+ apt-get install -y curl git python3 python3-pip && \
+ curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y && \
+ pip3 install --no-cache-dir --upgrade pip setuptools wheel tomli && \
+ pip3 install --no-cache-dir --no-build-isolation git+https://github.com/tenstorrent/tt-smi@v${TT_SMI_VERSION} && \
+ apt-get clean && \
+ rm -rf /var/lib/apt/lists/*
+
+ENTRYPOINT ["/usr/local/bin/tt-smi"]
+CMD ["--help"]
+
+LABEL org.opencontainers.image.title="${IMAGE_NAME}"
+LABEL org.opencontainers.image.version="${TT_SMI_VERSION}"
+LABEL org.opencontainers.image.created="${BUILD_DATE}"
diff --git a/docker/tt-smi/README.md b/docker/tt-smi/README.md
new file mode 100644
index 0000000000..a9ef70f80c
--- /dev/null
+++ b/docker/tt-smi/README.md
@@ -0,0 +1,9 @@
+# dstack TT SMI
+
+An Ubuntu-based image with [TT SMI](https://github.com/tenstorrent/tt-smi/) preinstalled. Suitable for Tenstorrent GPU detection.
+
+## Usage
+
+```shell
+docker run --device /dev/tenstorrent/ dstackai/tt-smi -s
+```
diff --git a/docs/CNAME b/docs/CNAME
deleted file mode 100644
index c909514661..0000000000
--- a/docs/CNAME
+++ /dev/null
@@ -1 +0,0 @@
-dstack.ai
\ No newline at end of file
diff --git a/docs/assets/images/kubernetes-logo.svg b/docs/assets/images/kubernetes-logo.svg
deleted file mode 100644
index 9a61c190a0..0000000000
--- a/docs/assets/images/kubernetes-logo.svg
+++ /dev/null
@@ -1,91 +0,0 @@
-
-
-
-
- Kubernetes logo with no border
-
-
-
-
-
- image/svg+xml
-
- Kubernetes logo with no border
- "kubectl" is pronounced "kyoob kuttel"
-
-
-
-
-
-
-
-
-
-
diff --git a/docs/assets/images/oci-logo.svg b/docs/assets/images/oci-logo.svg
deleted file mode 100644
index 561271d2fa..0000000000
--- a/docs/assets/images/oci-logo.svg
+++ /dev/null
@@ -1,4 +0,0 @@
-
-
-
-
\ No newline at end of file
diff --git a/docs/assets/images/plus.svg b/docs/assets/images/plus.svg
deleted file mode 100644
index 7a617a528b..0000000000
--- a/docs/assets/images/plus.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/assets/images/runpod-logo.svg b/docs/assets/images/runpod-logo.svg
deleted file mode 100644
index e2af977734..0000000000
--- a/docs/assets/images/runpod-logo.svg
+++ /dev/null
@@ -1,7 +0,0 @@
-
-
-
-
-
-
-
\ No newline at end of file
diff --git a/docs/assets/javascripts/extra.js b/docs/assets/javascripts/extra.js
deleted file mode 100644
index a1401b2d80..0000000000
--- a/docs/assets/javascripts/extra.js
+++ /dev/null
@@ -1,158 +0,0 @@
-controller = (function () {
- let setupEventListeners = function () {
- document.addEventListener('keydown', function (event) {
- if (event.keyCode === 75 && (event.metaKey || event.ctrlKey)) {
- document.querySelector('.md-search__input').focus()
- }
- });
- };
- return {
- init: function () {
- setupEventListeners();
- }
- };
-})();
-
-controller.init();
-
-function setupTermynal() {
- document.querySelectorAll(".use-termynal").forEach(node => {
- node.style.display = "block";
- new Termynal(node, {
- lineDelay: 500
- });
- });
- const progressLiteralStart = "---> 100%";
- const promptLiteralStart = "$ ";
- const customPromptLiteralStart = "# ";
- const termynalActivateClass = "termy";
- let termynals = [];
-
- function createTermynals() {
- document
- .querySelectorAll(`.${termynalActivateClass} .highlight`)
- .forEach(node => {
- const text = node.textContent;
- const lines = text.split(/(? {
- if (line) {
- isBlankSpace = false;
- }
- });
- dataValue = {};
- if (isBlankSpace) {
- dataValue["delay"] = 0;
- }
- if (buffer[buffer.length - 1] === "") {
- // A last single won't have effect
- // so put an additional one
- buffer.push("");
- }
- const bufferValue = buffer.join(" ");
- dataValue["value"] = bufferValue;
- useLines.push(dataValue);
- buffer = [];
- }
- }
- for (let line of lines) {
- if (line === progressLiteralStart) {
- saveBuffer();
- useLines.push({
- type: "progress"
- });
- } else if (line.startsWith(promptLiteralStart)) {
- saveBuffer();
- const value = line.replace(promptLiteralStart, "").trimEnd();
- useLines.push({
- type: "input",
- value: value
- });
- } else if (line.startsWith("// ")) {
- saveBuffer();
- const value = "💬 " + line.replace("// ", "").trimEnd();
- useLines.push({
- value: value,
- class: "termynal-comment",
- delay: 0
- });
- } else if (line.startsWith(customPromptLiteralStart)) {
- saveBuffer();
- const promptStart = line.indexOf(promptLiteralStart);
- if (promptStart === -1) {
- console.error("Custom prompt found but no end delimiter", line)
- }
- const prompt = line.slice(0, promptStart).replace(customPromptLiteralStart, "")
- let value = line.slice(promptStart + promptLiteralStart.length);
- useLines.push({
- type: "input",
- value: value,
- prompt: prompt
- });
- } else {
- buffer.push(line);
- }
- }
- saveBuffer();
- const div = document.createElement("div");
- node.replaceWith(div);
- const termynal = new Termynal(div, {
- lineData: useLines,
- noInit: true,
- lineDelay: 500,
- typeDelay: 20
- });
- termynals.push(termynal);
- });
- }
-
- function loadVisibleTermynals() {
- termynals = termynals.filter(termynal => {
- if (termynal.container.getBoundingClientRect().top - innerHeight <= 0) {
- termynal.init();
- return false;
- }
- return true;
- });
- }
- window.addEventListener("scroll", loadVisibleTermynals);
- createTermynals();
- loadVisibleTermynals();
-}
-
-function setupCustomCodeTitles() {
- document.querySelectorAll("div[editor-title]").forEach(div => {
- let code = div.getElementsByTagName('code')[0];
- // code.setAttribute("editor-title", div.getAttribute("editor-title"))
- let editorTitle = document.createElement("span")
- editorTitle.className = "editor-title"
- editorTitle.innerHTML = div.getAttribute("editor-title")
- code.appendChild(editorTitle)
- });
-}
-
-window.addEventListener("DOMContentLoaded", function() {
- let tabs = document.querySelector(".md-tabs")
- let header = document.querySelector(".md-header")
- let search = document.querySelector(".md-search")
- search.parentNode.insertBefore(tabs, search)
- header.classList.add("ready")
- setupTermynal()
- setupCustomCodeTitles()
-});
-
-(function () {
- document.querySelectorAll('.tx-faq__item').forEach(function (faqItem) {
- faqItem.querySelector('.tx-faq__item-title').addEventListener('click', function () {
- if (faqItem.classList.contains('_open')) {
- faqItem.classList.remove('_open')
- } else {
- faqItem.classList.add('_open')
- }
- });
- })
-})()
diff --git a/docs/assets/javascripts/termynal.js b/docs/assets/javascripts/termynal.js
deleted file mode 100644
index cbcb47be45..0000000000
--- a/docs/assets/javascripts/termynal.js
+++ /dev/null
@@ -1,266 +0,0 @@
-/**
- * termynal.js
- * A lightweight, modern and extensible animated terminal window, using
- * async/await.
- *
- * @author Ines Montani
- * @version 0.0.1
- * @license MIT
- */
-
-'use strict';
-
-/** Generate a terminal widget. */
-class Termynal {
- /**
- * Construct the widget's settings.
- * @param {(string|Node)=} container - Query selector or container element.
- * @param {Object=} options - Custom settings.
- * @param {string} options.prefix - Prefix to use for data attributes.
- * @param {number} options.startDelay - Delay before animation, in ms.
- * @param {number} options.typeDelay - Delay between each typed character, in ms.
- * @param {number} options.lineDelay - Delay between each line, in ms.
- * @param {number} options.progressLength - Number of characters displayed as progress bar.
- * @param {string} options.progressChar – Character to use for progress bar, defaults to █.
- * @param {number} options.progressPercent - Max percent of progress.
- * @param {string} options.cursor – Character to use for cursor, defaults to ▋.
- * @param {Object[]} lineData - Dynamically loaded line data objects.
- * @param {boolean} options.noInit - Don't initialise the animation.
- */
- constructor(container = '#termynal', options = {}) {
- this.container = (typeof container === 'string') ? document.querySelector(container) : container;
- this.pfx = `data-${options.prefix || 'ty'}`;
- this.originalStartDelay = this.startDelay = options.startDelay
- || parseFloat(this.container.getAttribute(`${this.pfx}-startDelay`)) || 300;
- this.originalTypeDelay = this.typeDelay = options.typeDelay
- || parseFloat(this.container.getAttribute(`${this.pfx}-typeDelay`)) || 60;
- this.originalLineDelay = this.lineDelay = options.lineDelay
- || parseFloat(this.container.getAttribute(`${this.pfx}-lineDelay`)) || 1500;
- this.progressLength = options.progressLength
- || parseFloat(this.container.getAttribute(`${this.pfx}-progressLength`)) || 40;
- this.progressChar = options.progressChar
- || this.container.getAttribute(`${this.pfx}-progressChar`) || '█';
- this.progressPercent = options.progressPercent
- || parseFloat(this.container.getAttribute(`${this.pfx}-progressPercent`)) || 100;
- this.cursor = options.cursor
- || this.container.getAttribute(`${this.pfx}-cursor`) || '▋';
- this.lineData = this.lineDataToElements(options.lineData || []);
- this.loadLines()
- if (!options.noInit) this.init()
- }
-
- loadLines() {
- // Load all the lines and create the container so that the size is fixed
- // Otherwise it would be changing and the user viewport would be constantly
- // moving as she/he scrolls
- const finish = this.generateFinish()
- finish.style.visibility = 'hidden'
- this.container.appendChild(finish)
- // Appends dynamically loaded lines to existing line elements.
- this.lines = [...this.container.querySelectorAll(`[${this.pfx}]`)].concat(this.lineData);
- for (let line of this.lines) {
- line.style.visibility = 'hidden'
- this.container.appendChild(line)
- }
- const restart = this.generateRestart()
- restart.style.visibility = 'hidden'
- this.container.appendChild(restart)
- this.container.setAttribute('data-termynal', '');
- }
-
- /**
- * Initialise the widget, get lines, clear container and start animation.
- */
- init() {
- /**
- * Calculates width and height of Termynal container.
- * If container is empty and lines are dynamically loaded, defaults to browser `auto` or CSS.
- */
- const containerStyle = getComputedStyle(this.container);
- this.container.style.width = containerStyle.width !== '0px' ?
- containerStyle.width : undefined;
- this.container.style.minHeight = containerStyle.height !== '0px' ?
- containerStyle.height : undefined;
-
- this.container.setAttribute('data-termynal', '');
- this.container.innerHTML = '';
- for (let line of this.lines) {
- line.style.visibility = 'visible'
- }
- this.start();
- }
-
- /**
- * Start the animation and rener the lines depending on their data attributes.
- */
- async start() {
- this.addFinish()
- await this._wait(this.startDelay);
-
- for (let line of this.lines) {
- const type = line.getAttribute(this.pfx);
- const delay = line.getAttribute(`${this.pfx}-delay`) || this.lineDelay;
-
- if (type == 'input') {
- line.setAttribute(`${this.pfx}-cursor`, this.cursor);
- await this.type(line);
- await this._wait(delay);
- }
-
- else if (type == 'progress') {
- await this.progress(line);
- await this._wait(delay);
- }
-
- else {
- this.container.appendChild(line);
- await this._wait(delay);
- }
-
- line.removeAttribute(`${this.pfx}-cursor`);
- }
- this.addRestart()
- this.finishElement.style.visibility = 'hidden'
- this.lineDelay = this.originalLineDelay
- this.typeDelay = this.originalTypeDelay
- this.startDelay = this.originalStartDelay
- }
-
- generateRestart() {
- const restart = document.createElement('a')
- restart.onclick = (e) => {
- e.preventDefault()
- this.container.innerHTML = ''
- this.init()
- }
- restart.href = '#'
- restart.setAttribute('data-terminal-control', '')
- restart.innerHTML = "restart ↻"
- return restart
- }
-
- generateFinish() {
- const finish = document.createElement('a')
- finish.onclick = (e) => {
- e.preventDefault()
- this.lineDelay = 0
- this.typeDelay = 0
- this.startDelay = 0
- }
- finish.href = '#'
- finish.setAttribute('data-terminal-control', '')
- finish.innerHTML = "fast →"
- this.finishElement = finish
- return finish
- }
-
- addRestart() {
- const restart = this.generateRestart()
- this.container.appendChild(restart)
- }
-
- addFinish() {
- const finish = this.generateFinish()
- this.container.appendChild(finish)
- }
-
- /**
- * Animate a typed line.
- * @param {Node} line - The line element to render.
- */
- async type(line) {
- const chars = [...line.textContent];
- line.textContent = '';
- this.container.appendChild(line);
-
- for (let char of chars) {
- const delay = line.getAttribute(`${this.pfx}-typeDelay`) || this.typeDelay;
- await this._wait(delay);
- line.textContent += char;
- }
- }
-
- /**
- * Animate a progress bar.
- * @param {Node} line - The line element to render.
- */
- async progress(line) {
- const progressLength = line.getAttribute(`${this.pfx}-progressLength`)
- || this.progressLength;
- const progressChar = line.getAttribute(`${this.pfx}-progressChar`)
- || this.progressChar;
- const chars = progressChar.repeat(progressLength);
- const progressPercent = line.getAttribute(`${this.pfx}-progressPercent`)
- || this.progressPercent;
- const typeDelay = line.getAttribute(`${this.pfx}-typeDelay`)
- || this.typeDelay;
- line.textContent = '';
- this.container.appendChild(line);
-
- for (let i = 1; i < chars.length + 1; i++) {
- await this._wait(typeDelay);
- const percent = Math.round(i / chars.length * 100);
- line.textContent = `${chars.slice(0, i)} ${percent}%`;
- if (percent>progressPercent) {
- break;
- }
- }
- }
-
- /**
- * Helper function for animation delays, called with `await`.
- * @param {number} time - Timeout, in ms.
- */
- _wait(time) {
- return new Promise(resolve => setTimeout(resolve, time));
- }
-
- /**
- * Converts line data objects into line elements.
- *
- * @param {Object[]} lineData - Dynamically loaded lines.
- * @param {Object} line - Line data object.
- * @returns {Element[]} - Array of line elements.
- */
- lineDataToElements(lineData) {
- return lineData.map(line => {
- let div = document.createElement('div');
- div.innerHTML = `${line.value || ''} `;
-
- return div.firstElementChild;
- });
- }
-
- /**
- * Helper function for generating attributes string.
- *
- * @param {Object} line - Line data object.
- * @returns {string} - String of attributes.
- */
- _attributes(line) {
- let attrs = '';
- for (let prop in line) {
- // Custom add class
- if (prop === 'class') {
- attrs += ` class=${line[prop]} `
- continue
- }
- if (prop === 'type') {
- attrs += `${this.pfx}="${line[prop]}" `
- } else if (prop !== 'value') {
- attrs += `${this.pfx}-${prop}="${line[prop]}" `
- }
- }
-
- return attrs;
- }
-}
-
-/**
-* HTML API: If current script has container(s) specified, initialise Termynal.
-*/
-if (document.currentScript.hasAttribute('data-termynal-container')) {
- const containers = document.currentScript.getAttribute('data-termynal-container');
- containers.split('|')
- .forEach(container => new Termynal(container))
-}
\ No newline at end of file
diff --git a/docs/assets/stylesheets/extra.css b/docs/assets/stylesheets/extra.css
deleted file mode 100644
index f3eb1b3df8..0000000000
--- a/docs/assets/stylesheets/extra.css
+++ /dev/null
@@ -1,1493 +0,0 @@
-@media screen and (min-width: 76.1875em) {
- .md-header {
- backdrop-filter: blur(5px);
- background-color: rgba(255, 255, 255, 0.6);
- }
-
- [dir=ltr] .md-header__source {
- margin-left: 0;
- width: 10rem;
- }
-
- .md-source__facts {
- font-size: 0.6rem;
- }
-
- .md-source__fact:before {
- height: 0.75rem;
- }
-
- .md-source {
- font-size: 0.75rem;
- }
-}
-@media screen and (max-width: 76.1875em) {
- .md-header {
- background-color: rgb(255, 255, 255);
- }
-}
-
-.md-copyright {
- width: inherit;
-}
-
-.md-copyright__highlight {
- font-size: 0.75rem;
- margin-top: -8px;
-}
-
-.md-copyright__highlight a {
- font-weight: 700;
-}
-
-.md-footer {
- /*border-top: 1px solid #E4E4E7;*/
-}
-.md-typeset a.md-footer__link {
- margin: 0.5rem 0 0.4rem;
- border: 1px solid black;
- color: black;
- border-radius: 5px;
- flex: 1;
-}
-
-.md-footer__link:focus, .md-footer__link:hover {
- opacity: 1;
-}
-
-.md-typeset a.md-footer__link:hover .md-ellipsis {
- color: var(--md-typeset-a-color);
- opacity: 1;
-}
-
-.md-footer__link--prev .md-footer__title {
- display: block;
-}
-
-.md-footer__direction {
- opacity: 1;
- font-weight: 800;
-}
-
-.md-footer__title {
- margin-top: 0.2rem;
- margin-bottom: 0.5rem;
- padding: 0;
-}
-
-.md-header[data-md-state=shadow] {
- box-shadow: none;
-}
-.md-sidebar__scrollwrap {
- margin-top: -25px;
- overflow-y: hidden;
-
- -webkit-mask-image: linear-gradient(rgba(0,0,0,1) 85%, rgba(0,0,0,0));
- mask-image: linear-gradient(rgba(0,0,0,1) 85%, rgba(0,0,0,0));
-
- padding-bottom: 40px;
-}
-
-.md-sidebar__scrollwrap:hover {
- overflow-y: scroll;
-}
-
-*::-webkit-scrollbar-thumb {
- background: linear-gradient(0deg, white 0%, white 4%, #e5e5e9 5%, #e5e5e9 93%, white 94%, white 100%);
- border-radius: 2px;
- padding-top: 200px;
-}
-
-.md-sidebar__scrollwrap::-webkit-scrollbar-thumb:hover {
- background-color: var(--md-default-fg-color--lighter)
-}
-
-.md-typeset :is(.admonition,details):is(.info,.tip,.warning,.c) {
- background-color: rgba(0,0,0,0.005);
- border-color: rgba(0,0,0,0.6);
-}
-
-.md-typeset :is(.info,.tip,.warning)>:is(.admonition-title) {
- color: var(--md-default-fg-color);
-}
-
-.md-typeset :is(.info,.tip,.warning)>:is(.admonition-title,summary):before,
-.md-typeset :is(.info,.tip,.warning)>:is(.admonition-title,summary):after {
- background-color: var(--md-default-fg-color);
-}
-
-[dir=ltr] .md-typeset :is(.admonition,details) {
- border-style: solid;
- /*border-width: 1px;*/
- border-width: 0;
- border-radius: 6px;
- box-shadow: none;
- padding: .6rem .8rem;
- background: -webkit-linear-gradient(45deg, rgba(0, 42, 255, 0.1), rgb(0 114 255 / 1%), rgba(0, 42, 255, 0.05));
-}
-
-.md-typeset iframe {
- border-radius: 6px;
-}
-
-[dir=ltr] .md-typeset :is(.admonition,details) blockquote {
- margin-left: 32px;
-}
-
-[dir=ltr] .md-typeset :is(.admonition,details):not(blockquote) > :is(.highlight,.termy,.md-typeset__table,p,h4,h3,.tabbed-set):not(.admonition-title) {
- padding-left: 32px;
-}
-
-.admonition-title, details > summary {
- border: none !important;
- background-color: transparent !important;
-}
-
-.md-typeset .admonition, .md-typeset details {
- font-size: 1em;
-}
-
-[dir=ltr] .md-typeset :is(.admonition-title,summary) {
- font-size: 18px !important;
- letter-spacing: -0.5px;
- /*font-weight: 800;*/
- font-weight: 700;
- /*padding-left: 18px;*/
- padding-bottom: 0;
- border: none;
- border-radius: 0;
-}
-
-.md-typeset .admonition.info:focus-within, .md-typeset details.info:focus-within {
- box-shadow: none;
-}
-
-.md-typeset :is(.info,.tip, .warning)>:is(.admonition-title) {
- margin-bottom: -12px;
-}
-
-.md-typeset :is(.info,.tip, .warning)>:is(summary) {
- margin-bottom: 12px;
- font-size: 1.1em !important;
-}
-
-.md-typeset :is(.info,.tip, .warning)>:is(.admonition-title,summary):before {
- /*display: none;*/
-}
-
-.md-header__title {
- margin-left: 1px !important;
- font-weight: 700;
- font-size: 20px;
- padding-top: 2px;
-}
-
-@media screen and (min-width: 76.1875em) {
- .md-header__topic:first-child {
- font-size: 30px;
- /*font-family: Poppins, metro-web, Metro, -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;*/
- /*font-weight: 500;*/
- }
-
- .md-header__title {
- flex-grow: unset;
- }
-
- .md-header__topic {
- position: relative;
- }
-
- .md-header__title--active .md-header__topic {
- opacity: 1;
- transition: inherit;
- transform: inherit;
- pointer-events: auto;
- }
-
- .md-header__title--active .md-header__topic+.md-header__topic {
- opacity: 0;
- }
-
- .md-header__topic+.md-header__topic {
- display: none;
- }
-}
-
-@media screen and (max-width: 76.1875em) {
- .md-nav--primary .md-nav__title .md-logo {
- padding: 0.1rem 0.4rem;
- }
- .md-nav__title .md-nav__button.md-logo :-webkit-any(img,svg) {
- max-width: 100px;
- }
- .md-nav--primary .md-nav__title {
- display: block;
- font-weight: 700;
- /*display: none;*/
- height: 10px;
- }
-
- .md-nav__source {
- background-color: transparent;
- }
-}
-
-.md-nav--secondary:not(:has(ul)) {
- display: none;
-}
-
-.md-nav--secondary {
- border: 1px solid black;
- padding: 20px 5px;
- margin-top: 20px;
- border-radius: 12px;
-}
-
-.md-nav--secondary .md-nav__title {
- background: transparent;
- box-shadow: none;
- padding: 2px 15px 3px;
- font-size: 17px;
- font-weight: 700;
- color: rgba(0, 0, 0, 0.87);
- position: relative;
-}
-
-@font-face {
- font-family: 'Poppins';
- font-style: normal;
- font-weight: 500;
- font-display: swap;
- src: url(https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLGT9Z11lFd2JQEl8qw.woff2) format('woff2');
- unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
-}
-/* latin-ext */
-@font-face {
- font-family: 'Poppins';
- font-style: normal;
- font-weight: 500;
- font-display: swap;
- src: url(https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLGT9Z1JlFd2JQEl8qw.woff2) format('woff2');
- unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
-}
-/* latin */
-@font-face {
- font-family: 'Poppins';
- font-style: normal;
- font-weight: 500;
- font-display: swap;
- src: url(https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLGT9Z1xlFd2JQEk.woff2) format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-/* devanagari */
-@font-face {
- font-family: 'Poppins';
- font-style: normal;
- font-weight: 600;
- font-display: swap;
- src: url(https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLEj6Z11lFd2JQEl8qw.woff2) format('woff2');
- unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
-}
-/* latin-ext */
-@font-face {
- font-family: 'Poppins';
- font-style: normal;
- font-weight: 600;
- font-display: swap;
- src: url(https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLEj6Z1JlFd2JQEl8qw.woff2) format('woff2');
- unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
-}
-/* latin */
-@font-face {
- font-family: 'Poppins';
- font-style: normal;
- font-weight: 600;
- font-display: swap;
- src: url(https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLEj6Z1xlFd2JQEk.woff2) format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-/* devanagari */
-@font-face {
- font-family: 'Poppins';
- font-style: normal;
- font-weight: 700;
- font-display: swap;
- src: url(https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLCz7Z11lFd2JQEl8qw.woff2) format('woff2');
- unicode-range: U+0900-097F, U+1CD0-1CF6, U+1CF8-1CF9, U+200C-200D, U+20A8, U+20B9, U+25CC, U+A830-A839, U+A8E0-A8FB;
-}
-/* latin-ext */
-@font-face {
- font-family: 'Poppins';
- font-style: normal;
- font-weight: 700;
- font-display: swap;
- src: url(https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLCz7Z1JlFd2JQEl8qw.woff2) format('woff2');
- unicode-range: U+0100-024F, U+0259, U+1E00-1EFF, U+2020, U+20A0-20AB, U+20AD-20CF, U+2113, U+2C60-2C7F, U+A720-A7FF;
-}
-/* latin */
-@font-face {
- font-family: 'Poppins';
- font-style: normal;
- font-weight: 700;
- font-display: swap;
- src: url(https://fonts.gstatic.com/s/poppins/v20/pxiByp8kv8JHgFVrLCz7Z1xlFd2JQEk.woff2) format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-
-/* latin */
-@font-face {
- font-family: 'Fira Mono';
- font-style: normal;
- font-weight: 400;
- src: local('Fira Mono Regular'), local('FiraMono-Regular'), url(https://fonts.gstatic.com/s/firamono/v6/N0bX2SlFPv1weGeLZDtgJv7Ss9XZYQ.woff2) format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-
-/* latin */
-@font-face {
- font-family: 'Fira Mono';
- font-style: normal;
- font-weight: 500;
- src: local('Fira Mono Medium'), local('FiraMono-Medium'), url(https://fonts.gstatic.com/s/firamono/v8/N0bS2SlFPv1weGeLZDto1d3HnvfUS5NBBA.woff2) format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-
-/* latin */
-@font-face {
- font-family: 'Fira Mono';
- font-style: normal;
- font-weight: 700;
- src: local('Fira Mono Bold'), local('FiraMono-Bold'), url(https://fonts.gstatic.com/s/firamono/v6/N0bS2SlFPv1weGeLZDtondvHnvfUS5NBBA.woff2) format('woff2');
- unicode-range: U+0000-00FF, U+0131, U+0152-0153, U+02BB-02BC, U+02C6, U+02DA, U+02DC, U+2000-206F, U+2074, U+20AC, U+2122, U+2191, U+2193, U+2212, U+2215, U+FEFF, U+FFFD;
-}
-
-/*label.md-nav__link {*/
-/* font-weight: 500;*/
-/*}*/
-
-.md-nav__link {
- margin-top: .6em;
-}
-
-.md-nav__link:hover {
- color: var(--md-default-fg-color);
-}
-
-.md-nav__item, .md-nav__link .md-typeset {
- /*color: rgba(0,0,0,0.87);*/
- font-weight: 500;
- font-size: 0.75rem;
-}
-
-.md-nav__item .md-nav__link:hover:not(.md-nav__link--active) {
- color: black;
-}
-
-.md-typeset pre > code, .md-typeset code {
- /*-webkit-font-smoothing: auto;*/
-}
-
-.md-sidebar.md-sidebar--secondary .md-typeset code {
- color: rgba(0,0,0,0.87);
-}
-
-.md-typeset :not(pre) :is(h1, h2, h3, h4) > code {
- color: inherit;
- background: inherit;
- padding: 0;
-}
-
-h4.doc-heading {
- font-size: inherit;
-}
-
-.md-typeset :not(pre, h1, h2, h3, h4) > code {
- background-color: rgba(163, 68, 215, 0.05);
- /*border: 1px solid #dce0e6;*/
- border-radius: 2px;
- font-weight: 600;
- color: var(--md-primary-fg-color);
- text-align: center;
- padding: 4px;
- height: 16px;
- margin: 0 4px;
-}
-
-.md-typeset :is(h1, h2, h3, h4) > code {
- background-color: inherit;
- color: inherit;
- /*padding: 0;
- margin: 0;*/
-}
-.md-typeset :is(h1, h2, h3, h4) > a > code {
- font-size: inherit;
- color: inherit;
-}
-
-
-.md-typeset :is(table) :not(pre, h1, h2, h3, h4) > code {
- font-size: .85em;
-}
-
-.md-typeset :not(pre, h1, h2, h3, h4) > code {
- font-size: 0.65rem;
-}
-
-.md-typeset :not(pre, h1, h2, h3, h4) > a code {
- color: #ce00ff;
-}
-
-.md-typeset pre > code {
- background-color: rgb(21, 22, 29);
- padding: 45px 30px 35px 40px;
- border-radius: 4px;
- font-size: 15px;
-
- /*border-radius: 6px;*/
- /*border-top: 1px solid #dce0e6;*/
- /*background-color: rgba(0,0,0,.87);*/
- /*padding: 15px 20px;*/
- /*font-size: .85em;*/
-}
-
-.md-typeset div[editor-title] pre > code:before {
- content: '';
- position: absolute;
- top: 15px;
- left: 15px;
- display: inline-block;
- width: 12px;
- height: 12px;
- border-radius: 50%;
- /* A little hack to display the window buttons in one pseudo element. */
- background: #d9515d;
- /*-webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;*/
- /* box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;*/
- -webkit-box-shadow: 20px 0 0 #f4c025, 40px 0 0 #3ec930;
- box-shadow: 20px 0 0 #f4c025, 40px 0 0 #3ec930;
-}
-
-.md-typeset div[editor-title] pre > code {
- padding: 65px 25px 35px 45px;
-}
-
-@media screen and (min-width: 60em) {
- [data-md-color-primary=white] .md-search__form {
- background-color: transparent;
- border-radius: 18px;
- border: 1px solid rgba(0,0,0,0.87);
- }
-
- [data-md-color-primary=white] .md-search__form:hover {
- background-color: transparent;
- border: 1px solid black;
- }
-}
-
-.md-search__input {
- font-size: .7rem;
-}
-
-.md-code__button:after {
- width: 1em;
- height: 1em;
-}
-
-.md-code__nav {
- top: 1em;
- right: .25em;
- background: none;
-}
-
-.md-code__nav .md-code__button {
- color: #a2a2a2;
-}
-
-.md-code__nav:hover .md-code__button {
- color: #eee;
-}
-
-pre:hover .md-code__nav,
-code .md-code__nav:hover {
- background: transparent;
-}
-
-code .md-code__nav:hover .md-code__button {
- color: var(--md-accent-fg-color);
-}
-
-.md-clipboard {
- top: 0.65em;
-}
-
-.md-clipboard:after {
- color: var(--md-default-fg-color--lighter);
-}
-
-.md-clipboard:hover:after {
- color: var(--md-default-fg-color--light)
-}
-
-.md-annotation:not([hidden]) {
- line-height: 1.225;
-}
-
-.md-annotation__index {
- margin-left: 0;
- margin-right: 0;
-}
-
-.md-annotation__index:after {
- background-color: rgba(0, 0, 0, 0.87);
- transform: scale(0.9);
-}
-
-@media screen and (max-width: 44.9375em) {
- .md-typeset pre > code {
- border: none;
- }
-}
-
-.footer__inner {
- background-color: var(--md-footer-bg-color--dark);
- margin-top: 0.7rem;
-}
-
-.md-footer__inner:not([hidden]) {
- gap: 20px !important;
-}
-
-.md-footer__link .md-footer__link--next {
- font-weight: 500;
-}
-
-.md-typeset .admonition.note {
- border-color: var(--md-primary-fg-color);
-}
-
-.md-typeset {
- line-height: 1.3rem;
- font-size: 0.8rem;
-}
-
-.md-typeset h1 {
- margin: 0 0 0.75em;
- font-size: 33px;
-}
-
-.md-typeset h2 {
- margin: 1.4em 0 0.64em;
- padding-top: 0.2em;
- font-size: 25px;
-}
-
-.md-typeset h1, .md-typeset h2 {
- font-weight: 400;
- /*letter-spacing: 0;*/
-}
-
-.md-typeset h1, .md-typeset h2, .md-typeset h3, .md-typeset h4, .md-typeset h5 {
- font-weight: 800;
- letter-spacing: -1px;
- color: rgb(0, 0, 0);
- text-transform: none;
-}
-
-.md-typeset h4 {
- font-size: 20px;
-}
-
-.md-typeset h5 {
- font-size: 16px;
-}
-
-.md-typeset h3 {
- font-size: 23px;
- margin-block-end: 0;
- padding-bottom: 0.7em;
- border-bottom: 1px solid rgba(243, 244, 246, 1);
-}
-
-[data-md-color-scheme=slate][data-md-color-primary=black], [data-md-color-primary=white] {
- --md-primary-fg-color: #0048ff;
- --md-accent-fg-color: #ce00ff;
- --md-typeset-a-color: #ce00ff;
- --md-code-hl-function-color: #e3b4fb;
- --md-code-hl-keyword-color: #e37cff;
- --md-code-hl-string-color: #b4f9c6;
- --md-code-fg-color: #eee;
- /*--md-code-fg-color: rgba(0, 0, 0, 0.95);*/
- --md-mermaid-label-fg-color: rgba(0, 0, 0, 0.95);
- --md-mermaid-edge-color: rgba(0, 0, 0, 0.95);
- --md-code-hl-comment-color: #757585;
- --md-code-hl-number-color: #d9548c;
- --md-code-hl-operator-color: #5b6369;
- --md-code-hl-punctuation-color: #5b6369;
- --md-code-bg-color: #f7f7fb;
- --md-code-hl-constant-color: var(--md-code-fg-color);
- /*--md-primary-bg-color: white;*/
- --md-default-fg-color--light: rgba(0,0,0,.6);
- --md-default-fg-color--lighter: rgb(159, 172, 190);
- --md-default-fg-color--lightest: #f6f9fc;
- --md-footer-fg-color--light: var(--md-default-fg-color);
- --md-code-hl-color--light: rgba(197, 173, 255, 0.12);
-}
-
-#__mermaid_0 .note {
- stroke: var(--md-primary-fg-color) !important;
-}
-
-.md-typeset .highlight :where(.l) {
- /*color: #eee !important;*/
- /*color: var(--md-code-fg-color) !important;*/
-}
-
-.highlight .sd {
- color: var(--md-code-hl-string-color);
-}
-
-.highlight .na, .highlight .nv, .highlight .vc, .highlight .vg, .highlight .vi {
- color: #c6c052;
-}
-
-.md-typeset .highlight .hll {
- box-shadow: none;
- /*box-shadow: 3px 0px 0px 0.1px var(--md-primary-fg-color) inset;*/
- margin: 0 -1.8em;
- padding: 0 1.8em;
-}
-
-body {
- --md-text-font-family: metro-web, Metro, -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif;
- --md-code-font-family: Fira Mono, ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, Liberation Mono, Courier New, monospace;
-}
-
-.md-content {
- /*border-left: 1px solid #E4E4E7;*/
-}
-
-.md-header__button.md-logo :where(img,svg) {
- height: 1.6rem !important;
-}
-
-.md-header__button.md-logo {
- margin: 0 0 0 0.5rem;
- padding: 0;
-}
-
-.md-header__button.md-logo:hover {
- opacity: 1;
-}
-
-.md-sidebar__inner {
- margin: 0 0;
-}
-
-@media screen and (min-width: 76.1875em) {
- .md-sidebar--primary .md-nav__link,
- .md-sidebar--primary .md-nav__item--section.md-nav__item .md-nav__link[for=__toc] {
- display: none;
- }
-
- .md-sidebar--primary .md-nav__item--section.md-nav__item .md-nav__link {
- display: flex;
- }
-
- .md-sidebar__inner > .md-nav--primary > .md-nav__list:not(.md-post__meta) > .md-nav__item > .md-nav > .md-nav__list > .md-nav__item:not(.md-nav__item--section) {
- display: none;
- }
-
- .md-nav__item--section > .md-nav__link {
- text-transform: uppercase;
- display: inline-block;
- font-size: 0.75rem;
- font-weight: 800;
- line-height: 1.4rem;
- letter-spacing: -0.5px;
- }
-
- .md-nav__item--section>.md-nav__link[for] {
- color: rgba(0,0,0,0.87);
- }
-
- .md-search__form > * {
- z-index: 101;
- }
-
- .md-search__form::before {
- content: "⌘";
- color: white;
- font-weight: 600;
- position: absolute;
- padding: 5px;
- margin: 4.5px;
- font-size: .65rem;
- background-color: rgba(0,0,0,.87);
- border-radius: 5px;
- right: 40px;
- z-index: 1;
- width: 26px;
- text-align: center;
- }
-
- .md-search__form::after {
- content: "K";
- color: white;
- font-weight: 600;
- position: absolute;
- padding: 5px;
- margin: 4.5px;
- font-size: .65rem;
- background-color: rgba(0,0,0,.87);
- border-radius: 5px;
- right: 10px;
- top: 0;
- /*z-index: 1;*/
- width: 26px;
- text-align: center;
- }
-
- .md-nav--lifted > .md-nav__list > .md-nav__item > [for] {
- display: none;
- }
-}
-
-.md-sidebar--primary .md-nav__link {
- padding: 3px 15px 4px;
- margin-top: 5px;
-}
-
-.md-sidebar--secondary .md-nav__link {
- padding-left: 15px;
- margin-left: -8px;
- border-left: 2px solid transparent;
- padding-top: 1px;
- padding-bottom: 1px;
-}
-
-.md-sidebar--secondary .md-nav__item {
- padding-left: 0.6rem;
-}
-
-.md-sidebar--secondary .md-nav__item .md-nav__link--passed {
- color: inherit;
-}
-
-.md-sidebar--secondary .md-nav__item .md-nav__link--active .md-typeset {
- font-weight: 700;
-}
-
-.md-sidebar--secondary .md-nav__item .md-nav__link--active {
- border-left: 2px solid var(--md-typeset-a-color);
- color: inherit;
-}
-
-.md-nav__item .md-nav__link--active, .md-nav__item .md-nav__link--active:hover {
- font-weight: 700;
- color: inherit;
-}
-
-.md-path__link {
- color: var(--md-default-fg-color);
- font-size: 0.7rem;
-}
-
-@media screen and (min-width: 76.1875em) {
- .md-nav__item--section>.md-nav>.md-nav__list>li.md-nav__item:not(.md-nav__item--nested):not(.md-nav__item--active) {
- padding-left: 0.4rem;
- /*margin-left: -4px;*/
- /*color: inherit;*/
- }
- .md-sidebar--primary a.md-nav__link--active {
- overflow: inherit;
- }
- .md-nav__item--section>.md-nav>.md-nav__list>.md-nav__item {
- padding-left: 0.4rem;
- }
- /*MKDocs Insiders fix*/
- /*.md-sidebar--primary a.md-nav__link--active::before {*/
- /* content: "•";*/
- /* min-width: 1.1rem;*/
- /* font-size: 2rem;*/
- /* height: 0;*/
- /* display: flex;*/
- /* background-color: #000000;*/
- /* !*Add absolute positioning*!*/
- /* position: relative;*/
- /* top: -1.48rem;*/
- /* margin-left: -24px;*/
- /*}*/
- .md-sidebar--primary .md-nav__link--active {
- font-weight: 700;
- justify-content: start;
- }
-}
-
-.md-footer {
- background-color: var(--md-default-bg-color);
- color: inherit;
- font-weight: 500;
-}
-
-.md-footer-meta {
- background-color: var(--md-default-bg-color);
-}
-
-.md-typeset a {
- letter-spacing: -0.5px;
-}
-
-html .md-footer-meta.md-typeset a:is(:focus,:hover) {
- color: var(--md-primary-fg-color) !important;
-}
-
-@media screen and (max-width: 76.1875em) {
- .md-sidebar--primary .md-nav__link {
- padding: inherit;
- margin: 5px 5px;
- }
-
- .md-sidebar--primary .md-nav__item .md-nav__link--active {
- color: inherit;
- background-color: inherit;
- border-radius: inherit;
- }
-
- .md-nav--primary .md-nav__title[for=__drawer] {
- background-color: inherit;
- }
-}
-
-@media screen and (min-width: 76.25em) {
- .md-nav--integrated>.md-nav__list>.md-nav__item--active .md-nav--secondary {
- margin-bottom: 0;
- }
-}
-
-.md-typeset :where(ol, ul) {
- list-style: none !important;
-}
-
-[dir=ltr] .md-typeset ol li, [dir=ltr] .md-typeset ul li {
- margin-left: 0;
- padding-left: 1.25rem;
- position: relative;
-}
-
-.md-typeset :where(ul) > li:before {
- background-color: rgba(0,0,0,87);
- border-radius: 50%;
- content: "";
- height: 0.48em;
- width: 0.48em;
- left: 0.25em;
- position: absolute;
- top: 0.6875em;
-}
-
-.md-typeset :where(ol) > li:before {
- /*color: #6b7280;*/
- content: counter(list-item,var(--list-counter-style,decimal)) ".";
- font-weight: 400;
- left: 0;
- position: absolute;
-}
-
-.md-typeset :where(ol) {
- margin-left: 0;
-}
-
-.md-typeset :where(ul,ol) li :where(ul,ol) {
- margin-top: 1.25em;
- margin-bottom: 1.25em;
-}
-
-@media screen and (min-width: 76.25em) {
- [dir=ltr] .md-sidebar--primary:not([hidden]) ~ .md-content > .md-content__inner {
- margin-left: 1.2rem;
- }
-
- .md-content__inner:before {
- display: none;
- }
-}
-
-.md-typeset .md-content__button {
- color: var(--md-default-fg-color--light);
-}
-
-/*.md-typeset p > img {*/
-/* border: 1px solid #E4E4E7;*/
-/*}*/
-
-.md-typeset figure p img {
- border: none;
- display: inline-block;
-}
-
-.md-typeset .grid.fit {
- grid-template-columns: repeat(auto-fit,minmax(15rem,1fr));
-}
-
-.md-typeset .tabbed-labels>label {
- padding: 18px 18px 16px !important;
- font-weight: 800 !important;
- font-size: 16.5px !important;
- line-height: 1.2 !important;
- -webkit-font-smoothing: auto !important;
- z-index: 1000 !important;
- color: rgba(0,0,0,.63)
-}
-
-.md-typeset .tabbed-labels--linked>label>a {
- /*MKDocs Insiders fix*/
- padding: initial;
-}
-
-.md-typeset .tabbed-labels--linked>label>a code {
- /*MKDocs Insiders fix*/
- /*background: initial;*/
- font-weight: 600;
- color: var(--md-primary-fg-color);
-}
-
-.md-typeset .highlight :is(.nd,.ni,.nl,.nt),
-.md-typeset .highlight :is(.k,.kd,.kn,.kp,.kr,.kt),
-.md-typeset .highlight :is(.nc,.ne,.nf,.nn) {
- font-weight: 100;
-}
-
-.md-typeset .tabbed-labels>label > code {
- background-color: transparent;
- letter-spacing: -0.25px;
-}
-
-.md-typeset .tabbed-set {
- border-radius: 0;
-}
-
-.md-typeset .tabbed-block>.highlight:first-child>pre>code, .md-typeset .tabbed-block>pre:first-child>code,
-.md-typeset .tabbed-block>.termy {
- margin-top: 17px;
-}
-
-@media screen and (min-width: 76.1875em) {
- .md-typeset .tabbed-block > .highlight:first-child > pre > code, .md-typeset .tabbed-block > pre:first-child > code {
- border-radius: 6px;
- }
-}
-
-.md-typeset .tabbed-set>input:checked~.tabbed-labels code,
-.md-typeset .tabbed-set>input:first-child:checked~.tabbed-labels>:first-child {
- /*MKDocs Insiders fix*/
- /*font-weight: 500;*/
- /*color: var(--md-code-fg-color);*/
-}
-
-.js .md-typeset .tabbed-labels:before {
- height: 100%;
- background: none;
- z-index: 1;
- padding: 5px;
- border-radius: 6px;
- border: 1px solid black;
-}
-
-.md-typeset .tabbed-labels {
- box-shadow: none !important;
-}
-
-.md-typeset .grid {
- grid-gap: 1.2rem;
- display: grid;
- grid-template-columns: repeat(auto-fill,minmax(15rem,1fr));
- margin: 1.6em 0;
-}
-
-.md-typeset .grid.cards>:-webkit-any(ul,ol) {
- display: contents;
-}
-
-.md-typeset .grid.cards>:-webkit-any(ul,ol)>li strong, .md-typeset .grid>.card strong {
- display: block;
- color: var(--md-default-fg-color);
- margin-bottom: 6px;
- font-weight: 800;
-}
-
-.md-typeset .grid.cards>:-webkit-any(ul,ol)>li a:hover strong,
-.md-typeset .grid>.card a:hover strong {
- color: var(--md-typeset-a-color);
-}
-
-.md-typeset .grid.cards > :-webkit-any(ul,ol) > li a,
-.md-typeset .grid.cards > :-webkit-any(ul,ol) > li span,
-.md-typeset .grid > .card a {
- color: var(--md-default-fg-color);
- text-decoration: none;
- display: block;
- margin: 0;
- padding: 1rem 1.4rem;
- border-radius: 6px;
- border: rgba(0,0,0,0.6) 0.5px solid;
-}
-
-.md-typeset .grid.cards>ol>li:focus-within,.md-typeset .grid.cards>ol>li:hover,.md-typeset .grid.cards>ul>li:focus-within,.md-typeset .grid.cards>ul>li:hover,.md-typeset .grid>.card:focus-within,.md-typeset .grid>.card:hover {
- box-shadow: none;
-}
-
-.md-typeset .grid.cards>:-webkit-any(ul,ol)>li, .md-typeset .grid>.card {
- font-size: 95%;
- line-height: 1.6;
- padding: 0;
-}
-
-.md-typeset .grid.cards>:-webkit-any(ul,ol)>li:before {
- display: none;
-}
-
-.md-header--shadow {
- box-shadow: none;
-}
-
-.md-tabs {
- background-color: transparent;
- flex-grow: 1;
- width: initial;
-}
-
-@media screen and (max-width: 76.25em) {
- .md-tabs {
- display: none;
- }
-}
-@media screen and (min-width: 76.1875em) {
- .md-tabs {
- padding-left: 2.5rem;
- display: none;
- }
-
- .ready .md-tabs {
- display: block;
- }
-
- [data-md-color-primary=white] .md-tabs {
- border-bottom: none;
- }
-
- .md-tabs[hidden] .md-tabs__link {
- opacity: inherit;
- transform: inherit;
- transition: inherit;
- }
-
- .md-tabs[hidden] {
- pointer-events: inherit;
- }
-
- /*.md-nav__title {
- display: none;
- }*/
-
- [dir=ltr] .md-tabs__list {
- display: flex;
- }
-
- .md-tabs__item {
- display: flex;
- height: 2.9rem;
- padding-left: 0;
- padding-right: 20px;
- }
-
- .md-tabs__item:nth-child(1) {
- display: none;
- }
-
- .md-tabs__item:nth-child(6) {
- margin-left: auto;
- }
-
- .md-tabs__item:nth-child(7) {
- padding-right: 1.2rem;
- }
-
- .md-tabs__item:nth-child(n+6):nth-child(-n+7) .md-tabs__link {
- visibility: hidden;
- width: 35px;
- display: inline-block;
- margin-top: 18px;
- }
-
- .md-tabs__item:nth-child(n+6) .md-tabs__link:before {
- width: 38px;
- height: 38px;
- margin-top: 4px;
- visibility: visible;
- }
-
- .md-tabs__item:nth-child(4) .md-tabs__link:after, .md-tabs__item:nth-child(8) .md-tabs__link:after {
- content: url('data:image/svg+xml, ');
- line-height: 14px;
- margin-left: 4px;
- position: relative;
- top: 0;
- margin-right: -7px;
- }
-
- .twemoji.external {
- position: relative;
- top: 2.5px;
- height: 18.5px;
- margin-left: -3px;
- }
-
- .tx-footer__section-link.external:after {
- content: url('data:image/svg+xml, ');
- line-height: 14px;
- margin-left: 5px;
- position: relative;
- top: 1.5px;
- margin-right: -7px;
- }
-
- .md-tabs__item:nth-child(6) .md-tabs__link:before {
- position: relative;
- content: '';
- width: 43px;
- height: 37px;
- display: inline-block;
- -webkit-mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- -webkit-mask-size: cover;
- mask-size: cover;
- background: -webkit-linear-gradient(45deg, #0048ff, #ce00ff);
- margin-top: 0;
- }
-
- .md-tabs__item:nth-child(7) .md-tabs__link:before {
- position: relative;
- content: '';
- width: 43px;
- height: 37px;
- display: inline-block;
- -webkit-mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- -webkit-mask-size: cover;
- mask-size: cover;
- background: -webkit-linear-gradient(45deg, black, black);
- margin-top: 0;
- }
-
- .md-tabs__link {
- display: flex;
- align-items: center;
- }
-
- .md-tabs__link {
- font-size: 0.95rem;
- font-weight: 600;
- color: black;
- letter-spacing: -0.5px;
- margin-top: 7px;
- line-height: 24px;
- }
-
- .md-tabs__link.md-tabs__link--active {
- color: var(--md-accent-fg-color);
- }
-
- .md-nav[aria-label="Community"] .md-nav__item:nth-child(1) {
- display: flex;
- }
-}
-
-.md-source__repository--active {
- font-weight: 700;
-}
-
-.md-source__icon {
- height: 2.6rem;
-}
-
-.md-source {
- font-size: 0.7rem;
-}
-
-.md-source:hover {
- opacity: 1;
-}
-
-[dir=ltr] .md-source__icon+.md-source__repository {
- margin-left: -2.6rem !important;
-}
-
-.md-source__icon.md-icon svg {
- height: 1.38rem;
- width: 1.38rem;
- fill: none;
- margin-left: -0.1rem;
- margin-top: 0.61rem;
-}
-
-.md-source__facts {
- color: black;
-}
-
-.md-social__link svg {
- max-height: 1.2rem;
-}
-
-@media screen and (min-width: 76.25em) {
- .md-search .md-search__inner {
- padding-top: 0.58rem;
- margin-right: 0.8rem;
- }
-
- [data-md-toggle=search]:checked ~ .md-header .md-search__inner, .md-search__scrollwrap {
- width: 30rem;
- }
-
- [data-md-toggle=search]:checked~.md-header .md-search__form .md-search__input+.md-search__icon {
- color: black;
- }
-
- [data-md-toggle=search]:checked~.md-header .md-search__form {
- border-radius: 5px 5px 0 0;
- border: none;
- border-bottom: 0.5px solid black;
- }
-
- .md-search__scrollwrap {
- border-radius: 0 0 5px 5px;
- }
-
- [dir=ltr] .md-search__options {
- right: 3.8rem;
- }
-
- .md-search__options .md-icon svg {
- width: 1rem;
- height: 1rem;
- }
-
- .md-search__options > * {
- color: var(--md-default-fg-color--light);
- }
-}
-
-.md-search-result mark {
- font-weight: 600;
-}
-
-.md-search__input::placeholder {
- color: inherit;
-}
-
-.md-top {
- font-weight: 500;
- box-shadow: 0 0 0.2rem rgb(0 0 0 / 5%), 0 0.2rem 0.9rem rgb(0 0 0 / 10%);
- color: var(--md-default-fg-color);
- border-radius: 20px;
-}
-
-.md-top:hover {
- background-color: white;
- color: var(--md-default-fg-color);
-}
-
-@media screen and (max-width: 44.9375em) {
- .md-typeset .tabbed-set {
- margin: 0 -.8rem
- }
-
- [dir=ltr] .md-content__inner>.tabbed-set .tabbed-labels {
- margin-left: 0.8rem;
- padding-left: 0;
- }
-}
-
-.md-banner {
- background: black;
- color: var(--md-default-bg-color);
- margin-bottom: 1px;
- font-weight: 500;
-}
-
-.md-typeset.md-banner__inner {
- margin: 0.3rem auto;
- text-align: center;
- font-size: 0.77rem;
-}
-
-.md-typeset.md-banner__inner a {
- color: var(--md-default-bg-color);
- border-bottom: 2px dotted;
- font-weight: 700;
-}
-
-.md-typeset.md-banner__inner .md-banner__button {
- color: var(--md-default-fg-color--lighter);
-}
-
-.md-typeset.md-banner__inner .md-banner__button:hover {
- color: var(--md-accent-fg-color);
-}
-
-.md-typeset .footnote-backref {
- vertical-align: inherit;
-}
-
-.md-go-to-action.secondary.discord:before {
- position: relative;
- top: 5px;
- content: url('data:image/svg+xml, ');
- padding-right: 10px;
-}
-
-.md-go-to-action.primary.discord:before {
- position: relative;
- top: 5px;
- content: url('data:image/svg+xml, ');
- padding-right: 10px;
-}
-
-.md-go-to-action.github:before {
- position: relative;
- top: 5px;
- content: url('data:image/svg+xml, ');
- padding-right: 10px;
-}
-
-[data-md-color-primary=white] .md-button {
- border: 1.5px solid rgba(0,0,0,0.87);
- line-height: 35px;
- color: rgba(0,0,0,0.87);
- margin-right: 5px;
- background: transparent;
- font-weight: 500 !important;
- padding: 0.4em 1.5em;
- font-size: 17px;
- border-radius: 4px;
-}
-
-/*[data-md-color-primary=white] .md-button:hover{
- background: transparent;
- border: 1.5px solid rgba(0,0,0,1);
- color: black !important;
-}*/
-
-.md-post .md-nav__title {
- font-weight: 500;
-}
-
-[data-md-color-primary=white] .md-button--primary {
- color: white;
- background: rgba(0,0,0,0.87);
-}
-
-[data-md-color-primary=white] .md-button--github:before {
- position: relative;
- top: 5px;
- content: url('data:image/svg+xml, ');
- padding-right: 10px;
-}
-
-/*[data-md-color-primary=white] .md-button:hover {
- background: inherit;
- color: inherit;
- border-color: inherit;
-}*/
-
-/*
-[data-md-color-primary=white] .md-button--primary:hover {
- background: rgba(0,0,0,1);
- color: white !important;
-}
-*/
-
-[dir=ltr] .md-typeset blockquote {
- /*border: 1px solid black;*/
- border: none;
- color: var(--md-default-fg-color);
- padding: 8px 25px;
- border-radius: 6px;
- background: -webkit-linear-gradient(45deg, rgba(0, 42, 255, 0.1), rgb(0 114 255 / 1%), rgba(0, 42, 255, 0.05));
-}
-
-a.md-go-to-action.secondary {
- color: rgba(0,0,0,0.87);
- background: white;
-}
-
-.md-post__content h2 a {
- color: rgba(0,0,0,0.87);
-}
-
-div[editor-title] code .editor-title {
- position: absolute;
- color: #a2a2a2;
- top: 10px;
- left: 0;
- width: 100%;
- text-align: center;
-}
-
-.md-status:after, .md-status:hover:after{
- background: rgba(0,0,0,0.7);
-}
-
-.md-ellipsis, .md-ellipsis .md-typeset {
- white-space: normal;
- font-size: 98%;
-}
-
-.md-header__topic .md-ellipsis {
- white-space: nowrap;
-}
-
-/*.md-blog-sidebar .md-nav__link--active {
- display: none;
-}*/
-
-[data-ty].no-newline, .no-newline {
- display: inline-block;
-}
-
-[data-ty].newline, .newline {
- display: block;
-}
-
-img.border {
- border: 0.25px rgba(0,0,0,0.2) solid;
- border-radius: 7px;
-}
-
-.md-typeset .reference-item:hover > .headerlink {
- display: none;
-}
-
-.md-typeset .reference-item {
- display: list-item;
- margin-left: .625em;
- font-weight: inherit;
- color: inherit;
- font-size: inherit;
- letter-spacing: inherit;
-}
-
-.md-typeset .reference-item a code {
- color: var(--md-typeset-a-color);
- font-size: .85em;
-}
-
-.md-typeset .reference-item code {
- background-color: rgba(163, 68, 215, 0.05);
- border-radius: 2px;
- font-weight: 600;
- color: var(--md-primary-fg-color);
- text-align: center;
- padding: 4px;
- height: 16px;
- margin: 0 4px;
-}
\ No newline at end of file
diff --git a/docs/assets/stylesheets/landing.css b/docs/assets/stylesheets/landing.css
deleted file mode 100644
index ba8b6f4ce7..0000000000
--- a/docs/assets/stylesheets/landing.css
+++ /dev/null
@@ -1,910 +0,0 @@
-.tx-landing {
- margin: 0 .8rem;
- color: var(--md-primary-bg-color)
-}
-
-.tx-landing__hero_text {
- display: flex;
- flex-direction: column;
- align-items: center;
- text-align: center;
-}
-
-.tx-landing__hero_text h1 {
- margin-bottom: .75rem;
- font-weight: 800;
- font-size: 2.5em;
- letter-spacing: -3px;
-}
-
-.tx-landing__hero_text h1 strong {
- font-weight: 800;
-}
-
-/*.tx-landing__hero_text h1*/ .gradient {
- background: linear-gradient(90deg, #4631C8 -1.29%, #CD4AE2 88.05%, #FFD43C 111.26%);
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- padding-right: 4px;
- margin-right: -4px;
-}
-
-/*.tx-landing__hero_text p {
- font-size: 0.95rem;
-}*/
-
-.tx-landing__hero_buttons {
- display: flex;
- align-items: flex-start;
- justify-content: center;
- gap: 24px;
-}
-
-.tx-container .tx-landing__hero_buttons .md-button {
- margin-bottom: 0.2rem;
- margin-right: 0;
-}
-
-.tx-landing__hero_button_container {
- text-align: center;
-}
-
-.tx-landing__hero_button_placeholder {
- color: #202128;
- font-size: 0.67rem;
- line-height: 24px;
- text-align: center;
- padding: 18px 5px 13px;
-}
-
-@media screen and (max-width: 76.1875em) {
- .tx-landing h1 {
- font-size: 1.4rem;
- }
-
- .tx-landing__hero_text {
- max-width: 30rem;
- margin-left: auto;
- margin-right: auto;
- }
-
- .tx-landing__hero_image {
- margin-top: 1.5rem;
- max-width: 26rem;
- }
-
- .tx-landing__hero_code {
- margin-top: 2.5rem;
- max-width: 750px;
- margin-left: auto;
- margin-right: auto;
- }
-
- .tx-landing__hero_buttons {
- flex-direction: column;
- align-items: center;
- gap: 0;
- }
-}
-
-@media screen and (min-width: 76.1875em) {
- .tx-container {
- padding-bottom: 3vw;
- }
-
- .tx-landing__hero {
- margin-bottom: 2.5rem;
- font-size: 1.1em;
- line-height: 1.5;
- }
-
- .tx-landing__hero_text {
- margin-top: 5.1rem;
- }
-
- .tx-landing__hero_text h1 {
- font-size: 2.8rem;
- max-width: 36rem;
- line-height: 1.2;
- }
-
- .tx-landing__hero_text p {
- max-width: 30rem;
- }
-
- .tx-landing__hero_image {
- order: 1;
- width: 30rem;
- margin-top: 0.5rem;
- margin-left: 3rem;
- }
-
- .tx-landing__hero_code {
- /*width: 100vw;*/
- position: relative;
- left: 50%;
- transform: translateX(-50%);
- margin-top: 2.5rem;
- padding-top: 4.5rem;
- padding-bottom: 4.5rem;
- /*border-top-left-radius: 2.5rem;*/
- /*border-top-right-radius: 2.5rem;*/
- border-radius: 2.5rem;
- background-image: url("/https/github.com/assets/images/hero_code_background.png");
- background-size: cover;
- background-position: center;
- background-repeat: no-repeat;
- }
-
- .tx-landing__hero_code > [data-termynal] {
- max-width: 750px;
- margin-left: auto;
- margin-right: auto;
- }
-}
-
-.md-header__buttons .md-button.discord:before,
-.md-typeset .md-button.discord:before {
- position: relative;
- top: 5px;
- content: '';
- width: 26px;
- height: 26px;
- display: inline-block;
- -webkit-mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- -webkit-mask-size: cover;
- mask-size: cover;
- margin-right: 5px;
- background: -webkit-linear-gradient(45deg, rgba(0, 0, 0, 0.87), rgba(0, 0, 0, 0.87));
-}
-
-.md-header__buttons .md-button.github:before,
-.md-typeset .md-button.github:before {
- position: relative;
- top: 5px;
- content: '';
- width: 26px;
- height: 26px;
- display: inline-block;
- -webkit-mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- -webkit-mask-size: cover;
- mask-size: cover;
- margin-right: 5px;
- background: black;
-}
-
-.md-header__buttons {
- margin-left: auto;
-}
-
-.md-header__buttons .md-button,
-.md-typeset .md-button {
- margin-top: 1.2rem;
- margin-bottom: 1.5rem;
- font-size: 22px;
- font-weight: 400 !important;
- text-align: center;
- border-radius: 3px;
- border-color: transparent;
- margin-right: 5px;
-}
-
-.md-header__buttons .md-button {
- font-size: 0.95rem;
-}
-
-.md-typeset .md-button {
- min-width: 225px;
- padding: 0.55em 2em;
-}
-
-.md-typeset .md-button.small {
- min-width: 150px;
- padding: 0.5em 1.9em;
- font-size: 19px;
-}
-
-.md-typeset .md-button {
- vertical-align: middle;
-}
-
-.md-typeset .md-button-secondary:hover, .md-typeset .md-button--primary:hover {
- transform: translateY(-2px);
- transition: opacity .2s ease,transform .2s ease;
-}
-
-.md-typeset .md-button .icon {
- display: inline-block;
- position: relative;
- width: 15px;
- height: 15px;
- margin-left: 7px;
- transition: opacity .2s ease,transform .2s ease;
-}
-
-.md-typeset .md-button-secondary .icon, .md-typeset .md-button--primary .icon {
- color: #a91ffe;
-}
-.md-typeset .md-button-secondary:hover .icon, .md-typeset .md-button--primary:hover .icon {
- color: #a91ffe;
- transform: translateX(3px)
-}
-
-
-[data-md-color-primary=white] .md-header__buttons .md-button--primary, [data-md-color-primary=white].md-header__buttons .md-button--primary:hover,
-[data-md-color-primary=white] .md-typeset .md-button--primary, [data-md-color-primary=white] .md-typeset .md-button--primary:hover {
- background: rgba(0, 0, 0, 0.87);
- border: 1.5px solid rgba(0, 0, 0, 0.87);
- border-radius: 8px;
- font-weight: 400 !important;
-}
-
-.md-header__buttons .md-button--primary,
-.md-header__buttons .md-button-secondary {
- font-weight: 500 !important;
- white-space: nowrap;
- padding: 0.45rem 1rem;
-}
-
-.md-button-secondary.external:after {
- content: url('data:image/svg+xml, ');
- line-height: 14px;
- margin-left: 5px;
- position: relative;
- top: 3px;
- margin-right: -7px;
-}
-
-.md-button--primary.sky.external:after {
- content: url('data:image/svg+xml, ');
- line-height: 14px;
- margin-left: 5px;
- position: relative;
- top: 2px;
- margin-right: -7px;
-}
-
-.md-header__buttons .md-button-secondary,
-.md-typeset .md-button-secondary,
-.md-header__buttons .md-button-secondary:hover,
-.md-typeset .md-button-secondary:hover {
- background: transparent;
- color: black;
- border: 1.5px solid rgba(0, 0, 0, 0.87);
- border-radius: 8px;
-}
-
-.md-header__buttons {
- padding-top: 9px;
-}
-
-.md-header__buttons .md-button-secondary {
-
-}
-
-.tx-landing__highlights {
- margin-bottom: 5vw;
- font-size: 17px;
- line-height: 1.5;
-}
-
-.tx-landing__highlights_text h2 {
- font-size: 2.2em;
- max-width: 500px;
- margin-top: 1.5em;
- margin-bottom: 1.8em;
- letter-spacing: -1.5px;
- line-height: 1.3;
-}
-
-.tx-landing__highlights_cta {
- margin-top: 3vw;
-}
-
-.tx-landing__highlights_cta a {
- display: inline-block;
- font-size: 19px;
- margin-top: 30px;
- border: 1px solid;
- padding: 10px 30px;
-}
-
-.tx-landing__highlights_text h2 .gradient {
- background: -webkit-linear-gradient(45deg, #0048ff, #ce00ff);
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
-}
-
-.tx-landing__highlights_grid .feature-cell {
- padding: 30px 40px;
- border-radius: 12px;
- border-color: black;
- border-width: 1px;
- border-style: solid;
- display: flex;
- flex-direction: column;
-}
-
-@media screen and (min-width: 76.1875em) {
- .tx-landing__highlights_grid {
- grid-gap: 20px !important;
- border: none;
-
- grid-template-columns: repeat(4, 1fr) !important;
- }
-
- .tx-landing__highlights_grid .feature-cell {
- }
-}
-
-.tx-landing__highlights_grid .feature-cell:hover {
- background: -webkit-linear-gradient(45deg, rgba(0, 42, 255, 0.015), rgba(0, 42, 255, 0.015), rgba(225, 101, 254, 0.025));
-}
-
-.tx-landing__highlights_grid .feature-cell strong {
- font-weight: 500;
-}
-
-.tx-landing__highlights_grid .feature-cell .feature-tags {
- gap: 2px;
- margin: 0 -5px;
- margin-top: auto;
- display: none;
-}
-
-.tx-landing__highlights_grid .feature-cell .feature-tags .feature-tag {
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 8px 20px;
- font-size: 0.85em;
- font-weight: 400;
- line-height: 1.44;
- color: black;
- margin-top: 20px;
- margin-right: 5px;
- border-radius: 30px;
- border-width: 0.5px;
- border-style: solid;
- white-space: nowrap;
-}
-
-.tx-landing__highlights_grid > a, .tx-landing__highlights_grid > a:hover {
- text-decoration: none;
- color: inherit;
-}
-
-.tx-landing__integrations_text {
- color: #202128;
- font-size: 0.65rem;
- line-height: 24px;
- text-align: center;
- padding: 21px 5px 3px;
-}
-
-.tx-landing__integrations_logos {
- display: flex;
- align-items: center;
- justify-content: center;
- gap: 14px;
- padding: 8px 5px 3px;
-}
-
-.tx-landing__integrations .logo-xlarge {
- width: 41px;
- margin-top: 2px;
-}
-
-.tx-landing__integrations .logo-large {
- width: 30px;
-}
-
-.tx-landing__integrations .logo-medium {
- width: 26px;
-}
-
-.tx-landing__highlights_grid {
- grid-gap: 2rem;
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
- margin-top: 40px;
- margin-bottom: 30px;
-}
-
-.tx-landing__highlights_grid .feature-icon svg {
- padding: 12px;
- background: rgba(125, 4, 233, 0.02);
- color: #002aff;
- width: 50px;
- height: 50px;
- border-radius: 25px;
- text-align: center;
- display: inline-flex;
- vertical-align: text-top;
- fill: currentColor;
- margin-bottom: 15px;
-}
-
-.tx-landing__highlights_grid h3 {
- font-size: 1.125em;
- font-weight: 700;
- border-bottom: none;
- padding-bottom: 0.2em;
- margin-top: 0;
- line-height: 32px;
-}
-
-.tx-landing__highlights_grid h3:after {
- content: url('data:image/svg+xml, ');
- margin-left: 2px;
- position: relative;
- top: 3px;
- margin-right: -7px;
-}
-
-.tx-landing__highlights_grid p {
- font-size: 16px;
- margin-top: 5px;
- margin-bottom: 5px;
- color: rgba(0, 0, 0, 0.87);
-}
-
-.tx-landing__features {
- margin-bottom: 5vw;
-}
-
-.tx-landing__features_text h2 {
- font-size: 1.7em;
- max-width: 500px;
- color: rgba(0, 0, 0, 0.87);
- margin-bottom: 1.5em;
-}
-
-.tx-landing__features_grid {
- grid-gap: 1.2rem;
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
-}
-
-.tx-landing__bottom_cta {
- margin-top: 9vw;
- /*margin-bottom: 5vw;*/
- font-size: 18px;
- line-height: 1.5;
-}
-
-.tx-landing__major_feature {
- font-size: 1.025em;
- margin-top: 5em;
-}
-
-.tx-landing__bottom_cta_text {
- font-size: 0.95em;
- max-width: 500px;
-}
-
-.tx-landing__major_feature h3 {
- padding-bottom: 0;
- border-bottom: none;
- background: -webkit-linear-gradient(45deg, #0048ff, #ce00ff);
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- font-size: 1.5em;
-}
-
-.tx-landing__major_feature img.border {
- border: 0.25px rgba(0,0,0,0.2) solid;
- border-radius: 7px;
-}
-
-.tx-landing__major_feature h2 {
- font-size: 1.8em;
- max-width: 500px;
- margin-top: 0.75em;
- margin-bottom: 0.75em;
- background: black;
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- letter-spacing: -1.5px;
-}
-
-.tx-landing__major_feature {
- margin-bottom: 7vw;
-}
-
-@media screen and (min-width: 76.1875em) {
- .tx-landing__major_feature .section {
- display: flex;
- }
-}
-
-.tx-landing__major_feature .block {
- max-width: 800px;
- width: 100%;
-}
-
-.tx-landing__major_feature .block.margin {
- margin-right: 50px;
-}
-
-.tx-landing__major_feature .block.large {
- width: 800px;
- max-width: 100%;
- flex: 0 0 auto;
-}
-
-/*.tx-landing__bottom_cta*/ a[data-terminal-control] {
- color: #e37cff;
-}
-
-/*.tx-landing__bottom_cta*/ [data-ty="input"]:before, [data-ty-prompt]:before {
- color: #e37cff;
-}
-
-/*.tx-landing__bottom_cta*/ [data-termynal] {
- font-size: 16px;
-}
-
-.tx-landing__bottom_cta .termy {
- max-width: 750px;
- margin-bottom: 2rem;
-}
-
-.tx-footer {
- padding-top: 2.5rem;
-}
-
-.md-footer__inner {
- padding: 0;
-}
-
-.tx-footer .md-main__inner {
- border-width: 0;
- /*border-top-width: 0.6px;*/
- border-image: linear-gradient(45deg, #0048ff, #ce00ff) 10;
- border-style: solid;
-}
-
-.tx-footer__section {
- display: flex;
- flex-direction: column;
- gap: 0.5rem;
- margin: 0 0.6rem;
-}
-
-.tx-footer__section-title {
- text-transform: uppercase;
- font-size: 0.8rem;
- font-weight: 700;
- color: black;
- letter-spacing: -0.5px;
- line-height: 24px;
- margin-top: 0.6rem;
- margin-bottom: 0.1rem;
-}
-
-.tx-footer__logo:hover {
- opacity: .7;
-}
-
-.tx-footer__copyright {
- margin-top: 0.6rem;
- font-size: 18px;
- line-height: 26px;
- color: black;
- font-weight: 500;
-}
-
-.tx-footer__section-link {
- font-size: 0.75rem;
- line-height: 26px;
- color: #151414;
- transition: opacity .2s ease;
-}
-
-.tx-footer__section-link:hover {
- opacity: .7;
-}
-
-@media screen and (max-width: 76.1875em) {
- .tx-footer .md-main__inner {
- flex-direction: column;
- gap: 1.5rem;
- margin-left: .8rem;
- margin-right: .8rem;
- }
-
- .tx-footer__section {
- margin-bottom: 1.5rem;
- }
-}
-
-@media screen and (min-width: 76.1875em) {
- .tx-footer {
- padding-bottom: 3.5rem;
- }
-
- .tx-footer__right-side {
- margin-left: auto;
- display: flex;
- gap: 4.5rem;
- }
-}
-
-.tx-landing__plans {
- margin-bottom: 2.75rem;
-}
-
-.tx-landing__plans_text {
-
-}
-
-.tx-landing__plans_text h2 {
- margin-bottom: 2rem;
- font-weight: 800;
- font-size: 2rem;
- text-align: center;
-}
-
-.tx-landing__plans_cards {
- display: grid;
- flex-wrap: wrap;
- gap: 2rem;
- grid-template-columns: repeat(auto-fill, minmax(15rem, 1fr));
-}
-
-.md-header__buttons .md-button--primary.sky, .md-header__buttons .md-button--primary.sky:hover,
-.md-typeset .md-button--primary.sky, .md-typeset .md-button--primary.sky:hover {
- background: -webkit-linear-gradient(45deg, #002aff, #002aff, #e165fe);
- border-radius: 8px;
- border: 1px solid transparent;
-}
-
-.plans_card.open_source {
-}
-
-.plans_card.dstack_sky {
- background: -webkit-linear-gradient(45deg, rgba(0, 42, 255, 0.2), rgb(0 114 255 / 1%), rgba(0, 42, 255, 0.07));
-}
-
-.plans_card.enterprise {
-}
-
-.plans_card {
- display: flex;
- flex-direction: column;
- border-color: black;
- border-radius: 0;
- border-width: 1px;
- border-style: solid;
- padding: 38px 46px;
-}
-
-@media screen and (min-width: 76.1875em) {
- .plans_card.open_source {
- padding: 38px 46px 38px 46px;
- border-right: none;
- border-top-left-radius: 12px;
- border-bottom-left-radius: 12px;
- /*margin-right: 5px;*/
- }
-
- .plans_card.dstack_sky {
- /*border-left: none;*/
- border-top-right-radius: 12px;
- border-bottom-right-radius: 12px;
- /*margin-left: 5px;*/
- }
-
- .plans_card.enterprise {
- margin: 0 -5px;
- }
-
- .tx-landing__plans_cards {
- gap: 0;
- }
-}
-
-.plans_card__title {
- margin-bottom: 0.7rem;
- font-size: 1.5em;
- font-weight: 800;
- line-height: 1.33;
-}
-
-.plans_card__subtitle-2 {
- color: rgba(0, 0, 0, 0.6);
- margin-bottom: 0.75rem;
- font-size: 0.9em;
-}
-
-.plans_card__subtitle {
- margin-bottom: 1rem;
- font-size: 0.9em;
- line-height: 1.44;
- color: black;
-}
-
-.plans_card__panel {
- font-size: 0.9em;
- line-height: 32px;
- margin-bottom: 1.5em;
-}
-
-.plans_card__items .item::before {
- -webkit-mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- -webkit-mask-size: cover;
- mask-size: cover;
- background: -webkit-linear-gradient(45deg, rgba(0, 0, 0, 0.87), rgba(0, 0, 0, 0.87));
- content: '';
- display: inline-block;
- width: 24px;
- height: 24px;
- margin-right: 20px;
- margin-left: 5px;
- position: relative;
- top: 5px;
-}
-
-.plans_card__items .item.crown::before {
- -webkit-mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- background: -webkit-linear-gradient(45deg, #0048ff, #ce00ff);
-}
-
-.plans_card__buttons_subtitle {
- margin-top: 18px;
- margin-left: 5px;
- color: #202128;
- font-size: 0.65rem;
- line-height: 22px;
-}
-
-.plans_card__services {
- display: flex;
- flex-wrap: wrap;
- gap: 10px;
- margin-bottom: 1.3rem;
-}
-
-.plans_card__service-item {
- display: flex;
- align-items: center;
- gap: 8px;
- padding: 7px 16px;
- border-radius: 30px;
- border: 0.5px solid black;
- font-size: .85em;
- line-height: 1.44;
- color: #2A292D;
-}
-
-.plans_card__service-item img {
- max-width: none;
- height: initial;
-}
-
-.plans_card__service-name {
- flex-shrink: 0;
- white-space: nowrap;
-}
-
-.plans_card__items {
- margin-bottom: 1.25rem;
-}
-
-.plans_card__buttons {
- margin-top: auto;
-}
-
-.plans_card__item {
- font-size: 1.0em;
- line-height: 2.0;
- color: black;
-}
-
-.plans_card__item .strong {
- color: #2A292D;
- font-weight: 700;
-}
-
-.highlighted {
- font-weight: 500;
- color: var(--md-typeset-a-color);
-}
-
-.plans_card__link {
- margin-top: 1.0rem;
- margin-bottom: 1.9rem;
- font-size: 1.0em;
- line-height: 1.66;
-}
-
-.plans_card__buttons .md-button {
- margin: 0;
-}
-
-@media screen and (max-width: 76.1875em) {
-
-}
-
-@media screen and (min-width: 76.1875em) {
- .tx-landing__plans_text h2 {
- font-size: 2.5rem;
- }
-}
-
-.typed-cursor {
- background: linear-gradient(90deg, #4631C8 -1.29%, #CD4AE2 88.05%, #FFD43C 111.26%);
- -webkit-background-clip: text;
- -webkit-text-fill-color: transparent;
- padding: 0 7px;
-}
-
-.tx-landing__quotes_grid {
- grid-gap: 1.2rem;
- display: grid;
- grid-template-columns: repeat(auto-fill, minmax(15rem, 2fr));
- margin-bottom: 2.4em;
-}
-
-.heart::after {
- position: relative;
- content: '';
- width: 45px;
- height: 40px;
- display: inline-block;
- -webkit-mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- mask: url('data:image/svg+xml, ') no-repeat 50% 50%;
- -webkit-mask-size: cover;
- mask-size: cover;
- background: -webkit-linear-gradient(45deg, #0048ff, #ce00ff);
- top: 4px;
- margin: 0 3px;
-}
-
-.tx-landing__quotes_grid .photo {
- height: 80px;
- float: left;
- margin: 0 15px 15px 0;
-}
-
-.tx-landing__quotes_grid .photo img {
- width: auto;
- height: 100%;
- aspect-ratio: 1;
- object-fit: cover;
- border-radius: 50px;
-}
-
-.tx-landing__quotes_grid h3 {
- border-bottom: none;
- font-size: 1em;
- font-weight: 700;
- margin: 0;
- padding: 0;
- margin-top: 13px;
-}
-
-.tx-landing__quotes_grid h4 {
- border-bottom: none;
- font-size: 0.95em;
- font-weight: 500;
- margin: 0;
- padding: 0;
- color: var(--md-primary-bg-color--light);)
-}
-
-.tx-landing__quotes_grid p {
- clear: both;
- font-size: 0.9em;
-}
-
-.tx-landing__quotes_grid .cell {
- padding: 26px 28px;
- border-radius: 12px;
- border: 1px solid black;
-}
\ No newline at end of file
diff --git a/docs/assets/stylesheets/termynal.css b/docs/assets/stylesheets/termynal.css
deleted file mode 100644
index 2c06d7f183..0000000000
--- a/docs/assets/stylesheets/termynal.css
+++ /dev/null
@@ -1,123 +0,0 @@
-/**
- * termynal.js
- *
- * @author Ines Montani
- * @version 0.0.1
- * @license MIT
- */
-
-:root {
- --color-bg: rgb(21, 22, 29);
- --color-text: #eee;
- --color-text-subtle: #a2a2a2;
-}
-
-[data-termynal] span {
- white-space: pre;
-}
-
-.small > [data-termynal] {
- font-size: 14px;
- line-height: 1.4;
-}
-
-[data-termynal] {
- overflow-x: scroll;
- /*white-space: pre;*/
- /*width: 750px;*/
- max-width: 100%;
- background: var(--color-bg);
- color: var(--color-text);
- /* font-size: 18px; */
- font-size: 14px;
- /* font-family: 'Fira Mono', Consolas, Menlo, Monaco, 'Courier New', Courier, monospace; */
- font-family: var(--md-code-font-family) !important;
- border-radius: 4px;
- padding: 45px 25px 25px;
- /*padding: 75px 45px 35px;*/
- position: relative;
- -webkit-box-sizing: border-box;
- box-sizing: border-box;
-}
-
-[data-termynal]:before {
- content: '';
- position: absolute;
- top: 15px;
- left: 15px;
- display: inline-block;
- width: 12px;
- height: 12px;
- border-radius: 50%;
- /* A little hack to display the window buttons in one pseudo element. */
- background: #d9515d;
- /*-webkit-box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;*/
- /* box-shadow: 25px 0 0 #f4c025, 50px 0 0 #3ec930;*/
- -webkit-box-shadow: 20px 0 0 #f4c025, 40px 0 0 #3ec930;
- box-shadow: 20px 0 0 #f4c025, 40px 0 0 #3ec930;
-}
-
-[data-termynal]:after {
- content: '';
- position: absolute;
- color: var(--color-text-subtle);
- top: 7px;
- left: 0;
- width: 100%;
- text-align: center;
-}
-
-a[data-terminal-control] {
- text-align: right;
- display: block;
- color: #aebbff;
-}
-
-[data-ty] {
- display: block;
- line-height: 2;
-}
-
-[data-ty]:before {
- /* Set up defaults and ensure empty lines are displayed. */
- content: '';
- display: inline-block;
- vertical-align: middle;
-}
-
-[data-ty="input"]:before,
-[data-ty-prompt]:before {
- margin-right: 0.75em;
- color: var(--color-text-subtle);
-}
-
-[data-ty="input"]:before {
- content: '$';
-}
-
-[data-ty][data-ty-prompt]:before {
- content: attr(data-ty-prompt);
-}
-
-[data-ty-cursor]:after {
- content: attr(data-ty-cursor);
- font-family: monospace;
- margin-left: 0.5em;
- -webkit-animation: blink 1s infinite;
- animation: blink 1s infinite;
-}
-
-
-/* Cursor animation */
-
-@-webkit-keyframes blink {
- 50% {
- opacity: 0;
- }
-}
-
-@keyframes blink {
- 50% {
- opacity: 0;
- }
-}
\ No newline at end of file
diff --git a/docs/blog/archive/say-goodbye-to-managed-notebooks.md b/docs/blog/archive/say-goodbye-to-managed-notebooks.md
deleted file mode 100644
index 55e00e1c04..0000000000
--- a/docs/blog/archive/say-goodbye-to-managed-notebooks.md
+++ /dev/null
@@ -1,101 +0,0 @@
----
-date: 2023-06-29
-description: Discover how cloud dev environments can benefit ML engineers and why why they are gaining popularity over managed notebooks .
-slug: say-goodbye-to-managed-notebooks
----
-
-# Say goodbye to managed notebooks
-
-Data science and ML tools have made significant advancements in recent years. This blog post aims to examine the
-advantages of cloud dev environments (CDE) for ML engineers and compare them with web-based managed notebooks.
-
-[//]: # (TODO: Should be technical and controversial)
-
-
-
-## Notebooks are here to stay
-
-Jupyter notebooks are instrumental for interactive work with data. They provide numerous advantages such as high
-interactivity, visualization support, remote accessibility, and effortless sharing.
-
-Managed notebook platforms, like Google Colab and AWS SageMaker have become popular thanks to their easy integration with clouds.
-With pre-configured environments, managed notebooks remove the need to worry about infrastructure.
-
-{ width=800 }
-
-## Reproducibility challenge
-
-As the code evolves, it needs to be converted into Python scripts and stored in Git for improved organization and
-version control. Notebooks alone cannot handle this task, which is why they must be a part of a developer
-environment that also supports Python scripts and Git.
-
-The JupyterLab project attempts to address this by turning notebooks into an IDE by adding a file browser,
-terminal, and Git support.
-
-{ width=800 }
-
-## IDEs get equipped for ML
-
-Recently, IDEs have improved in their ability to support machine learning. They have started to combine the benefits of
-traditional IDEs and managed notebooks.
-
-IDEs have upgraded their remote capabilities, with better SSH support. Additionally, they now offer built-in support for editing notebooks.
-
-Two popular IDEs, VS Code and PyCharm, have both integrated remote capabilities and seamless notebook editing features.
-
-{ width=800 }
-
-## The rise of app ecosystem
-
-Notebooks have been beneficial for their interactivity and sharing features. However, there are new alternatives like
-Streamlit and Gradio that allow developers to build data apps using Python code. These frameworks not only simplify
-app-building but also enhance reproducibility by integrating with Git.
-
-Hugging Face Spaces, for example, is a popular tool today for sharing Streamlit and Gradio apps with others.
-
-{ width=800 class="border"}
-
-## Say hello to cloud dev environments!
-
-Remote development within IDEs is becoming increasingly popular, and as a result, cloud dev environments have emerged as
-a new concept. Various managed services, such as Codespaces and GitPod, offer scalable infrastructure while maintaining
-the familiar IDE experience.
-
-One such open-source tool is `dstack`, which enables you to define your dev environment declaratively as code and run it on any cloud.
-
-
-
-```yaml
-type: dev-environment
-build:
- - apt-get update
- - apt-get install -y ffmpeg
- - pip install -r requirements.txt
-ide: vscode
-```
-
-
-
-With this tool, provisioning the required hardware, setting up the pre-built environment (no Docker is needed), and
-fetching your local code is automated.
-
-```shell
-$ dstack run .
-
- RUN CONFIGURATION USER PROJECT INSTANCE SPOT POLICY
- honest-jellyfish-1 .dstack.yml peter gcp a2-highgpu-1g on-demand
-
-Starting SSH tunnel...
-
-To open in VS Code Desktop, use one of these link:
- vscode://vscode-remote/ssh-remote+honest-jellyfish-1/workflow
-
-To exit, press Ctrl+C.
-```
-
-You can securely access the cloud development environment with the desktop IDE of your choice.
-
-{ width=800 }
-
-!!! info "Learn more"
- Check out our [guide](../../docs/concepts/dev-environments.md) for running dev environments in your cloud.
\ No newline at end of file
diff --git a/docs/blog/index.md b/docs/blog/index.md
deleted file mode 100644
index c58f16c501..0000000000
--- a/docs/blog/index.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Blog
-
diff --git a/docs/blog/posts/dstack-research.md b/docs/blog/posts/dstack-research.md
deleted file mode 100644
index 622797ece4..0000000000
--- a/docs/blog/posts/dstack-research.md
+++ /dev/null
@@ -1,39 +0,0 @@
----
-date: 2024-05-06
-description: Universities and research labs engaged in open-source AI can now access dstack Enterprise for free.
-slug: dstack-research
----
-
-# Launching research and open-source program
-
-To all universities and research labs developing open-source AI: If you're utilizing cloud GPUs or on-prem clusters
-to train and deploy AI, you can now use `dstack Enterprise` for free.
-
-{ width=650 }
-
-
-
-As recent developments show, access to and the ability to efficiently manage compute resources are key to training and
-utilizing AI models. Inefficiency in these processes leads to high costs and erodes competitiveness in the race for AI
-research.
-
-Universities and research labs working on open-source AI do more research than any other organizations. They require a
-lot of compute and often prefer focusing on AI rather than infrastructure.
-
-`dstack` is building an open-source foundation for more effective orchestration of compute resources for AI workloads.
-
-{ width=750 }
-
-Leveraging containers, `dstack` facilitates AI model training and deployment at scale while allowing the effective
-use of open-source models, training, and serving frameworks.
-
-`dstack Enterprise` is a self-hosted AI platform that extends the capabilities of the open-source `dstack` to simplify
-cost optimization, and compute utilization, and workload management for multiple teams.
-
-> To support universities and research labs engaged in open-source AI, we're thrilled to announce that `dstack Enterprise`
-> can now be used by them for free
-
-If you're a researcher facing GPU usage challenges and seeking a platform friendly to AI researchers, capable of
-seamless integration with the open-source ecosystem, share this program with your supervisor.
-
-To apply to this program, fill [this](https://tally.so/r/nrl2l5) form.
\ No newline at end of file
diff --git a/docs/changelog/index.md b/docs/changelog/index.md
deleted file mode 100644
index c58f16c501..0000000000
--- a/docs/changelog/index.md
+++ /dev/null
@@ -1,2 +0,0 @@
-# Blog
-
diff --git a/docs/docs/concepts/dev-environments.md b/docs/docs/concepts/dev-environments.md
deleted file mode 100644
index a191a0e454..0000000000
--- a/docs/docs/concepts/dev-environments.md
+++ /dev/null
@@ -1,107 +0,0 @@
-# Dev environments
-
-Before scheduling a task or deploying a model, you may want to run code interactively. Dev environments allow you to
-provision a remote machine set up with your code and favorite IDE with just one command.
-
-## Configuration
-
-First, create a YAML file in your project folder. Its name must end with `.dstack.yml` (e.g. `.dstack.yml` or `dev.dstack.yml` are
-both acceptable).
-
-
-
-```yaml
-type: dev-environment
-
-# Specify the Python version, or your Docker image
-python: "3.11"
-
-# This pre-configures the IDE with required extensions
-ide: vscode
-
-# Specify GPU, disk, and other resource requirements
-resources:
- gpu: 80GB
-```
-
-
-
-If you don't specify your Docker image, `dstack` uses the [base](https://hub.docker.com/r/dstackai/base/tags) image
-(pre-configured with Python, Conda, and essential CUDA drivers).
-
-!!! info "Reference"
- See the [.dstack.yml reference](../reference/dstack.yml/dev-environment.md)
- for all supported configuration options and multiple examples.
-
-## Running
-
-To run a configuration, use the [`dstack run`](../reference/cli/index.md#dstack-run) command followed by the working directory path,
-configuration file path, and other options.
-
-
-
-```shell
-$ dstack run . -f .dstack.yml
-
- BACKEND REGION RESOURCES SPOT PRICE
- tensordock unitedkingdom 10xCPU, 80GB, 1xA100 (80GB) no $1.595
- azure westus3 24xCPU, 220GB, 1xA100 (80GB) no $3.673
- azure westus2 24xCPU, 220GB, 1xA100 (80GB) no $3.673
-
-Continue? [y/n]: y
-
-Provisioning `fast-moth-1`...
----> 100%
-
-To open in VS Code Desktop, use this link:
- vscode://vscode-remote/ssh-remote+fast-moth-1/workflow
-```
-
-
-
-When `dstack` provisions the dev environment, it mounts the project folder contents.
-
-!!! info ".gitignore"
- If there are large files or folders you'd like to avoid uploading,
- you can list them in `.gitignore`.
-
-!!! info "Reference"
- See the [CLI reference](../reference/cli/index.md#dstack-run) for more details
- on how `dstack run` works.
-
-### VS Code
-
-To open the dev environment in your desktop IDE, use the link from the output
-(such as `vscode://vscode-remote/ssh-remote+fast-moth-1/workflow`).
-
-{ width=800 }
-
-### SSH
-
-Alternatively, while the CLI is attached to the run, you can connect to the dev environment via SSH:
-
-
-
-```shell
-$ ssh fast-moth-1
-```
-
-
-
-## Managing runs
-
-**Stopping runs**
-
-Once the run exceeds the max duration,
-or when you use [`dstack stop`](../reference/cli/index.md#dstack-stop),
-the dev environment and its cloud resources are deleted.
-
-**Listing runs**
-
-The [`dstack ps`](../reference/cli/index.md#dstack-ps) command lists all running runs and their status.
-
-[//]: # (TODO: Mention `dstack logs` and `dstack logs -d`)
-
-## What's next?
-
-1. Check the [`.dstack.yml` reference](../reference/dstack.yml/dev-environment.md) for more details and examples
\ No newline at end of file
diff --git a/docs/docs/concepts/gateways.md b/docs/docs/concepts/gateways.md
deleted file mode 100644
index 952fb2cb3f..0000000000
--- a/docs/docs/concepts/gateways.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Gateways
-
-Gateways handle the ingress traffic of running services.
-They provide [services](services.md) with HTTPS domains, handle authentication, distribute load, and perform auto-scaling.
-In order to run a service, you need to have at least one gateway set up.
-
-!!! info "dstack Sky"
- If you're using [dstack Sky :material-arrow-top-right-thin:{ .external }](https://sky.dstack.ai){:target="_blank"},
- the gateway is already set up for you.
-
-## Configuration
-
-First, create a YAML file in your project folder. Its name must end with `.dstack.yml` (e.g. `.dstack.yml` or `gateway.dstack.yml`
-are both acceptable).
-
-
-
-```yaml
-type: gateway
-name: example-gateway
-
-backend: aws
-region: eu-west-1
-domain: example.com
-```
-
-
-
-A domain name is required to create a gateway.
-
-!!! info "Reference"
- See the [.dstack.yml reference](../reference/dstack.yml/gateway.md)
- for all supported configuration options and examples.
-
-## Creating and updating gateways
-
-To create or update the gateway, simply call the [`dstack apply`](../reference/cli/index.md#dstack-apply) command:
-
-
-
-```shell
-$ dstack apply . -f examples/deployment/gateway.dstack.yml
-
-The example-gateway doesn't exist. Create it? [y/n]: y
-
- BACKEND REGION NAME HOSTNAME DOMAIN DEFAULT STATUS
- aws eu-west-1 example-gateway example.com ✓ submitted
-
-```
-
-
-
-## Updating DNS records
-
-Once the gateway is assigned a hostname, go to your domain's DNS settings
-and add an `A` DNS record for `*.` (e.g., `*.example.com`) pointing to the gateway's hostname.
-
-This will allow you to access runs and models using this domain.
-
-## Managing gateways
-
-**Deleting gateways**
-
-To delete a gateway, pass gateway configuration to [`dstack delete`](../reference/cli/index.md#dstack-delete):
-
-
-
-```shell
-$ dstack delete . -f examples/deployment/gateway.dstack.yml
-```
-
-
-
-**Listing gateways**
-
-The [`dstack gateway list`](../reference/cli/index.md#dstack-gateway-list) command lists existing gateways and their status.
-
-[//]: # (TODO: Ellaborate on default`)
-
-[//]: # (TODO: ## Accessing endpoints)
-
-## What's next?
-
-1. See [services](services.md) on how to run services
-2. Check the [`.dstack.yml` reference](../reference/dstack.yml/gateway.md) for more details and examples
\ No newline at end of file
diff --git a/docs/docs/concepts/pools.md b/docs/docs/concepts/pools.md
deleted file mode 100644
index 19cb8e098e..0000000000
--- a/docs/docs/concepts/pools.md
+++ /dev/null
@@ -1,117 +0,0 @@
-# Pools
-
-Pools enable the efficient reuse of cloud instances and on-premises servers across runs, simplifying their management.
-
-## Adding instances
-
-### Automatic provisioning
-
-By default, when using the `dstack run` command, it tries to reuse an instance from a pool. If no idle instance meets the
-requirements, `dstack` automatically provisions a new cloud instance and adds it to the pool.
-
-??? info "Reuse policy"
- To avoid provisioning new cloud instances with `dstack run`, use `--reuse`. Your run will be assigned to an idle instance in
- the pool. If there are no available idle instances in the pool, the run will fail.
-
-??? info "Idle duration"
- By default, `dstack run` sets the idle duration of a newly provisioned instance to `5m`.
- This means that if the run is finished and the instance remains idle for longer than five minutes, it is automatically
- removed from the pool. To override the default idle duration, use `--idle-duration DURATION` with `dstack run`.
-
-### Manual provisioning
-
-To manually provision a cloud instance and add it to a pool, use [`dstack pool add`](../reference/cli/index.md#dstack-pool-add):
-
-
-
-```shell
-$ dstack pool add --gpu 80GB
-
- BACKEND REGION RESOURCES SPOT PRICE
- tensordock unitedkingdom 10xCPU, 80GB, 1xA100 (80GB) no $1.595
- azure westus3 24xCPU, 220GB, 1xA100 (80GB) no $3.673
- azure westus2 24xCPU, 220GB, 1xA100 (80GB) no $3.673
-
-Continue? [y/n]: y
-```
-
-
-
-The `dstack pool add` command allows specifying resource requirements, along with the spot policy, idle duration, max
-price, retry policy, and other policies.
-
-??? info "Idle duration"
- The default idle duration if you're using `dstack pool add` is `72h`. To override it, use the `--idle-duration DURATION` argument.
-
-[//]: # (TODO: Mention the retry policy)
-
-You can also specify the policies via [`.dstack/profiles.yml`](../reference/profiles.yml.md) instead of passing them as arguments.
-For more details on policies and their defaults, refer to [`.dstack/profiles.yml`](../reference/profiles.yml.md).
-
-??? info "Limitations"
- The `dstack pool add` command is not supported for Kubernetes, VastAI, and RunPod backends yet.
-
-### Adding on-prem clusters
-
-Any on-prem server that can be accessed via SSH can be added to a pool and used to run workloads.
-
-To add on-prem servers to the pool, use the `dstack pool add-ssh` command and pass the hostname of your server along with
-the SSH key.
-
-
-
-```shell
-$ dstack pool add-ssh -i ~/.ssh/id_rsa ubuntu@54.73.155.119
-```
-
-
-
-The command accepts the same arguments as the standard `ssh` command.
-
-!!! warning "Requirements"
- The on-prem server should be pre-installed with CUDA 12.1 and NVIDIA Docker.
-
-Once the instance is provisioned, you'll see it in the pool and will be able to run workloads on it.
-
-#### Clusters
-
-If you want on-prem instances to run multi-node tasks, ensure these on-prem servers share the same private network.
-Additionally, you need to pass the `--network` option to `dstack pool add-ssh`:
-
-
-
-```shell
-$ dstack pool add-ssh -i ~/.ssh/id_rsa ubuntu@54.73.155.119 \
- --network 10.0.0.0/24
-```
-
-
-
-The `--network` argument accepts the IP address range (CIDR) of the private network of the instance.
-
-Once you've added multiple instances with the same network value, you can use them as a cluster to run
-[multi-node tasks](../reference/dstack.yml/task.md#_nodes).
-
-## Removing instances
-
-If the instance remains idle for the configured idle duration, `dstack` removes it and deletes all cloud resources.
-
-To remove an instance from the pool manually, use the `dstack pool rm` command.
-
-
-
-```shell
-$ dstack pool rm <instance name>
-```
-
-
-
-## List instances
-
-The [`dstack pool ps`](../reference/cli/index.md#dstack-pool-ps) command lists active instances and their status (`busy`
-or `idle`).
-
-[//]: # (#### Manage pools)
-
-[//]: # (TBA)
-
diff --git a/docs/docs/concepts/services.md b/docs/docs/concepts/services.md
deleted file mode 100644
index 1daa6ea80c..0000000000
--- a/docs/docs/concepts/services.md
+++ /dev/null
@@ -1,137 +0,0 @@
-# Services
-
-Services make it easy to deploy models and web applications as public,
-secure, and scalable endpoints. They are provisioned behind a [gateway](gateways.md) that
-automatically provides an HTTPS domain, handles authentication, distributes load, and performs auto-scaling.
-
-??? info "Gateways"
- If you're using the open-source server, you must set up a [gateway](gateways.md) before you can run a service.
-
- If you're using [dstack Sky :material-arrow-top-right-thin:{ .external }](https://sky.dstack.ai){:target="_blank"},
- the gateway is already set up for you.
-
-## Configuration
-
-First, create a YAML file in your project folder. Its name must end with `.dstack.yml` (e.g. `.dstack.yml` or `serve.dstack.yml`
-are both acceptable).
-
-
-
-```yaml
-type: service
-
-python: "3.11"
-env:
- - MODEL=NousResearch/Llama-2-7b-chat-hf
-commands:
- - pip install vllm
- - python -m vllm.entrypoints.openai.api_server --model $MODEL --port 8000
-port: 8000
-
-resources:
- gpu: 80GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- format: openai
- type: chat
- name: NousResearch/Llama-2-7b-chat-hf
-```
-
-
-
-If you don't specify your Docker image, `dstack` uses the [base](https://hub.docker.com/r/dstackai/base/tags) image
-(pre-configured with Python, Conda, and essential CUDA drivers).
-
-!!! info "Auto-scaling"
- By default, the service is deployed to a single instance. However, you can specify the
- [number of replicas and scaling policy](../reference/dstack.yml/service.md#replicas-and-auto-scaling).
- In this case, `dstack` auto-scales it based on the load.
-
-!!! info "Reference"
- See the [.dstack.yml reference](../reference/dstack.yml/service.md)
- for all supported configuration options and multiple examples.
-
-## Running
-
-To run a configuration, use the [`dstack run`](../reference/cli/index.md#dstack-run) command followed by the working directory path,
-configuration file path, and any other options.
-
-
-
-```shell
-$ dstack run . -f serve.dstack.yml
-
- BACKEND REGION RESOURCES SPOT PRICE
- tensordock unitedkingdom 10xCPU, 80GB, 1xA100 (80GB) no $1.595
- azure westus3 24xCPU, 220GB, 1xA100 (80GB) no $3.673
- azure westus2 24xCPU, 220GB, 1xA100 (80GB) no $3.673
-
-Continue? [y/n]: y
-
-Provisioning...
----> 100%
-
-Service is published at https://yellow-cat-1.example.com
-```
-
-
-
-When deploying the service, `dstack run` mounts the current folder's contents.
-
-!!! info ".gitignore"
- If there are large files or folders you'd like to avoid uploading,
- you can list them in `.gitignore`.
-
-!!! info "Reference"
- See the [CLI reference](../reference/cli/index.md#dstack-run) for more details
- on how `dstack run` works.
-
-## Service endpoint
-
-One the service is up, its endpoint is accessible at `https://.`.
-
-By default, the service endpoint requires the `Authorization` header with `Bearer `.
-
-
-
-```shell
-$ curl https://yellow-cat-1.example.com/v1/chat/completions \
- -H 'Content-Type: application/json' \
- -H 'Authorization: Bearer <dstack token>' \
- -d '{
- "model": "NousResearch/Llama-2-7b-chat-hf",
- "messages": [
- {
- "role": "user",
- "content": "Compose a poem that explains the concept of recursion in programming."
- }
- ]
- }'
-```
-
-
-
-Authorization can be disabled by setting `auth` to `false` in the service configuration file.
-
-### Model endpoint
-
-In case the service has the [model mapping](../reference/dstack.yml/service.md#model-mapping) configured, you will also be able
-to access the model at `https://gateway.` via the OpenAI-compatible interface.
-
-## Managing runs
-
-**Stopping runs**
-
-When you use [`dstack stop`](../reference/cli/index.md#dstack-stop), the service and its cloud resources are deleted.
-
-**Listing runs**
-
-The [`dstack ps`](../reference/cli/index.md#dstack-ps) command lists all running runs and their status.
-
-## What's next?
-
-1. Check the [Text Generation Inference :material-arrow-top-right-thin:{ .external }](https://github.com/dstackai/dstack/blob/master/examples/deployment/tgi/README.md){:target="_blank"} and [vLLM :material-arrow-top-right-thin:{ .external }](https://github.com/dstackai/dstack/blob/master/examples/deployment/vllm/README.md){:target="_blank"} examples
-2. Check the [`.dstack.yml` reference](../reference/dstack.yml/service.md) for more details and examples
-3. See [gateways](gateways.md) on how to set up a gateway
-4. Browse [examples :material-arrow-top-right-thin:{ .external }](https://github.com/dstackai/dstack/tree/master/examples){:target="_blank"}
\ No newline at end of file
diff --git a/docs/docs/concepts/tasks.md b/docs/docs/concepts/tasks.md
deleted file mode 100644
index 1f369d7550..0000000000
--- a/docs/docs/concepts/tasks.md
+++ /dev/null
@@ -1,108 +0,0 @@
-# Tasks
-
-Tasks allow for convenient scheduling of various batch jobs, such as training, fine-tuning, or
-data processing. They can also be used to run web applications
-when features offered by [services](services.md) are not needed, such as for debugging.
-
-You can run tasks on a single machine or on a cluster of nodes.
-
-## Configuration
-
-First, create a YAML file in your project folder. Its name must end with `.dstack.yml` (e.g. `.dstack.yml` or `train.dstack.yml`
-are both acceptable).
-
-
-
-```yaml
-type: task
-
-python: "3.11"
-env:
- - HF_HUB_ENABLE_HF_TRANSFER=1
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - tensorboard --logdir results/runs &
- - python fine-tuning/qlora/train.py
-ports:
- - 6000
-
-# (Optional) Configure `gpu`, `memory`, `disk`, etc
-resources:
- gpu: 80GB
-```
-
-
-
-If you don't specify your Docker image, `dstack` uses the [base](https://hub.docker.com/r/dstackai/base/tags) image
-(pre-configured with Python, Conda, and essential CUDA drivers).
-
-
-!!! info "Distributed tasks"
- By default, tasks run on a single instance. However, you can specify
- the [number of nodes](../reference/dstack.yml/task.md#_nodes).
- In this case, `dstack` provisions a cluster of instances.
-
-!!! info "Reference"
- See the [.dstack.yml reference](../reference/dstack.yml/task.md)
- for all supported configuration options and multiple examples.
-
-## Running
-
-To run a configuration, use the [`dstack run`](../reference/cli/index.md#dstack-run) command followed by the working directory path,
-configuration file path, and other options.
-
-
-
-```shell
-$ dstack run . -f train.dstack.yml
-
- BACKEND REGION RESOURCES SPOT PRICE
- tensordock unitedkingdom 10xCPU, 80GB, 1xA100 (80GB) no $1.595
- azure westus3 24xCPU, 220GB, 1xA100 (80GB) no $3.673
- azure westus2 24xCPU, 220GB, 1xA100 (80GB) no $3.673
-
-Continue? [y/n]: y
-
-Provisioning...
----> 100%
-
-TensorBoard 2.13.0 at http://localhost:6006/ (Press CTRL+C to quit)
-
-Epoch 0: 100% 1719/1719 [00:18<00:00, 92.32it/s, loss=0.0981, acc=0.969]
-Epoch 1: 100% 1719/1719 [00:18<00:00, 92.32it/s, loss=0.0981, acc=0.969]
-Epoch 2: 100% 1719/1719 [00:18<00:00, 92.32it/s, loss=0.0981, acc=0.969]
-```
-
-
-
-If the task specifies `ports`, `dstack run` automatically forwards them to your local machine for
-convenient and secure access.
-
-When running the task, `dstack run` mounts the current folder's contents.
-
-!!! info ".gitignore"
- If there are large files or folders you'd like to avoid uploading,
- you can list them in `.gitignore`.
-
-!!! info "Reference"
- See the [CLI reference](../reference/cli/index.md#dstack-run) for more details
- on how `dstack run` works.
-
-## Managing runs
-
-**Stoping runs**
-
-Once you use [`dstack stop`](../reference/cli/index.md#dstack-stop) (or when the run exceeds the
-`max_duration`), the instances return to the [pool](pools.md).
-
-**Listing runs**
-
-The [`dstack ps`](../reference/cli/index.md#dstack-ps) command lists all running runs and their status.
-
-[//]: # (TODO: Mention `dstack logs` and `dstack logs -d`)
-
-## What's next?
-
-1. Check the [QLoRA :material-arrow-top-right-thin:{ .external }](https://github.com/dstackai/dstack/blob/master/examples/fine-tuning/qlora/README.md){:target="_blank"} example
-2. Check the [`.dstack.yml` reference](../reference/dstack.yml/task.md) for more details and examples
-3. Browse [all examples :material-arrow-top-right-thin:{ .external }](https://github.com/dstackai/dstack/tree/master/examples){:target="_blank"}
\ No newline at end of file
diff --git a/docs/docs/concepts/volumes.md b/docs/docs/concepts/volumes.md
deleted file mode 100644
index dabb8d0576..0000000000
--- a/docs/docs/concepts/volumes.md
+++ /dev/null
@@ -1,108 +0,0 @@
-# Volumes
-
-Volumes allow you to persist data between runs. `dstack` simplifies managing volumes and lets you mount them to a specific
-directory when working with dev environments, tasks, and services.
-
-!!! info "Experimental"
- Volumes are currently experimental and only work with the `aws` backend. Support for other backends is coming soon.
-
-## Configuration
-
-First, create a YAML file in your project folder. Its name must end with `.dstack.yml` (e.g. `.dstack.yml` or `vol.dstack.yml`
-are both acceptable).
-
-
-
-```yaml
-type: volume
-name: my-new-volume
-backend: aws
-region: eu-central-1
-size: 100GB
-```
-
-
-
-If you use this configuration, `dstack` will create a new volume based on the specified options.
-
-!!! info "Registering existing volumes"
- If you prefer not to create a new volume but to reuse an existing one (e.g., created manually), you can
- [specify its ID via `volume_id`](../reference/dstack.yml/volume.md#register-volume). In this case, `dstack` will register the specified volume so that you can use it with development
- environments, tasks, and services.
-
-!!! info "Reference"
- See the [.dstack.yml reference](../reference/dstack.yml/dev-environment.md)
- for all supported configuration options and multiple examples.
-
-## Creating and registering volumes
-
-To create or register the volume, simply call the `dstack apply` command:
-
-
-
-```shell
-$ dstack apply -f volume.dstack.yml
-Volume my-new-volume does not exist yet. Create the volume? [y/n]: y
- NAME BACKEND REGION STATUS CREATED
- my-new-volume aws eu-central-1 submitted now
-
-```
-
-
-
-> When creating the volume `dstack` automatically creates an `ext4` file system on it.
-
-Once created, the volume can be attached with dev environments, tasks, and services.
-
-## Attaching volumes
-
-Dev environments, tasks, and services let you attach any number of volumes.
-To attach a volume, simply specify its name using the `volumes` property and specify where to mount its contents:
-
-
-
-```yaml
-type: dev-environment
-ide: vscode
-volumes:
- - name: my-new-volume
- path: /volume_data
-```
-
-
-
-Once you run this configuration, the contents of the volume will be attached to `/volume_data` inside the dev environment,
-and its contents will persist across runs.
-
-!!! info "Limitations"
- When you're running a dev environment, task, or service with `dstack`, it automatically mounts the project folder contents
- to `/workflow` (and sets that as the current working directory). Right now, `dstack` doesn't allow you to
- attach volumes to `/workflow` or any of its subdirectories.
-
-## Managing gateways
-
-**Deleting gateways**
-
-When the volume isn't attached to any active dev environment, task, or service, you can delete it using `dstack delete`:
-
-```shell
-$ dstack delete -f vol.dstack.yaml
-```
-
-If the volume was created using `dstack`, it will be physically destroyed along with the data.
-If you've registered an existing volume, it will be de-registered with `dstack` but will keep the data.
-
-**Listing volumes**
-
-The [`dstack volume list`](../reference/cli/index.md#dstack-gateway-list) command lists created and registered volumes.
-
-## FAQ
-
-??? info "Using volumes across backends"
- Since volumes are backed up by cloud network disks, you can only use them within the same cloud. If you need to access
- data across different backends, you should either use object storage (or replicate the data across multiple volumes).
-
-??? info "Using volumes across regions"
- Typically, network volumes are associated with specific regions, so you can't use them in other regions. Sometimes,
- volumes are also linked to availability zones, but some systems allow volumes that can be used across different
- availability zones within the same region.
\ No newline at end of file
diff --git a/docs/docs/index.md b/docs/docs/index.md
deleted file mode 100644
index ee9b54a4db..0000000000
--- a/docs/docs/index.md
+++ /dev/null
@@ -1,49 +0,0 @@
-# What is dstack?
-
-`dstack` is an open-source container orchestration engine for running AI workloads across diverse cloud providers
-and on-premises data centers. It simplifies provisioning compute resources, managing dev environments, executing tasks on clusters, and deploying services.
-
-!!! info "Cloud and on-premises"
- `dstack` allows workload orchestration on both cloud and on-premises clusters.
- Supported cloud providers include AWS, GCP, Azure, OCI, Lambda, TensorDock, Vast.ai, RunPod, and CUDO.
-
-!!! info "Accelerators"
- `dstack` supports NVIDIA GPUs and Google Cloud TPUs out of the box.
-
-## How does it work?
-
-!!! info "Installation"
- Before using `dstack`, [install](installation/index.md) the `dstack` server and configure credentials
- and other settings for each cloud account that you intend to use.
-
-#### 1. Define configurations
-
-`dstack` supports three types of run configurations:
-
-* [`dev environment`](concepts/dev-environments.md) — for interactive development using a desktop IDE
-* [`task`](concepts/tasks.md) — for any kind of batch jobs or web applications (supports distributed jobs)
-* [`service`](concepts/services.md)— for production-grade deployment (supports auto-scaling and authorization)
-
-Each type of run configuration allows you to specify commands for execution, required compute resources, retry policies, auto-scaling rules, authorization settings, and more.
-
-Configuration can be defined as YAML files within your repo.
-
-#### 2. Run configurations
-
-Run any defined configuration either via `dstack` CLI or API.
-
-`dstack` automatically provisions compute resources (whether from the cloud or on-premises), executes commands, handles interruptions, port-forwarding, auto-scaling, network, volumes, run failures, out-of-capacity errors, and more.
-
-#### 3. Manage pools
-
-Use [pools](concepts/pools.md) to manage the lifecycle of cloud instances and add/remove on-prem clusters.
-
-You can manually add or remove cloud instances from the pool, or have them provisioned on-demand and configure how long they remain idle before automatic termination.
-
-
-## Where do I start?
-
-1. Proceed to [installation](installation/index.md)
-2. See [quickstart](quickstart.md)
-3. Browse [examples :material-arrow-top-right-thin:{ .external }](https://github.com/dstackai/dstack/tree/master/examples){:target="_blank"}
-4. Join [Discord :material-arrow-top-right-thin:{ .external }](https://discord.gg/u8SmfwPpMd){:target="_blank"}
\ No newline at end of file
diff --git a/docs/docs/installation/index.md b/docs/docs/installation/index.md
deleted file mode 100644
index 99382d8d8e..0000000000
--- a/docs/docs/installation/index.md
+++ /dev/null
@@ -1,147 +0,0 @@
-# Installation
-
-To use the open-source version of `dstack` (which is self-hosted to use your own cloud accounts or data centers),
-go ahead and [set up the server](#set-up-the-server).
-
-To use [dstack Sky :material-arrow-top-right-thin:{ .external }](https://sky.dstack.ai){:target="_blank"}
-(a managed service that allows you to use either GPUs via marketplace, or connect to your own cloud accounts or data centers),
-proceed to [dstack Sky](#dstack-sky).
-
-## Set up the server
-
-### Configure backends
-
-Before starting the `dstack` server, create `~/.dstack/server/config.yml` and
-configure a backend for each cloud account that you'd like to use.
-
-
-
-```yaml
-projects:
- - name: main
- backends:
- - type: aws
- creds:
- type: access_key
- access_key: AIZKISCVKUKO5AAKLAEH
- secret_key: QSbmpqJIUBn1V5U3pyM9S6lwwiu8/fOJ2dgfwFdW
-```
-
-
-
-> Go to the [server/config.yml reference](../reference/server/config.yml.md#examples)
-> for details on how to configure backends for AWS, GCP, Azure, OCI, Lambda,
-> TensorDock, Vast.ai, RunPod, CUDO, Kubernetes, etc.
-
-### Start the server
-
-Once the `~/.dstack/server/config.yml` file is configured, proceed to start the server:
-
-=== "pip"
-
-
-
- ```shell
- $ pip install "dstack[all]" -U
- $ dstack server
-
- Applying ~/.dstack/server/config.yml...
-
- The admin token is "bbae0f28-d3dd-4820-bf61-8f4bb40815da"
- The server is running at http://127.0.0.1:3000/
- ```
-
-
-
-=== "Docker"
-
-
-
- ```shell
- $ docker run -p 3000:3000 \
- -v $HOME/.dstack/server/:/root/.dstack/server \
- dstackai/dstack
-
- Applying ~/.dstack/server/config.yml...
-
- The admin token is "bbae0f28-d3dd-4820-bf61-8f4bb40815da"
- The server is running at http://127.0.0.1:3000/
- ```
-
-
-
- > For more details on how to deploy `dstack` using Docker, check its [Docker repo](https://hub.docker.com/r/dstackai/dstack).
-
-> By default, `dstack` stores its state in `~/.dstack/server/data` using SQLite.
-> To use a database, set the [`DSTACK_DATABASE_URL`](../reference/cli/index.md#environment-variables) environment variable.
-
-Once the `dstack` server is up, feel free to use the CLI or API to work with it.
-
-### Set up the CLI
-
-To point the CLI to the `dstack` server, configure it
-with the server address, user token and project name:
-
-
-
-```shell
-$ pip install dstack
-$ dstack config --url http://127.0.0.1:3000 \
- --project main \
- --token bbae0f28-d3dd-4820-bf61-8f4bb40815da
-
-Configuration is updated at ~/.dstack/config.yml
-```
-
-
-
-This configuration is stored in `~/.dstack/config.yml`.
-
-### Add on-prem clusters
-
-If you'd like to use `dstack` to run workloads on your on-prem clusters,
-check out the [dstack pool add-ssh](../concepts/pools.md#adding-on-prem-clusters) command.
-
-## dstack Sky
-
-### Set up the CLI
-
-If you've signed up with [dstack Sky :material-arrow-top-right-thin:{ .external }](https://sky.dstack.ai){:target="_blank"},
-open the project settings, and copy the `dstack config` command to point the CLI to the project.
-
-{ width=800 }
-
-Then, install the CLI on your machine and use the copied command.
-
-
-
-```shell
-$ pip install dstack
-$ dstack config --url https://sky.dstack.ai \
- --project peterschmidt85 \
- --token bbae0f28-d3dd-4820-bf61-8f4bb40815da
-
-Configuration is updated at ~/.dstack/config.yml
-```
-
-
-
-### Configure backends
-
-By default, [dstack Sky :material-arrow-top-right-thin:{ .external }](https://sky.dstack.ai){:target="_blank"}
-uses the GPU from its marketplace, which requires a credit card to be attached in your account
-settings.
-
-To use your own cloud accounts, click the settings icon of the corresponding backend and specify credentials:
-
-{ width=800 }
-
-[//]: # (The `dstack server` command automatically updates `~/.dstack/config.yml`)
-[//]: # (with the `main` project.)
-
-## What's next?
-
-1. Check the [server/config.yml reference](../reference/server/config.yml.md) on how to configure backends
-2. Follow [quickstart](../quickstart.md)
-3. Browse [examples :material-arrow-top-right-thin:{ .external }](https://github.com/dstackai/dstack/tree/master/examples)
-4. Join the community via [Discord :material-arrow-top-right-thin:{ .external }](https://discord.gg/u8SmfwPpMd)
\ No newline at end of file
diff --git a/docs/docs/protips.md b/docs/docs/protips.md
deleted file mode 100644
index aadf8ded3f..0000000000
--- a/docs/docs/protips.md
+++ /dev/null
@@ -1,250 +0,0 @@
-# Protips
-
-Below are tips and tricks to use `dstack` more efficiently.
-
-## Dev environments
-
-Before running a task or service, it's recommended that you first start with a dev environment. Dev environments
-allow you to run commands interactively.
-
-Once the commands work, go ahead and run them as a task or a service.
-
-??? info "Notebooks"
- **VS Code**
-
- When you access a dev environment using your desktop VS Code, it allows you to work with Jupyter notebooks via its
- pre-configured and easy-to-use extension.
-
- **JupyterLab**
-
- If you prefer to use JupyterLab, you can run it as a task:
-
- ```yaml
- type: task
-
- commands:
- - pip install jupyterlab
- - jupyter lab --allow-root
-
- ports:
- - 8888
-
- ```
-
-## Tasks vs Services for web applications
-
-Tasks can be used not only for batch jobs but also for web applications.
-
-
-
-```yaml
-type: task
-
-python: "3.11"
-
-commands:
- - pip3 install streamlit
- - streamlit hello
-
-ports:
- - 8501
-
-```
-
-
-
-While you run a task, `dstack` forwards the remote ports to `localhost`.
-
-
-
-```shell
-$ dstack run . -f app.dstack.yml
-
- Welcome to Streamlit. Check out our demo in your browser.
-
- Local URL: http://localhost:8501
-```
-
-
-
-This allows you to access the remote `8501` port on `localhost:8501` while the CLI is attached.
-
-??? info "Port mapping"
- If you want to override the local port, use the `--port` option:
-
-
-
- ```shell
- $ dstack run . -f app.dstack.yml --port 3000:8501
- ```
-
-
-
- This will forward the remote `8501` port to `localhost:3000`.
-
-[Services](concepts/services.md) require a gateway but they also provide additional features for
-production-grade service deployment not offered by tasks, such as HTTPS domains and auto-scaling.
-If you run a web app as a task and it works, go ahead and run it as a service.
-
-## Environment variables
-
-If a configuration requires an environment variable that you don't want to hardcode in the YAML, you can define it
-without assigning a value:
-
-
-
-```yaml
-type: dev-environment
-
-env:
- - HUGGING_FACE_HUB_TOKEN
-
-python: "3.11"
-ide: vscode
-```
-
-
-
-Then, you can pass the environment variable either via the shell:
-
-```shell
-HUGGING_FACE_HUB_TOKEN=... dstack run . -f .dstack.yml
-```
-
-Or via the `-e` option of the `dstack run` command:
-
-```shell
-dstack run . -f .dstack.yml -e HUGGING_FACE_HUB_TOKEN=...
-```
-
-??? info ".env"
- A better way to configure environment variables not hardcoded in YAML is by specifying them in a `.env` file:
-
- ```
- HUGGING_FACE_HUB_TOKEN=...
- ```
-
- If you install [`direnv` :material-arrow-top-right-thin:{ .external }](https://direnv.net/){:target="_blank"},
- it will automatically pass the environment variables from the `.env` file to the `dstack run` command.
-
- Remember to add `.env` to `.gitignore` to avoid pushing it to the repo.
-
-## Data and models
-
-`dstack` has support for [volumes](concepts/volumes.md)
-to persist data across different runs and instance interruptions.
-Volumes are ideal for storing intermediate work and data that should be quickly accessible.
-
-You can also load and save data using an object storage like S3 or HuggingFace Datasets.
-For models, it's best to use services like HuggingFace Hub.
-`dstack` has no explicit support for object storage.
-You can load and save data directly from your code.
-
-## Idle instances
-
-By default, the `dstack` run command reuses an idle instance from the pool. If no instance matches the requirements, it creates a new one.
-
-When the run finishes, the instance remains idle for the configured time (by default, `5m`) before it gets destroyed.
-
-You can change the default idle duration by using ``--idle-duration DURATION`` with `dstack run`, or
-set `termination_idle_duration` in the configuration or profile.
-
-An idle instance can be destroyed at any time via `dstack pool rm INSTANCE_NAME`.
-
-## Profiles
-
-If you don't want to specify the same parameters for each configuration, you can define them once via [profiles](reference/profiles.yml.md)
-and reuse them across configurations.
-
-This can be handy, for example, for configuring parameters such as `max_duration`, `max_price`, `termination_idle_duration`,
-`regions`, etc.
-
-Set `default` to `true` in your profile, and it will be applied automatically to any run.
-
-## Attached mode
-
-By default, `dstack run` runs in attached mode.
-This means it streams the logs as they come in and, in the case of a task, forwards its ports to `localhost`.
-
-If you detach the CLI, you can re-attach it using `dstack logs -a RUN_NAME`.
-
-To run in detached mode, use `-d` with `dstack run`.
-
-## GPU
-
-`dstack` natively supports NVIDIA GPU, and Google Cloud TPU accelerator chips.
-
-The `gpu` property withing `resources` (or the `--gpu` option with `dstack run`)
-allows specifying not only memory size but also GPU names, their memory, and quantity.
-
-Examples:
-
-- `1` (any GPU)
-- `A100` (A100)
-- `24GB..` (any GPU starting from 24GB)
-- `24GB..40GB:2` (two GPUs between 24GB and 40GB)
-- `A10G,A100` (either A10G or A100)
-- `A100:80GB` (one A100 of 80GB)
-- `A100:2` (two A100)
-- `A100:40GB:2` (two A100 40GB)
-- `tpu-v2-8` (`v2` with 8 TPU cores)
-
-??? info "Google Cloud TPU"
- Currently, you can't specify other than 8 TPU cores. This means only single host workloads are supported.
- Support for multiple hosts is coming soon.
-
-## Service quotas
-
-If you're using your own AWS, GCP, Azure, or OCI accounts, before you can use GPUs or spot instances, you have to request the
-corresponding service quotas for each type of instance in each region.
-
-??? info "AWS"
- Check this [guide :material-arrow-top-right-thin:{ .external }](https://docs.aws.amazon.com/AWSEC2/latest/UserGuide/ec2-resource-limits.html){:target="_blank"} on EC2 service quotas.
- The relevant service quotas include:
-
- - `Running On-Demand P instances` (on-demand V100, A100 80GB x8)
- - `All P4, P3 and P2 Spot Instance Requests` (spot V100, A100 80GB x8)
- - `Running On-Demand G and VT instances` (on-demand T4, A10G, L4)
- - `All G and VT Spot Instance Requests` (spot T4, A10G, L4)
- - `Running Dedicated p5 Hosts` (on-demand H100)
- - `All P5 Spot Instance Requests` (spot H100)
-
-??? info "GCP"
- Check this [guide :material-arrow-top-right-thin:{ .external }](https://cloud.google.com/compute/resource-usage){:target="_blank"} on Compute Engine service quotas.
- The relevant service quotas include:
-
- - `NVIDIA V100 GPUs` (on-demand V100)
- - `Preemtible V100 GPUs` (spot V100)
- - `NVIDIA T4 GPUs` (on-demand T4)
- - `Preemtible T4 GPUs` (spot T4)
- - `NVIDIA L4 GPUs` (on-demand L4)
- - `Preemtible L4 GPUs` (spot L4)
- - `NVIDIA A100 GPUs` (on-demand A100)
- - `Preemtible A100 GPUs` (spot A100)
- - `NVIDIA A100 80GB GPUs` (on-demand A100 80GB)
- - `Preemtible A100 80GB GPUs` (spot A100 80GB)
- - `NVIDIA H100 GPUs` (on-demand H100)
- - `Preemtible H100 GPUs` (spot H100)
-
-??? info "Azure"
- Check this [guide :material-arrow-top-right-thin:{ .external }](https://learn.microsoft.com/en-us/azure/quotas/quickstart-increase-quota-portal){:target="_blank"} on Azure service quotas.
- The relevant service quotas include:
-
- - `Total Regional Spot vCPUs` (any spot instances)
- - `Standard NCASv3_T4 Family vCPUs` (on-demand T4)
- - `Standard NVADSA10v5 Family vCPUs` (on-demand A10)
- - `Standard NCADS_A100_v4 Family vCPUs` (on-demand A100 80GB)
- - `Standard NDASv4_A100 Family vCPUs` (on-demand A100 40GB x8)
- - `Standard NDAMSv4_A100Family vCPUs` (on-demand A100 80GB x8)
- - `Standard NCadsH100v5 Family vCPUs` (on-demand H100)
- - `Standard NDSH100v5 Family vCPUs` (on-demand H100 x8)
-
-??? info "OCI"
- Check this [guide :material-arrow-top-right-thin:{ .external }](https://docs.oracle.com/en-us/iaas/Content/General/Concepts/servicelimits.htm#Requesti){:target="_blank"} on requesting OCI service limits increase.
- The relevant service category is compute. The relevant resources include:
-
- - `GPUs for GPU.A10 based VM and BM instances` (on-demand A10)
- - `GPUs for GPU2 based VM and BM instances` (on-demand P100)
- - `GPUs for GPU3 based VM and BM instances` (on-demand V100)
-
-Note, for AWS, GCP, and Azure, service quota values are measured with the number of CPUs rather than GPUs.
diff --git a/docs/docs/quickstart.md b/docs/docs/quickstart.md
deleted file mode 100644
index 5cb0cea6b9..0000000000
--- a/docs/docs/quickstart.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# Quickstart
-
-!!! info "Installation"
- Before using `dstack`, either set up the open-source server, or sign up
- with `dstack Sky`.
- See [Installation](installation/index.md) for more details.
-
-## Initialize a repo
-
-To use `dstack`'s CLI in a folder, first run [`dstack init`](reference/cli/index.md#dstack-init) within that folder.
-
-
-
-```shell
-$ mkdir quickstart && cd quickstart
-$ dstack init
-```
-
-
-
-Your folder can be a regular local folder or a Git repo.
-
-## Define a configuration
-
-Define what you want to run as a YAML file. The filename must end with `.dstack.yml` (e.g., `.dstack.yml`
-or `train.dstack.yml` are both acceptable).
-
-=== "Dev environment"
-
- Dev environments allow you to quickly provision a machine with a pre-configured environment, resources, IDE, code, etc.
-
-
-
- ```yaml
- type: dev-environment
-
- # Use either `python` or `image` to configure environment
- python: "3.11"
- # image: ghcr.io/huggingface/text-generation-inference:latest
-
- ide: vscode
-
- # (Optional) Configure `gpu`, `memory`, `disk`, etc
- resources:
- gpu: 24GB
- ```
-
-
-
-=== "Task"
-
- Tasks make it very easy to run any scripts, be it for training, data processing, or web apps. They allow you to pre-configure the environment, resources, code, etc.
-
-
-
- ```yaml
- type: task
-
- python: "3.11"
- env:
- - HF_HUB_ENABLE_HF_TRANSFER=1
- commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
-
- # (Optional) Configure `gpu`, `memory`, `disk`, etc
- resources:
- gpu: 24GB
- ```
-
-
-
- Ensure `requirements.txt` and `train.py` are in your folder. You can take them from [`examples`](https://github.com/dstackai/dstack/tree/master/examples/fine-tuning/qlora).
-
-=== "Service"
-
- Services make it easy to deploy models and apps cost-effectively as public endpoints, allowing you to use any frameworks.
-
-
-
- ```yaml
- type: service
-
- image: ghcr.io/huggingface/text-generation-inference:latest
- env:
- - HUGGING_FACE_HUB_TOKEN # required to run gated models
- - MODEL_ID=mistralai/Mistral-7B-Instruct-v0.1
- commands:
- - text-generation-launcher --port 8000 --trust-remote-code
- port: 8000
-
- # (Optional) Configure `gpu`, `memory`, `disk`, etc
- resources:
- gpu: 24GB
- ```
-
-
-
-## Run configuration
-
-Run a configuration using the [`dstack run`](reference/cli/index.md#dstack-run) command, followed by the working directory path (e.g., `.`),
-and the path to the configuration file.
-
-
-
-```shell
-$ dstack run . -f train.dstack.yml
-
- BACKEND REGION RESOURCES SPOT PRICE
- tensordock unitedkingdom 10xCPU, 80GB, 1xA100 (80GB) no $1.595
- azure westus3 24xCPU, 220GB, 1xA100 (80GB) no $3.673
- azure westus2 24xCPU, 220GB, 1xA100 (80GB) no $3.673
-
-Continue? [y/n]: y
-
-Provisioning...
----> 100%
-
-Epoch 0: 100% 1719/1719 [00:18<00:00, 92.32it/s, loss=0.0981, acc=0.969]
-Epoch 1: 100% 1719/1719 [00:18<00:00, 92.32it/s, loss=0.0981, acc=0.969]
-Epoch 2: 100% 1719/1719 [00:18<00:00, 92.32it/s, loss=0.0981, acc=0.969]
-```
-
-
-
-The `dstack run` command automatically uploads your code, including any local uncommitted changes.
-To exclude any files from uploading, use `.gitignore`.
-
-## What's next?
-
-1. Read about [dev environments](concepts/dev-environments.md), [tasks](concepts/tasks.md),
- [services](concepts/services.md), and [pools](concepts/pools.md)
-2. Browse [examples :material-arrow-top-right-thin:{ .external }](https://github.com/dstackai/dstack/tree/master/examples){:target="_blank"}
-3. Join the community via [Discord :material-arrow-top-right-thin:{ .external }](https://discord.gg/u8SmfwPpMd)
\ No newline at end of file
diff --git a/docs/docs/reference/api/python/index.md b/docs/docs/reference/api/python/index.md
deleted file mode 100644
index 6c7d3cf821..0000000000
--- a/docs/docs/reference/api/python/index.md
+++ /dev/null
@@ -1,218 +0,0 @@
-# Python API
-
-The Python API enables running tasks, services, and managing runs programmatically.
-
-## Usage example
-
-Below is a quick example of submitting a task for running and displaying its logs.
-
-```python
-import sys
-
-from dstack.api import Task, GPU, Client, Resources
-
-client = Client.from_config()
-
-task = Task(
- image="ghcr.io/huggingface/text-generation-inference:latest",
- env={"MODEL_ID": "TheBloke/Llama-2-13B-chat-GPTQ"},
- commands=[
- "text-generation-launcher --trust-remote-code --quantize gptq",
- ],
- ports=["80"],
- resources=Resources(gpu=GPU(memory="24GB")),
-)
-
-run = client.runs.submit(
- run_name="my-awesome-run", # If not specified, a random name is assigned
- configuration=task,
- repo=None, # Specify to mount additional files
-)
-
-run.attach()
-
-try:
- for log in run.logs():
- sys.stdout.buffer.write(log)
- sys.stdout.buffer.flush()
-except KeyboardInterrupt:
- run.stop(abort=True)
-finally:
- run.detach()
-```
-
-!!! info "NOTE:"
- 1. The `configuration` argument in the `submit` method can be either `dstack.api.Task` or `dstack.api.Service`.
- 2. If you create `dstack.api.Task` or `dstack.api.Service`, you may specify the `image` argument. If `image` isn't
- specified, the default image will be used. For a private Docker registry, ensure you also pass the `registry_auth` argument.
- 3. The `repo` argument in the `submit` method allows the mounting of a local folder, a remote repo, or a
- programmatically created repo. In this case, the `commands` argument can refer to the files within this repo.
- 4. The `attach` method waits for the run to start and, for `dstack.api.Task` sets up an SSH tunnel and forwards
- configured `ports` to `localhost`.
-
-## `dstack.api` { #dstack.api data-toc-label="dstack.api" }
-
-### `dstack.api.Client` { #dstack.api.Client data-toc-label="Client" }
-
-::: dstack.api.Client
- options:
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
-
-### `dstack.api.RunCollection` { #dstack.api.Client.runs data-toc-label="RunCollection" }
-
-::: dstack.api.RunCollection
- options:
- show_bases: false
- show_symbol_type_heading: true
- show_root_toc_entry: false
- heading_level: 4
-
-### `dstack.api.RepoCollection` { #dstack.api.Client.repos data-toc-label="RepoCollection" }
-
-::: dstack.api.RepoCollection
- options:
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
-
-[//]: # (### `dstack.api.BackendCollection` { #dstack.api.Client.backends data-toc-label="BackendCollection" })
-
-[//]: # (::: dstack.api.BackendCollection)
-[//]: # ( options:)
-[//]: # ( show_bases: false)
-[//]: # ( show_root_heading: false)
-[//]: # ( show_root_toc_entry: false)
-[//]: # ( heading_level: 4)
-
-### `dstack.api.Task` { #dstack.api.Task data-toc-label="Task" }
-
-#SCHEMA# dstack.api.Task
- overrides:
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
- item_id_mapping:
- registry_auth: dstack.api.RegistryAuth
- resources: dstack.api.Resources
-
-### `dstack.api.Service` { #dstack.api.Service data-toc-label="Service" }
-
-#SCHEMA# dstack.api.Service
- overrides:
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
- item_id_mapping:
- scaling: dstack.api.Scaling
- registry_auth: dstack.api.RegistryAuth
- resources: dstack.api.Resources
-
-### `dstack.api.Run` { #dstack.api.Run data-toc-label="Run" }
-
-::: dstack.api.Run
- options:
- show_bases: false
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
-
-### `dstack.api.Resources` { #dstack.api.Resources data-toc-label="Resources" }
-
-#SCHEMA# dstack.api.Resources
- overrides:
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
- item_id_mapping:
- gpu: dstack.api.GPU
- memory: dstack.api.Memory
- Range: dstack.api.Range
-
-### `dstack.api.GPU` { #dstack.api.GPU data-toc-label="GPU" }
-
-#SCHEMA# dstack.api.GPU
- overrides:
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
- item_id_mapping:
- memory: dstack.api.Memory
- Range: dstack.api.Range
-
-### `dstack.api.Disk` { #dstack.api.Disk data-toc-label="Disk" }
-
-#SCHEMA# dstack.api.Disk
- overrides:
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
- item_id_mapping:
- memory: dstack.api.Memory
- Range: dstack.api.Range
-
-### `dstack.api.LocalRepo` { #dstack.api.LocalRepo data-toc-label="LocalRepo" }
-
-::: dstack.api.LocalRepo
- options:
- show_bases: false
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
-
-### `dstack.api.RemoteRepo` { #dstack.api.RemoteRepo data-toc-label="RemoteRepo" }
-
-::: dstack.api.RemoteRepo
- options:
- show_bases: false
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
-
-### `dstack.api.VirtualRepo` { #dstack.api.VirtualRepo data-toc-label="VirtualRepo" }
-
-::: dstack.api.VirtualRepo
- options:
- show_bases: false
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
-
-### `dstack.api.RegistryAuth` { #dstack.api.RegistryAuth data-toc-label="RegistryAuth" }
-
-#SCHEMA# dstack.api.RegistryAuth
- overrides:
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
-
-### `dstack.api.Scaling` { #dstack.api.Scaling data-toc-label="Scaling" }
-
-#SCHEMA# dstack.api.Scaling
- overrides:
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
-
-### `dstack.api.BackendType` { #dstack.api.BackendType data-toc-label="BackendType" }
-
-::: dstack.api.BackendType
- options:
- show_bases: false
- show_root_heading: false
- show_root_toc_entry: false
- heading_level: 4
-
-
\ No newline at end of file
diff --git a/docs/docs/reference/api/rest/index.md b/docs/docs/reference/api/rest/index.md
deleted file mode 100644
index 99948e1bf6..0000000000
--- a/docs/docs/reference/api/rest/index.md
+++ /dev/null
@@ -1,35 +0,0 @@
----
-title: REST API
----
-
-
-!!swagger openapi.json!!
diff --git a/docs/docs/reference/cli/index.md b/docs/docs/reference/cli/index.md
deleted file mode 100644
index 5b73b94348..0000000000
--- a/docs/docs/reference/cli/index.md
+++ /dev/null
@@ -1,359 +0,0 @@
-# CLI
-
-## Commands
-
-### dstack server
-
-This command starts the `dstack` server.
-
-
-
-```shell
-$ dstack server --help
-#GENERATE#
-```
-
-
-
-[//]: # (DSTACK_SERVER_ENVIRONMENT, DSTACK_SERVER_CONFIG_DISABLED, DSTACK_SENTRY_DSN, DSTACK_SENTRY_TRACES_SAMPLE_RATE, DSTACK_SERVER_BUCKET_REGION, DSTACK_SERVER_BUCKET, DSTACK_ALEMBIC_MIGRATIONS_LOCATION)
-
-### dstack init
-
-This command must be called inside a folder before you can use `dstack run` or `dstack apply`.
-
-**Git credentials**
-
-If the current folder is a remote Git repository, `dstack init` ensures that `dstack` can access it.
-By default, the command uses the remote repo's default Git credentials. These can be overridden with
-`--git-identity` (private SSH key) or `--token` (OAuth token).
-
-
-
-```shell
-$ dstack init --help
-#GENERATE#
-```
-
-
-
-**User SSH key**
-
-By default, `dstack` uses its own SSH key to access instances (`~/.dstack/ssh/id_rsa`).
-It is possible to override this key via the `--ssh-identity` argument.
-
-### dstack run
-
-This command runs a given configuration.
-
-
-
-```shell
-$ dstack run . --help
-#GENERATE#
-```
-
-
-
-??? info ".gitignore"
- When running anything via CLI, `dstack` uses the exact version of code from your project directory.
-
- If there are large files, consider creating a `.gitignore` file to exclude them for better performance.
-
-### dstack apply
-
-This command applies a given configuration. If a resource does not exist, `dstack apply` creates the resource.
-If a resource exists, `dstack apply` updates the resource in-place or re-creates the resource if the update is not possible.
-
-
-
-```shell
-$ dstack apply --help
-#GENERATE#
-```
-
-
-
-!!! info "NOTE:"
- The `dstack apply` command currently supports only `gateway` and `volume` configurations.
- Support for other configuration types is coming soon.
-
-### dstack delete
-
-This command deletes the resources defined by a given configuration.
-
-
-
-```shell
-$ dstack delete --help
-#GENERATE#
-```
-
-
-
-!!! info "NOTE:"
- The `dstack delete` command currently supports only `gateway` configurations.
- Support for other configuration types is coming soon.
-
-### dstack ps
-
-This command shows the status of runs.
-
-
-
-```shell
-$ dstack ps --help
-#GENERATE#
-```
-
-
-
-### dstack stop
-
-This command stops run(s) within the current repository.
-
-
-
-```shell
-$ dstack stop --help
-#GENERATE#
-```
-
-
-
-### dstack logs
-
-This command shows the output of a given run within the current repository.
-
-
-
-```shell
-$ dstack logs --help
-#GENERATE#
-```
-
-
-
-### dstack config
-
-Both the CLI and API need to be configured with the server address, user token, and project name
-via `~/.dstack/config.yml`.
-
-At startup, the server automatically configures CLI and API with the server address, user token, and
-the default project name (`main`). This configuration is stored via `~/.dstack/config.yml`.
-
-To use CLI and API on different machines or projects, use the `dstack config` command.
-
-
-
-```shell
-$ dstack config --help
-#GENERATE#
-```
-
-
-
-### dstack pool
-
-Pools allow for managing the lifecycle of instances and reusing them across runs.
-The default pool is created automatically.
-
-##### dstack pool add
-
-The `dstack pool add` command provisions a cloud instance and adds it to a pool. If no pool name is specified, the instance goes to the default pool.
-
-
-
-```shell
-$ dstack pool add --help
-#GENERATE#
-```
-
-
-
-##### dstack pool add-ssh
-
-The `dstack pool add-ssh` command adds an existing remote instance to a pool.
-If no pool name is specified, the instance goes to the default pool.
-
-
-
-```shell
-$ dstack pool add-ssh --help
-#GENERATE#
-```
-
-
-
-##### dstack pool ps
-
-The `dstack pool ps` command lists all active instances of a pool.
-If no pool name is specified, default pool instances are displayed.
-
-
-
-```shell
-$ dstack pool ps --help
-#GENERATE#
-```
-
-
-
-##### dstack pool rm
-
-The `dstack pool rm` command removes an instance from a pool.
-Cloud instances are terminated upon removal.
-
-
-
-```shell
-$ dstack pool rm --help
-#GENERATE#
-```
-
-
-
-##### dstack pool create
-
-The `dstack pool create` command creates a new pool.
-
-
-
-```shell
-$ dstack pool create --help
-#GENERATE#
-```
-
-
-
-##### dstack pool list
-
-The `dstack pool list` command lists all existing pools.
-
-
-
-```shell
-$ dstack pool delete --help
-#GENERATE#
-```
-
-
-
-##### dstack pool set-default
-
-The `dstack pool set-default` command sets the project's default pool.
-
-
-
-```shell
-$ dstack pool set-default --help
-#GENERATE#
-```
-
-
-
-##### dstack pool delete
-
-The `dstack pool delete` command deletes a specified pool.
-
-
-
-```shell
-$ dstack pool delete --help
-#GENERATE#
-```
-
-
-
-### dstack gateway
-
-A gateway is required for running services. It handles ingress traffic, authorization, domain mapping, model mapping
-for the OpenAI-compatible endpoint, and so on.
-
-##### dstack gateway list
-
-The `dstack gateway list` command displays the names and addresses of the gateways configured in the project.
-
-
-
-```shell
-$ dstack gateway list --help
-#GENERATE#
-```
-
-
-
-##### dstack gateway create
-
-The `dstack gateway create` command creates a new gateway instance in the project.
-
-
-
-```shell
-$ dstack gateway create --help
-#GENERATE#
-```
-
-
-
-##### dstack gateway delete
-
-The `dstack gateway delete` command deletes the specified gateway.
-
-
-
-```shell
-$ dstack gateway delete --help
-#GENERATE#
-```
-
-
-
-##### dstack gateway update
-
-The `dstack gateway update` command updates the specified gateway.
-
-
-
-```shell
-$ dstack gateway update --help
-#GENERATE#
-```
-
-
-
-### dstack volume
-
-The volumes commands.
-
-##### dstack volume list
-
-The `dstack volume list` command lists volumes.
-
-
-
-```shell
-$ dstack volume list --help
-#GENERATE#
-```
-
-
-
-## Environment variables
-
- * `DSTACK_CLI_LOG_LEVEL` – (Optional) Configures CLI logging level. Defaults to `INFO`.
- * `DSTACK_SERVER_LOG_LEVEL` – (Optional) Has the same effect as `--log-level`. Defaults to `INFO`.
- * `DSTACK_SERVER_HOST` – (Optional) Has the same effect as `--host`. Defaults to `127.0.0.1`.
- * `DSTACK_SERVER_PORT` – (Optional) Has the same effect as `--port`. Defaults to `3000`.
- * `DSTACK_SERVER_ADMIN_TOKEN` – (Optional) Has the same effect as `--token`. Defaults to `None`.
- * `DSTACK_DATABASE_URL` – (Optional) The database URL to use instead of default SQLite. Currently `dstack` supports Postgres. Example: `postgresql+asyncpg://myuser:mypassword@localhost:5432/mydatabase`. Defaults to `None`.
- * `DSTACK_SERVER_DIR` – (Optional) Sets path to store data and server configs. Defaults to `~/.dstack/server`.
-
-??? info "Internal environment variables"
- * `DSTACK_SERVER_ROOT_LOG_LEVEL` – (Optional) Sets root logger log level. Defaults to `ERROR`.
- * `DSTACK_SERVER_LOG_FORMAT` – (Optional) Sets format of log output. Can be `rich`, `standard`, `json`.. Defaults to `rich`.
- * `DSTACK_SERVER_UVICORN_LOG_LEVEL` – (Optional) Sets uvicorn logger log level. Defaults to `ERROR`.
- * `DSTACK_PROFILE` – (Optional) Has the same effect as `--profile`. Defaults to `None`.
- * `DSTACK_PROJECT` – (Optional) Has the same effect as `--project`. Defaults to `None`.
- * `DSTACK_RUNNER_VERSION` – (Optional) Sets exact runner version for debug. Defaults to `latest`.
- * `DSTACK_DEFAULT_CREDS_DISABLED` – (Optional) Disables default credentials detection if set. Defaults to `None`.
- * `DSTACK_LOCAL_BACKEND_ENABLED` – (Optional) Enables local backend for debug if set. Defaults to `None`.
\ No newline at end of file
diff --git a/docs/docs/reference/dstack.yml.md b/docs/docs/reference/dstack.yml.md
deleted file mode 100644
index 04b20b154c..0000000000
--- a/docs/docs/reference/dstack.yml.md
+++ /dev/null
@@ -1,5 +0,0 @@
-# .dstack.yml
-
-- [`dev-environment`](dstack.yml/dev-environment.md)
-- [`task`](dstack.yml/task.md)
-- [`service`](dstack.yml/service.md)
\ No newline at end of file
diff --git a/docs/docs/reference/dstack.yml/dev-environment.md b/docs/docs/reference/dstack.yml/dev-environment.md
deleted file mode 100644
index 1c129ad538..0000000000
--- a/docs/docs/reference/dstack.yml/dev-environment.md
+++ /dev/null
@@ -1,269 +0,0 @@
-# dev-environment
-
-The `dev-environment` configuration type allows running [dev environments](../../concepts/dev-environments.md).
-
-> Configuration files must have a name ending with `.dstack.yml` (e.g., `.dstack.yml` or `serve.dstack.yml` are both acceptable)
-> and can be located in the project's root directory or any nested folder.
-> Any configuration can be run via [`dstack run`](../cli/index.md#dstack-run).
-
-## Examples
-
-### Python version
-
-If you don't specify `image`, `dstack` uses the default Docker image pre-configured with
-`python`, `pip`, `conda` (Miniforge), and essential CUDA drivers.
-The `python` property determines which default Docker image is used.
-
-
-
-```yaml
-type: dev-environment
-
-python: "3.11"
-
-ide: vscode
-```
-
-
-
-!!! info "nvcc"
- Note that the default Docker image doesn't bundle `nvcc`, which is required for building custom CUDA kernels.
- To install it, use `conda install cuda`.
-
-### Docker image
-
-
-
-```yaml
-type: dev-environment
-
-image: ghcr.io/huggingface/text-generation-inference:latest
-
-ide: vscode
-```
-
-
-
-??? info "Private registry"
-
- Use the `registry_auth` property to provide credentials for a private Docker registry.
-
- ```yaml
- type: dev-environment
-
- image: ghcr.io/huggingface/text-generation-inference:latest
- registry_auth:
- username: peterschmidt85
- password: ghp_e49HcZ9oYwBzUbcSk2080gXZOU2hiT9AeSR5
-
- ide: vscode
- ```
-
-### Resources { #_resources }
-
-If you specify memory size, you can either specify an explicit size (e.g. `24GB`) or a
-range (e.g. `24GB..`, or `24GB..80GB`, or `..80GB`).
-
-
-
-```yaml
-type: dev-environment
-
-ide: vscode
-
-resources:
- # 200GB or more RAM
- memory: 200GB..
-
- # 4 GPUs from 40GB to 80GB
- gpu: 40GB..80GB:4
-
- # Shared memory
- shm_size: 16GB
-
- disk: 500GB
-```
-
-
-
-The `gpu` property allows specifying not only memory size but also GPU names
-and their quantity. Examples: `A100` (one A100), `A10G,A100` (either A10G or A100),
-`A100:80GB` (one A100 of 80GB), `A100:2` (two A100), `24GB..40GB:2` (two GPUs between 24GB and 40GB),
-`A100:40GB:2` (two A100 GPUs of 40GB).
-
-??? info "Google Cloud TPU"
- To use TPUs, specify its architecture prefixed by `tpu-` via the `gpu` property.
-
- ```yaml
- type: dev-environment
-
- ide: vscode
-
- resources:
- gpu: tpu-v2-8
- ```
-
- Currently, only 8 TPU cores can be specified, supporting single TPU device workloads. Multi-TPU support is coming soon.
-
-??? info "Shared memory"
- If you are using parallel communicating processes (e.g., dataloaders in PyTorch), you may need to configure
- `shm_size`, e.g. set it to `16GB`.
-
-### Environment variables
-
-
-
-```yaml
-type: dev-environment
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - HF_HUB_ENABLE_HF_TRANSFER=1
-
-ide: vscode
-```
-
-
-
-If you don't assign a value to an environment variable (see `HUGGING_FACE_HUB_TOKEN` above),
-`dstack` will require the value to be passed via the CLI or set in the current process.
-
-For instance, you can define environment variables in a `.env` file and utilize tools like `direnv`.
-
-#### Default environment variables
-
-The following environment variables are available in any run and are passed by `dstack` by default:
-
-| Name | Description |
-|-------------------------|-----------------------------------------|
-| `DSTACK_RUN_NAME` | The name of the run |
-| `DSTACK_REPO_ID` | The ID of the repo |
-| `DSTACK_GPUS_NUM` | The total number of GPUs in the run |
-
-### Spot policy
-
-You can choose whether to use spot instances, on-demand instances, or any available type.
-
-
-
-```yaml
-type: dev-environment
-
-ide: vscode
-
-spot_policy: auto
-```
-
-
-
-The `spot_policy` accepts `spot`, `on-demand`, and `auto`. The default for dev environments is `on-demand`.
-
-### Backends
-
-By default, `dstack` provisions instances in all configured backends. However, you can specify the list of backends:
-
-
-
-```yaml
-type: dev-environment
-
-ide: vscode
-
-backends: [aws, gcp]
-```
-
-
-
-### Regions
-
-By default, `dstack` uses all configured regions. However, you can specify the list of regions:
-
-
-
-```yaml
-type: dev-environment
-
-ide: vscode
-
-regions: [eu-west-1, eu-west-2]
-```
-
-
-
-### Volumes
-
-Volumes allow you to persist data between runs.
-To attach a volume, simply specify its name using the `volumes` property and specify where to mount its contents:
-
-
-
-```yaml
-type: dev-environment
-
-ide: vscode
-
-volumes:
- - name: my-new-volume
- path: /volume_data
-```
-
-
-
-Once you run this configuration, the contents of the volume will be attached to `/volume_data` inside the development
-environment, and its contents will persist across runs.
-
-!!! info "Limitations"
- When you're running a dev environment, task, or service with `dstack`, it automatically mounts the project folder contents
- to `/workflow` (and sets that as the current working directory). Right now, `dstack` doesn't allow you to
- attach volumes to `/workflow` or any of its subdirectories.
-
-The `dev-environment` configuration type supports many other options. See below.
-
-## Root reference
-
-#SCHEMA# dstack._internal.core.models.configurations.DevEnvironmentConfiguration
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `resources`
-
-#SCHEMA# dstack._internal.core.models.resources.ResourcesSpecSchema
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: resources-
-
-## `resources.gpu` { #resources-gpu data-toc-label="resources.gpu" }
-
-#SCHEMA# dstack._internal.core.models.resources.GPUSpecSchema
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `resources.disk` { #resources-disk data-toc-label="resources.disk" }
-
-#SCHEMA# dstack._internal.core.models.resources.DiskSpecSchema
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `registry_auth`
-
-#SCHEMA# dstack._internal.core.models.configurations.RegistryAuth
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `volumes`
-
-#SCHEMA# dstack._internal.core.models.volumes.VolumeMountPoint
- overrides:
- show_root_heading: false
- type:
- required: true
diff --git a/docs/docs/reference/dstack.yml/gateway.md b/docs/docs/reference/dstack.yml/gateway.md
deleted file mode 100644
index 6be8b4d2b0..0000000000
--- a/docs/docs/reference/dstack.yml/gateway.md
+++ /dev/null
@@ -1,47 +0,0 @@
-# gateway
-
-The `gateway` configuration type allows creating and updating [gateways](../../concepts/services.md).
-
-> Configuration files must have a name ending with `.dstack.yml` (e.g., `.dstack.yml` or `gateway.dstack.yml` are both acceptable)
-> and can be located in the project's root directory or any nested folder.
-> Any configuration can be applied via [`dstack apply`](../cli/index.md#dstack-apply).
-
-## Examples
-
-
-
-```yaml
-type: gateway
-name: example-gateway
-
-backend: aws
-region: eu-west-1
-domain: example.com
-```
-
-
-
-
-## Root reference
-
-#SCHEMA# dstack._internal.core.models.gateways.GatewayConfiguration
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `certificate[type=lets-encrypt]`
-
-#SCHEMA# dstack._internal.core.models.gateways.LetsEncryptGatewayCertificate
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `certificate[type=acm]`
-
-#SCHEMA# dstack._internal.core.models.gateways.ACMGatewayCertificate
- overrides:
- show_root_heading: false
- type:
- required: true
diff --git a/docs/docs/reference/dstack.yml/service.md b/docs/docs/reference/dstack.yml/service.md
deleted file mode 100644
index 25345e431c..0000000000
--- a/docs/docs/reference/dstack.yml/service.md
+++ /dev/null
@@ -1,442 +0,0 @@
-# service
-
-The `service` configuration type allows running [services](../../concepts/services.md).
-
-> Configuration files must have a name ending with `.dstack.yml` (e.g., `.dstack.yml` or `serve.dstack.yml` are both acceptable)
-> and can be located in the project's root directory or any nested folder.
-> Any configuration can be run via [`dstack run . -f PATH`](../cli/index.md#dstack-run).
-
-## Examples
-
-### Python version
-
-If you don't specify `image`, `dstack` uses the default Docker image pre-configured with
-`python`, `pip`, `conda` (Miniforge), and essential CUDA drivers.
-The `python` property determines which default Docker image is used.
-
-
-
-```yaml
-type: service
-
-python: "3.11"
-
-commands:
- - python3 -m http.server
-
-port: 8000
-```
-
-
-
-!!! info "nvcc"
- Note that the default Docker image doesn't bundle `nvcc`, which is required for building custom CUDA kernels.
- To install it, use `conda install cuda`.
-
-### Docker image
-
-
-
- ```yaml
- type: service
-
- image: dstackai/base:py3.11-0.4-cuda-12.1
-
- commands:
- - python3 -m http.server
-
- port: 8000
- ```
-
-
-
-??? info "Private Docker registry"
-
- Use the `registry_auth` property to provide credentials for a private Docker registry.
-
- ```yaml
- type: service
-
- image: dstackai/base:py3.11-0.4-cuda-12.1
-
- commands:
- - python3 -m http.server
- registry_auth:
- username: peterschmidt85
- password: ghp_e49HcZ9oYwBzUbcSk2080gXZOU2hiT9AeSR5
-
- port: 8000
- ```
-
-### OpenAI-compatible interface { #model-mapping }
-
-By default, if you run a service, its endpoint is accessible at `https://.`.
-
-If you run a model, you can optionally configure the mapping to make it accessible via the
-OpenAI-compatible interface.
-
-
-
-```yaml
-type: service
-
-python: "3.11"
-
-env:
- - MODEL=NousResearch/Llama-2-7b-chat-hf
-commands:
- - pip install vllm
- - python -m vllm.entrypoints.openai.api_server --model $MODEL --port 8000
-port: 8000
-
-resources:
- gpu: 24GB
-
-# Enable the OpenAI-compatible endpoint
-model:
- format: openai
- type: chat
- name: NousResearch/Llama-2-7b-chat-hf
-```
-
-
-
-In this case, with such a configuration, once the service is up, you'll be able to access the model at
-`https://gateway.` via the OpenAI-compatible interface.
-
-The `format` supports only `tgi` (Text Generation Inference)
-and `openai` (if you are using Text Generation Inference or vLLM with OpenAI-compatible mode).
-
-??? info "Chat template"
-
- By default, `dstack` loads the [chat template](https://huggingface.co/docs/transformers/main/en/chat_templating)
- from the model's repository. If it is not present there, manual configuration is required.
-
- ```yaml
- type: service
-
- image: ghcr.io/huggingface/text-generation-inference:latest
- env:
- - MODEL_ID=TheBloke/Llama-2-13B-chat-GPTQ
- commands:
- - text-generation-launcher --port 8000 --trust-remote-code --quantize gptq
- port: 8000
-
- resources:
- gpu: 80GB
-
- # Enable the OpenAI-compatible endpoint
- model:
- type: chat
- name: TheBloke/Llama-2-13B-chat-GPTQ
- format: tgi
- chat_template: "{% if messages[0]['role'] == 'system' %}{% set loop_messages = messages[1:] %}{% set system_message = messages[0]['content'] %}{% else %}{% set loop_messages = messages %}{% set system_message = false %}{% endif %}{% for message in loop_messages %}{% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}{{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}{% endif %}{% if loop.index0 == 0 and system_message != false %}{% set content = '<>\\n' + system_message + '\\n< >\\n\\n' + message['content'] %}{% else %}{% set content = message['content'] %}{% endif %}{% if message['role'] == 'user' %}{{ '[INST] ' + content.strip() + ' [/INST]' }}{% elif message['role'] == 'assistant' %}{{ ' ' + content.strip() + ' ' }}{% endif %}{% endfor %}"
- eos_token: ""
- ```
-
- ##### Limitations
-
- Please note that model mapping is an experimental feature with the following limitations:
-
- 1. Doesn't work if your `chat_template` uses `bos_token`. As a workaround, replace `bos_token` inside `chat_template` with the token content itself.
- 2. Doesn't work if `eos_token` is defined in the model repository as a dictionary. As a workaround, set `eos_token` manually, as shown in the example above (see Chat template).
-
- If you encounter any other issues, please make sure to file a [GitHub issue](https://github.com/dstackai/dstack/issues/new/choose).
-
-
-### Auto-scaling
-
-By default, `dstack` runs a single replica of the service.
-You can configure the number of replicas as well as the auto-scaling rules.
-
-
-
-```yaml
-type: service
-
-python: "3.11"
-
-env:
- - MODEL=NousResearch/Llama-2-7b-chat-hf
-commands:
- - pip install vllm
- - python -m vllm.entrypoints.openai.api_server --model $MODEL --port 8000
-port: 8000
-
-resources:
- gpu: 24GB
-
-# Enable the OpenAI-compatible endpoint
-model:
- format: openai
- type: chat
- name: NousResearch/Llama-2-7b-chat-hf
-
-replicas: 1..4
-scaling:
- metric: rps
- target: 10
-```
-
-
-
-The [`replicas`](#replicas) property can be a number or a range.
-
-> The [`metric`](#metric) property of [`scaling`](#scaling) only supports the `rps` metric (requests per second). In this
-> case `dstack` adjusts the number of replicas (scales up or down) automatically based on the load.
-
-Setting the minimum number of replicas to `0` allows the service to scale down to zero when there are no requests.
-
-### Resources { #_resources }
-
-If you specify memory size, you can either specify an explicit size (e.g. `24GB`) or a
-range (e.g. `24GB..`, or `24GB..80GB`, or `..80GB`).
-
-
-
-```yaml
-type: service
-
-python: "3.11"
-commands:
- - pip install vllm
- - python -m vllm.entrypoints.openai.api_server
- --model mistralai/Mixtral-8X7B-Instruct-v0.1
- --host 0.0.0.0
- --tensor-parallel-size 2 # Match the number of GPUs
-port: 8000
-
-resources:
- # 2 GPUs of 80GB
- gpu: 80GB:2
-
- disk: 200GB
-
-# Enable the OpenAI-compatible endpoint
-model:
- type: chat
- name: TheBloke/Mixtral-8x7B-Instruct-v0.1-GPTQ
- format: openai
-```
-
-
-
-The `gpu` property allows specifying not only memory size but also GPU names
-and their quantity. Examples: `A100` (one A100), `A10G,A100` (either A10G or A100),
-`A100:80GB` (one A100 of 80GB), `A100:2` (two A100), `24GB..40GB:2` (two GPUs between 24GB and 40GB),
-`A100:40GB:2` (two A100 GPUs of 40GB).
-
-??? info "Shared memory"
- If you are using parallel communicating processes (e.g., dataloaders in PyTorch), you may need to configure
- `shm_size`, e.g. set it to `16GB`.
-
-### Authorization
-
-By default, the service endpoint requires the `Authorization` header with `"Bearer "`.
-Authorization can be disabled by setting `auth` to `false`.
-
-
-
-```yaml
-type: service
-
-python: "3.11"
-
-commands:
- - python3 -m http.server
-
-port: 8000
-
-auth: false
-```
-
-
-
-### Environment variables
-
-
-
-```yaml
-type: service
-
-python: "3.11"
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - MODEL=NousResearch/Llama-2-7b-chat-hf
-commands:
- - pip install vllm
- - python -m vllm.entrypoints.openai.api_server --model $MODEL --port 8000
-port: 8000
-
-resources:
- gpu: 24GB
-```
-
-
-
-If you don't assign a value to an environment variable (see `HUGGING_FACE_HUB_TOKEN` above),
-`dstack` will require the value to be passed via the CLI or set in the current process.
-
-For instance, you can define environment variables in a `.env` file and utilize tools like `direnv`.
-
-#### Default environment variables
-
-The following environment variables are available in any run and are passed by `dstack` by default:
-
-| Name | Description |
-|-------------------------|-----------------------------------------|
-| `DSTACK_RUN_NAME` | The name of the run |
-| `DSTACK_REPO_ID` | The ID of the repo |
-| `DSTACK_GPUS_NUM` | The total number of GPUs in the run |
-
-### Spot policy
-
-You can choose whether to use spot instances, on-demand instances, or any available type.
-
-
-
-```yaml
-type: service
-
-commands:
- - python3 -m http.server
-
-port: 8000
-
-spot_policy: auto
-```
-
-
-
-The `spot_policy` accepts `spot`, `on-demand`, and `auto`. The default for services is `auto`.
-
-### Backends
-
-By default, `dstack` provisions instances in all configured backends. However, you can specify the list of backends:
-
-
-
-```yaml
-type: service
-
-commands:
- - python3 -m http.server
-
-port: 8000
-
-backends: [aws, gcp]
-```
-
-
-
-### Regions
-
-By default, `dstack` uses all configured regions. However, you can specify the list of regions:
-
-
-
-```yaml
-type: service
-
-commands:
- - python3 -m http.server
-
-port: 8000
-
-regions: [eu-west-1, eu-west-2]
-```
-
-
-
-### Volumes
-
-Volumes allow you to persist data between runs.
-To attach a volume, simply specify its name using the `volumes` property and specify where to mount its contents:
-
-
-
-```yaml
-type: service
-
-commands:
- - python3 -m http.server
-
-port: 8000
-
-volumes:
- - name: my-new-volume
- path: /volume_data
-```
-
-
-
-Once you run this configuration, the contents of the volume will be attached to `/volume_data` inside the service,
-and its contents will persist across runs.
-
-The `service` configuration type supports many other options. See below.
-
-## Root reference
-
-#SCHEMA# dstack._internal.core.models.configurations.ServiceConfiguration
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `model`
-
-#SCHEMA# dstack._internal.core.models.gateways.BaseChatModel
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `scaling`
-
-#SCHEMA# dstack._internal.core.models.configurations.ScalingSpec
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `resources`
-
-#SCHEMA# dstack._internal.core.models.resources.ResourcesSpecSchema
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: resources-
-
-## `resouces.gpu` { #resources-gpu data-toc-label="resources.gpu" }
-
-#SCHEMA# dstack._internal.core.models.resources.GPUSpecSchema
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `resouces.disk` { #resources-disk data-toc-label="resources.disk" }
-
-#SCHEMA# dstack._internal.core.models.resources.DiskSpecSchema
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `registry_auth`
-
-#SCHEMA# dstack._internal.core.models.configurations.RegistryAuth
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `volumes`
-
-#SCHEMA# dstack._internal.core.models.volumes.VolumeMountPoint
- overrides:
- show_root_heading: false
- type:
- required: true
diff --git a/docs/docs/reference/dstack.yml/task.md b/docs/docs/reference/dstack.yml/task.md
deleted file mode 100644
index 2ee08168a4..0000000000
--- a/docs/docs/reference/dstack.yml/task.md
+++ /dev/null
@@ -1,416 +0,0 @@
-# task
-
-The `task` configuration type allows running [tasks](../../concepts/tasks.md).
-
-> Configuration files must have a name ending with `.dstack.yml` (e.g., `.dstack.yml` or `serve.dstack.yml` are both acceptable)
-> and can be located in the project's root directory or any nested folder.
-> Any configuration can be run via [`dstack run`](../cli/index.md#dstack-run).
-
-## Examples
-
-### Python version
-
-If you don't specify `image`, `dstack` uses the default Docker image pre-configured with
-`python`, `pip`, `conda` (Miniforge), and essential CUDA drivers.
-The `python` property determines which default Docker image is used.
-
-
-
-```yaml
-type: task
-
-python: "3.11"
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
-```
-
-
-
-!!! info "nvcc"
- Note that the default Docker image doesn't bundle `nvcc`, which is required for building custom CUDA kernels.
- To install it, use `conda install cuda`.
-
-### Ports { #_ports }
-
-A task can configure ports. In this case, if the task is running an application on a port, `dstack run`
-will securely allow you to access this port from your local machine through port forwarding.
-
-
-
-```yaml
-type: task
-
-python: "3.11"
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - tensorboard --logdir results/runs &
- - python fine-tuning/qlora/train.py
-
-ports:
- - 6000
-```
-
-
-
-When running it, `dstack run` forwards `6000` port to `localhost:6000`, enabling secure access.
-See [tasks](../../concepts/tasks.md#configure-ports) for more detail.
-
-### Docker image
-
-
-
-```yaml
-type: dev-environment
-
-image: dstackai/base:py3.11-0.4-cuda-12.1
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
-```
-
-
-
-??? info "Private registry"
- Use the `registry_auth` property to provide credentials for a private Docker registry.
-
- ```yaml
- type: dev-environment
-
- image: dstackai/base:py3.11-0.4-cuda-12.1
- registry_auth:
- username: peterschmidt85
- password: ghp_e49HcZ9oYwBzUbcSk2080gXZOU2hiT9AeSR5
-
- commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
- ```
-
-### Resources { #_resources }
-
-If you specify memory size, you can either specify an explicit size (e.g. `24GB`) or a
-range (e.g. `24GB..`, or `24GB..80GB`, or `..80GB`).
-
-
-
-```yaml
-type: task
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
-
-resources:
- # 200GB or more RAM
- memory: 200GB..
-
- # 4 GPUs from 40GB to 80GB
- gpu: 40GB..80GB:4
-
- # Shared memory
- shm_size: 16GB
-
- disk: 500GB
-```
-
-
-
-The `gpu` property allows specifying not only memory size but also GPU names
-and their quantity. Examples: `A100` (one A100), `A10G,A100` (either A10G or A100),
-`A100:80GB` (one A100 of 80GB), `A100:2` (two A100), `24GB..40GB:2` (two GPUs between 24GB and 40GB),
-`A100:40GB:2` (two A100 GPUs of 40GB).
-
-??? info "Google Cloud TPU"
- To use TPUs, specify its architecture prefixed by `tpu-` via the `gpu` property.
-
- ```yaml
- type: task
-
- python: "3.11"
-
- commands:
- - pip install torch~=2.3.0 torch_xla[tpu]~=2.3.0 torchvision -f https://storage.googleapis.com/libtpu-releases/index.html
- - git clone --recursive https://github.com/pytorch/xla.git
- - python3 xla/test/test_train_mp_imagenet.py --fake_data --model=resnet50 --num_epochs=1
-
- resources:
- gpu: tpu-v2-8
- ```
-
- Currently, only 8 TPU cores can be specified, supporting single host workloads. Multi-host support is coming soon.
-
-??? info "Shared memory"
- If you are using parallel communicating processes (e.g., dataloaders in PyTorch), you may need to configure
- `shm_size`, e.g. set it to `16GB`.
-
-### Environment variables
-
-
-
-```yaml
-type: task
-
-python: "3.11"
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - HF_HUB_ENABLE_HF_TRANSFER=1
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
-```
-
-
-
-If you don't assign a value to an environment variable (see `HUGGING_FACE_HUB_TOKEN` above),
-`dstack` will require the value to be passed via the CLI or set in the current process.
-
-For instance, you can define environment variables in a `.env` file and utilize tools like `direnv`.
-
-##### Default environment variables
-
-The following environment variables are available in any run and are passed by `dstack` by default:
-
-| Name | Description |
-|-------------------------|-----------------------------------------|
-| `DSTACK_RUN_NAME` | The name of the run |
-| `DSTACK_REPO_ID` | The ID of the repo |
-| `DSTACK_GPUS_NUM` | The total number of GPUs in the run |
-| `DSTACK_NODES_NUM` | The number of nodes in the run |
-| `DSTACK_NODE_RANK` | The rank of the node |
-| `DSTACK_MASTER_NODE_IP` | The internal IP address the master node |
-
-### Distributed tasks { #_nodes }
-
-By default, the task runs on a single node. However, you can run it on a cluster of nodes.
-
-
-
-```yaml
-type: task
-
-# The size of the cluster
-nodes: 2
-
-python: "3.11"
-env:
- - HF_HUB_ENABLE_HF_TRANSFER=1
-commands:
- - pip install -r requirements.txt
- - torchrun
- --nproc_per_node=$DSTACK_GPUS_PER_NODE
- --node_rank=$DSTACK_NODE_RANK
- --nnodes=$DSTACK_NODES_NUM
- --master_addr=$DSTACK_MASTER_NODE_IP
- --master_port=8008 resnet_ddp.py
- --num_epochs 20
-
-resources:
- gpu: 24GB
-```
-
-
-
-If you run the task, `dstack` first provisions the master node and then runs the other nodes of the cluster.
-All nodes are provisioned in the same region.
-
-`dstack` is easy to use with `accelerate`, `torchrun`, and other distributed frameworks. All you need to do
-is pass the corresponding environment variables such as `DSTACK_GPUS_PER_NODE`, `DSTACK_NODE_RANK`, `DSTACK_NODES_NUM`,
-`DSTACK_MASTER_NODE_IP`, and `DSTACK_GPUS_NUM` (see [System environment variables](#default-environment-variables)).
-
-??? info "Backends"
- Running on multiple nodes is supported only with `aws`, `gcp`, `azure`, `oci`, and instances added via
- [`dstack pool add-ssh`](../../concepts/pools.md#adding-on-prem-clusters).
-
-### Arguments
-
-You can parameterize tasks with user arguments using `${{ run.args }}` in the configuration.
-
-
-
-```yaml
-type: task
-
-python: "3.11"
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py ${{ run.args }}
-```
-
-
-
-Now, you can pass your arguments to the `dstack run` command:
-
-
-
-```shell
-$ dstack run . -f train.dstack.yml --train_batch_size=1 --num_train_epochs=100
-```
-
-
-
-### Web applications
-
-Here's an example of using `ports` to run web apps with `tasks`.
-
-
-
-```yaml
-type: task
-
-python: "3.11"
-
-commands:
- - pip3 install streamlit
- - streamlit hello
-
-ports:
- - 8501
-
-```
-
-
-
-### Spot policy
-
-You can choose whether to use spot instances, on-demand instances, or any available type.
-
-
-
-```yaml
-type: task
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
-
-spot_policy: auto
-```
-
-
-
-The `spot_policy` accepts `spot`, `on-demand`, and `auto`. The default for tasks is `auto`.
-
-### Backends
-
-By default, `dstack` provisions instances in all configured backends. However, you can specify the list of backends:
-
-
-
-```yaml
-type: task
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
-
-backends: [aws, gcp]
-```
-
-
-
-### Regions
-
-By default, `dstack` uses all configured regions. However, you can specify the list of regions:
-
-
-
-```yaml
-type: task
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
-
-regions: [eu-west-1, eu-west-2]
-```
-
-
-
-### Volumes
-
-Volumes allow you to persist data between runs.
-To attach a volume, simply specify its name using the `volumes` property and specify where to mount its contents:
-
-
-
-```yaml
-type: task
-
-python: "3.11"
-
-commands:
- - pip install -r fine-tuning/qlora/requirements.txt
- - python fine-tuning/qlora/train.py
-
-volumes:
- - name: my-new-volume
- path: /volume_data
-```
-
-
-
-Once you run this configuration, the contents of the volume will be attached to `/volume_data` inside the task,
-and its contents will persist across runs.
-
-!!! info "Limitations"
- When you're running a dev environment, task, or service with `dstack`, it automatically mounts the project folder contents
- to `/workflow` (and sets that as the current working directory). Right now, `dstack` doesn't allow you to
- attach volumes to `/workflow` or any of its subdirectories.
-
-The `task` configuration type supports many other options. See below.
-
-## Root reference
-
-#SCHEMA# dstack._internal.core.models.configurations.TaskConfiguration
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `resources`
-
-#SCHEMA# dstack._internal.core.models.resources.ResourcesSpecSchema
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: resources-
-
-## `resouces.gpu` { #resources-gpu data-toc-label="resources.gpu" }
-
-#SCHEMA# dstack._internal.core.models.resources.GPUSpecSchema
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `resouces.disk` { #resources-disk data-toc-label="resources.disk" }
-
-#SCHEMA# dstack._internal.core.models.resources.DiskSpecSchema
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `registry_auth`
-
-#SCHEMA# dstack._internal.core.models.configurations.RegistryAuth
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `volumes[n]`
-
-#SCHEMA# dstack._internal.core.models.volumes.VolumeMountPoint
- overrides:
- show_root_heading: false
- type:
- required: true
diff --git a/docs/docs/reference/dstack.yml/volume.md b/docs/docs/reference/dstack.yml/volume.md
deleted file mode 100644
index 03351fb6eb..0000000000
--- a/docs/docs/reference/dstack.yml/volume.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# volume
-
-The `volume` configuration type allows creating, registering, and updating volumes.
-
-> Configuration files must have a name ending with `.dstack.yml` (e.g., `.dstack.yml` or `vol.dstack.yml` are both acceptable)
-> and can be located in the project's root directory or any nested folder.
-> Any configuration can be applied via [`dstack apply`](../cli/index.md#dstack-apply).
-
-## Examples
-
-### Creating a new volume { #create-volume }
-
-
-
-```yaml
-type: volume
-name: my-aws-volume
-backend: aws
-region: eu-central-1
-size: 100GB
-```
-
-
-
-### Registering an existing volume { #register-volume }
-
-
-
-```yaml
-type: volume
-name: my-external-volume
-backend: aws
-region: eu-central-1
-volume_id: vol1235
-```
-
-
-
-
-## Root reference
-
-#SCHEMA# dstack._internal.core.models.volumes.VolumeConfiguration
- overrides:
- show_root_heading: false
- type:
- required: true
diff --git a/docs/docs/reference/profiles.yml.md b/docs/docs/reference/profiles.yml.md
deleted file mode 100644
index a6c7a4990b..0000000000
--- a/docs/docs/reference/profiles.yml.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# profiles.yml
-
-Sometimes, you may want to reuse the same parameters across different [`.dstack.yml`](dstack.yml.md) configurations.
-
-This can be achieved by defining those parameters in a profile.
-
-Profiles can be defined on the repository level (via the `.dstack/profiles.yml` file in the root directory of the
-repository) or on the global level (via the `~/.dstack/profiles.yml` file).
-
-Any profile can be marked as default so that it will be applied automatically for any run. Otherwise, you can refer to a specific profile
-via `--profile NAME` in `dstack run`.
-
-### Example
-
-
-
-```yaml
-profiles:
- - name: my-profile
-
- # The spot pololicy can be "spot", "on-demand", or "auto"
- spot_policy: auto
-
- # Limit the maximum price of the instance per hour
- max_price: 1.5
-
- # Stop any run if it runs longer that this duration
- max_duration: 1d
-
- # Use only these backends
- backends: [azure, lambda]
-
- # If set to true, this profile will be applied automatically
- default: true
-```
-
-
-
-The profile configuration supports many properties. See below.
-
-### Root reference
-
-#SCHEMA# dstack._internal.core.models.profiles.Profile
- overrides:
- show_root_heading: false
- max_price:
- type: 'Optional[float]'
-
-### `retry`
-
-#SCHEMA# dstack._internal.core.models.profiles.ProfileRetry
- overrides:
- show_root_heading: false
diff --git a/docs/docs/reference/server/config.yml.md b/docs/docs/reference/server/config.yml.md
deleted file mode 100644
index 7781bf81de..0000000000
--- a/docs/docs/reference/server/config.yml.md
+++ /dev/null
@@ -1,955 +0,0 @@
-# ~/.dstack/server/config.yml
-
-The `~/.dstack/server/config.yml` file is used by the `dstack` server
-to [configure](../../installation/index.md#configure-backends) cloud accounts.
-
-> The `dstack` server allows you to configure backends for multiple projects.
-> If you don't need multiple projects, use only the `main` project.
-
-Each cloud account must be configured under the `backends` property of the respective project.
-See the examples below.
-
-## Examples
-
-### AWS
-
-There are two ways to configure AWS: using an access key or using the default credentials.
-
-=== "Access key"
-
- Create an access key by following the [this guide :material-arrow-top-right-thin:{ .external }](https://docs.aws.amazon.com/cli/latest/userguide/cli-authentication-user.html#cli-authentication-user-get).
- Once you've downloaded the `.csv` file with your IAM user's Access key ID and Secret access key, proceed to
- configure the backend.
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: aws
- creds:
- type: access_key
- access_key: KKAAUKLIZ5EHKICAOASV
- secret_key: pn158lMqSBJiySwpQ9ubwmI6VUU3/W2fdJdFwfgO
- ```
-
-
-
-=== "Default credentials"
-
- If you have default credentials set up (e.g. in `~/.aws/credentials`), configure the backend like this:
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: aws
- creds:
- type: default
- ```
-
-
-
-??? info "VPC"
- By default, `dstack` uses the default VPC. It's possible to customize it:
-
- === "vpc_name"
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: aws
- creds:
- type: default
-
- vpc_name: my-vpc
- ```
-
- === "vpc_ids"
- ```yaml
- projects:
- - name: main
- backends:
- - type: aws
- creds:
- type: default
-
- default_vpcs: true
- vpc_ids:
- us-east-1: vpc-0a2b3c4d5e6f7g8h
- us-east-2: vpc-9i8h7g6f5e4d3c2b
- us-west-1: vpc-4d3c2b1a0f9e8d7
- ```
-
- For the regions without configured `vpc_ids`, enable default VPCs by setting `default_vpcs` to `true`.
-
-??? info "Required AWS permissions"
- The following AWS policy permissions are sufficient for `dstack` to work:
-
- ```
- {
- "Version": "2012-10-17",
- "Statement": [
- {
- "Effect": "Allow",
- "Action": [
- "ec2:AttachVolume",
- "ec2:AuthorizeSecurityGroupEgress",
- "ec2:AuthorizeSecurityGroupIngress",
- "ec2:CancelSpotInstanceRequests",
- "ec2:CreateSecurityGroup",
- "ec2:CreateTags",
- "ec2:CreateVolume",
- "ec2:DeleteVolume",
- "ec2:DescribeAvailabilityZones",
- "ec2:DescribeImages",
- "ec2:DescribeInstances",
- "ec2:DescribeInstanceAttribute",
- "ec2:DescribeRouteTables",
- "ec2:DescribeSecurityGroups",
- "ec2:DescribeSubnets",
- "ec2:DescribeVpcs",
- "ec2:DescribeVolumes",
- "ec2:DetachVolume",
- "ec2:RunInstances",
- "ec2:TerminateInstances"
- ],
- "Resource": "*"
- },
- {
- "Effect": "Allow",
- "Action": [
- "servicequotas:ListServiceQuotas",
- "servicequotas:GetServiceQuota"
- ],
- "Resource": "*"
- },
- {
- "Effect": "Allow",
- "Action": [
- "elasticloadbalancing:CreateLoadBalancer",
- "elasticloadbalancing:CreateTargetGroup",
- "elasticloadbalancing:CreateListener",
- "elasticloadbalancing:RegisterTargets",
- "elasticloadbalancing:AddTags",
- "elasticloadbalancing:DeleteLoadBalancer",
- "elasticloadbalancing:DeleteTargetGroup",
- "elasticloadbalancing:DeleteListener",
- "elasticloadbalancing:DeregisterTargets"
- ],
- "Resource": "*"
- },
- {
- "Effect": "Allow",
- "Action": [
- "acm:DescribeCertificate",
- "acm:ListCertificates"
- ],
- "Resource": "*"
- }
- ]
- }
- ```
-
- The `elasticloadbalancing:*` and `acm:*` permissions are only needed for provisioning gateways with ACM (AWS Certificate Manager) certificates.
-
-??? info "Private subnets"
- By default, `dstack` utilizes public subnets and permits inbound SSH traffic exclusively for any provisioned instances.
- If you want `dstack` to use private subnets, set `public_ips` to `false`.
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: aws
- creds:
- type: default
-
- public_ips: false
- ```
-
- Using private subnets assumes that both the `dstack` server and users can access the configured VPC's private subnets
- (e.g., through VPC peering).
-
-### Azure
-
-There are two ways to configure Azure: using a client secret or using the default credentials.
-
-=== "Client secret"
-
- A client secret can be created using the [Azure CLI :material-arrow-top-right-thin:{ .external }](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli):
-
- ```shell
- SUBSCRIPTION_ID=...
- az ad sp create-for-rbac
- --name dstack-app \
- --role $DSTACK_ROLE \
- --scopes /subscriptions/$SUBSCRIPTION_ID \
- --query "{ tenant_id: tenant, client_id: appId, client_secret: password }"
- ```
-
- Once you have `tenant_id`, `client_id`, and `client_secret`, go ahead and configure the backend.
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: azure
- subscription_id: 06c82ce3-28ff-4285-a146-c5e981a9d808
- tenant_id: f84a7584-88e4-4fd2-8e97-623f0a715ee1
- creds:
- type: client
- client_id: acf3f73a-597b-46b6-98d9-748d75018ed0
- client_secret: 1Kb8Q~o3Q2hdEvrul9yaj5DJDFkuL3RG7lger2VQ
- ```
-
-
-
-=== "Default credentials"
-
- Obtain the `subscription_id` and `tenant_id` via the [Azure CLI :material-arrow-top-right-thin:{ .external }](https://learn.microsoft.com/en-us/cli/azure/install-azure-cli):
-
- ```shell
- az account show --query "{subscription_id: id, tenant_id: tenantId}"
- ```
-
- Then proceed to configure the backend:
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: azure
- subscription_id: 06c82ce3-28ff-4285-a146-c5e981a9d808
- tenant_id: f84a7584-88e4-4fd2-8e97-623f0a715ee1
- creds:
- type: default
- ```
-
-
-
-If you don't know your `subscription_id`, run
-
-```shell
-az account show --query "{subscription_id: id}"
-```
-
-??? info "Required Azure permissions"
- The following Azure permissions are sufficient for `dstack` to work:
- ```
- {
- "properties": {
- "roleName": "dstack-role",
- "description": "Minimal required permissions for using Azure with dstack",
- "assignableScopes": [
- "/subscriptions/${YOUR_SUBSCRIPTION_ID}"
- ],
- "permissions": [
- {
- "actions": [
- "Microsoft.Authorization/*/read",
- "Microsoft.Compute/availabilitySets/*",
- "Microsoft.Compute/locations/*",
- "Microsoft.Compute/virtualMachines/*",
- "Microsoft.Compute/virtualMachineScaleSets/*",
- "Microsoft.Compute/cloudServices/*",
- "Microsoft.Compute/disks/write",
- "Microsoft.Compute/disks/read",
- "Microsoft.Compute/disks/delete",
- "Microsoft.Network/networkSecurityGroups/*",
- "Microsoft.Network/locations/*",
- "Microsoft.Network/virtualNetworks/*",
- "Microsoft.Network/networkInterfaces/*",
- "Microsoft.Network/publicIPAddresses/*",
- "Microsoft.Resources/subscriptions/resourceGroups/read",
- "Microsoft.Resources/subscriptions/resourceGroups/write",
- "Microsoft.Resources/subscriptions/read"
- ],
- "notActions": [],
- "dataActions": [],
- "notDataActions": []
- }
- ]
- }
- }
- ```
-
-### GCP
-
-??? info "Enable APIs"
- First, ensure the required APIs are enabled in your GCP `project_id`.
-
- ```shell
- PROJECT_ID=...
- gcloud config set project $PROJECT_ID
- gcloud services enable cloudapis.googleapis.com
- gcloud services enable compute.googleapis.com
- ```
-
-There are two ways to configure GCP: using a service account or using the default credentials.
-
-=== "Service account"
-
- To create a service account, follow [this guide :material-arrow-top-right-thin:{ .external }](https://cloud.google.com/iam/docs/service-accounts-create). After setting up the service account [create a key :material-arrow-top-right-thin:{ .external }](https://cloud.google.com/iam/docs/keys-create-delete) for it and download the corresponding JSON file.
-
- Then go ahead and configure the backend by specifying the downloaded file path.
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: gcp
- project_id: gcp-project-id
- creds:
- type: service_account
- filename: ~/.dstack/server/gcp-024ed630eab5.json
- ```
-
-
-
-=== "Default credentials"
-
- Enable GCP application default credentials:
-
- ```shell
- gcloud auth application-default login
- ```
-
- Then configure the backend like this:
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: gcp
- project_id: gcp-project-id
- creds:
- type: default
- ```
-
-
-
-If you don't know your GCP project ID, run
-
-```shell
-gcloud projects list --format="json(projectId)"
-```
-
-=== "VPC"
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: gcp
- project_id: gcp-project-id
- creds:
- type: default
-
- vpc_name: my-custom-vpc
- ```
-
-
-
-=== "Shared VPC"
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: gcp
- project_id: gcp-project-id
- creds:
- type: default
-
- vpc_name: my-custom-vpc
- vpc_project_id: another-project-id
- ```
-
-
-
- To use a shared VPC, that VPC has to be configured with two additional firewall rules:
-
- * Allow `INGRESS` traffic on port `22`, with the target tag `dstack-runner-instance`
- * Allow `INGRESS` traffic on ports `22`, `80`, `443`, with the target tag `dstack-gateway-instance`
-
-??? info "Required GCP permissions"
- The following GCP permissions are sufficient for `dstack` to work:
-
- ```
- compute.disks.create
- compute.firewalls.create
- compute.images.useReadOnly
- compute.instances.create
- compute.instances.delete
- compute.instances.get
- compute.instances.setLabels
- compute.instances.setMetadata
- compute.instances.setTags
- compute.networks.get
- compute.networks.updatePolicy
- compute.regions.list
- compute.subnetworks.list
- compute.subnetworks.use
- compute.subnetworks.useExternalIp
- compute.zoneOperations.get
- ```
-
- If you plan to use TPUs, additional permissions are required:
-
- ```
- tpu.nodes.create
- tpu.nodes.delete
- tpu.nodes.get
- tpu.operations.get
- tpu.operations.list
- ```
-
- Also, the use of TPUs requires the `serviceAccountUser` role.
- For TPU VMs, dstack will use the default service account.
-
-??? info "Private subnets"
- By default, `dstack` utilizes public subnets and permits inbound SSH traffic exclusively for any provisioned instances.
- If you want `dstack` to use private subnets, set `public_ips` to `false`.
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: gcp
- creds:
- type: default
-
- public_ips: false
- ```
-
- Using private subnets assumes that both the `dstack` server and users can access the configured VPC's private subnets (e.g., through VPC peering). Additionally, [Cloud NAT](https://cloud.google.com/nat/docs/overview) must be configured to provide access to external resources for provisioned instances.
-
-### OCI
-
-There are two ways to configure OCI: using client credentials or using the default credentials.
-
-=== "Client credentials"
-
- Log into the [OCI Console :material-arrow-top-right-thin:{ .external }](https://cloud.oracle.com), go to `My profile`,
- select `API keys`, and click `Add API key`.
-
- Once you add a key, you'll see the configuration file. Copy its values to configure the backend as follows:
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: oci
- creds:
- type: client
- user: ocid1.user.oc1..g5vlaeqfu47akmaafq665xsgmyaqjktyfxtacfxc4ftjxuca7aohnd2ev66m
- tenancy: ocid1.tenancy.oc1..ajqsftvk4qarcfaak3ha4ycdsaahxmaita5frdwg3tqo2bcokpd3n7oizwai
- region: eu-frankfurt-1
- fingerprint: 77:32:77:00:49:7c:cb:56:84:75:8e:77:96:7d:53:17
- key_file: ~/.oci/private_key.pem
- ```
-
-
-
- Make sure to include either the path to your private key via `key_file` or the contents of the key via `key_content`.
-
-=== "Default credentials"
- If you have default credentials set up in `~/.oci/config`, configure the backend like this:
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: oci
- creds:
- type: default
- ```
-
-
-
-??? info "Required OCI permissions"
-
- This is an example of a restrictive policy for a group of `dstack` users:
-
- ```
- Allow group to read compartments in tenancy where target.compartment.name = ''
- Allow group to read marketplace-community-listings in compartment
- Allow group to manage app-catalog-listing in compartment
- Allow group to manage instances in compartment
- Allow group to manage compute-capacity-reports in compartment
- Allow group to manage volumes in compartment
- Allow group to manage volume-attachments in compartment
- Allow group to manage virtual-network-family in compartment
- ```
-
- To use this policy, create a compartment for `dstack` and specify it in `~/.dstack/server/config.yml`.
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: oci
- creds:
- type: default
- compartment_id: ocid1.compartment.oc1..aaaaaaaa
- ```
-
-### Lambda
-
-Log into your [Lambda Cloud :material-arrow-top-right-thin:{ .external }](https://lambdalabs.com/service/gpu-cloud) account, click API keys in the sidebar, and then click the `Generate API key`
-button to create a new API key.
-
-Then, go ahead and configure the backend:
-
-
-
-```yaml
-projects:
-- name: main
- backends:
- - type: lambda
- creds:
- type: api_key
- api_key: eersct_yrpiey-naaeedst-tk-_cb6ba38e1128464aea9bcc619e4ba2a5.iijPMi07obgt6TZ87v5qAEj61RVxhd0p
-```
-
-
-
-### TensorDock
-
-Log into your [TensorDock :material-arrow-top-right-thin:{ .external }](https://marketplace.tensordock.com/) account, click API in the sidebar, and use the `Create an Authorization`
-section to create a new authorization key.
-
-Then, go ahead and configure the backend:
-
-
-
-```yaml
-projects:
- - name: main
- backends:
- - type: tensordock
- creds:
- type: api_key
- api_key: 248e621d-9317-7494-dc1557fa5825b-98b
- api_token: FyBI3YbnFEYXdth2xqYRnQI7hiusssBC
-```
-
-
-
-The `tensordock` backend supports on-demand instances only. Spot instance support coming soon.
-
-### Vast.ai
-
-Log into your [Vast.ai :material-arrow-top-right-thin:{ .external }](https://cloud.vast.ai/) account, click Account in the sidebar, and copy your
-API Key.
-
-Then, go ahead and configure the backend:
-
-
-
-```yaml
-projects:
-- name: main
- backends:
- - type: vastai
- creds:
- type: api_key
- api_key: d75789f22f1908e0527c78a283b523dd73051c8c7d05456516fc91e9d4efd8c5
-```
-
-
-
-Also, the `vastai` backend supports on-demand instances only. Spot instance support coming soon.
-
-### RunPod
-
-Log into your [RunPod :material-arrow-top-right-thin:{ .external }](https://www.runpod.io/console/) console, click Settings in the sidebar, expand the `API Keys` section, and click
-the button to create a key.
-
-Then proceed to configuring the backend.
-
-
-
-```yaml
-projects:
- - name: main
- backends:
- - type: runpod
- creds:
- type: api_key
- api_key: US9XTPDIV8AR42MMINY8TCKRB8S4E7LNRQ6CAUQ9
-```
-
-
-
-### CUDO
-
-Log into your [CUDO Compute :material-arrow-top-right-thin:{ .external }](https://compute.cudo.org/) account, click API keys in the sidebar, and click the `Create an API key` button.
-
-Ensure you've created a project with CUDO Compute, then proceed to configuring the backend.
-
-
-
-```yaml
-projects:
- - name: main
- backends:
- - type: cudo
- project_id: my-cudo-project
- creds:
- type: api_key
- api_key: 7487240a466624b48de22865589
-```
-
-
-
-### DataCrunch
-
-Log into your [DataCrunch :material-arrow-top-right-thin:{ .external }](https://cloud.datacrunch.io/signin) account, click Account Settings in the sidebar, find `REST API Credentials` area and then click the `Generate Credentials` button.
-
-Then, go ahead and configure the backend:
-
-
-
-```yaml
-projects:
- - name: main
- backends:
- - type: datacrunch
- creds:
- type: api_key
- client_id: xfaHBqYEsArqhKWX-e52x3HH7w8T
- client_secret: B5ZU5Qx9Nt8oGMlmMhNI3iglK8bjMhagTbylZy4WzncZe39995f7Vxh8
-```
-
-
-
-### Kubernetes
-
-`dstack` supports both self-managed, and managed Kubernetes clusters.
-
-??? info "Prerequisite"
- To use GPUs with Kubernetes, the cluster must be installed with the
- [NVIDIA GPU Operator :material-arrow-top-right-thin:{ .external }](https://docs.nvidia.com/datacenter/cloud-native/gpu-operator/latest/index.html).
-
- [//]: # (TODO: Provide short yet clear instructions. Elaborate on whether it works with Kind.)
-
-To configure a Kubernetes backend, specify the path to the kubeconfig file,
-and the port that `dstack` can use for proxying SSH traffic.
-In case of a self-managed cluster, also specify the IP address of any node in the cluster.
-
-[//]: # (TODO: Mention that the Kind context has to be selected via `current-context` )
-
-=== "Self-managed"
-
- Here's how to configure the backend to use a self-managed cluster.
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: kubernetes
- kubeconfig:
- filename: ~/.kube/config
- networking:
- ssh_host: localhost # The external IP address of any node
- ssh_port: 32000 # Any port accessible outside of the cluster
- ```
-
-
-
- The port specified to `ssh_port` must be accessible outside of the cluster.
-
- ??? info "Kind"
- For example, if you are using Kind, make sure to add it via `extraPortMappings`:
-
-
-
- ```yaml
- kind: Cluster
- apiVersion: kind.x-k8s.io/v1alpha4
- nodes:
- - role: control-plane
- extraPortMappings:
- - containerPort: 32000 # Must be same as `ssh_port`
- hostPort: 32000 # Must be same as `ssh_port`
- ```
-
-
-
-[//]: # (TODO: Elaborate on the Kind's IP address on Linux)
-
-=== "Managed"
- Here's how to configure the backend to use a managed cluster (AWS, GCP, Azure).
-
-
-
- ```yaml
- projects:
- - name: main
- backends:
- - type: kubernetes
- kubeconfig:
- filename: ~/.kube/config
- networking:
- ssh_port: 32000 # Any port accessible outside of the cluster
- ```
-
-
-
- The port specified to `ssh_port` must be accessible outside of the cluster.
-
- ??? info "EKS"
- For example, if you are using EKS, make sure to add it via an ingress rule
- of the corresponding security group:
-
- ```shell
- aws ec2 authorize-security-group-ingress --group-id --protocol tcp --port 32000 --cidr 0.0.0.0/0
- ```
-
-[//]: # (TODO: Elaborate on gateways, and what backends allow configuring them)
-
-[//]: # (TODO: Should we automatically detect ~/.kube/config)
-
-## Root reference
-
-#SCHEMA# dstack._internal.server.services.config.ServerConfig
- overrides:
- show_root_heading: false
-
-## `projects[n]` { #projects data-toc-label="projects" }
-
-#SCHEMA# dstack._internal.server.services.config.ProjectConfig
- overrides:
- show_root_heading: false
- backends:
- type: 'Union[AWSConfigInfoWithCreds, AzureConfigInfoWithCreds, GCPConfigInfoWithCreds, LambdaConfigInfoWithCreds, TensorDockConfigInfoWithCreds, VastAIConfigInfoWithCreds, KubernetesConfig]'
-
-## `projects[n].backends[type=aws]` { #aws data-toc-label="backends[type=aws]" }
-
-#SCHEMA# dstack._internal.server.services.config.AWSConfig
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: aws-
-
-## `projects[n].backends[type=aws].creds` { #aws-creds data-toc-label="backends[type=aws].creds" }
-
-=== "Access key"
- #SCHEMA# dstack._internal.core.models.backends.aws.AWSAccessKeyCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-=== "Default"
- #SCHEMA# dstack._internal.core.models.backends.aws.AWSDefaultCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=azure]` { #azure data-toc-label="backends[type=azure]" }
-
-#SCHEMA# dstack._internal.server.services.config.AzureConfig
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: azure-
-
-## `projects[n].backends[type=azure].creds` { #azure-creds data-toc-label="backends[type=azure].creds" }
-
-=== "Client"
- #SCHEMA# dstack._internal.core.models.backends.azure.AzureClientCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-=== "Default"
- #SCHEMA# dstack._internal.core.models.backends.azure.AzureDefaultCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=datacrunch]` { #datacrunch data-toc-label="backends[type=datacrunch]" }
-
-#SCHEMA# dstack._internal.server.services.config.DataCrunchConfig
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: datacrunch-
-
-## `projects[n].backends[type=datacrunch].creds` { #datacrunch-creds data-toc-label="backends[type=datacrunch].creds" }
-
-#SCHEMA# dstack._internal.core.models.backends.datacrunch.DataCrunchAPIKeyCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=gcp]` { #gcp data-toc-label="backends[type=gcp]" }
-
-#SCHEMA# dstack._internal.server.services.config.GCPConfig
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: gcp-
-
-## `projects[n].backends[type=gcp].creds` { #gcp-creds data-toc-label="backends[type=gcp].creds" }
-
-=== "Service account"
- #SCHEMA# dstack._internal.server.services.config.GCPServiceAccountCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-=== "Default"
- #SCHEMA# dstack._internal.server.services.config.GCPDefaultCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=lambda]` { #lambda data-toc-label="backends[type=lambda]" }
-
-#SCHEMA# dstack._internal.server.services.config.LambdaConfig
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: lambda-
-
-## `projects[n].backends[type=lambda].creds` { #lambda-creds data-toc-label="backends[type=lambda].creds" }
-
-#SCHEMA# dstack._internal.core.models.backends.lambdalabs.LambdaAPIKeyCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=oci]` { #oci data-toc-label="backends[type=oci]" }
-
-#SCHEMA# dstack._internal.server.services.config.OCIConfig
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: oci-
-
-## `projects[n].backends[type=oci].creds` { #oci-creds data-toc-label="backends[type=oci].creds" }
-
-=== "Client"
- #SCHEMA# dstack._internal.core.models.backends.oci.OCIClientCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-=== "Default"
- #SCHEMA# dstack._internal.core.models.backends.oci.OCIDefaultCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=tensordock]` { #tensordock data-toc-label="backends[type=tensordock]" }
-
-#SCHEMA# dstack._internal.server.services.config.TensorDockConfig
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: tensordock-
-
-## `projects[n].backends[type=tensordock].creds` { #tensordock-creds data-toc-label="backends[type=tensordock].creds" }
-
-#SCHEMA# dstack._internal.core.models.backends.tensordock.TensorDockAPIKeyCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=vastai]` { #vastai data-toc-label="backends[type=vastai]" }
-
-#SCHEMA# dstack._internal.server.services.config.VastAIConfig
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: vastai-
-
-## `projects[n].backends[type=vastai].creds` { #vastai-creds data-toc-label="backends[type=vastai].creds" }
-
-#SCHEMA# dstack._internal.core.models.backends.vastai.VastAIAPIKeyCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=cudo]` { #cudo data-toc-label="backends[type=cudo]" }
-
-#SCHEMA# dstack._internal.server.services.config.CudoConfig
- overrides:
- show_root_heading: false
- type:
- required: true
- item_id_prefix: cudo-
-
-## `projects[n].backends[type=cudo].creds` { #cudo-creds data-toc-label="backends[type=cudo].creds" }
-
-#SCHEMA# dstack._internal.core.models.backends.cudo.CudoAPIKeyCreds
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=kubernetes]` { #kubernetes data-toc-label="backends[type=kubernetes]" }
-
-#SCHEMA# dstack._internal.server.services.config.KubernetesConfig
- overrides:
- show_root_heading: false
- type:
- required: true
-
-## `projects[n].backends[type=kubernetes].kubeconfig` { #kubeconfig data-toc-label="kubeconfig" }
-
-##SCHEMA# dstack._internal.server.services.config.KubeconfigConfig
- overrides:
- show_root_heading: false
-
-## `projects[n].backends[type=kubernetes].networking` { #networking data-toc-label="networking" }
-
-##SCHEMA# dstack._internal.core.models.backends.kubernetes.KubernetesNetworkingConfig
- overrides:
- show_root_heading: false
diff --git a/docs/index.md b/docs/index.md
deleted file mode 100644
index 55c1afa3f4..0000000000
--- a/docs/index.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-template: home.html
-title: AI container orchestration platform for everyone
-hide:
- - navigation
- - toc
- - footer
----
diff --git a/docs/overrides/.icons/custom/colored/github.svg b/docs/overrides/.icons/custom/colored/github.svg
deleted file mode 100644
index 66e5797f00..0000000000
--- a/docs/overrides/.icons/custom/colored/github.svg
+++ /dev/null
@@ -1,2 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/overrides/.icons/custom/github.svg b/docs/overrides/.icons/custom/github.svg
deleted file mode 100644
index fe24d0e0d5..0000000000
--- a/docs/overrides/.icons/custom/github.svg
+++ /dev/null
@@ -1 +0,0 @@
-
\ No newline at end of file
diff --git a/docs/overrides/assets/images/quotes/cudopete.png b/docs/overrides/assets/images/quotes/cudopete.png
deleted file mode 100644
index dd447d0f3d..0000000000
Binary files a/docs/overrides/assets/images/quotes/cudopete.png and /dev/null differ
diff --git a/docs/overrides/examples.html b/docs/overrides/examples.html
deleted file mode 100644
index 6b933ac34e..0000000000
--- a/docs/overrides/examples.html
+++ /dev/null
@@ -1,182 +0,0 @@
-{% extends "main.html" %}
-
-{% block container %}
-
-
-
-
-
-
-
Examples
-
-
-
-
Deployment
-
-
-
-
-
Fine-tuning
-
-
-
-
-
RAG
-
-
-
-
-
LLMs
-
-
-
-
-
-
-
-
-
-
-
-{% endblock %}
diff --git a/docs/overrides/home.html b/docs/overrides/home.html
deleted file mode 100644
index eb503da20b..0000000000
--- a/docs/overrides/home.html
+++ /dev/null
@@ -1,830 +0,0 @@
-{% extends "landing.html" %}
-
-{% block scripts %}
-{{ super() }}
-
-
-
-
-{% endblock %}
-
-{% block content %}
-
-
-
-
-
AI container orchestration platform for everyone
-
-
- dstack is an open-source orchestration platform for development, training, and deployment of AI models in any cloud or data center.
-
-
-
-
-
-
-
-
-
-
-
-
Dev environments
-
Before scheduling a task or deploying a model, you may want to run code interactively.
-
-
- Dev environments allow you to provision a remote machine set up with your code and favorite IDE
- with just one command.
-
-
-
- Learn more
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Tasks
-
-
Tasks allow for convenient scheduling of various batch jobs, such as training, fine-tuning, or
- data processing, as well as running web applications.
-
-
You can run tasks on a single machine or on a cluster of nodes.
-
-
- Learn more
-
-
-
-
-
-
-
-
-
Services
-
-
- Services make it very easy to deploy any kind of model as public,
- secure, and scalable endpoints.
-
-
-
- Learn more
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Pools
-
-
Pools enable the efficient reuse of cloud instances and on-premises servers across runs,
- simplifying their management.
-
-
- Learn more
-
-
-
-
-
-
-
-
Why community dstack
-
-
-
-
-
-
-
Andrew Spott
-
-
ML Engineer at Stealth Startup
-
-
- Thanks to @dstack , I get the convenience of having a personal Slurm cluster
- and using budget-friendly cloud GPUs, without paying the super-high premiums charged by the big three.
-
-
-
-
-
-
-
-
Alvaro Bartolome
-
-
ML Engineer at Argilla
-
-
- With @dstack it's incredibly easy to define a configuration within a repository
- and run it without worrying about GPU availability. It lets you focus on
- data and your research.
-
-
-
-
-
-
-
-
Park Chansung
-
-
ML Researcher at ETRI
-
-
- Thanks to @dstack , I can effortlessly access the top GPU options across different clouds,
- saving me time and money while pushing my AI work forward.
-
-
-
-
-
-
-
-
Eckart Burgwedel
-
-
CEO at Uberchord
-
-
- With @dstack , running an open-source LLM or a dev environment on a cloud GPU is as
- easy as running a local Docker container.
- It combines the ease of Docker with the auto-scaling capabilities of K8s.
-
-
-
-
-
-
-
-
Peter Hill
-
-
Co-Founder at CUDO Compute
-
-
- @dstack is instrumental in simplifying infrastructure provisioning and AI
- model development.
- if your organization is on the lookout for an platform to speed up the adoption of AI, I
- wholeheartedly recommend @dstack
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
Get started in a minute
-
-
-
-
-
Open-source
-
- Self-hosted
-
-
- Use your own cloud accounts or data centers.
-
-
-
-
-
-
AWS
-
-
-
-
-
Azure
-
-
-
-
-
GCP
-
-
-
-
-
OCI
-
-
-
-
-
Lambda
-
-
-
-
-
TensorDock
-
-
-
-
-
Vast.ai
-
-
-
-
-
RunPod
-
-
-
-
-
CUDO
-
-
-
-
-
K8S
-
-
-
-
-
-
-
-
-
-
dstack Sky
-
- Managed by dstack
-
-
-
- Access GPUs at the best possible rate.
-
-
-
-
-
-
Marketplace
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
FAQ
-
-
-
-
-
-
-
-
- dstack is an open-source orchestration platform for efficiently training and deploying AI
- models across any cloud or data center. It provides a unified interface to manage AI model
- development at any scale, whether in the cloud or on-premises.
-
-
- With dstack, you can utilize various cloud providers or on-prem infrastructure, along with
- any hardware, and leverage open-source frameworks and tools for both training and
- deployment.
-
-
-
-
-
-
- What is dstack Sky?
-
-
-
-
-
-
- dstack Sky is a managed version of dstack. Unlike the open-source
- dstack where you have to
- set up and manage the server yourself, dstack Sky takes care of hosting the server on your
- behalf. Most importantly, dstack Sky offers access to cloud GPUs through its marketplace,
- ensuring you get them at competitive rates.
-
-
- If needed, you can still configure dstack Sky to use your own cloud accounts or connect to
- your on-prem servers.
-
-
-
-
-
-
- What is the pricing for dstack?
-
-
-
-
-
-
- The open-source version of dstack is completely free for commercial use. You can use it with
- your own cloud accounts or data centers without any costs, and you can also rely on support
- from the open-source community, Discord, and other channels.
-
-
- If you use cloud GPUs through dstack Sky, you're only charged based on the compute prices
- offered by the marketplace provider. dstack Sky does not add any commission on top of these
- prices.
-
-
- If you need enterprise-grade SLAs, premium support, or additional features, please
- reach out to our
- team.
-
-
-
-
-
-
-
-{% endblock %}
diff --git a/docs/overrides/landing.html b/docs/overrides/landing.html
deleted file mode 100644
index 4eefbe6542..0000000000
--- a/docs/overrides/landing.html
+++ /dev/null
@@ -1,61 +0,0 @@
-{% extends "base.html" %}
-
-{% block header %}
- {% include "header.html" %}
-{% endblock %}
-
-{% block scripts %}
-
-
-{{ super() }}
-{% endblock %}
-
-{% block announce %}
-🔥 Access GPUs at the best rate with dstack Sky! Learn more .
-{% endblock %}
-
-{% block footer %}
-
-{% endblock %}
\ No newline at end of file
diff --git a/docs/overrides/main.html b/docs/overrides/main.html
deleted file mode 100644
index e3cd0d09bd..0000000000
--- a/docs/overrides/main.html
+++ /dev/null
@@ -1,116 +0,0 @@
-{% extends "base.html" %}
-
-{% block container %}
-
- {% if "navigation.path" in features %}
- {% include "path.html" %}
- {% endif %}
-
- {% block content %}
- {% include "partials/content.html" %}
-
- {% if page.previous_page or page.next_page %}
- {% if page.meta and page.meta.hide %}
- {% set hidden = "hidden" if "footer" in page.meta.hide %}
- {% endif %}
-
- {% endif %}
- {% endblock %}
-
-
-{% endblock %}
-
-{% block header %}
- {% include "header-2.html" %}
-{% endblock %}
-
-{% block scripts %}
-
-
-{{ super() }}
-{% endblock %}
-
-{% block announce %}
-🔥 Access GPUs at the best rate with dstack Sky! Learn more .
-{% endblock %}
-
-{% block footer %}
-
-{% endblock %}
\ No newline at end of file
diff --git a/docs/overrides/path.html b/docs/overrides/path.html
deleted file mode 100644
index 16233bb9a4..0000000000
--- a/docs/overrides/path.html
+++ /dev/null
@@ -1,20 +0,0 @@
-{#-
- This file was automatically generated - do not edit
--#}
-{% import "partials/path-item.html" as item with context %}
-{% if page.meta and page.meta.hide %}
- {% set hidden = "hidden" if "path" in page.meta.hide %}
-{% endif %}
-{% set depth = page.ancestors | length %}
-{% if nav.homepage %}
- {% set depth = depth + 1 %}
-{% endif %}
-{% if depth > 1 %}
-
-
- {% for nav_item in page.ancestors | reverse %}
- {{ item.render(nav_item) }}
- {% endfor %}
-
-
-{% endif %}
\ No newline at end of file
diff --git a/docs/pricing.md b/docs/pricing.md
deleted file mode 100644
index 19ce885525..0000000000
--- a/docs/pricing.md
+++ /dev/null
@@ -1,8 +0,0 @@
----
-template: pricing.html
-title: AI container orchestration platform for everyone
-hide:
- - navigation
- - toc
- - footer
----
diff --git a/docs/terms.md b/docs/terms.md
deleted file mode 100644
index 630079cd81..0000000000
--- a/docs/terms.md
+++ /dev/null
@@ -1,461 +0,0 @@
----
-hide:
- - navigation
- - footer
----
-
-# Terms of service
-
-## Agreement to terms
-
-We are dstack GmbH ("**Company**," "**we**," "**us**," "**our**"), a company registered in Germany at Franz-Joseph-Straße, 11, Munich,
-Bayern 80801.
-
-These Legal Terms constitute a legally binding agreement made between you, whether personally or on behalf of an
-entity ("**you**"), and dstack GmbH, concerning your access to and use of the Services. You agree that by accessing the
-Services, you have read, understood, and agreed to be bound by all of these Legal Terms. IF YOU DO NOT AGREE WITH ALL OF
-THESE LEGAL TERMS, THEN YOU ARE EXPRESSLY PROHIBITED FROM USING THE SERVICES AND YOU MUST DISCONTINUE USE IMMEDIATELY.
-
-Supplemental terms and conditions or documents that may be posted on the Services from time to time are hereby expressly
-incorporated herein by reference. We reserve the right, in our sole discretion, to make changes or modifications to
-these Legal Terms from time to time. We will alert you about any changes by updating the "Last updated" date of these
-Legal Terms, and you waive any right to receive specific notice of each such change. It is your responsibility to
-periodically review these Legal Terms to stay informed of updates. You will be subject to, and will be deemed to have
-been made aware of and to have accepted, the changes in any revised Legal Terms by your continued use of the Services
-after the date such revised Legal Terms are posted.
-
-## 1. Our services
-
-The information provided when using the Services is not intended for distribution to or use by any person or entity in
-any jurisdiction or country where such distribution or use would be contrary to law or regulation or which would subject
-us to any registration requirement within such jurisdiction or country. Accordingly, those persons who choose to access
-the Services from other locations do so on their own initiative and are solely responsible for compliance with local
-laws, if and to the extent local laws are applicable.
-
-The Services are not tailored to comply with industry-specific regulations (Health Insurance Portability and
-Accountability Act (HIPAA), Federal Information Security Management Act (FISMA), etc.), so if your interactions would be
-subjected to such laws, you may not use the Services. You may not use the Services in a way that would violate the
-Gramm-Leach-Bliley Act (GLBA).
-
-## 2. Intelliectual property rights
-
-**Our intellectual property**
-
-We are the owner or the licensee of all intellectual property rights in our Services, including all source code,
-databases, functionality, software, website designs, audio, video, text, photographs, and graphics in the Services (
-collectively, the "Content"), as well as the trademarks, service marks, and logos contained therein (the "Marks").
-
-Our Content and Marks are protected by copyright and trademark laws (and various other intellectual property rights and
-unfair competition laws) and treaties in the United States and around the world.
-
-The Content and Marks are provided in or through the Services "AS IS" for your personal, non-commercial use or internal
-business purpose only.
-
-**Your use of our Services**
-
-Subject to your compliance with these Legal Terms, including the "Prohibited activities" section below, we grant you a
-non-exclusive, non-transferable, revocable license to:
-
- * access the Services; and
- * download or print a copy of any portion of the Content to which you have properly gained access.
-solely for your personal, non-commercial use or internal business purpose.
-
-Except as set out in this section or elsewhere in our Legal Terms, no part of the Services and no Content or Marks may
-be copied, reproduced, aggregated, republished, uploaded, posted, publicly displayed, encoded, translated, transmitted,
-distributed, sold, licensed, or otherwise exploited for any commercial purpose whatsoever, without our express prior
-written permission.
-
-If you wish to make any use of the Services, Content, or Marks other than as set out in this section or elsewhere in our
-Legal Terms, please address your request to: hello@dstack.ai. If we ever grant you the permission to post, reproduce, or
-publicly display any part of our Services or Content, you must identify us as the owners or licensors of the Services,
-Content, or Marks and ensure that any copyright or proprietary notice appears or is visible on posting, reproducing, or
-displaying our Content.
-
-We reserve all rights not expressly granted to you in and to the Services, Content, and Marks.
-
-Any breach of these Intellectual Property Rights will constitute a material breach of our Legal Terms and your right to
-use our Services will terminate immediately.
-
-**Your submissions**
-
-Please review this section and the "Prohibited activities" section carefully prior to using our Services to understand
-the (a) rights you give us and (b) obligations you have when you post or upload any content through the Services.
-
-**Submissions**: By directly sending us any question, comment, suggestion, idea, feedback, or other information about the
-Services ("Submissions"), you agree to assign to us all intellectual property rights in such Submission. You agree that
-we shall own this Submission and be entitled to its unrestricted use and dissemination for any lawful purpose,
-commercial or otherwise, without acknowledgment or compensation to you.
-
-**You are responsible for what you post or upload**: By sending us Submissions through any part of the Services you:
-* confirm that you have read and agree with our "Prohibited activities" and will not post, send, publish, upload, or
-* transmit through the Services any Submission that is illegal, harassing, hateful, harmful, defamatory, obscene,
-* bullying, abusive, discriminatory, threatening to any person or group, sexually explicit, false, inaccurate, deceitful,
- or misleading;
-* to the extent permissible by applicable law, waive any and all moral rights to any such Submission;
-* warrant that any such Submission are original to you or that you have the necessary rights and licenses to submit such
- Submissions and that you have full authority to grant us the above-mentioned rights in relation to your Submissions; and
-* warrant and represent that your Submissions do not constitute confidential information.
-
-You are solely responsible for your Submissions and you expressly agree to reimburse us for any and all losses that we
-may suffer because of your breach of (a) this section, (b) any third party’s intellectual property rights, or (c)
-applicable law.
-
-## 3. User representations
-
-By using the Services, you represent and warrant that: (1) all registration information you submit will be true,
-accurate, current, and complete; (2) you will maintain the accuracy of such information and promptly update such
-registration information as necessary; (3) you have the legal capacity and you agree to comply with these Legal Terms; (
-4) you are not a minor in the jurisdiction in which you reside; (5) you will not access the Services through automated
-or non-human means, whether through a bot, script or otherwise; (6) you will not use the Services for any illegal or
-unauthorized purpose; and (7) your use of the Services will not violate any applicable law or regulation.
-
-If you provide any information that is untrue, inaccurate, not current, or incomplete, we have the right to suspend or
-terminate your account and refuse any and all current or future use of the Services (or any portion thereof).
-
-## 4. User registration
-
-You may be required to register to use the Services. You agree to keep your password confidential and will be
-responsible for all use of your account and password. We reserve the right to remove, reclaim, or change a username you
-select if we determine, in our sole discretion, that such username is inappropriate, obscene, or otherwise
-objectionable.
-
-## 5. Purchases and payment
-
-We accept the following forms of payment:
-
-* Visa
-* Mastercard
-
-You agree to provide current, complete, and accurate purchase and account information for all purchases made via the
-Services. You further agree to promptly update account and payment information, including email address, payment method,
-and payment card expiration date, so that we can complete your transactions and contact you as needed. Sales tax will be
-added to the price of purchases as deemed required by us. We may change prices at any time. All payments shall be in US
-dollars.
-
-You agree to pay all charges at the prices then in effect for your purchases and any applicable shipping fees, and you
-authorize us to charge your chosen payment provider for any such amounts upon placing your order. We reserve the right
-to correct any errors or mistakes in pricing, even if we have already requested or received payment.
-
-We reserve the right to refuse any order placed through the Services. We may, in our sole discretion, limit or cancel
-quantities purchased per person, per household, or per order. These restrictions may include orders placed by or under
-the same customer account, the same payment method, and/or orders that use the same billing or shipping address. We
-reserve the right to limit or prohibit orders that, in our sole judgment, appear to be placed by dealers, resellers, or
-distributors.
-
-## 6. Subscriptions
-
-**Billing and Renewal**
-
-e.g. by topping up their balance manually using their credit card.
-
-**Cancellation**
-
-You can cancel your subscription at any time by contacting us using the contact information provided below. Your
-cancellation will take effect at the end of the current paid term. If you have any questions or are unsatisfied with our
-Services, please email us at hello@dstack.ai .
-
-**Fee Changes**
-
-We may, from time to time, make changes to the subscription fee and will communicate any price changes to you in
-accordance with applicable law.
-
-## 7. Software
-
-We may include software for use in connection with our Services. If such software is accompanied by an end user license
-agreement ("EULA"), the terms of the EULA will govern your use of the software. If such software is not accompanied by a
-EULA, then we grant to you a non-exclusive, revocable, personal, and non-transferable license to use such software
-solely in connection with our services and in accordance with these Legal Terms. Any software and any related
-documentation is provided "AS IS" without warranty of any kind, either express or implied, including, without
-limitation, the implied warranties of merchantability, fitness for a particular purpose, or non-infringement. You accept
-any and all risk arising out of use or performance of any software. You may not reproduce or redistribute any software
-except in accordance with the EULA or these Legal Terms.
-
-## 8. Prohibited activities
-
-You may not access or use the Services for any purpose other than that for which we make the Services available. The
-Services may not be used in connection with any commercial endeavors except those that are specifically endorsed or
-approved by us.
-
-As a user of the Services, you agree not to:
-
-* Systematically retrieve data or other content from the Services to create or compile, directly or indirectly, a
- collection, compilation, database, or directory without written permission from us.
-* Trick, defraud, or mislead us and other users, especially in any attempt to learn sensitive account information such
- as user passwords.
-* Circumvent, disable, or otherwise interfere with security-related features of the Services, including features that
- prevent or restrict the use or copying of any Content or enforce limitations on the use of the Services and/or the
- Content contained therein.
-* Disparage, tarnish, or otherwise harm, in our opinion, us and/or the Services.
-* Use any information obtained from the Services in order to harass, abuse, or harm another person.
-* Make improper use of our support services or submit false reports of abuse or misconduct.
-* Use the Services in a manner inconsistent with any applicable laws or regulations.
-* Engage in unauthorized framing of or linking to the Services.
-* Upload or transmit (or attempt to upload or to transmit) viruses, Trojan horses, or other material, including
- excessive use of capital letters and spamming (continuous posting of repetitive text), that interferes with any
- party’s uninterrupted use and enjoyment of the Services or modifies, impairs, disrupts, alters, or interferes with the
- use, features, functions, operation, or maintenance of the Services.
-* Engage in any automated use of the system, such as using scripts to send comments or messages, or using any data
- mining, robots, or similar data gathering and extraction tools.
-* Delete the copyright or other proprietary rights notice from any Content.
-* Attempt to impersonate another user or person or use the username of another user.
-* Upload or transmit (or attempt to upload or to transmit) any material that acts as a passive or active information
- collection or transmission mechanism, including without limitation, clear graphics interchange formats ("gifs"), 1×1
- pixels, web bugs, cookies, or other similar devices (sometimes referred to as "spyware" or "passive collection
- mechanisms" or "pcms").
-* Interfere with, disrupt, or create an undue burden on the Services or the networks or services connected to the
- Services.
-* Harass, annoy, intimidate, or threaten any of our employees or agents engaged in providing any portion of the Services
- to you.
-* Attempt to bypass any measures of the Services designed to prevent or restrict access to the Services, or any portion
- of the Services.
-* Copy or adapt the Services' software, including but not limited to Flash, PHP, HTML, JavaScript, or other code.
-* Except as permitted by applicable law, decipher, decompile, disassemble, or reverse engineer any of the software
- comprising or in any way making up a part of the Services.
-* Except as may be the result of standard search engine or Internet browser usage, use, launch, develop, or distribute
- any automated system, including without limitation, any spider, robot, cheat utility, scraper, or offline reader that
- accesses the Services, or use or launch any unauthorized script or other software.
-* Use a buying agent or purchasing agent to make purchases on the Services.
-* Make any unauthorized use of the Services, including collecting usernames and/or email addresses of users by
- electronic or other means for the purpose of sending unsolicited email, or creating user accounts by automated means
- or under false pretenses.
-* Use the Services as part of any effort to compete with us or otherwise use the Services and/or the Content for any
- revenue-generating endeavor or commercial enterprise.
-
-## 9. User generated contributions
-
-The Services does not offer users to submit or post content.
-
-## 10. Contribution license
-
-You and Services agree that we may access, store, process, and use any information and personal data that you provide
-following the terms of the Privacy Policy and your choices (including settings).
-
-By submitting suggestions or other feedback regarding the Services, you agree that we can use and share such feedback
-for any purpose without compensation to you.
-
-## 11. Social media
-
-As part of the functionality of the Services, you may link your account with online accounts you have with third-party
-service providers (each such account, a "Third-Party Account") by either: (1) providing your Third-Party Account login
-information through the Services; or (2) allowing us to access your Third-Party Account, as is permitted under the
-applicable terms and conditions that govern your use of each Third-Party Account. You represent and warrant that you are
-entitled to disclose your Third-Party Account login information to us and/or grant us access to your Third-Party
-Account, without breach by you of any of the terms and conditions that govern your use of the applicable Third-Party
-Account, and without obligating us to pay any fees or making us subject to any usage limitations imposed by the
-third-party service provider of the Third-Party Account. By granting us access to any Third-Party Accounts, you
-understand that (1) we may access, make available, and store (if applicable) any content that you have provided to and
-stored in your Third-Party Account (the "Social Network Content") so that it is available on and through the Services
-via your account, including without limitation any friend lists and (2) we may submit to and receive from your
-Third-Party Account additional information to the extent you are notified when you link your account with the
-Third-Party Account. Depending on the Third-Party Accounts you choose and subject to the privacy settings that you have
-set in such Third-Party Accounts, personally identifiable information that you post to your Third-Party Accounts may be
-available on and through your account on the Services. Please note that if a Third-Party Account or associated service
-becomes unavailable or our access to such Third-Party Account is terminated by the third-party service provider, then
-Social Network Content may no longer be available on and through the Services. You will have the ability to disable the
-connection between your account on the Services and your Third-Party Accounts at any time. PLEASE NOTE THAT YOUR
-RELATIONSHIP WITH THE THIRD-PARTY SERVICE PROVIDERS ASSOCIATED WITH YOUR THIRD-PARTY ACCOUNTS IS GOVERNED SOLELY BY YOUR
-AGREEMENT(S) WITH SUCH THIRD-PARTY SERVICE PROVIDERS. We make no effort to review any Social Network Content for any
-purpose, including but not limited to, for accuracy, legality, or non-infringement, and we are not responsible for any
-Social Network Content. You acknowledge and agree that we may access your email address book associated with a
-Third-Party Account and your contacts list stored on your mobile device or tablet computer solely for purposes of
-identifying and informing you of those contacts who have also registered to use the Services. You can deactivate the
-connection between the Services and your Third-Party Account by contacting us using the contact information below or
-through your account settings (if applicable). We will attempt to delete any information stored on our servers that was
-obtained through such Third-Party Account, except the username and profile picture that become associated with your
-account.
-
-## 12. Third-party websites and content
-
-The Services may contain (or you may be sent via the Site) links to other websites ("Third-Party Websites") as well as
-articles, photographs, text, graphics, pictures, designs, music, sound, video, information, applications, software, and
-other content or items belonging to or originating from third parties ("Third-Party Content"). Such Third-Party Websites
-and Third-Party Content are not investigated, monitored, or checked for accuracy, appropriateness, or completeness by
-us, and we are not responsible for any Third-Party Websites accessed through the Services or any Third-Party Content
-posted on, available through, or installed from the Services, including the content, accuracy, offensiveness, opinions,
-reliability, privacy practices, or other policies of or contained in the Third-Party Websites or the Third-Party
-Content. Inclusion of, linking to, or permitting the use or installation of any Third-Party Websites or any Third-Party
-Content does not imply approval or endorsement thereof by us. If you decide to leave the Services and access the
-Third-Party Websites or to use or install any Third-Party Content, you do so at your own risk, and you should be aware
-these Legal Terms no longer govern. You should review the applicable terms and policies, including privacy and data
-gathering practices, of any website to which you navigate from the Services or relating to any applications you use or
-install from the Services. Any purchases you make through Third-Party Websites will be through other websites and from
-other companies, and we take no responsibility whatsoever in relation to such purchases which are exclusively between
-you and the applicable third party. You agree and acknowledge that we do not endorse the products or services offered on
-Third-Party Websites and you shall hold us blameless from any harm caused by your purchase of such products or services.
-Additionally, you shall hold us blameless from any losses sustained by you or harm caused to you relating to or
-resulting in any way from any Third-Party Content or any contact with Third-Party Websites.
-
-## 13. Services management
-
-We reserve the right, but not the obligation, to: (1) monitor the Services for violations of these Legal Terms; (2) take
-appropriate legal action against anyone who, in our sole discretion, violates the law or these Legal Terms, including
-without limitation, reporting such user to law enforcement authorities; (3) in our sole discretion and without
-limitation, refuse, restrict access to, limit the availability of, or disable (to the extent technologically feasible)
-any of your Contributions or any portion thereof; (4) in our sole discretion and without limitation, notice, or
-liability, to remove from the Services or otherwise disable all files and content that are excessive in size or are in
-any way burdensome to our systems; and (5) otherwise manage the Services in a manner designed to protect our rights and
-property and to facilitate the proper functioning of the Services.
-
-## 14. Privacy policy
-
-We care about data privacy and security. Please review our [Privacy Policy](https://dstack.ai/privacy/). By using the
-Services, you agree to be bound by our Privacy Policy, which is incorporated into these Legal Terms. Please be advised
-the Services are hosted in Germany and United States. If you access the Services from any other region of the world with
-laws or other requirements governing personal data collection, use, or disclosure that differ from applicable laws in
-Germany and United States, then through your continued use of the Services, you are transferring your data to Germany
-and United States, and you expressly consent to have your data transferred to and processed in Germany and United
-States.
-
-## 15. Term and termination
-
-These Legal Terms shall remain in full force and effect while you use the Services. WITHOUT LIMITING ANY OTHER PROVISION OF THESE LEGAL TERMS, WE RESERVE THE RIGHT TO, IN OUR SOLE DISCRETION AND WITHOUT NOTICE OR LIABILITY, DENY ACCESS TO AND USE OF THE SERVICES (INCLUDING BLOCKING CERTAIN IP ADDRESSES), TO ANY PERSON FOR ANY REASON OR FOR NO REASON, INCLUDING WITHOUT LIMITATION FOR BREACH OF ANY REPRESENTATION, WARRANTY, OR COVENANT CONTAINED IN THESE LEGAL TERMS OR OF ANY APPLICABLE LAW OR REGULATION. WE MAY TERMINATE YOUR USE OR PARTICIPATION IN THE SERVICES OR DELETE YOUR ACCOUNT AND ANY CONTENT OR INFORMATION THAT YOU POSTED AT ANY TIME, WITHOUT WARNING, IN OUR SOLE DISCRETION.
-
-If we terminate or suspend your account for any reason, you are prohibited from registering and creating a new account under your name, a fake or borrowed name, or the name of any third party, even if you may be acting on behalf of the third party. In addition to terminating or suspending your account, we reserve the right to take appropriate legal action, including without limitation pursuing civil, criminal, and injunctive redress.
-
-## 16. Modifications and interruptions
-
-We reserve the right to change, modify, or remove the contents of the Services at any time or for any reason at our sole
-discretion without notice. However, we have no obligation to update any information on our Services. We will not be
-liable to you or any third party for any modification, price change, suspension, or discontinuance of the Services.
-
-We cannot guarantee the Services will be available at all times. We may experience hardware, software, or other problems
-or need to perform maintenance related to the Services, resulting in interruptions, delays, or errors. We reserve the
-right to change, revise, update, suspend, discontinue, or otherwise modify the Services at any time or for any reason
-without notice to you. You agree that we have no liability whatsoever for any loss, damage, or inconvenience caused by
-your inability to access or use the Services during any downtime or discontinuance of the Services. Nothing in these
-Legal Terms will be construed to obligate us to maintain and support the Services or to supply any corrections, updates,
-or releases in connection therewith.
-
-## 17. Governing law
-
-These Legal Terms are governed by and interpreted following the laws of Germany, and the use of the United Nations
-Convention of Contracts for the International Sales of Goods is expressly excluded. If your habitual residence is in the
-EU, and you are a consumer, you additionally possess the protection provided to you by obligatory provisions of the law
-in your country to residence. dstack GmbH and yourself both agree to submit to the non-exclusive jurisdiction of the
-courts of Bayern, which means that you may make a claim to defend your consumer protection rights in regards to these
-Legal Terms in Germany, or in the EU country in which you reside.
-
-## 18. Dispute resolution
-
-**Informal Negotiations**
-
-To expedite resolution and control the cost of any dispute, controversy, or claim related to these Legal Terms (each a "
-Dispute" and collectively, the "Disputes") brought by either you or us (individually, a "Party" and collectively, the "
-Parties"), the Parties agree to first attempt to negotiate any Dispute (except those Disputes expressly provided below)
-informally for at least thirty (30) days before initiating arbitration. Such informal negotiations commence upon written
-notice from one Party to the other Party.
-
-**Binding Arbitration**
-
-Any dispute arising from the relationships between the Parties to these Legal Terms shall be determined by one
-arbitrator who will be chosen in accordance with the Arbitration and Internal Rules of the European Court of Arbitration
-being part of the European Centre of Arbitration having its seat in Strasbourg, and which are in force at the time the
-application for arbitration is filed, and of which adoption of this clause constitutes acceptance. The seat of
-arbitration shall be Munich , Germany . The language of the proceedings shall be German . Applicable rules of
-substantive law shall be the law of Germany .
-
-**Restrictions**
-
-The Parties agree that any arbitration shall be limited to the Dispute between the Parties individually. To the full
-extent permitted by law, (a) no arbitration shall be joined with any other proceeding; (b) there is no right or
-authority for any Dispute to be arbitrated on a class-action basis or to utilize class action procedures; and (c) there
-is no right or authority for any Dispute to be brought in a purported representative capacity on behalf of the general
-public or any other persons.
-
-**Exceptions to Informal Negotiations and Arbitration**
-
-The Parties agree that the following Disputes are not subject to the above provisions concerning informal negotiations
-binding arbitration: (a) any Disputes seeking to enforce or protect, or concerning the validity of, any of the
-intellectual property rights of a Party; (b) any Dispute related to, or arising from, allegations of theft, piracy,
-invasion of privacy, or unauthorized use; and (c) any claim for injunctive relief. If this provision is found to be
-illegal or unenforceable, then neither Party will elect to arbitrate any Dispute falling within that portion of this
-provision found to be illegal or unenforceable and such Dispute shall be decided by a court of competent jurisdiction
-within the courts listed for jurisdiction above, and the Parties agree to submit to the personal jurisdiction of that
-court.
-
-## 19. Corrections
-
-There may be information on the Services that contains typographical errors, inaccuracies, or omissions, including
-descriptions, pricing, availability, and various other information. We reserve the right to correct any errors,
-inaccuracies, or omissions and to change or update the information on the Services at any time, without prior notice.
-
-## 20. Disclaimer
-
-THE SERVICES ARE PROVIDED ON AN AS-IS AND AS-AVAILABLE BASIS. YOU AGREE THAT YOUR USE OF THE SERVICES WILL BE AT YOUR
-SOLE RISK. TO THE FULLEST EXTENT PERMITTED BY LAW, WE DISCLAIM ALL WARRANTIES, EXPRESS OR IMPLIED, IN CONNECTION WITH
-THE SERVICES AND YOUR USE THEREOF, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF MERCHANTABILITY, FITNESS FOR
-A PARTICULAR PURPOSE, AND NON-INFRINGEMENT. WE MAKE NO WARRANTIES OR REPRESENTATIONS ABOUT THE ACCURACY OR COMPLETENESS
-OF THE SERVICES' CONTENT OR THE CONTENT OF ANY WEBSITES OR MOBILE APPLICATIONS LINKED TO THE SERVICES AND WE WILL ASSUME
-NO LIABILITY OR RESPONSIBILITY FOR ANY (1) ERRORS, MISTAKES, OR INACCURACIES OF CONTENT AND MATERIALS, (2) PERSONAL
-INJURY OR PROPERTY DAMAGE, OF ANY NATURE WHATSOEVER, RESULTING FROM YOUR ACCESS TO AND USE OF THE SERVICES, (3) ANY
-UNAUTHORIZED ACCESS TO OR USE OF OUR SECURE SERVERS AND/OR ANY AND ALL PERSONAL INFORMATION AND/OR FINANCIAL INFORMATION
-STORED THEREIN, (4) ANY INTERRUPTION OR CESSATION OF TRANSMISSION TO OR FROM THE SERVICES, (5) ANY BUGS, VIRUSES, TROJAN
-HORSES, OR THE LIKE WHICH MAY BE TRANSMITTED TO OR THROUGH THE SERVICES BY ANY THIRD PARTY, AND/OR (6) ANY ERRORS OR
-OMISSIONS IN ANY CONTENT AND MATERIALS OR FOR ANY LOSS OR DAMAGE OF ANY KIND INCURRED AS A RESULT OF THE USE OF ANY
-CONTENT POSTED, TRANSMITTED, OR OTHERWISE MADE AVAILABLE VIA THE SERVICES. WE DO NOT WARRANT, ENDORSE, GUARANTEE, OR
-ASSUME RESPONSIBILITY FOR ANY PRODUCT OR SERVICE ADVERTISED OR OFFERED BY A THIRD PARTY THROUGH THE SERVICES, ANY
-HYPERLINKED WEBSITE, OR ANY WEBSITE OR MOBILE APPLICATION FEATURED IN ANY BANNER OR OTHER ADVERTISING, AND WE WILL NOT
-BE A PARTY TO OR IN ANY WAY BE RESPONSIBLE FOR MONITORING ANY TRANSACTION BETWEEN YOU AND ANY THIRD-PARTY PROVIDERS OF
-PRODUCTS OR SERVICES. AS WITH THE PURCHASE OF A PRODUCT OR SERVICE THROUGH ANY MEDIUM OR IN ANY ENVIRONMENT, YOU SHOULD
-USE YOUR BEST JUDGMENT AND EXERCISE CAUTION WHERE APPROPRIATE.
-
-## 21. Limitations of liability
-
-IN NO EVENT WILL WE OR OUR DIRECTORS, EMPLOYEES, OR AGENTS BE LIABLE TO YOU OR ANY THIRD PARTY FOR ANY DIRECT, INDIRECT,
-CONSEQUENTIAL, EXEMPLARY, INCIDENTAL, SPECIAL, OR PUNITIVE DAMAGES, INCLUDING LOST PROFIT, LOST REVENUE, LOSS OF DATA,
-OR OTHER DAMAGES ARISING FROM YOUR USE OF THE SERVICES, EVEN IF WE HAVE BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGES.
-NOTWITHSTANDING ANYTHING TO THE CONTRARY CONTAINED HEREIN, OUR LIABILITY TO YOU FOR ANY CAUSE WHATSOEVER AND REGARDLESS
-OF THE FORM OF THE ACTION, WILL AT ALL TIMES BE LIMITED TO THE LESSER OF THE AMOUNT PAID, IF ANY, BY YOU TO US DURING
-THE zero (0) MONTH PERIOD PRIOR TO ANY CAUSE OF ACTION ARISING OR $0.00 USD. CERTAIN US STATE LAWS AND INTERNATIONAL
-LAWS DO NOT ALLOW LIMITATIONS ON IMPLIED WARRANTIES OR THE EXCLUSION OR LIMITATION OF CERTAIN DAMAGES. IF THESE LAWS
-APPLY TO YOU, SOME OR ALL OF THE ABOVE DISCLAIMERS OR LIMITATIONS MAY NOT APPLY TO YOU, AND YOU MAY HAVE ADDITIONAL
-RIGHTS.
-
-## 22. Indemnification
-
-You agree to defend, indemnify, and hold us harmless, including our subsidiaries, affiliates, and all of our respective officers, agents, partners, and employees, from and against any loss, damage, liability, claim, or demand, including reasonable attorneys’ fees and expenses, made by any third party due to or arising out of: (1) use of the Services; (2) breach of these Legal Terms; (3) any breach of your representations and warranties set forth in these Legal Terms; (4) your violation of the rights of a third party, including but not limited to intellectual property rights; or (5) any overt harmful act toward any other user of the Services with whom you connected via the Services. Notwithstanding the foregoing, we reserve the right, at your expense, to assume the exclusive defense and control of any matter for which you are required to indemnify us, and you agree to cooperate, at your expense, with our defense of such claims. We will use reasonable efforts to notify you of any such claim, action, or proceeding which is subject to this indemnification upon becoming aware of it.
-
-## 23. User data
-
-We will maintain certain data that you transmit to the Services for the purpose of managing the performance of the
-Services, as well as data relating to your use of the Services. Although we perform regular routine backups of data, you
-are solely responsible for all data that you transmit or that relates to any activity you have undertaken using the
-Services. You agree that we shall have no liability to you for any loss or corruption of any such data, and you hereby
-waive any right of action against us arising from any such loss or corruption of such data.
-
-## 24. Electronic communications, transactions, and signatures
-
-Visiting the Services, sending us emails, and completing online forms constitute electronic communications. You consent
-to receive electronic communications, and you agree that all agreements, notices, disclosures, and other communications
-we provide to you electronically, via email and on the Services, satisfy any legal requirement that such communication
-be in writing. YOU HEREBY AGREE TO THE USE OF ELECTRONIC SIGNATURES, CONTRACTS, ORDERS, AND OTHER RECORDS, AND TO
-ELECTRONIC DELIVERY OF NOTICES, POLICIES, AND RECORDS OF TRANSACTIONS INITIATED OR COMPLETED BY US OR VIA THE SERVICES.
-You hereby waive any rights or requirements under any statutes, regulations, rules, ordinances, or other laws in any
-jurisdiction which require an original signature or delivery or retention of non-electronic records, or to payments or
-the granting of credits by any means other than electronic means.
-
-## 25. California users and residents
-
-If any complaint with us is not satisfactorily resolved, you can contact the Complaint Assistance Unit of the Division
-of Consumer Services of the California Department of Consumer Affairs in writing at 1625 North Market Blvd., Suite N
-112, Sacramento, California 95834 or by telephone at (800) 952-5210 or (916) 445-1254.
-
-## 26. Miscellaneous
-
-These Legal Terms and any policies or operating rules posted by us on the Services or in respect to the Services
-constitute the entire agreement and understanding between you and us. Our failure to exercise or enforce any right or
-provision of these Legal Terms shall not operate as a waiver of such right or provision. These Legal Terms operate to
-the fullest extent permissible by law. We may assign any or all of our rights and obligations to others at any time. We
-shall not be responsible or liable for any loss, damage, delay, or failure to act caused by any cause beyond our
-reasonable control. If any provision or part of a provision of these Legal Terms is determined to be unlawful, void, or
-unenforceable, that provision or part of the provision is deemed severable from these Legal Terms and does not affect
-the validity and enforceability of any remaining provisions. There is no joint venture, partnership, employment or
-agency relationship created between you and us as a result of these Legal Terms or use of the Services. You agree that
-these Legal Terms will not be construed against us by virtue of having drafted them. You hereby waive any and all
-defenses you may have based on the electronic form of these Legal Terms and the lack of signing by the parties hereto to
-execute these Legal Terms.
-
-## 27. Contact us
-
-In order to resolve a complaint regarding the Services or to receive further information regarding use of the Services,
-please contact us at **hello@dstack.ai**.
diff --git a/examples/.dstack.yml b/examples/.dstack.yml
index 80b0a6dd9e..dc8a9c58c3 100644
--- a/examples/.dstack.yml
+++ b/examples/.dstack.yml
@@ -1,6 +1,12 @@
type: dev-environment
-# This configuration launches a blank dev environment
+name: cursor
-python: "3.11"
+python: 3.12
+ide: cursor
-ide: vscode
\ No newline at end of file
+# Mount the repo directory to `/workflow` (the default working directory)
+repos:
+ - ..
+
+resources:
+ gpu: 1
diff --git a/examples/README.md b/examples/README.md
deleted file mode 100644
index 6f860b0cc8..0000000000
--- a/examples/README.md
+++ /dev/null
@@ -1,54 +0,0 @@
-# Examples
-
-This folder contains examples showing how to use `dstack`.
-
-> [!IMPORTANT]
-> Feel free to contribute your examples or enhance the existing ones—your PRs are warmly welcomed in this repo!
-
-## Getting started
-
-### Prerequisites
-
-To use the open-source version, make sure to [install the server](https://dstack.ai/docs/installation/) and configure backends.
-
-### Run examples
-
-#### Init the repo
-
-```shell
-git clone https://github.com/dstackai/dstack
-cd dstack
-dstack init
-```
-
-#### Run a dev environment
-
-Here's how to run a dev environment with the current repo:
-
-```shell
-dstack run . -f examples/.dstack.yml
-```
-
-#### Run other examples
-
-Here's how to run other examples, e.g. [`deployment/vllm`](deployment/vllm/):
-
-```shell
-dstack run . -f examples/deployment/vllm/serve.dstack.yml
-```
-
-## Featrued
-
-Here are some featured examples:
-
-- [Llama 3](llms/llama3)
-- [Alignment Handbook](fine-tuning/alignment-handbook)
-- [vLLM](deployment/vllm)
-- [Axolotl](fine-tuning/axolotl)
-- [TGI](deployment/tgi)
-- [Ollama](deployment/ollama)
-
-Browse [deployment](deployment), [fine-tuning](deployment), [llms](llms), and [misc](misc) for more.
-
-> [!IMPORTANT]
-> Feel free to contribute your examples or enhance the existing ones—your PRs are warmly welcomed in this repo!
\ No newline at end of file
diff --git a/gateway/src/dstack/gateway/auth/__init__.py b/examples/__init__.py
similarity index 100%
rename from gateway/src/dstack/gateway/auth/__init__.py
rename to examples/__init__.py
diff --git a/examples/deployment/infinity/README.md b/examples/deployment/infinity/README.md
deleted file mode 100644
index 5053be17ad..0000000000
--- a/examples/deployment/infinity/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Infinity
-
-The following command a text embedding model as a service:
-
-```shell
-dstack run . -f examples/deployment/infinity/serve.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve.dstack.yml).
-
-For more details, refer to [services](https://dstack.ai/docs/concepts/services).
\ No newline at end of file
diff --git a/examples/deployment/infinity/serve.dstack.yml b/examples/deployment/infinity/serve.dstack.yml
deleted file mode 100644
index 66a5289a18..0000000000
--- a/examples/deployment/infinity/serve.dstack.yml
+++ /dev/null
@@ -1,13 +0,0 @@
-type: service
-# This service deploys embeddings model and reranker model with Infinity. Learn more at https://dstack.ai/examples/infinity/
-
-image: michaelf34/infinity:latest
-env:
- - INFINITY_MODEL_ID=BAAI/bge-small-en-v1.5;BAAI/bge-reranker-base;
- - INFINITY_PORT=8000
-commands:
- - infinity_emb v2
-port: 8000
-
-resources:
- gpu: 16GB
diff --git a/examples/deployment/lorax/README.md b/examples/deployment/lorax/README.md
deleted file mode 100644
index 893eaf0206..0000000000
--- a/examples/deployment/lorax/README.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# LoRaX
-
-[LoRAX](https://github.com/predibase/lorax) allows serving multiple fine-tuned models optimized on
-the same endpoint by dynamically loading and switching LoRA adapters.
-
-## Service
-
-The following command deploys Mistral 7B Instruct as a base model via a service:
-
-```shell
-dstack run . -f examples/deployment/lorax/serve.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve.dstack.yml).
-
-## Task
-
-The following command runs Mistral 7B Instruct as a base model via a task:
-
-```shell
-dstack run . -f examples/deployment/lorax/serve-task.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve-task.dstack.yml).
-
-For more details, refer to [services](https://dstack.ai/docs/concepts/services) or [tasks](https://dstack.ai/docs/concepts/tasks).
\ No newline at end of file
diff --git a/examples/deployment/lorax/serve-task.dstack.yml b/examples/deployment/lorax/serve-task.dstack.yml
deleted file mode 100644
index 36ac0e950d..0000000000
--- a/examples/deployment/lorax/serve-task.dstack.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-type: task
-
-image: ghcr.io/predibase/lorax:latest
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - MODEL_ID=mistralai/Mistral-7B-Instruct-v0.1
-
-commands:
- - cd /usr/src
- - lorax-launcher --port 8000 --model-id $MODEL_ID
-
-ports:
- - 8000
-
-resources:
- gpu: 24GB
- shm_size: 1GB
diff --git a/examples/deployment/lorax/serve.dstack.yml b/examples/deployment/lorax/serve.dstack.yml
deleted file mode 100644
index a48513cfdc..0000000000
--- a/examples/deployment/lorax/serve.dstack.yml
+++ /dev/null
@@ -1,17 +0,0 @@
-type: service
-
-image: ghcr.io/predibase/lorax:latest
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - MODEL_ID=mistralai/Mistral-7B-Instruct-v0.1
-
-commands:
- - cd /usr/src
- - lorax-launcher --port 8000 --model-id $MODEL_ID
-
-port: 8000
-
-resources:
- gpu: 24GB
- shm_size: 1GB
diff --git a/examples/deployment/ollama/.dstack.yml b/examples/deployment/ollama/.dstack.yml
deleted file mode 100644
index 7775f8d2b6..0000000000
--- a/examples/deployment/ollama/.dstack.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-type: dev-environment
-# Launches a dev environment to play with Ollama
-
-image: ollama/ollama
-
-ide: vscode
-
-resources:
- gpu: 48GB..80GB
diff --git a/examples/deployment/ollama/README.md b/examples/deployment/ollama/README.md
deleted file mode 100644
index ce7bb3916d..0000000000
--- a/examples/deployment/ollama/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Ollama
-
-The following command deploys Mixtral 8x7B as a service:
-
-```shell
-dstack run . -f examples/deployment/ollama/serve.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve.dstack.yml).
-
-For more details, refer to [services](https://dstack.ai/docs/concepts/services).
\ No newline at end of file
diff --git a/examples/deployment/ollama/serve.dstack.yml b/examples/deployment/ollama/serve.dstack.yml
deleted file mode 100644
index 219d6222ef..0000000000
--- a/examples/deployment/ollama/serve.dstack.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-type: service
-# Deploys Mixtral 8x7B with Ollama
-
-image: ollama/ollama
-commands:
- - ollama serve &
- - sleep 3
- - ollama pull mixtral
- - fg
-port: 11434
-
-resources:
- gpu: 48GB..80GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- type: chat
- name: mixtral
- format: openai
\ No newline at end of file
diff --git a/examples/deployment/tei/README.md b/examples/deployment/tei/README.md
deleted file mode 100644
index 030f249f66..0000000000
--- a/examples/deployment/tei/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Text Embeddings Inference
-
-The following command a text embedding model as a service:
-
-```shell
-dstack run . -f examples/deployment/tae/serve.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve.dstack.yml).
-
-For more details, refer to [services](https://dstack.ai/docs/concepts/services).
\ No newline at end of file
diff --git a/examples/deployment/tei/serve.dstack.yml b/examples/deployment/tei/serve.dstack.yml
deleted file mode 100644
index a0ac770d86..0000000000
--- a/examples/deployment/tei/serve.dstack.yml
+++ /dev/null
@@ -1,12 +0,0 @@
-type: service
-# This service deploys an embeddings model with TEI
-
-image: ghcr.io/huggingface/text-embeddings-inference:latest
-env:
- - MODEL_ID=thenlper/gte-base
-commands:
- - text-embeddings-router --port 8000
-port: 8000
-
-resources:
- gpu: 16GB..
diff --git a/examples/deployment/tgi/.dstack.yml b/examples/deployment/tgi/.dstack.yml
deleted file mode 100644
index 856faa0a4e..0000000000
--- a/examples/deployment/tgi/.dstack.yml
+++ /dev/null
@@ -1,9 +0,0 @@
-type: dev-environment
-# Launches a dev environment to play with TGI
-
-image: ghcr.io/huggingface/text-generation-inference:latest
-
-ide: vscode
-
-resources:
- gpu: 24GB
\ No newline at end of file
diff --git a/examples/deployment/tgi/README.md b/examples/deployment/tgi/README.md
deleted file mode 100644
index 60fb18bfbd..0000000000
--- a/examples/deployment/tgi/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# Text Generation Inference
-
-## Service
-
-The following command deploys Llama 7B Instruct as a service:
-
-```shell
-dstack run . -f examples/deployment/tgi/serve.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve.dstack.yml).
-
-## Task
-
-The following command runs Llama 7B Instruct as a task:
-
-```shell
-dstack run . -f examples/deployment/tgi/serve-task.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve-task.dstack.yml).
-
-For more details, refer to [services](https://dstack.ai/docs/concepts/services) or [tasks](https://dstack.ai/docs/concepts/tasks).
\ No newline at end of file
diff --git a/examples/deployment/tgi/serve-gptq.dstack.yml b/examples/deployment/tgi/serve-gptq.dstack.yml
deleted file mode 100644
index f1a811896b..0000000000
--- a/examples/deployment/tgi/serve-gptq.dstack.yml
+++ /dev/null
@@ -1,20 +0,0 @@
-type: service
-# This service runs Llama 2 13B (quantized) with TGI
-
-image: ghcr.io/huggingface/text-generation-inference:latest
-env:
- - MODEL_ID=TheBloke/Mistral-7B-Instruct-v0.2-GPTQ
-commands:
- - text-generation-launcher --port 8000 --trust-remote-code --quantize gptq
-port: 8000
-
-resources:
- gpu: 24GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- type: chat
- name: TheBloke/Mistral-7B-Instruct-v0.2-GPTQ
- format: tgi
- chat_template: "{% if messages[0]['role'] == 'system' %}{% set loop_messages = messages[1:] %}{% set system_message = messages[0]['content'] %}{% else %}{% set loop_messages = messages %}{% set system_message = false %}{% endif %}{% for message in loop_messages %}{% if (message['role'] == 'user') != (loop.index0 % 2 == 0) %}{{ raise_exception('Conversation roles must alternate user/assistant/user/assistant/...') }}{% endif %}{% if loop.index0 == 0 and system_message != false %}{% set content = '<>\\n' + system_message + '\\n< >\\n\\n' + message['content'] %}{% else %}{% set content = message['content'] %}{% endif %}{% if message['role'] == 'user' %}{{ '[INST] ' + content.strip() + ' [/INST]' }}{% elif message['role'] == 'assistant' %}{{ ' ' + content.strip() + ' ' }}{% endif %}{% endfor %}"
- eos_token: ""
diff --git a/examples/deployment/tgi/serve-task.dstack.yml b/examples/deployment/tgi/serve-task.dstack.yml
deleted file mode 100644
index 5376e635b1..0000000000
--- a/examples/deployment/tgi/serve-task.dstack.yml
+++ /dev/null
@@ -1,15 +0,0 @@
-type: task
-# This task runs Llama 2 with TGI
-
-image: ghcr.io/huggingface/text-generation-inference:latest
-env:
- - HUGGING_FACE_HUB_TOKEN
- - MODEL_ID=mistralai/Mistral-7B-Instruct-v0.2
-commands:
- - text-generation-launcher --port 8000 --trust-remote-code
-ports:
- - 8000
-
-resources:
- gpu: 24GB
-
diff --git a/examples/deployment/tgi/serve.dstack.yml b/examples/deployment/tgi/serve.dstack.yml
deleted file mode 100644
index 81a27e4f0d..0000000000
--- a/examples/deployment/tgi/serve.dstack.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-type: service
-# This service runs Llama 2 with TGI
-
-image: ghcr.io/huggingface/text-generation-inference:latest
-env:
- - HUGGING_FACE_HUB_TOKEN
- - MODEL_ID=mistralai/Mistral-7B-Instruct-v0.2
-commands:
- - text-generation-launcher --port 8000 --trust-remote-code
-port: 8000
-
-resources:
- gpu: 24GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- format: tgi
- type: chat
- name: mistralai/Mistral-7B-Instruct-v0.2
diff --git a/examples/deployment/vllm/.dstack.yml b/examples/deployment/vllm/.dstack.yml
deleted file mode 100644
index d59d5f6dec..0000000000
--- a/examples/deployment/vllm/.dstack.yml
+++ /dev/null
@@ -1,11 +0,0 @@
-type: dev-environment
-# Launches a dev environment to play with vllm
-
-image: vllm/vllm-openai:latest
-env:
- - PYTHONPATH=/workspace
-
-ide: vscode
-
-resources:
- gpu: 24GB
diff --git a/examples/deployment/vllm/README.md b/examples/deployment/vllm/README.md
deleted file mode 100644
index e87766a894..0000000000
--- a/examples/deployment/vllm/README.md
+++ /dev/null
@@ -1,23 +0,0 @@
-# vLLM
-
-## Service
-
-The following command deploys Llama 7B Instruct as a service:
-
-```shell
-dstack run . -f examples/deployment/vllm/serve.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve.dstack.yml).
-
-## Task
-
-The following command runs Llama 7B Instruct as a task:
-
-```shell
-dstack run . -f examples/deployment/vllm/serve-task.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve-task.dstack.yml).
-
-For more details, refer to [services](https://dstack.ai/docs/concepts/services) or [tasks](https://dstack.ai/docs/concepts/tasks).
\ No newline at end of file
diff --git a/examples/deployment/vllm/serve-task.dstack.yml b/examples/deployment/vllm/serve-task.dstack.yml
deleted file mode 100644
index 60b90cccc3..0000000000
--- a/examples/deployment/vllm/serve-task.dstack.yml
+++ /dev/null
@@ -1,14 +0,0 @@
-type: task
-# This task runs Llama 2 with vllm
-
-image: vllm/vllm-openai:latest
-env:
- - MODEL=NousResearch/Llama-2-7b-chat-hf
- - PYTHONPATH=/workspace
-commands:
- - python3 -m vllm.entrypoints.openai.api_server --model $MODEL --port 8000
-ports:
- - 8000
-
-resources:
- gpu: 24GB
diff --git a/examples/deployment/vllm/serve.dstack.yml b/examples/deployment/vllm/serve.dstack.yml
deleted file mode 100644
index 849c187d4a..0000000000
--- a/examples/deployment/vllm/serve.dstack.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-type: service
-# This service runs Llama 2 with vllm
-
-image: vllm/vllm-openai:latest
-env:
- - MODEL=NousResearch/Llama-2-7b-chat-hf
- - PYTHONPATH=/workspace
-commands:
- - python3 -m vllm.entrypoints.openai.api_server --model $MODEL --port 8000
-port: 8000
-
-resources:
- gpu: 24GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- format: openai
- type: chat
- name: NousResearch/Llama-2-7b-chat-hf
diff --git a/examples/distributed-training/torchrun/.dstack.yml b/examples/distributed-training/torchrun/.dstack.yml
new file mode 100644
index 0000000000..4eccdb263e
--- /dev/null
+++ b/examples/distributed-training/torchrun/.dstack.yml
@@ -0,0 +1,24 @@
+type: task
+name: train-distrib
+
+nodes: 2
+
+python: 3.12
+env:
+ - NCCL_DEBUG=INFO
+commands:
+ - git clone https://github.com/pytorch/examples.git pytorch-examples
+ - cd pytorch-examples/distributed/ddp-tutorial-series
+ - uv pip install -r requirements.txt
+ - |
+ torchrun \
+ --nproc-per-node=$DSTACK_GPUS_PER_NODE \
+ --node-rank=$DSTACK_NODE_RANK \
+ --nnodes=$DSTACK_NODES_NUM \
+ --master-addr=$DSTACK_MASTER_NODE_IP \
+ --master-port=12345 \
+ multinode.py 50 10
+
+resources:
+ gpu: 1..8
+ shm_size: 16GB
diff --git a/examples/fine-tuning/alignment-handbook/README.md b/examples/fine-tuning/alignment-handbook/README.md
deleted file mode 100644
index 1e3df46732..0000000000
--- a/examples/fine-tuning/alignment-handbook/README.md
+++ /dev/null
@@ -1,111 +0,0 @@
-# Alignment Handbook
-
-[Alignment Handbook](https://github.com/huggingface/alignment-handbook) provides robust recipes to continue pretraining
-and to align language models with human and AI preferences. It basically comes with two types of recipes and four types
-of scripts that were used to create Hugging Face [Zephyr models](https://huggingface.co/HuggingFaceH4):
-
-- Accelerate recipes: configurations for [DeepSpeed Zero3](https://huggingface.co/docs/accelerate/v0.11.0/en/deepspeed),
-- [FSDP(Fully Sharded Data Parallel)](https://pytorch.org/tutorials/intermediate/FSDP_tutorial.html), and multi GPU.
-
-- Training recipes: configurations of how GPT2, StarChat2-15B, Zephyr-141B-A35B, Zephyr-7B-Beta, and Zephyr-7B-Gemma
- models were fine-tuned.
-
-- Scripts: [`run_cpt.py`](https://github.com/huggingface/alignment-handbook/blob/main/scripts/run_cpt.py) for continual
- pre-training, [`run_sft.py`](https://github.com/huggingface/alignment-handbook/blob/main/scripts/run_sft.py) for
- supervised fine-tuning, [`run_dpo.py`](https://github.com/huggingface/alignment-handbook/blob/main/scripts/run_dpo.py)
- for aligning with preferences via [DPO](https://arxiv.org/abs/2305.18290),
- and [`run_orpo.py`](https://github.com/huggingface/alignment-handbook/blob/main/scripts/run_orpo.py) aligning
- with [ORPO](https://arxiv.org/abs/2403.07691).
-
-## Basics
-
-Alignment Handbook provides all the code you need to run CPT, SFT, DPO, and ORPO within Hugging Face OSS ecosystem
-such as `transformers`, `peft`, `accelerate`, `trl`. All you need to do is to modify recipes for accelerate and
-training, and run appropriate script.
-
-For instance, if you want to QLoRA fine-tune Gemma 7B model on your own SFT dataset hosted on Hugging Face Hub, you can
-prepare a `yaml` config file as [config.yaml](config.yaml). This config is based on the Zephyr-7B-Gemma recipe except
-the following modification:
-
-- `dataset_mixer` field to point which SFT dataset to be used.
-- `hub_model_id` and `output_dir` fields to point where the model and its checkpoints should be saved.
-- `LoRA arguments` related fields to indicate that this fine-tuning is based on QLoRA methodology.
-
-With the `config.yaml` file configured, you can run the following command to QLoRA fine-tune Gemma 7B model on 2
-GPUs:
-
-```shell
-ACCELERATE_LOG_LEVEL=info accelerate launch \
- --config_file config.yaml \
- --num_processes=2 \
- scripts/run_sft.py \
- recipes/{model_name}/{task}/config_qlora.yaml
-```
-
-For more details and other alignment methods, please check out the
-alignment-handbook's [official repository](https://github.com/huggingface/alignment-handbook).
-
-## Running via `dstack`
-
-This example demonstrate how to run an Alignment Handbook recipe via `dstack`.
-
-First, define the [`train.dstack.yaml`](train.dstack.yaml) task configuration file as following:
-
-```yaml
-type: task
-
-python: "3.11"
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - WANDB_API_KEY
-
-commands:
- - conda install cuda
- - git clone https://github.com/huggingface/alignment-handbook.git
- - mkdir -p alignment-handbook/recipes/custom/
- - cp config.yaml alignment-handbook/recipes/custom/config.yaml
-
- - cd alignment-handbook
- - python -m pip install .
- - python -m pip install flash-attn --no-build-isolation
-
- - pip install wandb
- - wandb login $WANDB_API_KEY
-
- - ACCELERATE_LOG_LEVEL=info accelerate launch
- --config_file recipes/accelerate_configs/multi_gpu.yaml
- --num_processes=$DSTACK_GPUS_NUM
- scripts/run_sft.py
- recipes/custom/config.yaml
-
-ports:
- - 6006
-
-resources:
- gpu:
- memory: 40GB
- name: A6000
- count: 2
-```
-
-> [!NOTE]
-> Feel free to adjust `resources` to specify the required resources.
-
-The task clones the `huggingface/alignment-handbook` repo, and copies our local `config.yaml` to the recipies subfolder.
-Then, the task installs dependencies, and launches the recipe.
-
-Our `config.yaml` sets `report_to` to `wandb` and `tensorboard`. That's why we the task also installs `wandb`.
-
-To run the task, use the following command:
-
-```shell
-HUGGING_FACE_HUB_TOKEN=<...> \
-WANDB_API_KEY=<...> \
-dstack run . -f examples/fine-tuning/alignment-handbook/train.dstack.yaml
-```
-
-## Results
-
-- [merged_ds_coding](https://huggingface.co/datasets/chansung/merged_ds_coding): SFT dataset for solely coding task. It roughly contains 60k training dataset.
-- [chansung/coding_llamaduo_60k_v0.2](https://huggingface.co/chansung/coding_llamaduo_60k_v0.2): QLoRA adapter for Gemma 7B with the exactly the same configuration as in [`config.yaml`](./config.yaml). This adapter is fine-tuned on the `merged_ds_coding` dataset with 2xA6000 GPUs via `dstack` Sky.
\ No newline at end of file
diff --git a/examples/fine-tuning/alignment-handbook/config.yaml b/examples/fine-tuning/alignment-handbook/config.yaml
deleted file mode 100644
index abeab49c93..0000000000
--- a/examples/fine-tuning/alignment-handbook/config.yaml
+++ /dev/null
@@ -1,64 +0,0 @@
-# Model arguments
-model_name_or_path: google/gemma-7b
-model_revision: main
-tokenizer_name_or_path: philschmid/gemma-tokenizer-chatml # Custom tokenizer with <|im_start|> and <|im_end|> tokens
-torch_dtype: bfloat16
-use_flash_attention_2: true
-
-# LoRA arguments
-load_in_4bit: true
-use_peft: true
-lora_r: 16
-lora_alpha: 16
-lora_dropout: 0.05
-lora_target_modules:
-- q_proj
-- k_proj
-- v_proj
-- o_proj
-- gate_proj
-- up_proj
-- down_proj
-
-# Data training arguments
-dataset_mixer:
- chansung/merged_ds_coding: 1.0
-dataset_splits:
-- train_sft
-- test_sft
-preprocessing_num_workers: 12
-
-# SFT trainer config
-bf16: true
-dataset_kwargs:
- add_special_tokens: false # We already wrap and in the chat template
- append_concat_token: false # No need to add across samples
-do_eval: true
-evaluation_strategy: epoch
-gradient_accumulation_steps: 2
-gradient_checkpointing: true
-gradient_checkpointing_kwargs:
- use_reentrant: false
-hub_model_id: chansung/coding_llamaduo_60k_v0.2
-hub_strategy: every_save
-learning_rate: 2.0e-04
-log_level: info
-logging_steps: 5
-logging_strategy: steps
-lr_scheduler_type: cosine
-max_seq_length: 2048
-max_steps: -1
-num_train_epochs: 5
-output_dir: data/coding_llamaduo_60k_v0.2
-overwrite_output_dir: true
-per_device_eval_batch_size: 2
-per_device_train_batch_size: 2
-push_to_hub: true
-report_to:
-- tensorboard
-- wandb
-save_strategy: "steps"
-save_steps: 100
-save_total_limit: 1
-seed: 42
-warmup_ratio: 0.1
\ No newline at end of file
diff --git a/examples/fine-tuning/alignment-handbook/train.dstack.yaml b/examples/fine-tuning/alignment-handbook/train.dstack.yaml
deleted file mode 100644
index 67fdb119e4..0000000000
--- a/examples/fine-tuning/alignment-handbook/train.dstack.yaml
+++ /dev/null
@@ -1,35 +0,0 @@
-type: task
-
-python: "3.11"
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - WANDB_API_KEY
-
-commands:
- - conda install cuda
- - git clone https://github.com/huggingface/alignment-handbook.git
- - mkdir -p alignment-handbook/recipes/custom/
- - cp config.yaml alignment-handbook/recipes/custom/config.yaml
-
- - cd alignment-handbook
- - python -m pip install .
- - python -m pip install flash-attn --no-build-isolation
-
- - pip install wandb
- - wandb login $WANDB_API_KEY
-
- - ACCELERATE_LOG_LEVEL=info accelerate launch
- --config_file recipes/accelerate_configs/multi_gpu.yaml
- --num_processes=2
- scripts/run_sft.py
- recipes/custom/config.yaml
-
-ports:
- - 6006
-
-resources:
- gpu:
- memory: 40GB
- name: A6000
- count: 2
\ No newline at end of file
diff --git a/examples/fine-tuning/axolotl/README.md b/examples/fine-tuning/axolotl/README.md
deleted file mode 100644
index 3f8c5afea2..0000000000
--- a/examples/fine-tuning/axolotl/README.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Axolotl
-
-[`axolotl`](https://github.com/OpenAccess-AI-Collective/axolotl) streamlines the fine-tuning of AI models, offering support for multiple configurations and architectures.
-
-Furthermore, `axolotl` provides a set of [`yaml` examples](https://github.com/OpenAccess-AI-Collective/axolotl/tree/main/examples) for almost all kinds of LLMs such as LLaMA2 family, Gemma family, LLaMA3 family, Jamba, and so on. It's recommended to navigate through the examples to get a sense about the role of each parameters, and adjust them for your specific use cases. Also, it is worth checking out all configs/parameters options with a brief description from [this doc](https://github.com/OpenAccess-AI-Collective/axolotl/blob/main/docs/config.qmd).
-
-The example below replicates the [FSDP+QLoRA on LLaMA3 70B](https://github.com/OpenAccess-AI-Collective/axolotl/blob/main/examples/llama-3/qlora-fsdp-70b.yaml), except that here we use Llama3 8B. You can see the [`config.yaml`](config.yaml).
-
-## Running with `dstack`
-
-Running `axolotl` with `dstack` is very straightforward.
-
-First, define the [`train.dstack.yaml`](train.dstack.yaml) task configuration file as follows:
-
-```yaml
-type: task
-
-image: winglian/axolotl-cloud:main-20240429-py3.11-cu121-2.2.1
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - WANDB_API_KEY
-
-commands:
- - accelerate launch -m axolotl.cli.train config.yaml
-
-ports:
- - 6006
-
-resources:
- gpu:
- memory: 24GB..
- count: 2
-```
-
-> [!NOTE]
-> Feel free to adjust `resources` to specify the required resources.
-
-We are using the official Docker image provided by Axolotl team (`winglian/axolotl-cloud:main-20240429-py3.11-cu121-2.2.1`). If you want to see other images, their official [repo](https://hub.docker.com/r/winglian/axolotl-cloud/tags). Note, `dstack` requires the CUDA driver to be 12.1+.
-
-To run the task, use the following command:
-
-```shell
-HUGGING_FACE_HUB_TOKEN=<...> \
-WANDB_API_KEY=<...> \
-dstack run . -f examples/fine-tuning/axolotl/train.dstack.yaml
-```
-
-To push the final fine-tuned model to Hugging Face Hub, set `hub_model_id` in [`config.yaml`](config.yaml).
-
-### Building `axolotl` from sources
-
-If you'd like to build `axolot` from sources (e.g. if you intend to modify its source code), follow its [installation guide](https://github.com/OpenAccess-AI-Collective/axolotl?tab=readme-ov-file#condapip-venv).
-
-Example:
-
-```yaml
-type: task
-
-python: 3.11
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - WANDB_API_KEY
-
-commands:
- - conda install cuda
- - pip3 install torch torchvision torchaudio
-
- - git clone https://github.com/OpenAccess-AI-Collective/axolotl.git
- - cd axolotl
-
- - pip3 install packaging
- - pip3 install -e '.[flash-attn,deepspeed]'
-
- - accelerate launch -m axolotl.cli.train ../config.yaml
-
-ports:
- - 6006
-
-resources:
- gpu:
- memory: 24GB..
- count: 2
-```
diff --git a/examples/fine-tuning/axolotl/config.yaml b/examples/fine-tuning/axolotl/config.yaml
deleted file mode 100644
index 5087bc4348..0000000000
--- a/examples/fine-tuning/axolotl/config.yaml
+++ /dev/null
@@ -1,82 +0,0 @@
-base_model: meta-llama/Meta-Llama-3-8B
-model_type: LlamaForCausalLM
-tokenizer_type: AutoTokenizer # PreTrainedTokenizerFast
-
-load_in_8bit: false
-load_in_4bit: true
-strict: false
-
-datasets:
- - path: tatsu-lab/alpaca
- type: alpaca
-dataset_prepared_path: last_run_prepared
-val_set_size: 0.05
-output_dir: ./out/qlora-llama3-8B
-
-adapter: qlora
-lora_model_dir:
-
-sequence_len: 512
-sample_packing: false
-pad_to_sequence_len: true
-
-lora_r: 8
-lora_alpha: 16
-lora_dropout: 0.05
-lora_target_modules:
-lora_target_linear: true
-lora_fan_in_fan_out:
-
-wandb_project: dstack+axolotl
-wandb_entity:
-wandb_watch:
-wandb_name: llama3-8b-fp16-fsdp+qlora
-wandb_log_model:
-
-gradient_accumulation_steps: 4
-micro_batch_size: 1
-num_epochs: 4
-optimizer: adamw_torch
-lr_scheduler: cosine
-learning_rate: 0.00001
-
-train_on_inputs: false
-group_by_length: false
-bf16: auto
-fp16:
-tf32: false
-
-gradient_checkpointing: true
-gradient_checkpointing_kwargs:
- use_reentrant: true
-early_stopping_patience:
-resume_from_checkpoint:
-local_rank:
-logging_steps: 1
-xformers_attention:
-flash_attention: true
-
-warmup_steps: 10
-evals_per_epoch: 4
-eval_table_size:
-saves_per_epoch: 1
-debug:
-deepspeed:
-weight_decay: 0.0
-fsdp:
- - full_shard
- - auto_wrap
-fsdp_config:
- fsdp_limit_all_gathers: true
- fsdp_sync_module_states: true
- fsdp_offload_params: true
- fsdp_use_orig_params: false
- fsdp_cpu_ram_efficient_loading: true
- fsdp_auto_wrap_policy: TRANSFORMER_BASED_WRAP
- fsdp_transformer_layer_cls_to_wrap: LlamaDecoderLayer
- fsdp_state_dict_type: FULL_STATE_DICT
- fsdp_sharding_strategy: FULL_SHARD
-special_tokens:
- pad_token: <|end_of_text|>
-
-hub_model_id: chansung/axolotl_llama3_8b_fsdp_qlora
\ No newline at end of file
diff --git a/examples/fine-tuning/axolotl/train.dstack.yaml b/examples/fine-tuning/axolotl/train.dstack.yaml
deleted file mode 100644
index 1239b496ce..0000000000
--- a/examples/fine-tuning/axolotl/train.dstack.yaml
+++ /dev/null
@@ -1,18 +0,0 @@
-type: task
-
-image: winglian/axolotl-cloud:main-20240429-py3.11-cu121-2.2.1
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - WANDB_API_KEY
-
-commands:
- - accelerate launch -m axolotl.cli.train config.yaml
-
-ports:
- - 6006
-
-resources:
- gpu:
- memory: 24GB..
- count: 2
\ No newline at end of file
diff --git a/examples/fine-tuning/pytorch-distributed/train.dstack.yml b/examples/fine-tuning/pytorch-distributed/train.dstack.yml
deleted file mode 100644
index 12f38aa5a4..0000000000
--- a/examples/fine-tuning/pytorch-distributed/train.dstack.yml
+++ /dev/null
@@ -1,24 +0,0 @@
-type: task
-
-nodes: 2
-
-commands:
- - git clone https://github.com/r4victor/pytorch-distributed-resnet.git
- - cd pytorch-distributed-resnet
- - mkdir -p data
- - cd data
- - wget -c --quiet https://www.cs.toronto.edu/~kriz/cifar-10-python.tar.gz
- - tar -xvzf cifar-10-python.tar.gz
- - cd ..
- - pip3 install -r requirements.txt torch
- - mkdir -p saved_models
- - torchrun --nproc_per_node=$DSTACK_GPUS_PER_NODE
- --node_rank=$DSTACK_NODE_RANK
- --nnodes=$DSTACK_NODES_NUM
- --master_addr=$DSTACK_MASTER_NODE_IP
- --master_port=8008 resnet_ddp.py
- --num_epochs 20
-
-resources:
- gpu: 1..2
- shm_size: 16GB
diff --git a/examples/fine-tuning/qlora/README.md b/examples/fine-tuning/qlora/README.md
deleted file mode 100644
index 133ec70bb4..0000000000
--- a/examples/fine-tuning/qlora/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# QLoRA
-
-The following command runs the task to fine-tune an LLM using QLoRA:
-
-```shell
-dstack run . -f examples/fine-tuning/qlora/task.dstack.yml
-```
-
-See the configuration at [train.dstack.yml](train.dstack.yml).
-
-For more details, refer to [tasks](https://dstack.ai/docs/concepts/tasks).
\ No newline at end of file
diff --git a/examples/fine-tuning/qlora/requirements.txt b/examples/fine-tuning/qlora/requirements.txt
deleted file mode 100644
index 3041543739..0000000000
--- a/examples/fine-tuning/qlora/requirements.txt
+++ /dev/null
@@ -1,10 +0,0 @@
-accelerate==0.21.0
-peft==0.4.0
-bitsandbytes==0.40.2
-transformers==4.31.0
-trl==0.4.7
-scipy
-tensorboard
-sentencepiece
-hf-transfer
-protobuf<5
\ No newline at end of file
diff --git a/examples/fine-tuning/qlora/train.dstack.yml b/examples/fine-tuning/qlora/train.dstack.yml
deleted file mode 100644
index 029c472de0..0000000000
--- a/examples/fine-tuning/qlora/train.dstack.yml
+++ /dev/null
@@ -1,18 +0,0 @@
-type: task
-# This task fine-tunes Llama 2 with QLoRA. Learn more at https://dstack.ai/examples/qlora/
-
-python: "3.11"
-
-env:
- - HUGGING_FACE_HUB_TOKEN
- - HF_HUB_ENABLE_HF_TRANSFER=1
-
-commands:
- - pip install -r examples/fine-tuning/qlora/requirements.txt
- - tensorboard --logdir results/runs &
- - python examples/fine-tuning/qlora/train.py --merge_and_push ${{ run.args }}
-ports:
- - 6006
-
-resources:
- gpu: 16GB..24GB
diff --git a/examples/llms/chat-ui/README.md b/examples/llms/chat-ui/README.md
deleted file mode 100644
index 5af67a27e8..0000000000
--- a/examples/llms/chat-ui/README.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Chat UI
-
-This example walks you through setting up [Chat UI](https://github.com/huggingface/chat-ui) locally
-to chat with an LLM deployed using `dstack`.
-
-### Clone the repo
-
-```shell
-git clone https://github.com/huggingface/chat-ui
-cd chat-ui
-```
-
-### Run local MongoDB
-
-```shell
-docker run -d -p 27017:27017 --name mongo-chatui mongo:latest
-```
-
-### Create `.env.local`
-
-```shell
-MONGODB_URL=mongodb://localhost:27017
-
-MODELS=`[
- {
- "name": "",
- "displayName": "My model",
- "endpoints": [
- {
- "type": "openai",
- "baseURL" : "https://gateway.",
- "apiKey": ""
- }
- ]
- }
-]`
-```
-
-Replace `` with your `dstack` gateway's domain (e.g. `.sky.dstack.ai` if you are using [dstack Sky](https://sky.dstack.ai)).
-
-Replace `` with your `dstack` user's token.
-
-Replace `` with the name of the deployed mode,
-
-### Run Chat UI
-
-```shell
-npm run dev
-```
-
-Now you can conveniently chat with your model! 🤗
-
-
\ No newline at end of file
diff --git a/examples/llms/chat-ui/images/dstack-chat-ui-llama3.png b/examples/llms/chat-ui/images/dstack-chat-ui-llama3.png
deleted file mode 100644
index d59249cd51..0000000000
Binary files a/examples/llms/chat-ui/images/dstack-chat-ui-llama3.png and /dev/null differ
diff --git a/examples/llms/code-llama/tgi-gptq.dstack.yml b/examples/llms/code-llama/tgi-gptq.dstack.yml
deleted file mode 100644
index 95e9cef4bd..0000000000
--- a/examples/llms/code-llama/tgi-gptq.dstack.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-type: service
-# This service deploys Code Llama 70B (GPTQ) with TGI
-
-image: ghcr.io/huggingface/text-generation-inference:latest
-env:
- - MODEL_ID=TheBloke/CodeLlama-70B-Instruct-GPTQ
-commands:
- - text-generation-server download-weights $MODEL_ID --trust-remote-code
- - text-generation-launcher
- --port 80
- --trust-remote-code
- --quantize gptq
-port: 80
-
-resources:
- gpu: 80GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- type: chat
- name: TheBloke/CodeLlama-70B-Instruct-GPTQ
- format: tgi
- eos_token: ""
diff --git a/examples/llms/deepseek/trl/amd/.dstack.yml b/examples/llms/deepseek/trl/amd/.dstack.yml
new file mode 100644
index 0000000000..fe3dbc31ae
--- /dev/null
+++ b/examples/llms/deepseek/trl/amd/.dstack.yml
@@ -0,0 +1,41 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: trl-train
+
+image: rocm/pytorch:rocm6.2.3_ubuntu22.04_py3.10_pytorch_release_2.3.0
+
+# Required environment variables
+env:
+ - WANDB_API_KEY
+ - WANDB_PROJECT
+ - MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
+
+# Commands of the task
+commands:
+ - git clone https://github.com/huggingface/trl.git
+ - pip install trl
+ - pip install "numpy<2"
+ - pip install peft
+ - pip install wandb
+ - cd trl/trl/scripts
+ - python sft.py
+ --model_name_or_path $MODEL_ID
+ --dataset_name trl-lib/Capybara
+ --learning_rate 2.0e-4
+ --num_train_epochs 1
+ --packing
+ --per_device_train_batch_size 2
+ --gradient_accumulation_steps 8
+ --gradient_checkpointing
+ --logging_steps 25
+ --eval_strategy steps
+ --eval_steps 100
+ --use_peft
+ --lora_r 32
+ --lora_alpha 16
+ --report_to wandb
+ --output_dir DeepSeek-R1-Distill-Qwen-1.5B-SFT
+
+resources:
+ gpu: MI300X
+ disk: 150GB
diff --git a/examples/llms/deepseek/trl/amd/deepseek_v2.dstack.yml b/examples/llms/deepseek/trl/amd/deepseek_v2.dstack.yml
new file mode 100644
index 0000000000..4c719dcd5e
--- /dev/null
+++ b/examples/llms/deepseek/trl/amd/deepseek_v2.dstack.yml
@@ -0,0 +1,59 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: trl-train
+
+image: rocm/pytorch:rocm6.2.3_ubuntu22.04_py3.10_pytorch_release_2.3.0
+
+# Required environment variables
+env:
+ - WANDB_API_KEY
+ - WANDB_PROJECT
+ - MODEL_ID=deepseek-ai/DeepSeek-V2-Lite
+ - ACCELERATE_USE_FSDP=False
+# Commands of the task
+commands:
+ - git clone https://github.com/huggingface/peft.git
+ - pip install trl
+ - pip install "numpy<2"
+ - pip install peft
+ - pip install wandb
+ - cd peft/examples/sft
+ - python train.py
+ --seed 100
+ --model_name_or_path "deepseek-ai/DeepSeek-V2-Lite"
+ --dataset_name "smangrul/ultrachat-10k-chatml"
+ --chat_template_format "chatml"
+ --add_special_tokens False
+ --append_concat_token False
+ --splits "train,test"
+ --max_seq_len 512
+ --num_train_epochs 1
+ --logging_steps 5
+ --log_level "info"
+ --logging_strategy "steps"
+ --eval_strategy "epoch"
+ --save_strategy "epoch"
+ --hub_private_repo True
+ --hub_strategy "every_save"
+ --packing True
+ --learning_rate 1e-4
+ --lr_scheduler_type "cosine"
+ --weight_decay 1e-4
+ --warmup_ratio 0.0
+ --max_grad_norm 1.0
+ --output_dir "deepseek-sft-lora"
+ --per_device_train_batch_size 8
+ --per_device_eval_batch_size 8
+ --gradient_accumulation_steps 4
+ --gradient_checkpointing True
+ --use_reentrant True
+ --dataset_text_field "content"
+ --use_peft_lora True
+ --lora_r 16
+ --lora_alpha 16
+ --lora_dropout 0.05
+ --lora_target_modules "all-linear"
+
+resources:
+ gpu: MI300X
+ disk: 150GB
diff --git a/examples/llms/deepseek/trl/amd/grpo.dstack.yml b/examples/llms/deepseek/trl/amd/grpo.dstack.yml
new file mode 100644
index 0000000000..c1a76e528b
--- /dev/null
+++ b/examples/llms/deepseek/trl/amd/grpo.dstack.yml
@@ -0,0 +1,32 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: trl-train-grpo
+
+image: rocm/pytorch:rocm6.2.3_ubuntu22.04_py3.10_pytorch_release_2.3.0
+
+# Required environment variables
+env:
+ - WANDB_API_KEY
+ - WANDB_PROJECT
+ - MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
+# Mount files
+files:
+ - grpo_train.py
+# Commands of the task
+commands:
+ - pip install trl
+ - pip install datasets
+ # numpy version less than 2 is required for the scipy installation with AMD.
+ - pip install "numpy<2"
+ - python grpo_train.py
+ --model_name_or_path $MODEL_ID
+ --dataset_name trl-lib/tldr
+ --per_device_train_batch_size 2
+ --logging_steps 25
+ --output_dir Deepseek-Distill-Qwen-1.5B-GRPO
+ --trust_remote_code
+
+# GRPO fine-tuning of DeepSeek-R1-Distill-Qwen-1.5B consumes 70% of VRAM
+resources:
+ gpu: MI300X
+ disk: 150GB
diff --git a/examples/llms/deepseek/trl/amd/grpo_train.py b/examples/llms/deepseek/trl/amd/grpo_train.py
new file mode 100644
index 0000000000..ab59291de6
--- /dev/null
+++ b/examples/llms/deepseek/trl/amd/grpo_train.py
@@ -0,0 +1,60 @@
+import argparse
+
+from datasets import load_dataset
+from transformers import AutoModelForCausalLM
+from trl import GRPOConfig, GRPOTrainer
+
+
+def parse_args():
+ parser = argparse.ArgumentParser(description="Train a model using GRPOTrainer.")
+ parser.add_argument(
+ "--model_name_or_path",
+ type=str,
+ required=True,
+ help="Path to the model or model identifier from huggingface.co/models",
+ )
+ parser.add_argument(
+ "--dataset_name", type=str, required=True, help="Name of the dataset to use"
+ )
+ parser.add_argument(
+ "--per_device_train_batch_size",
+ type=int,
+ default=1,
+ help="Batch size per device for training",
+ )
+ parser.add_argument("--logging_steps", type=int, default=10, help="Logging steps interval")
+ parser.add_argument(
+ "--output_dir", type=str, default="output", help="Output directory for the trained model"
+ )
+ parser.add_argument(
+ "--trust_remote_code", action="store_true", help="Trust remote code when loading the model"
+ )
+ return parser.parse_args()
+
+
+def reward_len(completions, **kwargs):
+ return [abs(20 - len(completion)) for completion in completions]
+
+
+def main():
+ args = parse_args()
+
+ dataset = load_dataset(args.dataset_name, split="train")
+ training_args = GRPOConfig(
+ output_dir=args.output_dir,
+ logging_steps=args.logging_steps,
+ per_device_train_batch_size=args.per_device_train_batch_size,
+ )
+
+ model = AutoModelForCausalLM.from_pretrained(
+ args.model_name_or_path, trust_remote_code=args.trust_remote_code
+ )
+ trainer = GRPOTrainer(
+ model=model, reward_funcs=reward_len, args=training_args, train_dataset=dataset
+ )
+
+ trainer.train()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/examples/llms/deepseek/trl/nvidia/.dstack.yml b/examples/llms/deepseek/trl/nvidia/.dstack.yml
new file mode 100644
index 0000000000..23564c3c86
--- /dev/null
+++ b/examples/llms/deepseek/trl/nvidia/.dstack.yml
@@ -0,0 +1,38 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: trl-train
+
+python: 3.12
+
+# Required environment variables
+env:
+ - WANDB_API_KEY
+ - WANDB_PROJECT
+ - MODEL_ID=deepseek-ai/DeepSeek-R1-Distill-Qwen-1.5B
+# Commands of the task
+commands:
+ - git clone https://github.com/huggingface/trl.git
+ - pip install trl
+ - pip install peft
+ - pip install wandb
+ - cd trl/trl/scripts
+ - python sft.py
+ --model_name_or_path $MODEL_ID
+ --dataset_name trl-lib/Capybara
+ --learning_rate 2.0e-4
+ --num_train_epochs 1
+ --packing
+ --per_device_train_batch_size 2
+ --gradient_accumulation_steps 8
+ --gradient_checkpointing
+ --logging_steps 25
+ --eval_strategy steps
+ --eval_steps 100
+ --use_peft
+ --lora_r 32
+ --lora_alpha 16
+ --report_to wandb
+ --output_dir DeepSeek-R1-Distill-Qwen-1.5B-SFT
+
+resources:
+ gpu: 24GB
diff --git a/examples/llms/deepseek/trl/nvidia/deepseek_v2.dstack.yml b/examples/llms/deepseek/trl/nvidia/deepseek_v2.dstack.yml
new file mode 100644
index 0000000000..4ad972e813
--- /dev/null
+++ b/examples/llms/deepseek/trl/nvidia/deepseek_v2.dstack.yml
@@ -0,0 +1,64 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: trl-train-deepseek-v2
+
+python: "3.10"
+
+nvcc: true
+# Required environment variables
+env:
+ - WANDB_API_KEY
+ - WANDB_PROJECT
+ - MODEL_ID=deepseek-ai/DeepSeek-V2-Lite
+ - ACCELERATE_USE_FSDP=False
+# Commands of the task
+commands:
+ - git clone https://github.com/huggingface/peft.git
+ - pip install trl
+ - pip install peft
+ - pip install wandb
+ - pip install bitsandbytes
+ - cd peft/examples/sft
+ - python train.py
+ --seed 100
+ --model_name_or_path "deepseek-ai/DeepSeek-V2-Lite"
+ --dataset_name "smangrul/ultrachat-10k-chatml"
+ --chat_template_format "chatml"
+ --add_special_tokens False
+ --append_concat_token False
+ --splits "train,test"
+ --max_seq_len 512
+ --num_train_epochs 1
+ --logging_steps 5
+ --log_level "info"
+ --logging_strategy "steps"
+ --eval_strategy "epoch"
+ --save_strategy "epoch"
+ --hub_private_repo True
+ --hub_strategy "every_save"
+ --bf16 True
+ --packing True
+ --learning_rate 1e-4
+ --lr_scheduler_type "cosine"
+ --weight_decay 1e-4
+ --warmup_ratio 0.0
+ --max_grad_norm 1.0
+ --output_dir "deepseek-sft-lora"
+ --per_device_train_batch_size 8
+ --per_device_eval_batch_size 8
+ --gradient_accumulation_steps 4
+ --gradient_checkpointing True
+ --use_reentrant True
+ --dataset_text_field "content"
+ --use_peft_lora True
+ --lora_r 16
+ --lora_alpha 16
+ --lora_dropout 0.05
+ --lora_target_modules "all-linear"
+ --use_4bit_quantization True
+ --use_nested_quant True
+ --bnb_4bit_compute_dtype "bfloat16"
+
+resources:
+ # Consumes ~25GB of VRAM for QLoRA fine-tuning deepseek-ai/DeepSeek-V2-Lite
+ gpu: 48GB
diff --git a/examples/llms/llama3/README.md b/examples/llms/llama3/README.md
deleted file mode 100644
index 7dca55df01..0000000000
--- a/examples/llms/llama3/README.md
+++ /dev/null
@@ -1,29 +0,0 @@
-# Llama 3
-
-## Deploy Llama 8B
-
-The following command deploys Llama 3 8B as a service:
-
-```shell
-dstack run . -f examples/llms/llama3/ollama-8b.dstack.yml
-```
-
-See the configuration at [ollama-8b.dstack.yml](ollama-8b.dstack.yml).
-
-## Deploy Llama 70B
-
-The following command deploys Llama 3 70B as a service:
-
-```shell
-dstack run . -f examples/llms/llama3/ollama-70b.dstack.yml
-```
-
-See the configuration at [ollama-70b.dstack.yml](ollama-70b.dstack.yml).
-
-For more details, refer to [services](https://dstack.ai/docs/concepts/services).
-
-## Run Chat UI
-
-Refer to [chat-ui](../chat-ui/README.md) to learn how to launch a UI for chatting with the LLM you've deployed to `dstack`.
-
-
\ No newline at end of file
diff --git a/examples/llms/llama3/ollama-70b.dstack.yml b/examples/llms/llama3/ollama-70b.dstack.yml
deleted file mode 100644
index b65e52f736..0000000000
--- a/examples/llms/llama3/ollama-70b.dstack.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-type: service
-# Deploys Llama 3 70B with Ollama
-
-image: ollama/ollama
-commands:
- - ollama serve &
- - sleep 3
- - ollama pull llama3:70b
- - fg
-port: 11434
-
-resources:
- gpu: 80GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- type: chat
- name: llama3:70b
- format: openai
diff --git a/examples/llms/llama3/ollama-8b.dstack.yml b/examples/llms/llama3/ollama-8b.dstack.yml
deleted file mode 100644
index f5841e6235..0000000000
--- a/examples/llms/llama3/ollama-8b.dstack.yml
+++ /dev/null
@@ -1,19 +0,0 @@
-type: service
-# Deploys Llama 3 8B with Ollama
-
-image: ollama/ollama
-commands:
- - ollama serve &
- - sleep 3
- - ollama pull llama3
- - fg
-port: 11434
-
-resources:
- gpu: 16GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- type: chat
- name: llama3
- format: openai
diff --git a/examples/llms/mixtral/README.md b/examples/llms/mixtral/README.md
deleted file mode 100644
index 0451dd9a5e..0000000000
--- a/examples/llms/mixtral/README.md
+++ /dev/null
@@ -1,11 +0,0 @@
-# Mixtral 8x7B
-
-The following command deploys Mixtral 8x7B as a service:
-
-```shell
-dstack run . -f examples/llms/mixtral/serve.dstack.yml
-```
-
-See the configuration at [serve.dstack.yml](serve.dstack.yml).
-
-For more details, refer to [services](https://dstack.ai/docs/concepts/services).
\ No newline at end of file
diff --git a/examples/llms/mixtral/tgi-gptq.dstack.yml b/examples/llms/mixtral/tgi-gptq.dstack.yml
deleted file mode 100644
index 6f3945c10a..0000000000
--- a/examples/llms/mixtral/tgi-gptq.dstack.yml
+++ /dev/null
@@ -1,21 +0,0 @@
-type: service
-# This service deploys Mixtral (GPTQ) with TGI
-
-image: ghcr.io/huggingface/text-generation-inference:latest
-env:
- - MODEL_ID=TheBloke/Mixtral-8x7B-Instruct-v0.1-GPTQ
-commands:
- - text-generation-launcher
- --port 80
- --trust-remote-code
- --quantize gptq
-port: 80
-
-resources:
- gpu: 25GB..50GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- type: chat
- name: TheBloke/Mixtral-8x7B-Instruct-v0.1-GPTQ
- format: tgi
diff --git a/examples/llms/mixtral/tgi.dstack.yml b/examples/llms/mixtral/tgi.dstack.yml
deleted file mode 100644
index 31868de97f..0000000000
--- a/examples/llms/mixtral/tgi.dstack.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-type: service
-# This service deploys Mixtral with TGI
-
-image: ghcr.io/huggingface/text-generation-inference:latest
-env:
- - HUGGING_FACE_HUB_TOKEN
- - MODEL_ID=mistralai/Mixtral-8x7B-Instruct-v0.1
-commands:
- - text-generation-launcher
- --port 80
- --trust-remote-code
- --num-shard $DSTACK_GPUS_NUM
-port: 80
-
-resources:
- gpu: 80GB:2
- disk: 200GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- type: chat
- name: TheBloke/Mixtral-8x7B-Instruct-v0.1-GPTQ
- format: tgi
diff --git a/examples/llms/mixtral/vllm.dstack.yml b/examples/llms/mixtral/vllm.dstack.yml
deleted file mode 100644
index 59d0376a3f..0000000000
--- a/examples/llms/mixtral/vllm.dstack.yml
+++ /dev/null
@@ -1,23 +0,0 @@
-type: service
-# This service deploys Mixtral with vLLM
-
-python: "3.11"
-env:
- - HUGGING_FACE_HUB_TOKEN
-commands:
- - pip install vllm
- - python -m vllm.entrypoints.openai.api_server
- --model mistralai/Mixtral-8x7B-Instruct-v0.1
- --host 0.0.0.0
- --tensor-parallel-size $DSTACK_GPUS_NUM
-port: 8000
-
-resources:
- gpu: 80GB:2
- disk: 200GB
-
-# (Optional) Enable the OpenAI-compatible endpoint
-model:
- type: chat
- name: TheBloke/Mixtral-8x7B-Instruct-v0.1-GPTQ
- format: openai
\ No newline at end of file
diff --git a/examples/misc/airflow/README.md b/examples/misc/airflow/README.md
new file mode 100644
index 0000000000..fa1a15f762
--- /dev/null
+++ b/examples/misc/airflow/README.md
@@ -0,0 +1,81 @@
+# Airflow
+
+This example shows how to run the `dstack` CLI and API from Airflow pipelines.
+It uses Airflow 2 and the [TaskFlow API](https://airflow.apache.org/docs/apache-airflow/stable/tutorial/taskflow.html).
+
+## Preparing a virtual environment
+
+`dstack` and Airflow may have conflicting dependencies, so it's recommended to install
+`dstack` to a separate virtual environment available to Airflow.
+
+Ensure the virtual environment created for `dstack` is
+available to all the workers in case your Airflow runs in a distributed environment.
+
+## Running dstack CLI
+
+To run the `dstack` CLI from Airflow,
+we can run it as regular bash commands using [BashOperator](https://airflow.apache.org/docs/apache-airflow/stable/howto/operator/bash.html).
+The only special step here is that we need to activate a virtual environment before running `dstack`:
+
+```python
+
+DSTACK_VENV_PATH = "/path/to/dstack-venv"
+
+@dag(...)
+def pipeline(...):
+ ...
+ @task.bash
+ def dstack_cli_apply_venv() -> str:
+ return (
+ f"source {DSTACK_VENV_PATH}/bin/activate"
+ f" && cd {DSTACK_REPO_PATH}"
+ " && dstack apply -y -f task.dstack.yml --repo ."
+ )
+```
+
+## Running dstack API
+
+To run the `dstack` API from Airflow, we can use [ExternalPythonOperator](https://airflow.apache.org/docs/apache-airflow/stable/howto/operator/python.html#externalpythonoperator). Specify a path to the Python binary inside the dstack virtual environment, and
+Airflow will run the code inside that virtual environment:
+
+```python
+
+DSTACK_VENV_PYTHON_BINARY_PATH = f"{DSTACK_VENV_PATH}/bin/python"
+
+@dag(...)
+def pipeline(...):
+ ...
+ @task.external_python(task_id="external_python", python=DSTACK_VENV_PYTHON_BINARY_PATH)
+ def dstack_api_submit_venv():
+ from dstack.api import Client, Task
+
+ task = Task(
+ name="my-airflow-task",
+ commands=[
+ "echo 'Running dstack task via Airflow'",
+ "sleep 10",
+ "echo 'Finished'",
+ ]
+ )
+ # Pick up config from `~/.dstack/config.yml`
+ # or set explicitly from Ariflow Variables.
+ client = Client.from_config()
+
+ run = client.runs.apply_configuration(
+ configuration=task,
+ )
+ run.attach()
+ try:
+ for log in run.logs():
+ sys.stdout.buffer.write(log)
+ sys.stdout.buffer.flush()
+ except KeyboardInterrupt:
+ run.stop(abort=True)
+ finally:
+ run.detach()
+```
+
+## Source code
+
+The source code for this example can be found in
+[`examples/misc/airflow`](https://github.com/dstackai/dstack/blob/master/examples/misc/airflow).
diff --git a/examples/misc/airflow/dags/dstack-repo/task.dstack.yml b/examples/misc/airflow/dags/dstack-repo/task.dstack.yml
new file mode 100644
index 0000000000..53812c25e1
--- /dev/null
+++ b/examples/misc/airflow/dags/dstack-repo/task.dstack.yml
@@ -0,0 +1,5 @@
+type: task
+commands:
+ - echo "Running dstack task via Airflow"
+ - sleep 10
+ - echo "Finished"
diff --git a/examples/misc/airflow/dags/dstack_tasks.py b/examples/misc/airflow/dags/dstack_tasks.py
new file mode 100644
index 0000000000..8002e123b5
--- /dev/null
+++ b/examples/misc/airflow/dags/dstack_tasks.py
@@ -0,0 +1,96 @@
+import os
+import sys
+from datetime import datetime, timedelta
+
+from airflow.configuration import conf
+from airflow.decorators import dag, task
+
+# dstack repo files are stored in the dags folder as an example.
+# Put dstack repo files in another place if appropriate.
+DAGS_DIR_PATH = os.path.join(conf.get("core", "DAGS_FOLDER"))
+DSTACK_REPO_PATH = f"{DAGS_DIR_PATH}/dstack-repo"
+
+# A separate virtual environment should be created for dstack if dstack cannot be
+# installed into the main Airflow environment. For example, due to incompatible dependencies.
+DSTACK_VENV_PATH = "/path/to/dstack-venv" # Change this !
+DSTACK_VENV_PYTHON_BINARY_PATH = f"{DSTACK_VENV_PATH}/bin/python"
+
+
+default_args = {
+ "owner": "airflow",
+ "retries": 1,
+ "retry_delay": timedelta(minutes=5),
+ "start_date": datetime(2024, 11, 13),
+}
+
+
+@dag(
+ default_args=default_args,
+ schedule_interval=timedelta(days=1),
+ catchup=False,
+ description="Examples of running dstack via Airflow",
+)
+def dstack_tasks():
+ @task.bash
+ def dstack_cli_apply() -> str:
+ """
+ This task shows how to run the dstack CLI when
+ dstack is installed into the main Airflow environment.
+ NOT RECOMMENDED since dstack and Airflow may have conflicting dependencies.
+ """
+ return f"cd {DSTACK_REPO_PATH} && dstack apply -y -f task.dstack.yml --repo ."
+
+ @task.bash
+ def dstack_cli_apply_venv() -> str:
+ """
+ This task shows how to run the dstack CLI when
+ dstack is installed into a separate virtual environment available to Airflow.
+ """
+ return (
+ f". {DSTACK_VENV_PATH}/bin/activate"
+ f" && cd {DSTACK_REPO_PATH}"
+ " && dstack apply -y -f task.dstack.yml --repo ."
+ )
+
+ @task.external_python(task_id="external_python", python=DSTACK_VENV_PYTHON_BINARY_PATH)
+ def dstack_api_submit_venv():
+ """
+ This task shows how to run the dstack API when
+ dstack is installed into a separate virtual environment available to Airflow.
+ Note that the venv must have the `pendulum` package installed.
+ """
+ from dstack.api import Client, Task
+
+ task = Task(
+ name="my-airflow-task",
+ commands=[
+ "echo 'Running dstack task via Airflow'",
+ "sleep 10",
+ "echo 'Finished'",
+ ],
+ )
+ # Pick up config from `~/.dstack/config.yml`
+ # or set explicitly from Ariflow Variables.
+ client = Client.from_config()
+
+ run = client.runs.apply_configuration(
+ configuration=task,
+ )
+ run.attach()
+ try:
+ for log in run.logs():
+ sys.stdout.buffer.write(log)
+ sys.stdout.buffer.flush()
+ except KeyboardInterrupt:
+ run.stop(abort=True)
+ finally:
+ run.detach()
+
+ # Uncomment a task you want to run
+
+ # dstack_cli_apply()
+ # dstack_cli_apply_venv()
+ dstack_api_submit_venv()
+
+
+dstack_tasks()
diff --git a/examples/misc/http.server/serve.dstack.yml b/examples/misc/http.server/.dstack.yml
similarity index 100%
rename from examples/misc/http.server/serve.dstack.yml
rename to examples/misc/http.server/.dstack.yml
diff --git a/examples/misc/http.server/README.md b/examples/misc/http.server/README.md
index a521a0d074..c98b57f4be 100644
--- a/examples/misc/http.server/README.md
+++ b/examples/misc/http.server/README.md
@@ -5,19 +5,19 @@
The following command runs `http.server` as a service:
```shell
-dstack run . -f examples/misc/http.server/serve.dstack.yml
+dstack apply -f examples/misc/http.server/.dstack.yml
```
-See the configuration at [serve.dstack.yml](serve.dstack.yml).
+See the configuration at [.dstack.yml](.dstack.yml).
## Task
The following command runs `http.server` as a task:
```shell
-dstack run . -f examples/misc/http.server/serve-task.dstack.yml
+dstack apply -f examples/misc/http.server/task.dstack.yml
```
-See the configuration at [serve.dstack.yml](serve-task.dstack.yml).
+See the configuration at [task.dstack.yml](task.dstack.yml).
-For more details, refer to [services](https://dstack.ai/docs/concepts/services) or [tasks](https://dstack.ai/docs/concepts/tasks).
\ No newline at end of file
+For more details, refer to [services](https://dstack.ai/docs/services) or [tasks](https://dstack.ai/docs/tasks).
diff --git a/examples/misc/http.server/serve-task.dstack.yml b/examples/misc/http.server/task.dstack.yml
similarity index 100%
rename from examples/misc/http.server/serve-task.dstack.yml
rename to examples/misc/http.server/task.dstack.yml
diff --git a/examples/misc/ray/README.md b/examples/misc/ray/README.md
new file mode 100644
index 0000000000..e25b87c206
--- /dev/null
+++ b/examples/misc/ray/README.md
@@ -0,0 +1,71 @@
+# Ray
+
+This example shows how use `dstack` to spin up a [Ray](https://docs.ray.io/en/latest/ray-overview/index.html) cluster and run Ray jobs on it.
+
+## Create a fleet
+
+First create a fleet for the Ray cluster. We'll use one instance for a master node and three instances for worker nodes:
+
+```yaml
+type: fleet
+name: ray-fleet
+nodes: 4
+placement: cluster
+backends: [gcp]
+resources:
+ cpu: 8..
+ memory: 32GB..
+ gpu: 1
+```
+
+```shell
+dstack apply -f fleet.dstack.yaml
+```
+
+## Launch Ray cluster
+
+The following `dstack` task launches Ray master and worker nodes.
+`dstack` makes the Ray dashboard available at `localhost:8265`.
+
+```yaml
+type: task
+name: ray-cluster
+nodes: 4
+commands:
+ - pip install -U "ray[default]"
+ - |
+ if [ $DSTACK_NODE_RANK = 0 ]; then
+ ray start --head --port=6379;
+ else
+ ray start --address=$DSTACK_MASTER_NODE_IP:6379
+ fi
+ports:
+ - 8265 # ray dashboard port
+resources:
+ shm_size: 8GB
+```
+
+```shell
+dstack apply -f cluster.dstack.yaml
+```
+
+## Run Ray jobs
+
+Install Ray locally:
+
+```shell
+pip install ray
+```
+
+Now you can submit Ray jobs to the cluster available at `localhost:8265`:
+
+```shell
+RAY_ADDRESS='http://localhost:8265' ray job submit \
+--working-dir . \
+--runtime-env-json='{"pip": ["ray[train]", "torch", "torchvision", "tqdm", "filelock"]}' \
+-- python tasks/pytorch-mnist.py
+```
+
+See more examples in the [Ray docs](https://docs.ray.io/en/latest/train/examples.html).
+
+Using Ray via `dstack` is a powerful way to get access to the rich Ray ecosystem while benefiting from `dstack`'s provisioning capabilities.
diff --git a/examples/misc/ray/cluster.dstack.yaml b/examples/misc/ray/cluster.dstack.yaml
new file mode 100644
index 0000000000..c30ff6bc25
--- /dev/null
+++ b/examples/misc/ray/cluster.dstack.yaml
@@ -0,0 +1,15 @@
+type: task
+name: ray-cluster
+nodes: 4
+commands:
+ - pip install -U "ray[default]"
+ - >
+ if [ $DSTACK_NODE_RANK = 0 ]; then
+ ray start --head --port=6379;
+ else
+ ray start --address=$DSTACK_MASTER_NODE_IP:6379
+ fi
+ports:
+ - 8265 # ray dashboard port
+resources:
+ shm_size: 8GB
diff --git a/examples/misc/ray/fleet.dstack.yaml b/examples/misc/ray/fleet.dstack.yaml
new file mode 100644
index 0000000000..66712afb1d
--- /dev/null
+++ b/examples/misc/ray/fleet.dstack.yaml
@@ -0,0 +1,9 @@
+type: fleet
+name: ray-fleet
+nodes: 4
+placement: cluster
+backends: [gcp]
+resources:
+ cpu: 8..
+ memory: 32GB..
+ gpu: 1
diff --git a/examples/misc/ray/tasks/pytorch-mnist.py b/examples/misc/ray/tasks/pytorch-mnist.py
new file mode 100644
index 0000000000..b1049d885d
--- /dev/null
+++ b/examples/misc/ray/tasks/pytorch-mnist.py
@@ -0,0 +1,168 @@
+# This example runs distributed training of a PyTorch model on Fashion MNIST with Ray Train.
+# Source: https://docs.ray.io/en/latest/train/examples/pytorch/torch_fashion_mnist_example.html
+
+# Copyright 2023 Ray Authors
+
+# 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.
+
+import os
+from typing import Dict
+
+import ray.train
+import torch
+from filelock import FileLock
+from ray.train import ScalingConfig
+from ray.train.torch import TorchTrainer
+from torch import nn
+from torch.utils.data import DataLoader
+from torchvision import datasets, transforms
+from torchvision.transforms import Normalize, ToTensor
+from tqdm import tqdm
+
+
+def get_dataloaders(batch_size):
+ # Transform to normalize the input images
+ transform = transforms.Compose([ToTensor(), Normalize((0.5,), (0.5,))])
+
+ with FileLock(os.path.expanduser("~/data.lock")):
+ # Download training data from open datasets
+ training_data = datasets.FashionMNIST(
+ root="~/data",
+ train=True,
+ download=True,
+ transform=transform,
+ )
+
+ # Download test data from open datasets
+ test_data = datasets.FashionMNIST(
+ root="~/data",
+ train=False,
+ download=True,
+ transform=transform,
+ )
+
+ # Create data loaders
+ train_dataloader = DataLoader(training_data, batch_size=batch_size, shuffle=True)
+ test_dataloader = DataLoader(test_data, batch_size=batch_size)
+
+ return train_dataloader, test_dataloader
+
+
+# Model Definition
+class NeuralNetwork(nn.Module):
+ def __init__(self):
+ super(NeuralNetwork, self).__init__()
+ self.flatten = nn.Flatten()
+ self.linear_relu_stack = nn.Sequential(
+ nn.Linear(28 * 28, 512),
+ nn.ReLU(),
+ nn.Dropout(0.25),
+ nn.Linear(512, 512),
+ nn.ReLU(),
+ nn.Dropout(0.25),
+ nn.Linear(512, 10),
+ nn.ReLU(),
+ )
+
+ def forward(self, x):
+ x = self.flatten(x)
+ logits = self.linear_relu_stack(x)
+ return logits
+
+
+def train_func_per_worker(config: Dict):
+ lr = config["lr"]
+ epochs = config["epochs"]
+ batch_size = config["batch_size_per_worker"]
+
+ # Get dataloaders inside the worker training function
+ train_dataloader, test_dataloader = get_dataloaders(batch_size=batch_size)
+
+ # [1] Prepare Dataloader for distributed training
+ # Shard the datasets among workers and move batches to the correct device
+ # =======================================================================
+ train_dataloader = ray.train.torch.prepare_data_loader(train_dataloader)
+ test_dataloader = ray.train.torch.prepare_data_loader(test_dataloader)
+
+ model = NeuralNetwork()
+
+ # [2] Prepare and wrap your model with DistributedDataParallel
+ # Move the model to the correct GPU/CPU device
+ # ============================================================
+ model = ray.train.torch.prepare_model(model)
+
+ loss_fn = nn.CrossEntropyLoss()
+ optimizer = torch.optim.SGD(model.parameters(), lr=lr, momentum=0.9)
+
+ # Model training loop
+ for epoch in range(epochs):
+ if ray.train.get_context().get_world_size() > 1:
+ # Required for the distributed sampler to shuffle properly across epochs.
+ train_dataloader.sampler.set_epoch(epoch)
+
+ model.train()
+ for X, y in tqdm(train_dataloader, desc=f"Train Epoch {epoch}"):
+ pred = model(X)
+ loss = loss_fn(pred, y)
+
+ optimizer.zero_grad()
+ loss.backward()
+ optimizer.step()
+
+ model.eval()
+ test_loss, num_correct, num_total = 0, 0, 0
+ with torch.no_grad():
+ for X, y in tqdm(test_dataloader, desc=f"Test Epoch {epoch}"):
+ pred = model(X)
+ loss = loss_fn(pred, y)
+
+ test_loss += loss.item()
+ num_total += y.shape[0]
+ num_correct += (pred.argmax(1) == y).sum().item()
+
+ test_loss /= len(test_dataloader)
+ accuracy = num_correct / num_total
+
+ # [3] Report metrics to Ray Train
+ # ===============================
+ ray.train.report(metrics={"loss": test_loss, "accuracy": accuracy})
+
+
+def train_fashion_mnist(num_workers=2, use_gpu=False):
+ global_batch_size = 32
+
+ train_config = {
+ "lr": 1e-3,
+ "epochs": 10,
+ "batch_size_per_worker": global_batch_size // num_workers,
+ }
+
+ # Configure computation resources
+ scaling_config = ScalingConfig(num_workers=num_workers, use_gpu=use_gpu)
+
+ # Initialize a Ray TorchTrainer
+ trainer = TorchTrainer(
+ train_loop_per_worker=train_func_per_worker,
+ train_loop_config=train_config,
+ scaling_config=scaling_config,
+ )
+
+ # [4] Start distributed training
+ # Run `train_func_per_worker` on all workers
+ # =============================================
+ result = trainer.fit()
+ print(f"Training result: {result}")
+
+
+if __name__ == "__main__":
+ train_fashion_mnist(num_workers=3, use_gpu=True)
diff --git a/examples/misc/ray/tasks/quicksort.py b/examples/misc/ray/tasks/quicksort.py
new file mode 100644
index 0000000000..2975499f7d
--- /dev/null
+++ b/examples/misc/ray/tasks/quicksort.py
@@ -0,0 +1,72 @@
+# This example sorts the list in a distributed and parallel fashion.
+# Source: https://docs.ray.io/en/latest/ray-core/patterns/nested-tasks.html#code-example
+
+# Copyright 2023 Ray Authors
+
+# 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.
+
+import time
+
+import ray
+from numpy import random
+
+
+def partition(collection):
+ # Use the last element as the pivot
+ pivot = collection.pop()
+ greater, lesser = [], []
+ for element in collection:
+ if element > pivot:
+ greater.append(element)
+ else:
+ lesser.append(element)
+ return lesser, pivot, greater
+
+
+def quick_sort(collection):
+ if len(collection) <= 200000: # magic number
+ return sorted(collection)
+ else:
+ lesser, pivot, greater = partition(collection)
+ lesser = quick_sort(lesser)
+ greater = quick_sort(greater)
+ return lesser + [pivot] + greater
+
+
+@ray.remote
+def quick_sort_distributed(collection):
+ # Tiny tasks are an antipattern.
+ # Thus, in our example we have a "magic number" to
+ # toggle when distributed recursion should be used vs
+ # when the sorting should be done in place. The rule
+ # of thumb is that the duration of an individual task
+ # should be at least 1 second.
+ if len(collection) <= 200000: # magic number
+ return sorted(collection)
+ else:
+ lesser, pivot, greater = partition(collection)
+ lesser = quick_sort_distributed.remote(lesser)
+ greater = quick_sort_distributed.remote(greater)
+ return ray.get(lesser) + [pivot] + ray.get(greater)
+
+
+for size in [200000, 4000000, 8000000]:
+ print(f"Array size: {size}")
+ unsorted = random.randint(1000000, size=(size)).tolist()
+ s = time.time()
+ quick_sort(unsorted)
+ print(f"Sequential execution: {(time.time() - s):.3f}")
+ s = time.time()
+ ray.get(quick_sort_distributed.remote(unsorted))
+ print(f"Distributed execution: {(time.time() - s):.3f}")
+ print("--" * 10)
diff --git a/examples/misc/spark/README.md b/examples/misc/spark/README.md
new file mode 100644
index 0000000000..f9a37252e8
--- /dev/null
+++ b/examples/misc/spark/README.md
@@ -0,0 +1,62 @@
+# Spark
+
+This example shows how use `dstack` to spin up an [Apache Spark](https://spark.apache.org/docs/latest/index.html) cluster and run tasks on it.
+
+## Create a fleet
+
+First create a fleet for the Spark cluster. We'll use one instance as the Spark master node and one instance as the Spark worker node. We'll also provision a third instance that we'll use to submit Spark apps to the cluster so that we don't need to run anything locally:
+
+```yaml
+type: fleet
+name: spark-fleet
+nodes: 3
+placement: cluster
+backends: [gcp]
+```
+
+```shell
+dstack apply -f fleet.dstack.yaml
+```
+
+## Launch Spark cluster
+
+The following `dstack` task launches Spark master and worker nodes. `dstack` makes the cluster UI available at `localhost:8080`, and Spark apps can be submitted to `localhost:7077`.
+
+```yaml
+type: task
+name: spark-cluster
+image: spark
+nodes: 2
+commands:
+ - export SPARK_MASTER_HOST=$DSTACK_MASTER_NODE_IP
+ - export SPARK_NO_DAEMONIZE=true
+ - if [ $DSTACK_NODE_RANK = 0 ]; then /opt/spark/sbin/start-master.sh; else /opt/spark/sbin/start-worker.sh spark://$DSTACK_MASTER_NODE_IP:7077; fi
+ports:
+ - 7077
+ - 8080
+```
+
+```shell
+dstack apply -f cluster.dstack.yaml
+```
+
+## Run Spark app
+
+If you have Spark installed locally, you can submit your code directly to `localhost:7077`. In this example, we run another `dstack` task to submit code to the Spark cluster. You should provide it with `SPARK_CLUSTER_IP` set to the IP address of the Spark cluster master node. (You can find it in the output of `dstack apply -f cluster.dstack.yaml`.)
+
+```yaml
+type: task
+name: spark-task
+image: spark
+env:
+ - SPARK_CLUSTER_IP
+commands:
+ - pip install pyspark
+ - python3 tasks/words.py
+```
+
+```shell
+export SPARK_CLUSTER_IP=
+
+dstack apply -f task.dstack.yaml
+```
diff --git a/examples/misc/spark/cluster.dstack.yaml b/examples/misc/spark/cluster.dstack.yaml
new file mode 100644
index 0000000000..386f8d2ff7
--- /dev/null
+++ b/examples/misc/spark/cluster.dstack.yaml
@@ -0,0 +1,11 @@
+type: task
+name: spark-cluster
+image: spark
+nodes: 2
+commands:
+ - export SPARK_MASTER_HOST=$DSTACK_MASTER_NODE_IP
+ - export SPARK_NO_DAEMONIZE=true
+ - if [ $DSTACK_NODE_RANK = 0 ]; then /opt/spark/sbin/start-master.sh; else /opt/spark/sbin/start-worker.sh spark://$DSTACK_MASTER_NODE_IP:7077; fi
+ports:
+ - 7077
+ - 8080
diff --git a/examples/misc/spark/fleet.dstack.yaml b/examples/misc/spark/fleet.dstack.yaml
new file mode 100644
index 0000000000..b821874c8e
--- /dev/null
+++ b/examples/misc/spark/fleet.dstack.yaml
@@ -0,0 +1,5 @@
+type: fleet
+name: spark-fleet
+nodes: 3
+placement: cluster
+backends: [gcp]
diff --git a/examples/misc/spark/task.dstack.yaml b/examples/misc/spark/task.dstack.yaml
new file mode 100644
index 0000000000..7f30020643
--- /dev/null
+++ b/examples/misc/spark/task.dstack.yaml
@@ -0,0 +1,8 @@
+type: task
+name: spark-task
+image: spark
+env:
+ - SPARK_CLUSTER_IP
+commands:
+ - pip install pyspark
+ - python3 tasks/words.py
diff --git a/examples/misc/spark/tasks/words.py b/examples/misc/spark/tasks/words.py
new file mode 100644
index 0000000000..72f9a8d28b
--- /dev/null
+++ b/examples/misc/spark/tasks/words.py
@@ -0,0 +1,39 @@
+# A trivial Spark app example that counts words occurencies in a text
+
+import os
+from operator import add
+
+from pyspark.sql import SparkSession
+
+SPARK_CLUSTER_IP = os.environ["SPARK_CLUSTER_IP"]
+
+# Initialize a Spark session
+spark = SparkSession.builder.master(f"spark://{SPARK_CLUSTER_IP}:7077").getOrCreate()
+
+data = [
+ "Apache Spark is a unified analytics engine",
+ "for large-scale data processing",
+ "Spark runs on Hadoop, Apache Mesos, Kubernetes",
+ "Standalone, or in the cloud",
+ "It can access diverse data sources",
+]
+
+# Parallelize the data (create an RDD)
+lines = spark.sparkContext.parallelize(data)
+
+# Split each line into words
+words = lines.flatMap(lambda line: line.split())
+
+# Map each word to a pair of (word, 1)
+word_pairs = words.map(lambda word: (word, 1))
+
+# Reduce by key (word) to count occurrences
+word_counts = word_pairs.reduceByKey(add)
+
+# Collect the results and print
+results = word_counts.collect()
+for word, count in results:
+ print(f"{word}: {count}")
+
+# Stop the Spark session
+spark.stop()
diff --git a/examples/misc/streamlit/serve.dstack.yml b/examples/misc/streamlit/.dstack.yml
similarity index 100%
rename from examples/misc/streamlit/serve.dstack.yml
rename to examples/misc/streamlit/.dstack.yml
diff --git a/examples/misc/streamlit/README.md b/examples/misc/streamlit/README.md
index 5f758b1a9e..855c84b61d 100644
--- a/examples/misc/streamlit/README.md
+++ b/examples/misc/streamlit/README.md
@@ -5,19 +5,19 @@
The following command runs `streamlit hello` as a service with disabled authentication:
```shell
-dstack run . -f examples/misc/streamlit/serve.dstack.yml
+dstack apply -f examples/misc/streamlit/.dstack.yml
```
-See the configuration at [serve.dstack.yml](serve.dstack.yml).
+See the configuration at [.dstack.yml](.dstack.yml).
## Task
The following command runs `streamlit hello` as a task:
```shell
-dstack run . -f examples/misc/streamlit/serve-task.dstack.yml
+dstack apply -f examples/misc/streamlit/task.dstack.yml
```
-See the configuration at [serve-task.dstack.yml](serve-task.dstack.yml).
+See the configuration at [task.dstack.yml](task.dstack.yml).
-For more details, refer to [services](https://dstack.ai/docs/concepts/services) or [tasks](https://dstack.ai/docs/concepts/tasks).
\ No newline at end of file
+For more details, refer to [services](https://dstack.ai/docs/services) or [tasks](https://dstack.ai/docs/tasks).
diff --git a/examples/misc/streamlit/serve-task.dstack.yml b/examples/misc/streamlit/task.dstack.yml
similarity index 100%
rename from examples/misc/streamlit/serve-task.dstack.yml
rename to examples/misc/streamlit/task.dstack.yml
diff --git a/examples/models/gpt-oss/amd/120b.dstack.yml b/examples/models/gpt-oss/amd/120b.dstack.yml
new file mode 100644
index 0000000000..662fb9f403
--- /dev/null
+++ b/examples/models/gpt-oss/amd/120b.dstack.yml
@@ -0,0 +1,31 @@
+type: service
+name: gpt-oss-120b
+
+model: openai/gpt-oss-120b
+
+env:
+ - HF_TOKEN
+ - MODEL=openai/gpt-oss-120b
+ # To enable AITER, set below to 1. Otherwise, set it to 0.
+ - VLLM_ROCM_USE_AITER=1
+ # To enable AITER Triton unified attention
+ - VLLM_USE_AITER_UNIFIED_ATTENTION=1
+ # below is required in order to enable AITER unified attention by disabling AITER MHA
+ - VLLM_ROCM_USE_AITER_MHA=0
+image: rocm/vllm-dev:open-mi300-08052025
+commands:
+ - |
+ vllm serve $MODEL \
+ --tensor-parallel $DSTACK_GPUS_NUM \
+ --no-enable-prefix-caching \
+ --disable-log-requests \
+ --compilation-config '{"full_cuda_graph": true}'
+port: 8000
+
+volumes:
+ # Cache downloaded models
+ - /root/.cache/huggingface:/root/.cache/huggingface
+
+resources:
+ gpu: MI300X:8
+ shm_size: 32GB
diff --git a/gateway/src/dstack/gateway/config/__init__.py b/examples/plugins/__init__.py
similarity index 100%
rename from gateway/src/dstack/gateway/config/__init__.py
rename to examples/plugins/__init__.py
diff --git a/examples/plugins/example_plugin/.python-version b/examples/plugins/example_plugin/.python-version
new file mode 100644
index 0000000000..2c0733315e
--- /dev/null
+++ b/examples/plugins/example_plugin/.python-version
@@ -0,0 +1 @@
+3.11
diff --git a/examples/plugins/example_plugin/Dockerfile b/examples/plugins/example_plugin/Dockerfile
new file mode 100644
index 0000000000..54b5660ecb
--- /dev/null
+++ b/examples/plugins/example_plugin/Dockerfile
@@ -0,0 +1,9 @@
+# Example of including plugins into the dstack server Docker image
+FROM dstackai/dstack:latest
+
+# Installing plugin from Docker context
+COPY . plugins/example_plugin
+RUN uv tool install "dstack[all]" --with plugins/example_plugin
+
+# Installing some other plugins from pypi/git
+# RUN uv tool install "dstack[all]" --with plugin1 --with plugin2
diff --git a/examples/plugins/example_plugin/README.md b/examples/plugins/example_plugin/README.md
new file mode 100644
index 0000000000..112cb3a293
--- /dev/null
+++ b/examples/plugins/example_plugin/README.md
@@ -0,0 +1,52 @@
+## Overview
+
+This is a basic `dstack` plugin example.
+You can use it as a reference point when implementing new `dstack` plugins.
+
+## Steps
+
+1. Init the plugin package:
+
+ ```
+ uv init --library
+ ```
+
+2. Define `ApplyPolicy` and `Plugin` subclasses:
+
+ ```python
+ from dstack.plugins import ApplyPolicy, Plugin, RunSpec, get_plugin_logger
+
+
+ logger = get_plugin_logger(__name__)
+
+
+ class ExamplePolicy(ApplyPolicy):
+
+ def on_run_apply(self, user: str, project: str, spec: RunSpec) -> RunSpec:
+ # ...
+ return spec
+
+
+ class ExamplePlugin(Plugin):
+
+ def get_apply_policies(self) -> list[ApplyPolicy]:
+ return [ExamplePolicy()]
+
+ ```
+
+3. Specify a "dstack.plugins" entry point in `pyproject.toml`:
+
+ ```toml
+ [project.entry-points."dstack.plugins"]
+ example_plugin = "example_plugin:ExamplePlugin"
+ ```
+
+4. Make sure to install the plugin and enable it in the `server/config.yml`:
+
+ ```yaml
+ plugins:
+ - example_plugin
+ projects:
+ - name: main
+ # ...
+ ```
diff --git a/examples/plugins/example_plugin/enterprise.Dockerfile b/examples/plugins/example_plugin/enterprise.Dockerfile
new file mode 100644
index 0000000000..f59d900ae1
--- /dev/null
+++ b/examples/plugins/example_plugin/enterprise.Dockerfile
@@ -0,0 +1,9 @@
+# Example of including plugins into the dstack Enterprise Docker image
+FROM ghcr.io/dstackai/dstack-enterprise:latest
+
+# Installing plugin from Docker context
+COPY . plugins/example_plugin
+RUN uv pip install plugins/example_plugin
+
+# Installing some other plugins from pypi/git
+# RUN uv pip install plugin-name
diff --git a/examples/plugins/example_plugin/pyproject.toml b/examples/plugins/example_plugin/pyproject.toml
new file mode 100644
index 0000000000..66f954a59a
--- /dev/null
+++ b/examples/plugins/example_plugin/pyproject.toml
@@ -0,0 +1,17 @@
+[project]
+name = "example-plugin"
+version = "0.1.0"
+description = "A dstack plugin example"
+readme = "README.md"
+authors = [
+ { name = "Victor Skvortsov", email = "victor@dstack.ai" }
+]
+requires-python = ">=3.10"
+dependencies = []
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[project.entry-points."dstack.plugins"]
+example_plugin = "example_plugin:ExamplePlugin"
diff --git a/examples/plugins/example_plugin/src/example_plugin/__init__.py b/examples/plugins/example_plugin/src/example_plugin/__init__.py
new file mode 100644
index 0000000000..f431e5c282
--- /dev/null
+++ b/examples/plugins/example_plugin/src/example_plugin/__init__.py
@@ -0,0 +1,34 @@
+from dstack.api import Service
+from dstack.plugins import ApplyPolicy, GatewaySpec, Plugin, RunSpec, get_plugin_logger
+
+logger = get_plugin_logger(__name__)
+
+
+class ExamplePolicy(ApplyPolicy):
+ def on_run_apply(self, user: str, project: str, spec: RunSpec) -> RunSpec:
+ # Forcing some limits
+ spec.configuration.max_price = 2.0
+ spec.configuration.max_duration = "1d"
+ # Setting some extra tags
+ if spec.configuration.tags is None:
+ spec.configuration.tags = {}
+ spec.configuration.tags |= {
+ "team": "my_team",
+ }
+ # Forbid something
+ if spec.configuration.privileged:
+ logger.warning("User %s tries to run privileged containers", user)
+ raise ValueError("Running privileged containers is forbidden")
+ # Set some service-specific properties
+ if isinstance(spec.configuration, Service):
+ spec.configuration.https = True
+ return spec
+
+ def on_gateway_apply(self, user: str, project: str, spec: GatewaySpec) -> GatewaySpec:
+ # Forbid creating new gateways altogether
+ raise ValueError("Creating gateways is forbidden")
+
+
+class ExamplePlugin(Plugin):
+ def get_apply_policies(self) -> list[ApplyPolicy]:
+ return [ExamplePolicy()]
diff --git a/gateway/src/dstack/gateway/core/__init__.py b/examples/plugins/example_plugin/src/example_plugin/py.typed
similarity index 100%
rename from gateway/src/dstack/gateway/core/__init__.py
rename to examples/plugins/example_plugin/src/example_plugin/py.typed
diff --git a/examples/plugins/example_plugin_server/.python-version b/examples/plugins/example_plugin_server/.python-version
new file mode 100644
index 0000000000..2c0733315e
--- /dev/null
+++ b/examples/plugins/example_plugin_server/.python-version
@@ -0,0 +1 @@
+3.11
diff --git a/examples/plugins/example_plugin_server/README.md b/examples/plugins/example_plugin_server/README.md
new file mode 100644
index 0000000000..032cf0bdca
--- /dev/null
+++ b/examples/plugins/example_plugin_server/README.md
@@ -0,0 +1,29 @@
+## Overview
+
+If you wish to hook up your own plugin server through `dstack` builtin `rest_plugin`, here's a basic example on how to do so.
+
+## Steps
+
+1. Install the plugin server:
+
+ ```bash
+ uv pip install examples/plugins/example_plugin_server
+ ```
+
+2. Start the plugin server:
+
+ ```bash
+ python -m example_plugin_server.main
+ ```
+
+3. Enable `rest_plugin` in `server/config.yaml`:
+
+ ```yaml
+ plugins:
+ - rest_plugin
+ ```
+
+4. Point the `dstack` server to your plugin server:
+ ```bash
+ export DSTACK_PLUGIN_SERVICE_URI=http://127.0.0.1:8000
+ ```
diff --git a/gateway/src/dstack/gateway/openai/__init__.py b/examples/plugins/example_plugin_server/__init__.py
similarity index 100%
rename from gateway/src/dstack/gateway/openai/__init__.py
rename to examples/plugins/example_plugin_server/__init__.py
diff --git a/examples/plugins/example_plugin_server/pyproject.toml b/examples/plugins/example_plugin_server/pyproject.toml
new file mode 100644
index 0000000000..cc5d3b1c0a
--- /dev/null
+++ b/examples/plugins/example_plugin_server/pyproject.toml
@@ -0,0 +1,18 @@
+[project]
+name = "dstack-plugin-server"
+version = "0.1.0"
+description = "Example plugin server"
+readme = "README.md"
+requires-python = ">=3.10"
+dependencies = [
+ "fastapi",
+ "uvicorn",
+ "dstack",
+]
+
+[build-system]
+requires = ["hatchling"]
+build-backend = "hatchling.build"
+
+[tool.hatch.build.targets.wheel]
+packages = ["src/example_plugin_server"]
diff --git a/gateway/src/dstack/gateway/registry/__init__.py b/examples/plugins/example_plugin_server/src/example_plugin_server/__init__.py
similarity index 100%
rename from gateway/src/dstack/gateway/registry/__init__.py
rename to examples/plugins/example_plugin_server/src/example_plugin_server/__init__.py
diff --git a/examples/plugins/example_plugin_server/src/example_plugin_server/main.py b/examples/plugins/example_plugin_server/src/example_plugin_server/main.py
new file mode 100644
index 0000000000..1733a6e998
--- /dev/null
+++ b/examples/plugins/example_plugin_server/src/example_plugin_server/main.py
@@ -0,0 +1,66 @@
+import logging
+import os
+
+import uvicorn
+from fastapi import FastAPI
+
+from dstack.plugins.builtin.rest_plugin import (
+ FleetSpecRequest,
+ FleetSpecResponse,
+ GatewaySpecRequest,
+ GatewaySpecResponse,
+ RunSpecRequest,
+ RunSpecResponse,
+ VolumeSpecRequest,
+ VolumeSpecResponse,
+)
+from example_plugin_server.utils import configure_logging
+
+configure_logging()
+logger = logging.getLogger(__name__)
+
+app = FastAPI()
+
+
+@app.post("/apply_policies/on_run_apply")
+async def on_run_apply(request: RunSpecRequest) -> RunSpecResponse:
+ logger.info(
+ f"Received run spec request from user {request.user} and project {request.project}"
+ )
+ response = RunSpecResponse(spec=request.spec, error=None)
+ return response
+
+
+@app.post("/apply_policies/on_fleet_apply")
+async def on_fleet_apply(request: FleetSpecRequest) -> FleetSpecResponse:
+ logger.info(
+ f"Received fleet spec request from user {request.user} and project {request.project}"
+ )
+ response = FleetSpecResponse(spec=request.spec, error=None)
+ return response
+
+
+@app.post("/apply_policies/on_volume_apply")
+async def on_volume_apply(request: VolumeSpecRequest) -> VolumeSpecResponse:
+ logger.info(
+ f"Received volume spec request from user {request.user} and project {request.project}"
+ )
+ response = VolumeSpecResponse(spec=request.spec, error=None)
+ return response
+
+
+@app.post("/apply_policies/on_gateway_apply")
+async def on_gateway_apply(request: GatewaySpecRequest) -> GatewaySpecResponse:
+ logger.info(
+ f"Received gateway spec request from user {request.user} and project {request.project}"
+ )
+ response = GatewaySpecResponse(spec=request.spec, error=None)
+ return response
+
+
+if __name__ == "__main__":
+ uvicorn.run(
+ app,
+ host="127.0.0.1",
+ port=int(os.getenv("DSTACK_REST_PLUGIN_SERVER_PORT", 8000)),
+ )
diff --git a/examples/plugins/example_plugin_server/src/example_plugin_server/utils.py b/examples/plugins/example_plugin_server/src/example_plugin_server/utils.py
new file mode 100644
index 0000000000..b07406682f
--- /dev/null
+++ b/examples/plugins/example_plugin_server/src/example_plugin_server/utils.py
@@ -0,0 +1,7 @@
+import logging
+import os
+
+
+def configure_logging():
+ log_level = os.getenv("LOG_LEVEL", "INFO").upper()
+ logging.basicConfig(level=log_level)
diff --git a/examples/server-deployment/cloudformation/README.md b/examples/server-deployment/cloudformation/README.md
new file mode 100644
index 0000000000..2e2057df47
--- /dev/null
+++ b/examples/server-deployment/cloudformation/README.md
@@ -0,0 +1,17 @@
+# Deploying server to a private VPC via AWS CloudFormation
+
+If you'd like to deploy the server to a private AWS VPC, you can use
+our CloudFormation [template](https://console.aws.amazon.com/cloudformation/home#/stacks/quickcreate?templateURL=https://get-dstack.s3.eu-west-1.amazonaws.com/cloudformation/template.yaml).
+
+First, ensure, you've set up a private VPC with public and private subnets.
+
+
+
+Create a stack using the template, and specify the VPC and private subnets.
+Once, the stack is created, go to `Outputs` for the server URL and admin token.
+
+> To access the server URL, ensure you're connected to the VPC, e.g. via VPN client.
+
+!!! info "Source code"
+ If you'd like to adjust anything, the source code of the template can be found at
+ [`examples/server-deployment/cloudformation/template.yaml`](https://github.com/dstackai/dstack/blob/master/examples/server-deployment/cloudformation/template.yaml).
diff --git a/examples/server-deployment/cloudformation/template.yaml b/examples/server-deployment/cloudformation/template.yaml
new file mode 100644
index 0000000000..09ab404941
--- /dev/null
+++ b/examples/server-deployment/cloudformation/template.yaml
@@ -0,0 +1,266 @@
+AWSTemplateFormatVersion: '2010-09-09'
+Description: 'CloudFormation template for deploying a dstack server'
+
+Parameters:
+ VpcId:
+ Description: ID of an existing Virtual Private Cloud (VPC).
+ Type: 'AWS::EC2::VPC::Id'
+ PrivateSubnetIds:
+ Description: IDs of existing private subnets within the specified VPC.
+ Type: 'List'
+
+ DstackVersion:
+ Type: String
+ Description: The version of dstack server
+ Default: latest
+
+ AdminToken:
+ Type: String
+ Description: The secure token of the admin user. If not specified, it's generated randomly.
+ Default: ''
+
+Resources:
+ LitestreamBucket:
+ Type: 'AWS::S3::Bucket'
+ DeletionPolicy: Retain
+ Properties:
+ BucketName: !Join
+ - '-'
+ - - 'dstack-server-litestream-bucket'
+ - !Select
+ - 0
+ - !Split
+ - '-'
+ - !Select
+ - 2
+ - !Split
+ - /
+ - !Ref AWS::StackId
+
+ TaskDefinitionRole:
+ Type: AWS::IAM::Role
+ Properties:
+ AssumeRolePolicyDocument:
+ Version: '2012-10-17'
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service: ecs-tasks.amazonaws.com
+ Action: sts:AssumeRole
+ Policies:
+ - PolicyName: !Join [ '-', [ 'dstack-server-task-definition-policy', !Ref 'AWS::StackName' ] ]
+ PolicyDocument:
+ Version: '2012-10-17'
+ Statement:
+ - Effect: Allow
+ Action:
+ - ec2:AttachVolume
+ - ec2:AuthorizeSecurityGroupEgress
+ - ec2:AuthorizeSecurityGroupIngress
+ - ec2:CancelSpotInstanceRequests
+ - ec2:CreateSecurityGroup
+ - ec2:CreateTags
+ - ec2:CreateVolume
+ - ec2:DeleteVolume
+ - ec2:DescribeAvailabilityZones
+ - ec2:DescribeImages
+ - ec2:DescribeInstances
+ - ec2:DescribeInstanceAttribute
+ - ec2:DescribeInstanceTypes
+ - ec2:DescribeRouteTables
+ - ec2:DescribeSecurityGroups
+ - ec2:DescribeSubnets
+ - ec2:DescribeVpcs
+ - ec2:DescribeVolumes
+ - ec2:DetachVolume
+ - ec2:RunInstances
+ - ec2:TerminateInstances
+ Resource: '*'
+ - Effect: Allow
+ Action:
+ - servicequotas:ListServiceQuotas
+ - servicequotas:GetServiceQuota
+ Resource: '*'
+ - Effect: Allow
+ Action:
+ - elasticloadbalancing:CreateLoadBalancer
+ - elasticloadbalancing:CreateTargetGroup
+ - elasticloadbalancing:CreateListener
+ - elasticloadbalancing:RegisterTargets
+ - elasticloadbalancing:AddTags
+ - elasticloadbalancing:DeleteLoadBalancer
+ - elasticloadbalancing:DeleteTargetGroup
+ - elasticloadbalancing:DeleteListener
+ - elasticloadbalancing:DeregisterTargets
+ Resource: '*'
+ - Effect: Allow
+ Action:
+ - acm:DescribeCertificate
+ - acm:ListCertificates
+ Resource: '*'
+ - Effect: Allow
+ Action:
+ - s3:*
+ Resource:
+ - !Sub 'arn:aws:s3:::${LitestreamBucket}'
+ - !Sub 'arn:aws:s3:::${LitestreamBucket}/*'
+
+ TaskExecutionRole:
+ Type: AWS::IAM::Role
+ Properties:
+ AssumeRolePolicyDocument:
+ Version: '2012-10-17'
+ Statement:
+ - Effect: Allow
+ Principal:
+ Service: ecs-tasks.amazonaws.com
+ Action: sts:AssumeRole
+ ManagedPolicyArns:
+ - arn:aws:iam::aws:policy/service-role/AmazonECSTaskExecutionRolePolicy
+
+ Cluster:
+ Type: AWS::ECS::Cluster
+ Properties:
+ ClusterName: !Join [ '-', [ 'dstack-server', !Ref 'AWS::StackName' ] ]
+ CapacityProviders:
+ - FARGATE
+ DefaultCapacityProviderStrategy:
+ - CapacityProvider: FARGATE
+ Weight: 1
+ Configuration:
+ ExecuteCommandConfiguration:
+ Logging: DEFAULT
+
+ TaskDefinition:
+ Type: AWS::ECS::TaskDefinition
+ Properties:
+ Family: !Join [ '-', [ 'dstack-server-task-definition-family', !Ref 'AWS::StackName' ] ]
+ NetworkMode: awsvpc
+ RequiresCompatibilities:
+ - FARGATE
+ Cpu: '1024'
+ Memory: '2048'
+ ExecutionRoleArn: !GetAtt TaskExecutionRole.Arn
+ TaskRoleArn: !GetAtt TaskDefinitionRole.Arn
+ ContainerDefinitions:
+ - Name: dstack-server
+ Image: !Join [ ':', [ 'dstackai/dstack', !Ref DstackVersion ] ]
+ PortMappings:
+ - ContainerPort: 8000
+ LogConfiguration:
+ LogDriver: awslogs
+ Options:
+ awslogs-group: !Join [ '-', [ 'dstack-server', !Ref 'AWS::StackName' ] ]
+ awslogs-region: !Ref AWS::Region
+ awslogs-stream-prefix: dstack-server
+ Environment:
+ - Name: DSTACK_SERVER_PORT
+ Value: '8000'
+ - Name: DSTACK_SERVER_ADMIN_TOKEN
+ Value: !If [ AdminTokenEmpty, !Select [ 2, !Split [ '/', !Ref AWS::StackId ] ], !Ref AdminToken ]
+ - Name: LITESTREAM_REPLICA_URL
+ Value: !Join ['', ['s3://', !Ref LitestreamBucket]]
+ - Name: DSTACK_SERVER_CLOUDWATCH_LOG_GROUP
+ Value: !Join [ '-', [ 'dstack-server-runs', !Ref 'AWS::StackName' ] ]
+ - Name: DSTACK_SERVER_CLOUDWATCH_LOG_REGION
+ Value: !Ref AWS::Region
+
+ LoadBalancerSecurityGroup:
+ Type: AWS::EC2::SecurityGroup
+ Properties:
+ GroupDescription: Access to the public facing load balancer
+ VpcId: !Ref VpcId
+ SecurityGroupIngress:
+ - CidrIp: 0.0.0.0/0
+ FromPort: 80
+ ToPort: 80
+ IpProtocol: tcp
+
+ LoadBalancer:
+ Type: AWS::ElasticLoadBalancingV2::LoadBalancer
+ Properties:
+ Scheme: internal
+ SecurityGroups: [ !Ref 'LoadBalancerSecurityGroup' ]
+ Subnets: !Split [',', !Join [',', !Ref PrivateSubnetIds]]
+ Type: application
+
+ ListenerHTTP:
+ Type: AWS::ElasticLoadBalancingV2::Listener
+ Properties:
+ DefaultActions:
+ - TargetGroupArn: !Ref TargetGroup
+ Type: forward
+ LoadBalancerArn: !Ref LoadBalancer
+ Port: 80
+ Protocol: HTTP
+
+ ContainerSecurityGroup:
+ Type: AWS::EC2::SecurityGroup
+ Properties:
+ GroupDescription: Security group for container
+ VpcId: !Ref VpcId
+ SecurityGroupIngress:
+ - IpProtocol: tcp
+ FromPort: 8000
+ ToPort: 8000
+ SourceSecurityGroupId: !Ref LoadBalancerSecurityGroup
+
+ Service:
+ Type: AWS::ECS::Service
+ DependsOn: ListenerHTTP
+ Properties:
+ ServiceName: dstack-server
+ Cluster: !Ref Cluster
+ TaskDefinition: !Ref TaskDefinition
+ DesiredCount: 1
+ DeploymentConfiguration:
+ MinimumHealthyPercent: 0
+ MaximumPercent: 100
+ HealthCheckGracePeriodSeconds: 300
+ LaunchType: FARGATE
+ NetworkConfiguration:
+ AwsvpcConfiguration:
+ Subnets: !Split [',', !Join [',', !Ref PrivateSubnetIds]]
+ SecurityGroups:
+ - !Ref ContainerSecurityGroup
+ LoadBalancers:
+ - ContainerName: dstack-server
+ ContainerPort: 8000
+ TargetGroupArn: !Ref TargetGroup
+
+ TargetGroup:
+ Type: AWS::ElasticLoadBalancingV2::TargetGroup
+ Properties:
+ TargetType: ip
+ Port: 8000
+ Protocol: HTTP
+ VpcId: !Ref VpcId
+ HealthCheckPath: /
+ HealthCheckIntervalSeconds: 30
+ Matcher:
+ HttpCode: '200'
+ HealthyThresholdCount: 2
+ UnhealthyThresholdCount: 3
+
+ LogGroup:
+ Type: AWS::Logs::LogGroup
+ Properties:
+ LogGroupName: !Join [ '-', [ 'dstack-server', !Ref 'AWS::StackName' ] ]
+ RetentionInDays: 30
+
+ RunsLogGroup:
+ Type: AWS::Logs::LogGroup
+ Properties:
+ LogGroupName: !Join [ '-', [ 'dstack-server-runs', !Ref 'AWS::StackName' ] ]
+ RetentionInDays: 30
+
+Conditions:
+ AdminTokenEmpty: !Equals [ !Ref AdminToken, '' ]
+
+Outputs:
+ ServerUrl:
+ Description: The URL of the dstack server
+ Value: !GetAtt LoadBalancer.DNSName
+ AdminToken:
+ Description: The token of the admin useer
+ Value: !If [ AdminTokenEmpty, !Select [ 2, !Split [ '/', !Ref AWS::StackId ] ], !Ref AdminToken ]
diff --git a/examples/single-node-training/axolotl/amd/.dstack.yml b/examples/single-node-training/axolotl/amd/.dstack.yml
new file mode 100644
index 0000000000..1e9886faa3
--- /dev/null
+++ b/examples/single-node-training/axolotl/amd/.dstack.yml
@@ -0,0 +1,44 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: axolotl-amd-llama31-train
+image: runpod/pytorch:2.1.2-py3.10-rocm6.0.2-ubuntu22.04
+# Required environment variables
+env:
+ - HF_TOKEN
+ - WANDB_API_KEY
+ - WANDB_PROJECT
+ - WANDB_NAME=axolotl-amd-llama31-train
+ - HUB_MODEL_ID
+# Commands of the task
+commands:
+ - export PATH=/opt/conda/envs/py_3.10/bin:$PATH
+ - pip uninstall torch torchvision torchaudio -y
+ - python3 -m pip install --pre torch==2.3.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.0/
+ - git clone https://github.com/OpenAccess-AI-Collective/axolotl
+ - cd axolotl
+ - git checkout d4f6c65
+ - pip install -e .
+ # Latest pynvml is not compatible with axolotl commit d4f6c65, so we need to fall back to version 11.5.3
+ - pip uninstall pynvml -y
+ - pip install pynvml==11.5.3
+ - cd ..
+ - wget https://dstack-binaries.s3.amazonaws.com/flash_attn-2.0.4-cp310-cp310-linux_x86_64.whl
+ - pip install flash_attn-2.0.4-cp310-cp310-linux_x86_64.whl
+ - wget https://dstack-binaries.s3.amazonaws.com/xformers-0.0.26-cp310-cp310-linux_x86_64.whl
+ - pip install xformers-0.0.26-cp310-cp310-linux_x86_64.whl
+ - git clone --recurse https://github.com/ROCm/bitsandbytes
+ - cd bitsandbytes
+ - git checkout rocm_enabled
+ - pip install -r requirements-dev.txt
+ - cmake -DBNB_ROCM_ARCH="gfx942" -DCOMPUTE_BACKEND=hip -S .
+ - make
+ - pip install .
+ - cd ..
+ - accelerate launch -m axolotl.cli.train -- axolotl/examples/llama-3/fft-8b.yaml
+ --wandb-project "$WANDB_PROJECT"
+ --wandb-name "$WANDB_NAME"
+ --hub-model-id "$HUB_MODEL_ID"
+
+resources:
+ gpu: MI300X
+ disk: 150GB
diff --git a/examples/single-node-training/axolotl/amd/build-flash-attention.yml b/examples/single-node-training/axolotl/amd/build-flash-attention.yml
new file mode 100644
index 0000000000..030729ce46
--- /dev/null
+++ b/examples/single-node-training/axolotl/amd/build-flash-attention.yml
@@ -0,0 +1,37 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: build-flash-attention
+
+image: runpod/pytorch:2.1.2-py3.10-rocm6.0.2-ubuntu22.04
+
+# Required environment variables
+env:
+ - HF_TOKEN
+ - GPU_ARCHS="gfx90a;gfx942"
+ - AWS_ACCESS_KEY_ID
+ - AWS_SECRET_ACCESS_KEY
+ - AWS_REGION
+ - BUCKET_NAME
+
+# Commands of the task
+commands:
+ - apt-get update -y
+ - apt-get install awscli -y
+ - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
+ - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
+ - aws configure set region $AWS_REGION
+ - export PATH=/opt/conda/envs/py_3.10/bin:$PATH
+ - pip uninstall torch torchvision torchaudio -y
+ - python3 -m pip install --pre torch==2.3.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.0/
+ - pip install ninja
+ - pip install wheel setuptools
+ - git clone https://github.com/ROCm/flash-attention.git
+ - cd flash-attention
+ - git checkout stride_fix
+ - python setup.py bdist_wheel -d dist/
+ - cd dist
+ - aws s3 cp "$(ls -1 | head -n 1)" s3://$BUCKET_NAME/ --acl public-read
+
+resources:
+ gpu: MI300X
+ disk: 150GB
diff --git a/examples/single-node-training/axolotl/amd/build-xformers.dstack.yml b/examples/single-node-training/axolotl/amd/build-xformers.dstack.yml
new file mode 100644
index 0000000000..064a3a233a
--- /dev/null
+++ b/examples/single-node-training/axolotl/amd/build-xformers.dstack.yml
@@ -0,0 +1,38 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: build-flash-attention
+
+image: runpod/pytorch:2.1.2-py3.10-rocm6.0.2-ubuntu22.04
+
+# Required environment variables
+env:
+ - HF_TOKEN
+ - GPU_ARCHS="gfx90a;gfx942"
+ - AWS_ACCESS_KEY_ID
+ - AWS_SECRET_ACCESS_KEY
+ - AWS_REGION
+ - BUCKET_NAME
+
+# Commands of the task
+commands:
+ - apt-get update -y
+ - apt-get install awscli -y
+ - aws configure set aws_access_key_id $AWS_ACCESS_KEY_ID
+ - aws configure set aws_secret_access_key $AWS_SECRET_ACCESS_KEY
+ - aws configure set region $AWS_REGION
+ - export PATH=/opt/conda/envs/py_3.10/bin:$PATH
+ - pip uninstall torch torchvision torchaudio -y
+ - python3 -m pip install --pre torch==2.3.0 torchvision torchaudio --index-url https://download.pytorch.org/whl/rocm6.0/
+ - pip install ninja
+ - pip install wheel setuptools
+ - git clone https://github.com/ROCm/xformers
+ - cd xformers
+ - git checkout dfc196d
+ - git submodule update --init --recursive
+ - python setup.py bdist_wheel -d dist/
+ - cd dist
+ - aws s3 cp "$(ls -1 | head -n 1)" s3://$BUCKET_NAME/ --acl public-read
+
+resources:
+ gpu: MI300X
+ disk: 150GB
diff --git a/examples/single-node-training/optimum-tpu/llama31/.dstack.yml b/examples/single-node-training/optimum-tpu/llama31/.dstack.yml
new file mode 100644
index 0000000000..c93862e678
--- /dev/null
+++ b/examples/single-node-training/optimum-tpu/llama31/.dstack.yml
@@ -0,0 +1,30 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: train-tpu
+
+python: "3.11"
+
+# Required environment variables
+env:
+ - HF_TOKEN
+
+# Mount files
+files:
+ - train.py
+ - config.yaml
+
+# Commands of the task
+commands:
+ - git clone -b add_llama_31_support https://github.com/dstackai/optimum-tpu.git
+ - mkdir -p optimum-tpu/examples/custom/
+ - cp train.py optimum-tpu/examples/custom/train.py
+ - cp config.yaml optimum-tpu/examples/custom/config.yaml
+ - cd optimum-tpu
+ - pip install -e . -f https://storage.googleapis.com/libtpu-releases/index.html
+ - pip install datasets evaluate
+ - pip install accelerate -U
+ - pip install peft
+ - python examples/custom/train.py examples/custom/config.yaml
+
+resources:
+ gpu: v5litepod-8
diff --git a/examples/single-node-training/optimum-tpu/llama31/config.yaml b/examples/single-node-training/optimum-tpu/llama31/config.yaml
new file mode 100644
index 0000000000..2d3677f2f4
--- /dev/null
+++ b/examples/single-node-training/optimum-tpu/llama31/config.yaml
@@ -0,0 +1,10 @@
+per_device_train_batch_size: 24
+per_device_eval_batch_size: 8
+num_train_epochs: 1
+max_steps: -1
+output_dir: "./finetuned_models/llama3_fine_tuned"
+optim: "adafactor"
+dataset_name: "Abirate/english_quotes"
+model_name: "meta-llama/Meta-Llama-3.1-8B"
+lora_r: 4
+push_to_hub: True
diff --git a/examples/single-node-training/optimum-tpu/llama31/train.py b/examples/single-node-training/optimum-tpu/llama31/train.py
new file mode 100644
index 0000000000..0c8c8a614b
--- /dev/null
+++ b/examples/single-node-training/optimum-tpu/llama31/train.py
@@ -0,0 +1,140 @@
+from dataclasses import dataclass, field
+from typing import Optional
+
+from datasets import load_dataset
+from optimum.tpu import AutoModelForCausalLM, fsdp_v2
+from peft import LoraConfig, TaskType, get_peft_model
+from transformers import (
+ AutoTokenizer,
+ DataCollatorForLanguageModeling,
+ HfArgumentParser,
+ Trainer,
+ TrainingArguments,
+)
+
+
+@dataclass
+class ScriptArguments:
+ per_device_train_batch_size: Optional[int] = field(
+ default=8, metadata={"help": "Batch size per device for training."}
+ )
+ per_device_eval_batch_size: Optional[int] = field(
+ default=8, metadata={"help": "Batch size per device for evaluation."}
+ )
+ num_train_epochs: Optional[int] = field(
+ default=1,
+ metadata={"help": "The number of training epochs for the SFTTrainer."},
+ )
+ max_steps: int = field(
+ default=-1, metadata={"help": "How many optimizer update steps to take"}
+ )
+ output_dir: str = field(
+ default="./results",
+ metadata={
+ "help": "The output directory where the model predictions and checkpoints will be written."
+ },
+ )
+ optim: Optional[str] = field(
+ default="adafactor",
+ metadata={"help": "The optimizer to use."},
+ )
+ dataset_name: Optional[str] = field(
+ default="Abirate/english_quotes",
+ metadata={"help": "The dataset to use."},
+ )
+ model_name: Optional[str] = field(
+ default="meta-llama/Meta-Llama-3.1-8B",
+ metadata={
+ "help": "Only models Gemma 2B, Gemma 7B, Llama-2 7B and Llama-3 8B Llama-3.1 8B are tested with TPU v5e"
+ },
+ )
+ lora_r: Optional[int] = field(default=4, metadata={"help": "LoRA attention dimension."})
+ max_seq_length: Optional[int] = field(
+ default=1024, metadata={"help": "Maximum sequence length to use."}
+ )
+ packing: Optional[bool] = field(
+ default=True,
+ metadata={"help": "Use packing dataset creating."},
+ )
+ push_to_hub: Optional[bool] = field(
+ default=True,
+ metadata={"help": "Push fined tuned model to hub."},
+ )
+
+
+def create_and_prepare_model(args):
+ base_model = AutoModelForCausalLM.from_pretrained(args.model_name)
+ lora_config = LoraConfig(
+ r=args.lora_r, # the dimension of the low-rank matrices
+ lora_alpha=8, # scaling factor for LoRA activations vs pre-trained weight activations
+ lora_dropout=0.05,
+ bias="none",
+ inference_mode=False,
+ task_type=TaskType.CAUSAL_LM,
+ target_modules=["o_proj", "v_proj"],
+ ) #
+
+ model = get_peft_model(base_model, lora_config)
+ tokenizer = AutoTokenizer.from_pretrained(args.model_name)
+ # Add custom token for padding Llama
+ tokenizer.add_special_tokens({"pad_token": tokenizer.eos_token})
+ return model, tokenizer
+
+
+def create_and_prepare_trainer(model, tokenizer, dataset, args):
+ data = dataset.map(lambda samples: tokenizer(samples["quote"]), batched=True)
+ fsdp_training_args = fsdp_v2.get_fsdp_training_args(model)
+
+ trainer = Trainer(
+ model=model,
+ train_dataset=data["train"],
+ args=TrainingArguments(
+ per_device_train_batch_size=args.per_device_train_batch_size,
+ num_train_epochs=args.num_train_epochs,
+ max_steps=args.max_steps,
+ output_dir=args.output_dir,
+ optim=args.optim,
+ logging_steps=1,
+ dataloader_drop_last=True, # Required by FSDP v2 and SPMD.
+ **fsdp_training_args,
+ ),
+ data_collator=DataCollatorForLanguageModeling(tokenizer, mlm=False),
+ )
+
+ return trainer
+
+
+def parse_config() -> ScriptArguments:
+ import sys
+
+ import yaml
+
+ # Ensure a YAML file is provided as an argument
+ if len(sys.argv) != 2:
+ sys.exit(1)
+
+ config_path = sys.argv[1]
+
+ # Read the YAML file
+ with open(config_path, "r") as f:
+ config = yaml.safe_load(f)
+
+ # Parse arguments using HfArgumentParser
+ parser = HfArgumentParser(ScriptArguments)
+ script_args = parser.parse_dict(config)[0]
+ return script_args
+
+
+if __name__ == "__main__":
+ args = parse_config()
+ fsdp_v2.use_fsdp_v2()
+ dataset = load_dataset(args.dataset_name)
+ model, tokenizer = create_and_prepare_model(args)
+ trainer = create_and_prepare_trainer(model, tokenizer, dataset, args)
+ trainer.train()
+ if args.push_to_hub:
+ kwargs = {
+ "finetuned_from": args.model_name,
+ "dataset": args.dataset_name,
+ }
+ trainer.push_to_hub(**kwargs)
diff --git a/examples/single-node-training/qlora/.dstack.yml b/examples/single-node-training/qlora/.dstack.yml
new file mode 100644
index 0000000000..7d87f630aa
--- /dev/null
+++ b/examples/single-node-training/qlora/.dstack.yml
@@ -0,0 +1,21 @@
+type: task
+
+python: "3.11"
+
+env:
+ - HF_TOKEN
+ - HF_HUB_ENABLE_HF_TRANSFER=1
+
+files:
+ - requirements.txt
+ - train.py
+
+commands:
+ - pip install -r requirements.txt
+ - tensorboard --logdir results/runs &
+ - python train.py --merge_and_push ${{ run.args }}
+ports:
+ - 6006
+
+resources:
+ gpu: 16GB..24GB
diff --git a/examples/single-node-training/qlora/README.md b/examples/single-node-training/qlora/README.md
new file mode 100644
index 0000000000..eda65cfe25
--- /dev/null
+++ b/examples/single-node-training/qlora/README.md
@@ -0,0 +1,11 @@
+# QLoRA
+
+The following command runs the task to fine-tune an LLM using QLoRA:
+
+```shell
+dstack apply -f examples/single-node-training/qlora/.dstack.yml
+```
+
+See the configuration at [.dstack.yml](.dstack.yml).
+
+For more details, refer to [tasks](https://dstack.ai/docs/tasks).
diff --git a/gateway/src/dstack/gateway/stats/__init__.py b/examples/single-node-training/qlora/requirements.txt
similarity index 100%
rename from gateway/src/dstack/gateway/stats/__init__.py
rename to examples/single-node-training/qlora/requirements.txt
diff --git a/examples/fine-tuning/qlora/train.py b/examples/single-node-training/qlora/train.py
similarity index 100%
rename from examples/fine-tuning/qlora/train.py
rename to examples/single-node-training/qlora/train.py
diff --git a/examples/single-node-training/trl/amd/.dstack.yml b/examples/single-node-training/trl/amd/.dstack.yml
new file mode 100644
index 0000000000..8e6baad788
--- /dev/null
+++ b/examples/single-node-training/trl/amd/.dstack.yml
@@ -0,0 +1,35 @@
+type: task
+# The name is optional, if not specified, generated randomly
+name: trl-amd-llama31-train
+
+# If `image` is not specified, dstack uses its default image
+image: runpod/pytorch:2.1.2-py3.10-rocm6.1-ubuntu22.04
+
+# Required environment variables
+env:
+ - HF_TOKEN
+
+files:
+ - train.py
+
+commands:
+ - export PATH=/opt/conda/envs/py_3.10/bin:$PATH
+ - git clone https://github.com/ROCm/bitsandbytes
+ - cd bitsandbytes
+ - git checkout rocm_enabled
+ - pip install -r requirements-dev.txt
+ - cmake -DBNB_ROCM_ARCH="gfx942" -DCOMPUTE_BACKEND=hip -S . # Use to target specific gpu arch
+ - make
+ - pip install .
+ - pip install trl
+ - pip install peft
+ - pip install transformers datasets huggingface-hub scipy
+ - cd ..
+ - python train.py
+
+# Uncomment to leverage spot instances
+#spot_policy: auto
+
+resources:
+ gpu: MI300X
+ disk: 150GB
diff --git a/examples/single-node-training/trl/amd/train.py b/examples/single-node-training/trl/amd/train.py
new file mode 100644
index 0000000000..15118fc2a1
--- /dev/null
+++ b/examples/single-node-training/trl/amd/train.py
@@ -0,0 +1,61 @@
+from datasets import load_dataset
+from peft import LoraConfig, get_peft_model
+from transformers import AutoModelForCausalLM, AutoTokenizer, TrainingArguments
+from trl import SFTTrainer
+
+# Base model and tokenizer names.
+base_model_name = "meta-llama/Meta-Llama-3.1-8B"
+
+# Load base model to GPU memory.
+device = "cuda:0"
+base_model = AutoModelForCausalLM.from_pretrained(base_model_name, trust_remote_code=True).to(
+ device
+)
+
+# Load tokenizer.
+tokenizer = AutoTokenizer.from_pretrained(base_model_name, trust_remote_code=True)
+tokenizer.pad_token = tokenizer.eos_token
+tokenizer.padding_side = "right"
+
+# Dataset for fine-tuning.
+training_dataset_name = "mlabonne/guanaco-llama2-1k"
+training_dataset = load_dataset(training_dataset_name, split="train")
+
+
+# Training parameters for SFTTrainer.
+training_arguments = TrainingArguments(
+ output_dir="./results",
+ num_train_epochs=1,
+ per_device_train_batch_size=4,
+ gradient_accumulation_steps=1,
+ optim="paged_adamw_32bit",
+ save_steps=50,
+ logging_steps=50,
+ learning_rate=4e-5,
+ weight_decay=0.001,
+ fp16=False,
+ bf16=False,
+ max_grad_norm=0.3,
+ max_steps=-1,
+ warmup_ratio=0.03,
+ group_by_length=True,
+ lr_scheduler_type="constant",
+ report_to="tensorboard",
+)
+
+peft_config = LoraConfig(lora_alpha=16, lora_dropout=0.1, r=64, bias="none", task_type="CAUSAL_LM")
+peft_model = get_peft_model(base_model, peft_config)
+peft_model.print_trainable_parameters()
+
+# Initialize an SFT trainer.
+sft_trainer = SFTTrainer(
+ model=base_model,
+ train_dataset=training_dataset,
+ peft_config=peft_config,
+ dataset_text_field="text",
+ tokenizer=tokenizer,
+ args=training_arguments,
+)
+
+# Run the trainer.
+sft_trainer.train()
diff --git a/frontend/.babelrc b/frontend/.babelrc
new file mode 100644
index 0000000000..4d3ac7addb
--- /dev/null
+++ b/frontend/.babelrc
@@ -0,0 +1,35 @@
+{
+ "presets": [
+ [
+ "@babel/preset-env",
+ {
+ "targets": {
+ "browsers": "last 2 versions"
+ }
+ }
+ ],
+ "@babel/preset-typescript",
+ "@babel/preset-react"
+ ],
+ "plugins": [
+ "@babel/plugin-transform-runtime",
+ "@babel/plugin-proposal-class-properties"
+ ],
+ "env": {
+ "development": {
+ "plugins": ["react-refresh/babel"]
+ },
+ "production": {
+ "presets": [
+ [
+ "minify",
+ {
+ "builtIns": false,
+ "evaluate": false,
+ "mangle": false
+ }
+ ]
+ ]
+ }
+ }
+}
diff --git a/frontend/.gitignore b/frontend/.gitignore
new file mode 100644
index 0000000000..f41806b3cf
--- /dev/null
+++ b/frontend/.gitignore
@@ -0,0 +1,3 @@
+/node_modules/
+/.idea/
+build
diff --git a/frontend/.justfile b/frontend/.justfile
new file mode 100644
index 0000000000..b949968413
--- /dev/null
+++ b/frontend/.justfile
@@ -0,0 +1,32 @@
+# Justfile for building frontend
+#
+# Run `just` to see all available commands
+
+default:
+ @just --list
+
+[private]
+install-frontend:
+ #!/usr/bin/env bash
+ set -e
+ cd {{source_directory()}}
+ npm install
+
+run-frontend:
+ #!/usr/bin/env bash
+ set -e
+ cd {{source_directory()}}
+ npm run start
+
+run-frontend-sky:
+ #!/usr/bin/env bash
+ set -e
+ cd {{source_directory()}}
+ npm run start-sky
+
+build-frontend:
+ #!/usr/bin/env bash
+ set -e
+ cd {{source_directory()}}
+ npm run build
+ cp -r build/ ../src/dstack/_internal/server/statics/
diff --git a/frontend/.prettierrc b/frontend/.prettierrc
new file mode 100644
index 0000000000..c750ce9d9a
--- /dev/null
+++ b/frontend/.prettierrc
@@ -0,0 +1,7 @@
+{
+ "semi": true,
+ "trailingComma": "all",
+ "singleQuote": true,
+ "printWidth": 128,
+ "tabWidth": 4
+}
diff --git a/frontend/eslint.config.cjs b/frontend/eslint.config.cjs
new file mode 100644
index 0000000000..9750398241
--- /dev/null
+++ b/frontend/eslint.config.cjs
@@ -0,0 +1,77 @@
+const { defineConfig, globalIgnores } = require('eslint/config');
+const i18N = require('eslint-plugin-i18n');
+const simpleImportSort = require('eslint-plugin-simple-import-sort');
+const react = require('eslint-plugin-react');
+const { FlatCompat } = require('@eslint/eslintrc');
+const js = require('@eslint/js');
+const typescriptEslint = require('@typescript-eslint/eslint-plugin');
+const tsParser = require('@typescript-eslint/parser');
+
+const compat = new FlatCompat({
+ baseDirectory: __dirname,
+ recommendedConfig: js.configs.recommended,
+ allConfig: js.configs.all,
+});
+
+const BASE_CONFIG = {
+ extends: compat.extends(
+ 'eslint:recommended',
+ 'plugin:@typescript-eslint/eslint-recommended',
+ 'plugin:@typescript-eslint/recommended',
+ 'prettier',
+ 'plugin:prettier/recommended',
+ 'plugin:react/recommended',
+ ),
+
+ plugins: {
+ '@typescript-eslint': typescriptEslint,
+ i18n: i18N,
+ 'simple-import-sort': simpleImportSort,
+ react: react,
+ },
+
+ languageOptions: {
+ parser: tsParser,
+ },
+ settings: {},
+
+ rules: {
+ 'react/jsx-no-target-blank': 'off',
+ 'react/no-unescaped-entities': 'off',
+ 'i18n/no-russian-character': 1,
+
+ 'simple-import-sort/imports': [
+ 'error',
+ {
+ groups: [
+ ['^react', 'lodash', '^\\w', '^@?\\w'],
+ ['^components', '^layouts'],
+ ['^consts', '^hooks', '^libs', '^routes', '^services', '^types'],
+ ['^App', '^pages'],
+ ['^\\./(?=.*/)(?!/?$)', '^\\.(?!/?$)', '^\\./?$'],
+ ['./constants/.'],
+ ['./definitions/.', './types'],
+ ['^.+\\.svg', '^.+\\.png$', '^.+\\.jpg', '^.+\\.s?css$'],
+ ],
+ },
+ ],
+ },
+};
+
+module.exports = defineConfig([
+ globalIgnores([
+ 'node_modules',
+ 'build',
+ 'server.js',
+ 'src/locale',
+ 'src/types',
+ 'src/setupProxy.js',
+ 'webpack/**/*',
+ 'webpack/env.js',
+ 'webpack/prod.js',
+ 'public',
+ 'staticServer.js',
+ 'webpack.config.js',
+ ]),
+ { ...BASE_CONFIG },
+]);
diff --git a/frontend/jest.config.ts b/frontend/jest.config.ts
new file mode 100644
index 0000000000..0fc7934ef3
--- /dev/null
+++ b/frontend/jest.config.ts
@@ -0,0 +1,188 @@
+/*
+ * For a detailed explanation regarding each configuration property and type check, visit:
+ * https://jestjs.io/docs/en/configuration.html
+ */
+
+export default {
+ // All imported modules in your tests should be mocked automatically
+ // automock: false,
+
+ // Stop running tests after `n` failures
+ // bail: 0,
+
+ // The directory where Jest should store its cached dependency information
+ // cacheDirectory: "/private/var/folders/2c/kgqgdjnd513_j7gml91lytx00000gn/T/jest_dx",
+
+ // Automatically clear mock calls and instances between every test
+ clearMocks: true,
+
+ // Indicates whether the coverage information should be collected while executing the test
+ // collectCoverage: false,
+
+ // An array of glob patterns indicating a set of files for which coverage information should be collected
+ // collectCoverageFrom: undefined,
+
+ // The directory where Jest should output its coverage files
+ coverageDirectory: '/tests/__coverage__/',
+
+ // An array of regexp pattern strings used to skip coverage collection
+ // coveragePathIgnorePatterns: [
+ // "/node_modules/"
+ // ],
+
+ // Indicates which provider should be used to instrument code for coverage
+ // coverageProvider: "babel",
+
+ // A list of reporter names that Jest uses when writing coverage reports
+ // coverageReporters: [
+ // "json",
+ // "text",
+ // "lcov",
+ // "clover"
+ // ],
+
+ // An object that configures minimum threshold enforcement for coverage results
+ // coverageThreshold: undefined,
+
+ // A path to a custom dependency extractor
+ // dependencyExtractor: undefined,
+
+ // Make calling deprecated APIs throw helpful error messages
+ // errorOnDeprecated: false,
+
+ // Force coverage collection from ignored files using an array of glob patterns
+ // forceCoverageMatch: [],
+
+ // A path to a module which exports an async function that is triggered once before all test suites
+ // globalSetup: undefined,
+
+ // A path to a module which exports an async function that is triggered once after all test suites
+ // globalTeardown: undefined,
+
+ // A set of global variables that need to be available in all test environments
+ globals: {},
+
+ // The maximum amount of workers used to run your tests. Can be specified as % or a number. E.g. maxWorkers: 10% will use 10% of your CPU amount + 1 as the maximum worker number. maxWorkers: 2 will use a maximum of 2 workers.
+ // maxWorkers: "50%",
+
+ // An array of directory names to be searched recursively up from the requiring module's location
+ moduleDirectories: ['node_modules', 'src', 'tests'],
+
+ // An array of file extensions your modules use
+ moduleFileExtensions: ['js', 'jsx', 'ts', 'tsx'],
+
+ // A map from regular expressions to module names or to arrays of module names that allow to stub out resources with a single module
+ moduleNameMapper: {
+ '\\.svg': '/tests/__mocks__/svgrMock.ts',
+ '\\.(jpg|jpeg|png|gif|eot|otf|webp|svg|ttf|woff|woff2|mp4|webm|wav|mp3|m4a|aac|oga)$':
+ '/tests/__mocks__/fileMock.ts',
+ '\\.(css|less|scss|sss|styl)$': 'identity-obj-proxy',
+ },
+
+ // An array of regexp pattern strings, matched against all module paths before considered 'visible' to the module loader
+ // modulePathIgnorePatterns: [],
+
+ // Activates notifications for test results
+ // notify: false,
+
+ // An enum that specifies notification mode. Requires { notify: true }
+ // notifyMode: "failure-change",
+
+ // A preset that is used as a base for Jest's configuration
+ // preset: undefined,
+ preset: 'ts-jest',
+
+ // Run tests from one or more projects
+ // projects: undefined,
+
+ // Use this configuration option to add custom reporters to Jest
+ // reporters: undefined,
+
+ // Automatically reset mock state between every test
+ // resetMocks: false,
+
+ // Reset the module registry before running each individual test
+ // resetModules: false,
+
+ // A path to a custom resolver
+ // resolver: undefined,
+
+ // Automatically restore mock state between every test
+ // restoreMocks: false,
+
+ // The root directory that Jest should scan for tests and modules within
+ rootDir: '.',
+
+ // A list of paths to directories that Jest should use to search for files in
+ roots: ['/src/', '/tests/'],
+
+ // Allows you to use a custom runner instead of Jest's default test runner
+ // runner: "jest-runner",
+
+ // The paths to modules that run some code to configure or set up the testing environment before each test
+ setupFiles: ['/tests/__mocks__/shim.ts'],
+
+ // A list of paths to modules that run some code to configure or set up the testing framework before each test
+ setupFilesAfterEnv: ['/tests/setupEnzyme.ts'],
+
+ // The number of seconds after which a test is considered as slow and reported as such in the results.
+ // slowTestThreshold: 5,
+
+ // A list of paths to snapshot serializer modules Jest should use for snapshot testing
+ // snapshotSerializers: [],
+
+ // The test environment that will be used for testing
+ testEnvironment: 'jest-environment-jsdom',
+
+ // Options that will be passed to the testEnvironment
+ // testEnvironmentOptions: {},
+
+ // Adds a location field to test results
+ // testLocationInResults: false,
+
+ // The glob patterns Jest uses to detect test files
+ // testMatch: [
+ // "**/__tests__/**/*.[jt]s?(x)",
+ // "**/?(*.)+(spec|test).[tj]s?(x)"
+ // ],
+
+ // An array of regexp pattern strings that are matched against all test paths, matched tests are skipped
+ // testPathIgnorePatterns: [
+ // "/node_modules/"
+ // ],
+
+ // The regexp pattern or array of patterns that Jest uses to detect test files
+ testRegex: ['/src/.*\\.test.(ts|tsx)$'],
+
+ // This option allows the use of a custom results processor
+ // testResultsProcessor: undefined,
+
+ // This option allows use of a custom test runner
+ // testRunner: "jasmine2",
+
+ // This option sets the URL for the jsdom environment. It is reflected in properties such as location.href
+ // testURL: "http://localhost",
+
+ // Setting this value to "fake" allows the use of fake timers for functions such as "setTimeout"
+ // timers: "real",
+
+ // A map from regular expressions to paths to transformers
+ transform: {
+ '\\.[jt]sx?$': 'babel-jest',
+ },
+
+ // An array of regexp pattern strings that are matched against all source file paths, matched files will skip transformation
+ transformIgnorePatterns: ['/node_modules/'],
+
+ // An array of regexp pattern strings that are matched against all modules before the module loader will automatically return a mock for them
+ // unmockedModulePathPatterns: undefined,
+
+ // Indicates whether each individual test should be reported during the run
+ // verbose: undefined,
+
+ // An array of regexp patterns that are matched against all source file paths before re-running tests in watch mode
+ // watchPathIgnorePatterns: [],
+
+ // Whether to use watchman for file crawling
+ // watchman: true,
+};
diff --git a/frontend/openapi-config.ts b/frontend/openapi-config.ts
new file mode 100644
index 0000000000..258a49c086
--- /dev/null
+++ b/frontend/openapi-config.ts
@@ -0,0 +1,30 @@
+import { intersectionWith } from 'lodash';
+import type { ConfigFile } from '@rtk-query/codegen-openapi';
+
+import type { OperationDefinition } from '@rtk-query/codegen-openapi/src/types';
+
+const filterEndpoint =
+ (tags: string[]) =>
+ (_, { operation }: OperationDefinition) => {
+ const test = (a: string, b: string) => a.toLowerCase().includes(b.toLowerCase());
+
+ return Boolean(intersectionWith(operation.tags as string[], tags, test).length);
+ };
+
+const FILES = {
+ './src/api-services/userPayments.ts': {
+ filterEndpoints: filterEndpoint(['user_payments']),
+ exportName: 'userPayments',
+ },
+};
+
+const config: ConfigFile = {
+ schemaFile: 'http://127.0.0.1:8000/openapi.json',
+ apiFile: './src/services/mainApi.ts',
+ apiImport: 'mainApi',
+ outputFiles: FILES,
+ hooks: true,
+ tag: true,
+};
+
+export default config;
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
new file mode 100644
index 0000000000..e76e6e8b13
--- /dev/null
+++ b/frontend/package-lock.json
@@ -0,0 +1,25177 @@
+{
+ "name": "dstackai",
+ "version": "2.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "dstackai",
+ "version": "2.0.0",
+ "license": "Apache 2.0",
+ "dependencies": {
+ "@cloudscape-design/chat-components": "^1.0.62",
+ "@cloudscape-design/collection-hooks": "^1.0.74",
+ "@cloudscape-design/component-toolkit": "^1.0.0-beta.120",
+ "@cloudscape-design/components": "^3.0.1188",
+ "@cloudscape-design/design-tokens": "^3.0.60",
+ "@cloudscape-design/global-styles": "^1.0.45",
+ "@hookform/resolvers": "^2.9.10",
+ "@reduxjs/toolkit": "^1.9.1",
+ "@types/yup": "^0.29.14",
+ "ace-builds": "^1.36.3",
+ "classnames": "^2.5.1",
+ "css-minimizer-webpack-plugin": "^4.2.2",
+ "date-fns": "^2.29.3",
+ "i18next": "^24.0.2",
+ "js-yaml": "^4.1.0",
+ "lodash": "^4.17.21",
+ "openai": "^4.33.1",
+ "prismjs": "^1.30.0",
+ "rc-tooltip": "^5.2.2",
+ "react": "^18.3.1",
+ "react-avatar": "^5.0.3",
+ "react-bus": "^4.0.1",
+ "react-dom": "^18.3.1",
+ "react-helmet": "^6.1.0",
+ "react-hook-form": "^7.53.0",
+ "react-i18next": "^12.1.4",
+ "react-redux": "^8.0.5",
+ "react-router-dom": "^6.27.0",
+ "react-string-replace": "^1.1.1",
+ "redux": "^5.0.1",
+ "yup": "^0.32.11"
+ },
+ "devDependencies": {
+ "@babel/cli": "^7.25.9",
+ "@babel/core": "^7.26.0",
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
+ "@babel/plugin-transform-runtime": "^7.25.9",
+ "@babel/preset-env": "^7.26.0",
+ "@babel/preset-react": "^7.25.9",
+ "@babel/preset-typescript": "^7.26.0",
+ "@babel/register": "^7.25.9",
+ "@cfaester/enzyme-adapter-react-18": "^0.8.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "^9.28.0",
+ "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
+ "@rtk-query/codegen-openapi": "^2.0.0",
+ "@svgr/webpack": "^6.5.1",
+ "@testing-library/jest-dom": "^6.6.3",
+ "@testing-library/react": "^16.0.1",
+ "@testing-library/user-event": "^14.5.2",
+ "@types/axios": "^0.14.0",
+ "@types/date-fns": "^2.6.0",
+ "@types/enzyme": "^3.10.18",
+ "@types/jest": "^29.5.14",
+ "@types/js-yaml": "^4.0.9",
+ "@types/lodash": "^4.17.13",
+ "@types/node": "^22.10.1",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@types/react-helmet": "^6.1.11",
+ "@types/react-redux": "^7.1.34",
+ "@types/react-router-dom": "^5.3.3",
+ "@types/react-test-renderer": "^18.3.0",
+ "@typescript-eslint/eslint-plugin": "^8.33.1",
+ "@typescript-eslint/parser": "^8.33.1",
+ "@webpack-cli/serve": "^2.0.5",
+ "babel-loader": "^9.2.1",
+ "babel-preset-minify": "^0.5.2",
+ "circular-dependency-plugin": "^5.2.2",
+ "copy-webpack-plugin": "^11.0.0",
+ "cross-env": "^7.0.3",
+ "css-loader": "^6.7.3",
+ "enzyme": "^3.11.0",
+ "eslint": "^9.39.2",
+ "eslint-config-prettier": "^10.1.5",
+ "eslint-plugin-i18n": "^2.4.0",
+ "eslint-plugin-prettier": "^5.4.1",
+ "eslint-plugin-react": "^7.37.5",
+ "eslint-plugin-simple-import-sort": "^12.1.1",
+ "favicons": "^7.2.0",
+ "favicons-webpack-plugin": "^6.0.1",
+ "file-loader": "^6.2.0",
+ "html-webpack-plugin": "^5.6.3",
+ "http-proxy-middleware": "^2.0.6",
+ "identity-obj-proxy": "^3.0.0",
+ "jest": "^29.7.0",
+ "jest-styled-components": "^7.2.0",
+ "lint-staged": "^16.1.2",
+ "loader-utils": "^3.3.1",
+ "mini-css-extract-plugin": "^2.9.2",
+ "npx": "^10.2.2",
+ "postcss": "^8.4.49",
+ "postcss-loader": "^7.0.2",
+ "postcss-preset-env": "7.8.3",
+ "prettier": "^3.5.3",
+ "react-dev-utils": "^12.0.1",
+ "react-refresh": "^0.14.2",
+ "react-test-renderer": "^18.3.1",
+ "resolve-url-loader": "^5.0.0",
+ "sass": "^1.81.0",
+ "sass-loader": "^16.0.3",
+ "style-loader": "^4.0.0",
+ "ts-jest": "^29.2.5",
+ "ts-node": "^10.9.2",
+ "typescript": "^5.7.2",
+ "webpack": "^5.96.1",
+ "webpack-cli": "^5.1.4",
+ "webpack-dev-server": "^5.1.0",
+ "webpack-merge": "^6.0.1",
+ "webpack-nano": "^1.1.1"
+ }
+ },
+ "node_modules/@adobe/css-tools": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/@adobe/css-tools/-/css-tools-4.4.0.tgz",
+ "integrity": "sha512-Ff9+ksdQQB3rMncgqDK78uLznstjyfIf2Arnh22pW8kBpLs6rpKDwgnZT46hin5Hl1WzazzK64DOrhSwYpS7bQ==",
+ "dev": true
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@apidevtools/json-schema-ref-parser": {
+ "version": "9.0.6",
+ "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-9.0.6.tgz",
+ "integrity": "sha512-M3YgsLjI0lZxvrpeGVk9Ap032W6TPQkH6pRAZz81Ac3WUNF79VQooAFnp8umjvVzUmD93NkogxEwbSce7qMsUg==",
+ "dev": true,
+ "dependencies": {
+ "@jsdevtools/ono": "^7.1.3",
+ "call-me-maybe": "^1.0.1",
+ "js-yaml": "^3.13.1"
+ }
+ },
+ "node_modules/@apidevtools/json-schema-ref-parser/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/@apidevtools/json-schema-ref-parser/node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@apidevtools/openapi-schemas": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/@apidevtools/openapi-schemas/-/openapi-schemas-2.1.0.tgz",
+ "integrity": "sha512-Zc1AlqrJlX3SlpupFGpiLi2EbteyP7fXmUOGup6/DnkRgjP9bgMM/ag+n91rsv0U1Gpz0H3VILA/o3bW7Ua6BQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@apidevtools/swagger-methods": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-methods/-/swagger-methods-3.0.2.tgz",
+ "integrity": "sha512-QAkD5kK2b1WfjDS/UQn/qQkbwF31uqRjPTrsCs5ZG9BQGAkjwvqGFjjPqAuzac/IYzpPtRzjCP1WrTuAIjMrXg==",
+ "dev": true
+ },
+ "node_modules/@apidevtools/swagger-parser": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/@apidevtools/swagger-parser/-/swagger-parser-10.1.0.tgz",
+ "integrity": "sha512-9Kt7EuS/7WbMAUv2gSziqjvxwDbFSg3Xeyfuj5laUODX8o/k/CpsAKiQ8W7/R88eXFTMbJYg6+7uAmOWNKmwnw==",
+ "dev": true,
+ "dependencies": {
+ "@apidevtools/json-schema-ref-parser": "9.0.6",
+ "@apidevtools/openapi-schemas": "^2.1.0",
+ "@apidevtools/swagger-methods": "^3.0.2",
+ "@jsdevtools/ono": "^7.1.3",
+ "ajv": "^8.6.3",
+ "ajv-draft-04": "^1.0.0",
+ "call-me-maybe": "^1.0.1"
+ },
+ "peerDependencies": {
+ "openapi-types": ">=7"
+ }
+ },
+ "node_modules/@babel/cli": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/cli/-/cli-7.25.9.tgz",
+ "integrity": "sha512-I+02IfrTiSanpxJBlZQYb18qCxB6c2Ih371cVpfgIrPQrjAYkf45XxomTJOG8JBWX5GY35/+TmhCMdJ4ZPkL8Q==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "commander": "^6.2.0",
+ "convert-source-map": "^2.0.0",
+ "fs-readdir-recursive": "^1.1.0",
+ "glob": "^7.2.0",
+ "make-dir": "^2.1.0",
+ "slash": "^2.0.0"
+ },
+ "bin": {
+ "babel": "bin/babel.js",
+ "babel-external-helpers": "bin/babel-external-helpers.js"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "optionalDependencies": {
+ "@nicolo-ribaudo/chokidar-2": "2.1.8-no-fsevents.3",
+ "chokidar": "^3.6.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.28.6.tgz",
+ "integrity": "sha512-JYgintcMjRiCvS8mMECzaEn+m3PfoQiyqukOMCCVQtoJGYJw8j/8LBJEiqkHLkfwCcs74E3pbAUFNg7d9VNJ+Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.0.tgz",
+ "integrity": "sha512-qETICbZSLe7uXv9VE8T/RWOdIE5qqyTucOt4zLYMafj2MRO271VGgLd4RACJMeBO37UPWhXiKMBk7YlJ0fOzQA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz",
+ "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.0",
+ "@babel/generator": "^7.26.0",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.0",
+ "@babel/parser": "^7.26.0",
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.26.0",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.0.tgz",
+ "integrity": "sha512-/AIkAmInnWwgEAJGQr9vY0c66Mj6kjkE2ZPB1PurTRaRAh3U+J45sAQMjQDJdh4WbR3l0x5xkimXBKyBXXAu2w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.26.0",
+ "@babel/types": "^7.26.0",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.25.9.tgz",
+ "integrity": "sha512-gv7320KBUFJz1RnylIg5WWYPRXKZ884AGkYpgpWW02TH66Dl+HaC1t1CKd0z3R4b6hdYEcmrNZHUmfCP+1u3/g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.25.9.tgz",
+ "integrity": "sha512-C47lC7LIDCnz0h4vai/tpNOI95tCd5ZT3iBt/DBH5lXKHZsyNQv18yf1wIIg2ntiQNgmAvA+DgZ82iW8Qdym8g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz",
+ "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-create-class-features-plugin": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.25.9.tgz",
+ "integrity": "sha512-UTZQMvt0d/rSz6KI+qdu7GQze5TIajwTS++GUozlw8VBJDEOAqSXwm1WvmYEZwqdqSGQshRocPDqrt4HBZB3fQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-create-regexp-features-plugin": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.25.9.tgz",
+ "integrity": "sha512-ORPNZ3h6ZRkOyAa/SaHU+XsLZr0UQzRwuDQ0cczIA17nAzZ+85G5cVkOJIj7QavLZGSe8QXUmNFxSZzjcZF9bw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "regexpu-core": "^6.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-define-polyfill-provider": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.2.tgz",
+ "integrity": "sha512-LV76g+C502biUK6AyZ3LK10vDpDyCzZnhZFXkH1L75zHPj68+qc8Zfpx2th+gzwA2MzyK+1g/3EPl62yFnVttQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.22.6",
+ "@babel/helper-plugin-utils": "^7.22.5",
+ "debug": "^4.1.1",
+ "lodash.debounce": "^4.0.8",
+ "resolve": "^1.14.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/@babel/helper-member-expression-to-functions": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.25.9.tgz",
+ "integrity": "sha512-wbfdZ9w5vk0C0oyHqAJbc62+vet5prjj01jjJ8sKn3j9h3MQQlflEdXYvuqRWjHnM12coDEqiC1IRCi0U/EKwQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
+ "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-optimise-call-expression": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.25.9.tgz",
+ "integrity": "sha512-FIpuNaz5ow8VyrYcnXQTDRGvV6tTjkNtCK/RYNDXGSLlUD6cBuQTSw43CShGxjvfBTfcUA/r6UhUCbtYqkhcuQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz",
+ "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-remap-async-to-generator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.25.9.tgz",
+ "integrity": "sha512-IZtukuUeBbhgOcaW2s06OXTzVNJR0ybm4W5xC1opWFFJMZbwRj5LCk+ByYH7WdZPZTt8KnFwA8pvjN2yqcPlgw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-wrap-function": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-replace-supers": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.25.9.tgz",
+ "integrity": "sha512-IiDqTOTBQy0sWyeXyGSC5TBJpGFXBkRynjBeXsvbhQFKj2viwJC76Epz35YLU1fpe/Am6Vppb7W7zM4fPQzLsQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-member-expression-to-functions": "^7.25.9",
+ "@babel/helper-optimise-call-expression": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-simple-access": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.25.9.tgz",
+ "integrity": "sha512-c6WHXuiaRsJTyHYLJV75t9IqsmTbItYfdj99PnzYGQZkYKvan5/2jKJ7gu31J3/BJ/A18grImSPModuyG/Eo0Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-skip-transparent-expression-wrappers": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.25.9.tgz",
+ "integrity": "sha512-K4Du3BFa3gvyhzgPcntrkDgZzQaq6uozzcpGbOO1OEJaI+EJdqWIMTLgFgQf6lrfiDFo5FU+BxKepI9RmZqahA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+ "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-wrap-function": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.25.9.tgz",
+ "integrity": "sha512-ETzz9UTjQSTmw39GboatdymDq4XIQbR8ySgVrylRhPOFpsd+JrKHIuF0de7GCWmem+T4uC5z7EZguod7Wj4A4g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.28.6.tgz",
+ "integrity": "sha512-xOBvwq86HHdB7WUDTfKfT/Vuxh7gElQ+Sfti2Cy6yIWNW05P8iUslOVcZ4/sKbE+/jQaukQAdz/gf3724kYdqw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.28.6.tgz",
+ "integrity": "sha512-TeR9zWR18BvbfPmGbLampPMW+uW1NZnJlRuuHso8i87QZNq2JRF9i6RgxRqtEq+wQGsS19NNTWr2duhnE49mfQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/types": "^7.28.6"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.25.9.tgz",
+ "integrity": "sha512-ZkRyVkThtxQ/J6nv3JFYv1RYY+JT5BvU0y3k5bWrmuG4woXypRa4PXmm9RhOwodRkYFWqC0C0cqcJ4OqR7kW+g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.25.9.tgz",
+ "integrity": "sha512-MrGRLZxLD/Zjj0gdU15dfs+HH/OXvnw/U4jJD8vpcP2CJQapPEv1IWwjc/qMg7ItBlPwSv1hRBbb7LeuANdcnw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.25.9.tgz",
+ "integrity": "sha512-2qUwwfAFpJLZqxd02YW9btUCZHl+RFvdDkNfZwaIJrvB8Tesjsk8pEQkTvGwZXLqXUx/2oyY3ySRhm6HOXuCug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.25.9.tgz",
+ "integrity": "sha512-6xWgLZTJXwilVjlnV7ospI3xi+sl8lN8rXXbBD6vYn3UYDlGsag8wrZkKcSI8G6KgqKP7vNFaDgeDnfAABq61g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/plugin-transform-optional-chaining": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.13.0"
+ }
+ },
+ "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.25.9.tgz",
+ "integrity": "sha512-aLnMXYPnzwwqhYSCyXfKkIkYgJ8zv9RK+roo9DkTXz38ynIhd9XCbN08s3MGvqL2MYGVUGdRQLL/JqBIeJhJBg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-class-properties": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz",
+ "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==",
+ "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.21.0-placeholder-for-preset-env.2",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
+ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-async-generators": {
+ "version": "7.8.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
+ "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-bigint": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
+ "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-properties": {
+ "version": "7.12.13",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
+ "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.12.13"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-class-static-block": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
+ "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-assertions": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.26.0.tgz",
+ "integrity": "sha512-QCWT5Hh830hK5EQa7XzuqIkQU9tT/whqbDz7kuaZMHFl1inRRg7JnuAEOQ0Ur0QUl0NufCk1msK2BeY79Aj/eg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.26.0.tgz",
+ "integrity": "sha512-e2dttdsJ1ZTpi3B9UYGLw41hifAubg19AtCu/2I/F1QNVclOBr1dYpTdmdyZ84Xiz43BS/tCUkMAZNLv12Pi+A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-import-meta": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
+ "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-json-strings": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
+ "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.25.9.tgz",
+ "integrity": "sha512-ld6oezHQMZsZfp6pWtbjaNDF2tiiCYYDqQszHt5VV437lewP9aSi2Of99CK0D0XB21k7FLgnLcmQKyKzynfeAA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
+ "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
+ "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-numeric-separator": {
+ "version": "7.10.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
+ "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.10.4"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-object-rest-spread": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
+ "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-catch-binding": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
+ "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-optional-chaining": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
+ "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.8.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-private-property-in-object": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
+ "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-top-level-await": {
+ "version": "7.14.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
+ "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.14.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-typescript": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-typescript/-/plugin-syntax-typescript-7.25.9.tgz",
+ "integrity": "sha512-hjMgRy5hb8uJJjUcdWunWVcoi9bGpJp8p5Ol1229PoN6aytsLwNMgmdftO23wnCLMfVmTwZDWMPNq/D1SY60JQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
+ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-arrow-functions": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.25.9.tgz",
+ "integrity": "sha512-6jmooXYIwn9ca5/RylZADJ+EnSxVUS5sjeJ9UPk6RWRzXCmOJCy6dqItPJFpw2cuCangPK4OYr5uhGKcmrm5Qg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-generator-functions": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.25.9.tgz",
+ "integrity": "sha512-RXV6QAzTBbhDMO9fWwOmwwTuYaiPbggWQ9INdZqAYeSHyG7FzQ+nOZaUUjNwKv9pV3aE4WFqFm1Hnbci5tBCAw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-remap-async-to-generator": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.25.9.tgz",
+ "integrity": "sha512-NT7Ejn7Z/LjUH0Gv5KsBCxh7BH3fbLTV0ptHvpeMvrt3cPThHfJfst9Wrb7S8EvJ7vRTFI7z+VAvFVEQn/m5zQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-remap-async-to-generator": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.25.9.tgz",
+ "integrity": "sha512-toHc9fzab0ZfenFpsyYinOX0J/5dgJVA2fm64xPewu7CoYHWEivIWKxkK2rMi4r3yQqLnVmheMXRdG+k239CgA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.25.9.tgz",
+ "integrity": "sha512-1F05O7AYjymAtqbsFETboN1NvBdcnzMerO+zlMyJBEz6WkMdejvGWw9p05iTSjC85RLlBseHHQpYaM4gzJkBGg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-properties": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.25.9.tgz",
+ "integrity": "sha512-bbMAII8GRSkcd0h0b4X+36GksxuheLFjP65ul9w6C3KgAamI3JqErNgSrosX6ZPj+Mpim5VvEbawXxJCyEUV3Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-class-static-block": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.26.0.tgz",
+ "integrity": "sha512-6J2APTs7BDDm+UMqP1useWqhcRAXo0WIoVj26N7kPFB6S73Lgvyka4KTZYIxtgYXiN5HTyRObA72N2iu628iTQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-classes": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.25.9.tgz",
+ "integrity": "sha512-mD8APIXmseE7oZvZgGABDyM34GUmK45Um2TXiBUt7PnuAxrgoSVf123qUzPxEr/+/BHrRn5NMZCdE2m/1F8DGg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-computed-properties": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.25.9.tgz",
+ "integrity": "sha512-HnBegGqXZR12xbcTHlJ9HGxw1OniltT26J5YpfruGqtUHlz/xKf/G2ak9e+t0rVqrjXa9WOhvYPz1ERfMj23AA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/template": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.25.9.tgz",
+ "integrity": "sha512-WkCGb/3ZxXepmMiX101nnGiU+1CAdut8oHyEOHxkKuS1qKpU2SMXE2uSvfz8PBuLd49V6LEsbtyPhWC7fnkgvQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dotall-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.25.9.tgz",
+ "integrity": "sha512-t7ZQ7g5trIgSRYhI9pIJtRl64KHotutUJsh4Eze5l7olJv+mRSg4/MmbZ0tv1eeqRbdvo/+trvJD/Oc5DmW2cA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-duplicate-keys": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.25.9.tgz",
+ "integrity": "sha512-LZxhJ6dvBb/f3x8xwWIuyiAHy56nrRG3PeYTpBkkzkYRRQ6tJLu68lEF5VIqMUZiAV7a8+Tb78nEoMCMcqjXBw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.25.9.tgz",
+ "integrity": "sha512-0UfuJS0EsXbRvKnwcLjFtJy/Sxc5J5jhLHnFhy7u4zih97Hz6tJkLU+O+FMMrNZrosUPxDi6sYxJ/EA8jDiAog==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-dynamic-import": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.25.9.tgz",
+ "integrity": "sha512-GCggjexbmSLaFhqsojeugBpeaRIgWNTcgKVq/0qIteFEqY2A+b9QidYadrWlnbWQUrW5fn+mCvf3tr7OeBFTyg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.25.9.tgz",
+ "integrity": "sha512-KRhdhlVk2nObA5AYa7QMgTMTVJdfHprfpAk4DjZVtllqRg9qarilstTKEhpVjyt+Npi8ThRyiV8176Am3CodPA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-builder-binary-assignment-operator-visitor": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-export-namespace-from": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.25.9.tgz",
+ "integrity": "sha512-2NsEz+CxzJIVOPx2o9UsW1rXLqtChtLoVnwYHHiB04wS5sgn7mrV45fWMBX0Kk+ub9uXytVYfNP2HjbVbCB3Ww==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-for-of": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.25.9.tgz",
+ "integrity": "sha512-LqHxduHoaGELJl2uhImHwRQudhCM50pT46rIBNvtT/Oql3nqiS3wOwP+5ten7NpYSXrrVLgtZU3DZmPtWZo16A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-function-name": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.25.9.tgz",
+ "integrity": "sha512-8lP+Yxjv14Vc5MuWBpJsoUCd3hD6V9DgBon2FVYL4jJgbnVQ9fTgYmonchzZJOVNgzEgbxp4OwAf6xz6M/14XA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-json-strings": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.25.9.tgz",
+ "integrity": "sha512-xoTMk0WXceiiIvsaquQQUaLLXSW1KJ159KP87VilruQm0LNNGxWzahxSS6T6i4Zg3ezp4vA4zuwiNUR53qmQAw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-literals": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.25.9.tgz",
+ "integrity": "sha512-9N7+2lFziW8W9pBl2TzaNht3+pgMIRP74zizeCSrtnSKVdUl8mAjjOP2OOVQAfZ881P2cNjDj1uAMEdeD50nuQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-logical-assignment-operators": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.25.9.tgz",
+ "integrity": "sha512-wI4wRAzGko551Y8eVf6iOY9EouIDTtPb0ByZx+ktDGHwv6bHFimrgJM/2T021txPZ2s4c7bqvHbd+vXG6K948Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-member-expression-literals": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.25.9.tgz",
+ "integrity": "sha512-PYazBVfofCQkkMzh2P6IdIUaCEWni3iYEerAsRWuVd8+jlM1S9S9cz1dF9hIzyoZ8IA3+OwVYIp9v9e+GbgZhA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.25.9.tgz",
+ "integrity": "sha512-g5T11tnI36jVClQlMlt4qKDLlWnG5pP9CSM4GhdRciTNMRgkfpo5cR6b4rGIOYPgRRuFAvwjPQ/Yk+ql4dyhbw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.25.9.tgz",
+ "integrity": "sha512-dwh2Ol1jWwL2MgkCzUSOvfmKElqQcuswAZypBSUsScMXvgdT8Ekq5YA6TtqpTVWH+4903NmboMuH1o9i8Rxlyg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-simple-access": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.25.9.tgz",
+ "integrity": "sha512-hyss7iIlH/zLHaehT+xwiymtPOpsiwIIRlCAOwBB04ta5Tt+lNItADdlXw3jAWZ96VJ2jlhl/c+PNIQPKNfvcA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-modules-umd": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.25.9.tgz",
+ "integrity": "sha512-bS9MVObUgE7ww36HEfwe6g9WakQ0KF07mQF74uuXdkoziUPfKyu/nIm663kz//e5O1nPInPFx36z7WJmJ4yNEw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-transforms": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.25.9.tgz",
+ "integrity": "sha512-oqB6WHdKTGl3q/ItQhpLSnWWOpjUJLsOCLVyeFgeTktkBSCiurvPOsyt93gibI9CmuKvTUEtWmG5VhZD+5T/KA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-new-target": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.25.9.tgz",
+ "integrity": "sha512-U/3p8X1yCSoKyUj2eOBIx3FOn6pElFOKvAAGf8HTtItuPyB+ZeOqfn+mvTtg9ZlOAjsPdK3ayQEjqHjU/yLeVQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.25.9.tgz",
+ "integrity": "sha512-ENfftpLZw5EItALAD4WsY/KUWvhUlZndm5GC7G3evUsVeSJB6p0pBeLQUnRnBCBx7zV0RKQjR9kCuwrsIrjWog==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-numeric-separator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.25.9.tgz",
+ "integrity": "sha512-TlprrJ1GBZ3r6s96Yq8gEQv82s8/5HnCVHtEJScUj90thHQbwe+E5MLhi2bbNHBEJuzrvltXSru+BUxHDoog7Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-rest-spread": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.25.9.tgz",
+ "integrity": "sha512-fSaXafEE9CVHPweLYw4J0emp1t8zYTXyzN3UuG+lylqkvYd7RMrsOQ8TYx5RF231be0vqtFC6jnx3UmpJmKBYg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-transform-parameters": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-object-super": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.25.9.tgz",
+ "integrity": "sha512-Kj/Gh+Rw2RNLbCK1VAWj2U48yxxqL2x0k10nPtSdRa0O2xnHXalD0s+o1A6a0W43gJ00ANo38jxkQreckOzv5A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-replace-supers": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-catch-binding": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.25.9.tgz",
+ "integrity": "sha512-qM/6m6hQZzDcZF3onzIhZeDHDO43bkNNlOX0i8n3lR6zLbu0GN2d8qfM/IERJZYauhAHSLHy39NF0Ctdvcid7g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-optional-chaining": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.25.9.tgz",
+ "integrity": "sha512-6AvV0FsLULbpnXeBjrY4dmWF8F7gf8QnvTEoO/wX/5xm/xE1Xo8oPuD3MPS+KS9f9XBEAWN7X1aWr4z9HdOr7A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.25.9.tgz",
+ "integrity": "sha512-wzz6MKwpnshBAiRmn4jR8LYz/g8Ksg0o80XmwZDlordjwEk9SxBzTWC7F5ef1jhbrbOW2DJ5J6ayRukrJmnr0g==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-methods": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.25.9.tgz",
+ "integrity": "sha512-D/JUozNpQLAPUVusvqMxyvjzllRaF8/nSrP1s2YGQT/W4LHK4xxsMcHjhOGTS01mp9Hda8nswb+FblLdJornQw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-private-property-in-object": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.25.9.tgz",
+ "integrity": "sha512-Evf3kcMqzXA3xfYJmZ9Pg1OvKdtqsDMSWBDzZOPLvHiTt36E75jLDQo5w1gtRU95Q4E5PDttrTf25Fw8d/uWLw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-property-literals": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.25.9.tgz",
+ "integrity": "sha512-IvIUeV5KrS/VPavfSM/Iu+RE6llrHrYIKY1yfCzyO/lMXHQ+p7uGhonmGVisv6tSBSVgWzMBohTcvkC9vQcQFA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-constant-elements": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-constant-elements/-/plugin-transform-react-constant-elements-7.25.9.tgz",
+ "integrity": "sha512-Ncw2JFsJVuvfRsa2lSHiC55kETQVLSnsYGQ1JDDwkUeWGTL/8Tom8aLTnlqgoeuopWrbbGndrc9AlLYrIosrow==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-display-name": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-display-name/-/plugin-transform-react-display-name-7.25.9.tgz",
+ "integrity": "sha512-KJfMlYIUxQB1CJfO3e0+h0ZHWOTLCPP115Awhaz8U0Zpq36Gl/cXlpoyMRnUWlhNUBAzldnCiAZNvCDj7CrKxQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx/-/plugin-transform-react-jsx-7.25.9.tgz",
+ "integrity": "sha512-s5XwpQYCqGerXl+Pu6VDL3x0j2d82eiV77UJ8a2mDHAW7j9SWRqQ2y1fNo1Z74CdcYipl5Z41zvjj4Nfzq36rw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/plugin-syntax-jsx": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-development": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-development/-/plugin-transform-react-jsx-development-7.25.9.tgz",
+ "integrity": "sha512-9mj6rm7XVYs4mdLIpbZnHOYdpW42uoiBCTVowg7sP1thUOiANgMb4UtpRivR0pp5iL+ocvUv7X4mZgFRpJEzGw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/plugin-transform-react-jsx": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-pure-annotations": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-pure-annotations/-/plugin-transform-react-pure-annotations-7.25.9.tgz",
+ "integrity": "sha512-KQ/Takk3T8Qzj5TppkS1be588lkbTp5uj7w6a0LeQaTMSckU/wK0oJ/pih+T690tkgI5jfmg2TqDJvd41Sj1Cg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.25.9.tgz",
+ "integrity": "sha512-vwDcDNsgMPDGP0nMqzahDWE5/MLcX8sv96+wfX7as7LoF/kr97Bo/7fI00lXY4wUXYfVmwIIyG80fGZ1uvt2qg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "regenerator-transform": "^0.15.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-regexp-modifiers": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.26.0.tgz",
+ "integrity": "sha512-vN6saax7lrA2yA/Pak3sCxuD6F5InBjn9IcrIKQPjpsLvuHYLVroTxjdlVRHjjBWxKOqIwpTXDkOssYT4BFdRw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-reserved-words": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.25.9.tgz",
+ "integrity": "sha512-7DL7DKYjn5Su++4RXu8puKZm2XBPHyjWLUidaPEkCUBbE7IPcsrkRHggAOOKydH1dASWdcUBxrkOGNxUv5P3Jg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-runtime": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.25.9.tgz",
+ "integrity": "sha512-nZp7GlEl+yULJrClz0SwHPqir3lc0zsPrDHQUcxGspSL7AKrexNSEfTbfqnDNJUO13bgKyfuOLMF8Xqtu8j3YQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "babel-plugin-polyfill-corejs2": "^0.4.10",
+ "babel-plugin-polyfill-corejs3": "^0.10.6",
+ "babel-plugin-polyfill-regenerator": "^0.6.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.25.9.tgz",
+ "integrity": "sha512-MUv6t0FhO5qHnS/W8XCbHmiRWOphNufpE1IVxhK5kuN3Td9FT1x4rx4K42s3RYdMXCXpfWkGSbCSd0Z64xA7Ng==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-spread": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.25.9.tgz",
+ "integrity": "sha512-oNknIB0TbURU5pqJFVbOOFspVlrpVwo2H1+HUIsVDvp5VauGGDP1ZEvO8Nn5xyMEs3dakajOxlmkNW7kNgSm6A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-sticky-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.25.9.tgz",
+ "integrity": "sha512-WqBUSgeVwucYDP9U/xNRQam7xV8W5Zf+6Eo7T2SRVUFlhRiMNFdFz58u0KZmCVVqs2i7SHgpRnAhzRNmKfi2uA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-template-literals": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.25.9.tgz",
+ "integrity": "sha512-o97AE4syN71M/lxrCtQByzphAdlYluKPDBzDVzMmfCobUjjhAryZV0AIpRPrxN0eAkxXO6ZLEScmt+PNhj2OTw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.25.9.tgz",
+ "integrity": "sha512-v61XqUMiueJROUv66BVIOi0Fv/CUuZuZMl5NkRoCVxLAnMexZ0A3kMe7vvZ0nulxMuMp0Mk6S5hNh48yki08ZA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-typescript": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typescript/-/plugin-transform-typescript-7.25.9.tgz",
+ "integrity": "sha512-7PbZQZP50tzv2KGGnhh82GSyMB01yKY9scIjf1a+GfZCtInOWqUH5+1EBU4t9fyR5Oykkkc9vFTs4OHrhHXljQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-annotate-as-pure": "^7.25.9",
+ "@babel/helper-create-class-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.25.9",
+ "@babel/plugin-syntax-typescript": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.25.9.tgz",
+ "integrity": "sha512-s5EDrE6bW97LtxOcGj1Khcx5AaXwiMmi4toFWRDP9/y0Woo6pXC+iyPu/KuhKtfSrNFd7jJB+/fkOtZy6aIC6Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-property-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.25.9.tgz",
+ "integrity": "sha512-Jt2d8Ga+QwRluxRQ307Vlxa6dMrYEMZCgGxoPR8V52rxPyldHu3hdlHspxaqYmE7oID5+kB+UKUB/eWS+DkkWg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.25.9.tgz",
+ "integrity": "sha512-yoxstj7Rg9dlNn9UQxzk4fcNivwv4nUYz7fYXBaKxvw/lnmPuOm/ikoELygbYq68Bls3D/D+NBPHiLwZdZZ4HA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-unicode-sets-regex": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.25.9.tgz",
+ "integrity": "sha512-8BYqO3GeVNHtx69fdPshN3fnzUNLrWdHhk/icSwigksJGczKSizZ+Z6SBCxTs723Fr5VSNorTIK7a+R2tISvwQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-create-regexp-features-plugin": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/preset-env": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.26.0.tgz",
+ "integrity": "sha512-H84Fxq0CQJNdPFT2DrfnylZ3cf5K43rGfWK4LJGPpjKHiZlk0/RzwEus3PDDZZg+/Er7lCA03MVacueUuXdzfw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.26.0",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.25.9",
+ "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.25.9",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.25.9",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.25.9",
+ "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.25.9",
+ "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
+ "@babel/plugin-syntax-import-assertions": "^7.26.0",
+ "@babel/plugin-syntax-import-attributes": "^7.26.0",
+ "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
+ "@babel/plugin-transform-arrow-functions": "^7.25.9",
+ "@babel/plugin-transform-async-generator-functions": "^7.25.9",
+ "@babel/plugin-transform-async-to-generator": "^7.25.9",
+ "@babel/plugin-transform-block-scoped-functions": "^7.25.9",
+ "@babel/plugin-transform-block-scoping": "^7.25.9",
+ "@babel/plugin-transform-class-properties": "^7.25.9",
+ "@babel/plugin-transform-class-static-block": "^7.26.0",
+ "@babel/plugin-transform-classes": "^7.25.9",
+ "@babel/plugin-transform-computed-properties": "^7.25.9",
+ "@babel/plugin-transform-destructuring": "^7.25.9",
+ "@babel/plugin-transform-dotall-regex": "^7.25.9",
+ "@babel/plugin-transform-duplicate-keys": "^7.25.9",
+ "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.25.9",
+ "@babel/plugin-transform-dynamic-import": "^7.25.9",
+ "@babel/plugin-transform-exponentiation-operator": "^7.25.9",
+ "@babel/plugin-transform-export-namespace-from": "^7.25.9",
+ "@babel/plugin-transform-for-of": "^7.25.9",
+ "@babel/plugin-transform-function-name": "^7.25.9",
+ "@babel/plugin-transform-json-strings": "^7.25.9",
+ "@babel/plugin-transform-literals": "^7.25.9",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.25.9",
+ "@babel/plugin-transform-member-expression-literals": "^7.25.9",
+ "@babel/plugin-transform-modules-amd": "^7.25.9",
+ "@babel/plugin-transform-modules-commonjs": "^7.25.9",
+ "@babel/plugin-transform-modules-systemjs": "^7.25.9",
+ "@babel/plugin-transform-modules-umd": "^7.25.9",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.25.9",
+ "@babel/plugin-transform-new-target": "^7.25.9",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.25.9",
+ "@babel/plugin-transform-numeric-separator": "^7.25.9",
+ "@babel/plugin-transform-object-rest-spread": "^7.25.9",
+ "@babel/plugin-transform-object-super": "^7.25.9",
+ "@babel/plugin-transform-optional-catch-binding": "^7.25.9",
+ "@babel/plugin-transform-optional-chaining": "^7.25.9",
+ "@babel/plugin-transform-parameters": "^7.25.9",
+ "@babel/plugin-transform-private-methods": "^7.25.9",
+ "@babel/plugin-transform-private-property-in-object": "^7.25.9",
+ "@babel/plugin-transform-property-literals": "^7.25.9",
+ "@babel/plugin-transform-regenerator": "^7.25.9",
+ "@babel/plugin-transform-regexp-modifiers": "^7.26.0",
+ "@babel/plugin-transform-reserved-words": "^7.25.9",
+ "@babel/plugin-transform-shorthand-properties": "^7.25.9",
+ "@babel/plugin-transform-spread": "^7.25.9",
+ "@babel/plugin-transform-sticky-regex": "^7.25.9",
+ "@babel/plugin-transform-template-literals": "^7.25.9",
+ "@babel/plugin-transform-typeof-symbol": "^7.25.9",
+ "@babel/plugin-transform-unicode-escapes": "^7.25.9",
+ "@babel/plugin-transform-unicode-property-regex": "^7.25.9",
+ "@babel/plugin-transform-unicode-regex": "^7.25.9",
+ "@babel/plugin-transform-unicode-sets-regex": "^7.25.9",
+ "@babel/preset-modules": "0.1.6-no-external-plugins",
+ "babel-plugin-polyfill-corejs2": "^0.4.10",
+ "babel-plugin-polyfill-corejs3": "^0.10.6",
+ "babel-plugin-polyfill-regenerator": "^0.6.1",
+ "core-js-compat": "^3.38.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-modules": {
+ "version": "0.1.6-no-external-plugins",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
+ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@babel/types": "^7.4.4",
+ "esutils": "^2.0.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/@babel/preset-react": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/preset-react/-/preset-react-7.25.9.tgz",
+ "integrity": "sha512-D3to0uSPiWE7rBrdIICCd0tJSIGpLaaGptna2+w7Pft5xMqLpA1sz99DK5TZ1TjGbdQ/VI1eCSZ06dv3lT4JOw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-transform-react-display-name": "^7.25.9",
+ "@babel/plugin-transform-react-jsx": "^7.25.9",
+ "@babel/plugin-transform-react-jsx-development": "^7.25.9",
+ "@babel/plugin-transform-react-pure-annotations": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/preset-typescript": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/preset-typescript/-/preset-typescript-7.26.0.tgz",
+ "integrity": "sha512-NMk1IGZ5I/oHhoXEElcm+xUnL/szL6xflkFZmoEU9xj1qSJXpiS7rsspYo92B4DRCDvZn2erT5LdsCeXAKNCkg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "@babel/plugin-syntax-jsx": "^7.25.9",
+ "@babel/plugin-transform-modules-commonjs": "^7.25.9",
+ "@babel/plugin-transform-typescript": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/register": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/register/-/register-7.25.9.tgz",
+ "integrity": "sha512-8D43jXtGsYmEeDvm4MWHYUpWf8iiXgWYx3fW7E7Wb7Oe6FWqJPl5K6TuFW0dOwNZzEE5rjlaSJYH9JjrUKJszA==",
+ "dev": true,
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "find-cache-dir": "^2.0.0",
+ "make-dir": "^2.1.0",
+ "pirates": "^4.0.6",
+ "source-map-support": "^0.5.16"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.6.tgz",
+ "integrity": "sha512-05WQkdpL9COIMz4LjTxGpPNCdlpyimKppYNoJ5Di5EUObifl8t4tuLuUBBZEpoLYOmfvIWrsp9fCl0HoPRVTdA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/template": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz",
+ "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.25.9",
+ "@babel/generator": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.25.9",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.28.6.tgz",
+ "integrity": "sha512-0ZrskXVEHSWIqZM/sQZ4EV3jZJXRkio/WCxaqKZP1g//CEWEPSfeZFcms4XeKBCHU0ZKnIkdJeU/kF+eRp5lBg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@bcoe/v8-coverage": {
+ "version": "0.2.3",
+ "resolved": "https://registry.npmjs.org/@bcoe/v8-coverage/-/v8-coverage-0.2.3.tgz",
+ "integrity": "sha512-0hYQ8SB4Db5zvZB4axdMHGwEaQjkZzFjQiN9LVYvIFB2nSUHW9tYpxWriPrWDASIxiaXax83REcLxuSdnGPZtw==",
+ "dev": true
+ },
+ "node_modules/@cfaester/enzyme-adapter-react-18": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@cfaester/enzyme-adapter-react-18/-/enzyme-adapter-react-18-0.8.0.tgz",
+ "integrity": "sha512-3Z3ThTUouHwz8oIyhTYQljEMNRFtlVyc3VOOHCbxs47U6cnXs8K9ygi/c1tv49s7MBlTXeIcuN+Ttd9aPtILFQ==",
+ "dev": true,
+ "dependencies": {
+ "enzyme-shallow-equal": "^1.0.0",
+ "function.prototype.name": "^1.1.6",
+ "has": "^1.0.4",
+ "react-is": "^18.2.0",
+ "react-shallow-renderer": "^16.15.0"
+ },
+ "peerDependencies": {
+ "enzyme": "^3.11.0",
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/@cloudscape-design/chat-components": {
+ "version": "1.0.62",
+ "resolved": "https://registry.npmjs.org/@cloudscape-design/chat-components/-/chat-components-1.0.62.tgz",
+ "integrity": "sha512-8Tqc5JqLmSMQe2nG0q1I7Q8m08kfuLJCFhTqgfYZDKu9g/HVP8d8Q42FPCcHesGWq1xM+S1wSioxJ5uhdzWE8A==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@cloudscape-design/component-toolkit": "^1.0.0-beta",
+ "@cloudscape-design/test-utils-core": "^1.0.0",
+ "clsx": "^1.2.1"
+ },
+ "peerDependencies": {
+ "@cloudscape-design/components": "^3",
+ "react": ">=18.2.0"
+ }
+ },
+ "node_modules/@cloudscape-design/collection-hooks": {
+ "version": "1.0.74",
+ "resolved": "https://registry.npmjs.org/@cloudscape-design/collection-hooks/-/collection-hooks-1.0.74.tgz",
+ "integrity": "sha512-yAcD7vjFqbwqMCamUcKRXp403u8RcmC9izyPEYiWod9elt7x0GT1ypPyo9ZRyQuFrBsv2nwubBUrChcYaWooZw==",
+ "license": "Apache-2.0",
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@cloudscape-design/component-toolkit": {
+ "version": "1.0.0-beta.120",
+ "resolved": "https://registry.npmjs.org/@cloudscape-design/component-toolkit/-/component-toolkit-1.0.0-beta.120.tgz",
+ "integrity": "sha512-QQfquFjubZvDpJ+Tlt3UHI3KWGvMhwoksY6tG7E41qOrS9y+YbDJuJyiqaCbm5S2PzZ33JBL0bWsXrJesZu6tA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@juggle/resize-observer": "^3.3.1",
+ "tslib": "^2.3.1"
+ }
+ },
+ "node_modules/@cloudscape-design/components": {
+ "version": "3.0.1188",
+ "resolved": "https://registry.npmjs.org/@cloudscape-design/components/-/components-3.0.1188.tgz",
+ "integrity": "sha512-Ajk7wFr2boPO7v4pgBLjdLVcA7myBiCk5hzpzURGcg+oogX9lYtXHv80k60dqyn1kzx+J0xnZwEjLa0oRmflmA==",
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@cloudscape-design/collection-hooks": "^1.0.0",
+ "@cloudscape-design/component-toolkit": "^1.0.0-beta",
+ "@cloudscape-design/test-utils-core": "^1.0.0",
+ "@cloudscape-design/theming-runtime": "^1.0.0",
+ "@dnd-kit/core": "^6.0.8",
+ "@dnd-kit/sortable": "^7.0.2",
+ "@dnd-kit/utilities": "^3.2.1",
+ "ace-builds": "^1.34.0",
+ "clsx": "^1.1.0",
+ "d3-shape": "^1.3.7",
+ "date-fns": "^2.25.0",
+ "intl-messageformat": "^10.3.1",
+ "mnth": "^2.0.0",
+ "react-keyed-flatten-children": "^2.2.1",
+ "react-transition-group": "^4.4.2",
+ "tslib": "^2.4.0",
+ "weekstart": "^1.1.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@cloudscape-design/design-tokens": {
+ "version": "3.0.60",
+ "resolved": "https://registry.npmjs.org/@cloudscape-design/design-tokens/-/design-tokens-3.0.60.tgz",
+ "integrity": "sha512-ybj8FfjdhuHZflVDA//ooHJdwc+vny9MESvB95AJpVDhf6PXoaOpWAObn4hkMC770Wk/YwXtKXbx7rjJJQr6ZA==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@cloudscape-design/global-styles": {
+ "version": "1.0.45",
+ "resolved": "https://registry.npmjs.org/@cloudscape-design/global-styles/-/global-styles-1.0.45.tgz",
+ "integrity": "sha512-fSrbVpK9W+bg8tmUYqU9Wh2JGciUCGEByVUQDbgMY6feXtYEUKRP2MBL6kEHvoJB7lssZbHdh5/gYaiyxg+P5w==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/@cloudscape-design/test-utils-core": {
+ "version": "1.0.44",
+ "resolved": "https://registry.npmjs.org/@cloudscape-design/test-utils-core/-/test-utils-core-1.0.44.tgz",
+ "integrity": "sha512-2nGG763Nsbac03ct4KfqH+ec/0UVrs/sjILQTInAPg9em3E9W1IPbF4nV0MBKUd1irgxwKmmbBiZNFfTFjpiqA==",
+ "dependencies": {
+ "css-selector-tokenizer": "^0.8.0",
+ "css.escape": "^1.5.1"
+ }
+ },
+ "node_modules/@cloudscape-design/theming-runtime": {
+ "version": "1.0.63",
+ "resolved": "https://registry.npmjs.org/@cloudscape-design/theming-runtime/-/theming-runtime-1.0.63.tgz",
+ "integrity": "sha512-PDiNTdnLCDGHTWwNOQkyF/o5OJEScDLglsIY01qNA4NesiVzK9AtSJBlPTgZFWH5Bjp6ukkxdRuX/Ak+28GGLw==",
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@cspotcode/source-map-support/-/source-map-support-0.8.1.tgz",
+ "integrity": "sha512-IchNf6dN4tHoMFIn/7OE8LWZ19Y6q/67Bmf6vnGREv8RSbBVb9LPJxEcnwrcwX6ixSvaiGoomAUvu4YSxXrVgw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "0.3.9"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@cspotcode/source-map-support/node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.9.tgz",
+ "integrity": "sha512-3Belt6tdc8bPgAtbcmdtNJlirVoTmEb5e2gC94PnkwEW9jI6CAHUeoG85tjWP5WquqfavoMtMwiG4P926ZKKuQ==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.0.3",
+ "@jridgewell/sourcemap-codec": "^1.4.10"
+ }
+ },
+ "node_modules/@csstools/postcss-cascade-layers": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-cascade-layers/-/postcss-cascade-layers-1.1.1.tgz",
+ "integrity": "sha512-+KdYrpKC5TgomQr2DlZF4lDEpHcoxnj5IGddYYfBWJAKfj1JtuHUIqMa+E1pJJ+z3kvDViWMqyqPlG4Ja7amQA==",
+ "dev": true,
+ "dependencies": {
+ "@csstools/selector-specificity": "^2.0.2",
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-color-function": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-color-function/-/postcss-color-function-1.1.1.tgz",
+ "integrity": "sha512-Bc0f62WmHdtRDjf5f3e2STwRAl89N2CLb+9iAwzrv4L2hncrbDwnQD9PCq0gtAt7pOI2leIV08HIBUd4jxD8cw==",
+ "dev": true,
+ "dependencies": {
+ "@csstools/postcss-progressive-custom-properties": "^1.1.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-font-format-keywords": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-font-format-keywords/-/postcss-font-format-keywords-1.0.1.tgz",
+ "integrity": "sha512-ZgrlzuUAjXIOc2JueK0X5sZDjCtgimVp/O5CEqTcs5ShWBa6smhWYbS0x5cVc/+rycTDbjjzoP0KTDnUneZGOg==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-hwb-function": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-hwb-function/-/postcss-hwb-function-1.0.2.tgz",
+ "integrity": "sha512-YHdEru4o3Rsbjmu6vHy4UKOXZD+Rn2zmkAmLRfPet6+Jz4Ojw8cbWxe1n42VaXQhD3CQUXXTooIy8OkVbUcL+w==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-ic-unit": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-ic-unit/-/postcss-ic-unit-1.0.1.tgz",
+ "integrity": "sha512-Ot1rcwRAaRHNKC9tAqoqNZhjdYBzKk1POgWfhN4uCOE47ebGcLRqXjKkApVDpjifL6u2/55ekkpnFcp+s/OZUw==",
+ "dev": true,
+ "dependencies": {
+ "@csstools/postcss-progressive-custom-properties": "^1.1.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-is-pseudo-class": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-is-pseudo-class/-/postcss-is-pseudo-class-2.0.7.tgz",
+ "integrity": "sha512-7JPeVVZHd+jxYdULl87lvjgvWldYu+Bc62s9vD/ED6/QTGjy0jy0US/f6BG53sVMTBJ1lzKZFpYmofBN9eaRiA==",
+ "dev": true,
+ "dependencies": {
+ "@csstools/selector-specificity": "^2.0.0",
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-nested-calc": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-nested-calc/-/postcss-nested-calc-1.0.0.tgz",
+ "integrity": "sha512-JCsQsw1wjYwv1bJmgjKSoZNvf7R6+wuHDAbi5f/7MbFhl2d/+v+TvBTU4BJH3G1X1H87dHl0mh6TfYogbT/dJQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-normalize-display-values": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-normalize-display-values/-/postcss-normalize-display-values-1.0.1.tgz",
+ "integrity": "sha512-jcOanIbv55OFKQ3sYeFD/T0Ti7AMXc9nM1hZWu8m/2722gOTxFg7xYu4RDLJLeZmPUVQlGzo4jhzvTUq3x4ZUw==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-oklab-function": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-oklab-function/-/postcss-oklab-function-1.1.1.tgz",
+ "integrity": "sha512-nJpJgsdA3dA9y5pgyb/UfEzE7W5Ka7u0CX0/HIMVBNWzWemdcTH3XwANECU6anWv/ao4vVNLTMxhiPNZsTK6iA==",
+ "dev": true,
+ "dependencies": {
+ "@csstools/postcss-progressive-custom-properties": "^1.1.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-progressive-custom-properties": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-progressive-custom-properties/-/postcss-progressive-custom-properties-1.3.0.tgz",
+ "integrity": "sha512-ASA9W1aIy5ygskZYuWams4BzafD12ULvSypmaLJT2jvQ8G0M3I8PRQhC0h7mG0Z3LI05+agZjqSR9+K9yaQQjA==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.3"
+ }
+ },
+ "node_modules/@csstools/postcss-stepped-value-functions": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-stepped-value-functions/-/postcss-stepped-value-functions-1.0.1.tgz",
+ "integrity": "sha512-dz0LNoo3ijpTOQqEJLY8nyaapl6umbmDcgj4AD0lgVQ572b2eqA1iGZYTTWhrcrHztWDDRAX2DGYyw2VBjvCvQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-text-decoration-shorthand": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-text-decoration-shorthand/-/postcss-text-decoration-shorthand-1.0.0.tgz",
+ "integrity": "sha512-c1XwKJ2eMIWrzQenN0XbcfzckOLLJiczqy+YvfGmzoVXd7pT9FfObiSEfzs84bpE/VqfpEuAZ9tCRbZkZxxbdw==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-trigonometric-functions": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-trigonometric-functions/-/postcss-trigonometric-functions-1.0.2.tgz",
+ "integrity": "sha512-woKaLO///4bb+zZC2s80l+7cm07M7268MsyG3M0ActXXEFi6SuhvriQYcb58iiKGbjwwIU7n45iRLEHypB47Og==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/postcss-unset-value": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@csstools/postcss-unset-value/-/postcss-unset-value-1.0.2.tgz",
+ "integrity": "sha512-c8J4roPBILnelAsdLr4XOAR/GsTm0GJi4XpcfvoWk3U6KiTCqiFYc63KhRMQQX35jYMp4Ao8Ij9+IZRgMfJp1g==",
+ "dev": true,
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/@csstools/selector-specificity": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@csstools/selector-specificity/-/selector-specificity-2.2.0.tgz",
+ "integrity": "sha512-+OJ9konv95ClSTOJCmMZqpd5+YGsB2S+x6w3E1oaM8UuR5j8nTNHYSz8c9BEPGDOCMQYIEEGlVPj/VY64iTbGw==",
+ "dev": true,
+ "engines": {
+ "node": "^14 || ^16 || >=18"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ }
+ },
+ "node_modules/@discoveryjs/json-ext": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/@dnd-kit/accessibility": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@dnd-kit/accessibility/-/accessibility-3.1.0.tgz",
+ "integrity": "sha512-ea7IkhKvlJUv9iSHJOnxinBcoOI3ppGnnL+VDJ75O45Nss6HtZd8IdN8touXPDtASfeI2T2LImb8VOZcL47wjQ==",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@dnd-kit/core": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/@dnd-kit/core/-/core-6.1.0.tgz",
+ "integrity": "sha512-J3cQBClB4TVxwGo3KEjssGEXNJqGVWx17aRTZ1ob0FliR5IjYgTxl5YJbKTzA6IzrtelotH19v6y7uoIRUZPSg==",
+ "dependencies": {
+ "@dnd-kit/accessibility": "^3.1.0",
+ "@dnd-kit/utilities": "^3.2.2",
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@dnd-kit/sortable": {
+ "version": "7.0.2",
+ "resolved": "https://registry.npmjs.org/@dnd-kit/sortable/-/sortable-7.0.2.tgz",
+ "integrity": "sha512-wDkBHHf9iCi1veM834Gbk1429bd4lHX4RpAwT0y2cHLf246GAvU2sVw/oxWNpPKQNQRQaeGXhAVgrOl1IT+iyA==",
+ "dependencies": {
+ "@dnd-kit/utilities": "^3.2.0",
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "@dnd-kit/core": "^6.0.7",
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@dnd-kit/utilities": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/@dnd-kit/utilities/-/utilities-3.2.2.tgz",
+ "integrity": "sha512-+MKAJEOfaBe5SmV6t34p80MMKhjvUz0vRrvVJbPT0WElzaOJ/1xs+D+KDv+tD/NE5ujfrChEcshd4fLn0wpiqg==",
+ "dependencies": {
+ "tslib": "^2.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@emnapi/runtime": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/@emnapi/runtime/-/runtime-1.8.1.tgz",
+ "integrity": "sha512-mehfKSMWjjNol8659Z8KxEMrdSJDDot5SXMq00dM8BN4o+CLNXQ0xH2V7EchNHV4RmbZLmmPdEaXZc5H2FXmDg==",
+ "dev": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "tslib": "^2.4.0"
+ }
+ },
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
+ "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.1",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.1.tgz",
+ "integrity": "sha512-aw1gNayWpdI/jSYVgzN5pL0cfzU02GT3NBpeT/DXbx1/1x7ZKxFPd9bwrzygx/qiwIQiJ1sw/zD8qY/kRvlGHA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@types/json-schema": "^7.0.15"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.1.tgz",
+ "integrity": "sha512-gtF186CXhIl1p4pJNGZw8Yc6RlshoePRvE0X91oPGb3vZ8pM3qOS9W9NGPat9LziaBV7XrJWGylNQXkGcnM3IQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.2.tgz",
+ "integrity": "sha512-q1mjIoW1VX4IvSocvM/vbTiveKC4k9eLrajNEuSsmjymSDEbpGddtpfOoN7YGAqBK3NG+uqo8ia4PDTt8buCYA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@exodus/schemasafe": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/@exodus/schemasafe/-/schemasafe-1.3.0.tgz",
+ "integrity": "sha512-5Aap/GaRupgNx/feGBwLLTVv8OQFfv3pq2lPRzPg9R+IOBnDgghTGW7l7EuVXOvg5cc/xSAlRW8rBrjIC3Nvqw==",
+ "dev": true
+ },
+ "node_modules/@formatjs/ecma402-abstract": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/@formatjs/ecma402-abstract/-/ecma402-abstract-2.2.1.tgz",
+ "integrity": "sha512-O4ywpkdJybrjFc9zyL8qK5aklleIAi5O4nYhBVJaOFtCkNrnU+lKFeJOFC48zpsZQmR8Aok2V79hGpHnzbmFpg==",
+ "dependencies": {
+ "@formatjs/fast-memoize": "2.2.2",
+ "@formatjs/intl-localematcher": "0.5.6",
+ "tslib": "2"
+ }
+ },
+ "node_modules/@formatjs/fast-memoize": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/@formatjs/fast-memoize/-/fast-memoize-2.2.2.tgz",
+ "integrity": "sha512-mzxZcS0g1pOzwZTslJOBTmLzDXseMLLvnh25ymRilCm8QLMObsQ7x/rj9GNrH0iUhZMlFisVOD6J1n6WQqpKPQ==",
+ "dependencies": {
+ "tslib": "2"
+ }
+ },
+ "node_modules/@formatjs/icu-messageformat-parser": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/@formatjs/icu-messageformat-parser/-/icu-messageformat-parser-2.9.1.tgz",
+ "integrity": "sha512-7AYk4tjnLi5wBkxst2w7qFj38JLMJoqzj7BhdEl7oTlsWMlqwgx4p9oMmmvpXWTSDGNwOKBRc1SfwMh5MOHeNg==",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.2.1",
+ "@formatjs/icu-skeleton-parser": "1.8.5",
+ "tslib": "2"
+ }
+ },
+ "node_modules/@formatjs/icu-skeleton-parser": {
+ "version": "1.8.5",
+ "resolved": "https://registry.npmjs.org/@formatjs/icu-skeleton-parser/-/icu-skeleton-parser-1.8.5.tgz",
+ "integrity": "sha512-zRZ/e3B5qY2+JCLs7puTzWS1Jb+t/K+8Jur/gEZpA2EjWeLDE17nsx8thyo9P48Mno7UmafnPupV2NCJXX17Dg==",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.2.1",
+ "tslib": "2"
+ }
+ },
+ "node_modules/@formatjs/intl-localematcher": {
+ "version": "0.5.6",
+ "resolved": "https://registry.npmjs.org/@formatjs/intl-localematcher/-/intl-localematcher-0.5.6.tgz",
+ "integrity": "sha512-roz1+Ba5e23AHX6KUAWmLEyTRZegM5YDuxuvkHCyK3RJddf/UXB2f+s7pOMm9ktfPGla0g+mQXOn5vsuYirnaA==",
+ "dependencies": {
+ "tslib": "2"
+ }
+ },
+ "node_modules/@hookform/resolvers": {
+ "version": "2.9.11",
+ "resolved": "https://registry.npmjs.org/@hookform/resolvers/-/resolvers-2.9.11.tgz",
+ "integrity": "sha512-bA3aZ79UgcHj7tFV7RlgThzwSSHZgvfbt2wprldRkYBcMopdMvHyO17Wwp/twcJasNFischFfS7oz8Katz8DdQ==",
+ "peerDependencies": {
+ "react-hook-form": "^7.0.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.6",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+ "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@img/sharp-darwin-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-arm64/-/sharp-darwin-arm64-0.33.5.tgz",
+ "integrity": "sha512-UT4p+iz/2H4twwAoLCqfA9UH5pI6DggwKEGuaPy7nCVQ8ZsiY5PIcrRvD1DzuY3qYL07NtIQcWnBSY/heikIFQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-darwin-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-darwin-x64/-/sharp-darwin-x64-0.33.5.tgz",
+ "integrity": "sha512-fyHac4jIc1ANYGRDxtiqelIbdWkIuQaI84Mv45KvGRRxSAa7o7d1ZKAOBaYbnepLC1WqxfpimdeWfvqqSGwR2Q==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-darwin-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-arm64/-/sharp-libvips-darwin-arm64-1.0.4.tgz",
+ "integrity": "sha512-XblONe153h0O2zuFfTAbQYAX2JhYmDHeWikp1LM9Hul9gVPjFY427k6dFEcOL72O01QxQsWi761svJ/ev9xEDg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-darwin-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-darwin-x64/-/sharp-libvips-darwin-x64-1.0.4.tgz",
+ "integrity": "sha512-xnGR8YuZYfJGmWPvmlunFaWJsb9T/AO2ykoP3Fz/0X5XV2aoYBPkX6xqCQvUTKKiLddarLaxpzNe+b1hjeWHAQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm/-/sharp-libvips-linux-arm-1.0.5.tgz",
+ "integrity": "sha512-gvcC4ACAOPRNATg/ov8/MnbxFDJqf/pDePbBnuBDcjsI8PssmjoKMAz4LtLaVi+OnSb5FK/yIOamqDwGmXW32g==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-arm64/-/sharp-libvips-linux-arm64-1.0.4.tgz",
+ "integrity": "sha512-9B+taZ8DlyyqzZQnoeIvDVR/2F4EbMepXMc/NdVbkzsJbzkUjhXv/70GQJ7tdLA4YJgNP25zukcxpX2/SueNrA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-s390x": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-s390x/-/sharp-libvips-linux-s390x-1.0.4.tgz",
+ "integrity": "sha512-u7Wz6ntiSSgGSGcjZ55im6uvTrOxSIS8/dgoVMoiGE9I6JAfU50yH5BoDlYA1tcuGS7g/QNtetJnxA6QEsCVTA==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linux-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linux-x64/-/sharp-libvips-linux-x64-1.0.4.tgz",
+ "integrity": "sha512-MmWmQ3iPFZr0Iev+BAgVMb3ZyC4KeFc3jFxnNbEPas60e1cIfevbtuyf9nDGIzOaW9PdnDciJm+wFFaTlj5xYw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-arm64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-arm64/-/sharp-libvips-linuxmusl-arm64-1.0.4.tgz",
+ "integrity": "sha512-9Ti+BbTYDcsbp4wfYib8Ctm1ilkugkA/uscUn6UXK1ldpC1JjiXbLfFZtRlBhjPZ5o1NCLiDbg8fhUPKStHoTA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-libvips-linuxmusl-x64": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@img/sharp-libvips-linuxmusl-x64/-/sharp-libvips-linuxmusl-x64-1.0.4.tgz",
+ "integrity": "sha512-viYN1KX9m+/hGkJtvYYp+CCLgnJXwiQB39damAO7WMdKWlIhmYTfHjwSbQeUK/20vY154mwezd9HflVFM1wVSw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm/-/sharp-linux-arm-0.33.5.tgz",
+ "integrity": "sha512-JTS1eldqZbJxjvKaAkxhZmBqPRGmxgu+qFKSInv8moZ2AmT5Yib3EQ1c6gp493HvrvV8QgdOXdyaIBrhvFhBMQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm": "1.0.5"
+ }
+ },
+ "node_modules/@img/sharp-linux-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-arm64/-/sharp-linux-arm64-0.33.5.tgz",
+ "integrity": "sha512-JMVv+AMRyGOHtO1RFBiJy/MBsgz0x4AWrT6QoEVVTyh1E39TrCUpTRI7mx9VksGX4awWASxqCYLCV4wBZHAYxA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-s390x": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-s390x/-/sharp-linux-s390x-0.33.5.tgz",
+ "integrity": "sha512-y/5PCd+mP4CA/sPDKl2961b+C9d+vPAveS33s6Z3zfASk2j5upL6fXVPZi7ztePZ5CuH+1kW8JtvxgbuXHRa4Q==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-s390x": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linux-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linux-x64/-/sharp-linux-x64-0.33.5.tgz",
+ "integrity": "sha512-opC+Ok5pRNAzuvq1AG0ar+1owsu842/Ab+4qvU879ippJBHvyY5n2mxF1izXqkPYlGuP/M556uh53jRLJmzTWA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linux-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-arm64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-arm64/-/sharp-linuxmusl-arm64-0.33.5.tgz",
+ "integrity": "sha512-XrHMZwGQGvJg2V/oRSUfSAfjfPxO+4DkiRh6p2AFjLQztWUuY/o8Mq0eMQVIY7HJ1CDQUJlxGGZRw1a5bqmd1g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-linuxmusl-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-linuxmusl-x64/-/sharp-linuxmusl-x64-0.33.5.tgz",
+ "integrity": "sha512-WT+d/cgqKkkKySYmqoZ8y3pxx7lx9vVejxW/W4DOFMYVSkErR+w7mf2u8m/y4+xHe7yY9DAXQMWQhpnMuFfScw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.4"
+ }
+ },
+ "node_modules/@img/sharp-wasm32": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-wasm32/-/sharp-wasm32-0.33.5.tgz",
+ "integrity": "sha512-ykUW4LVGaMcU9lu9thv85CbRMAwfeadCJHRsg2GmeRa/cJxsVY9Rbd57JcMxBkKHag5U/x7TSBpScF4U8ElVzg==",
+ "cpu": [
+ "wasm32"
+ ],
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "@emnapi/runtime": "^1.2.0"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-ia32": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-ia32/-/sharp-win32-ia32-0.33.5.tgz",
+ "integrity": "sha512-T36PblLaTwuVJ/zw/LaH0PdZkRz5rd3SmMHX8GSmR7vtNSP5Z6bQkExdSK7xGWyxLw4sUknBuugTelgw2faBbQ==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@img/sharp-win32-x64": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/@img/sharp-win32-x64/-/sharp-win32-x64-0.33.5.tgz",
+ "integrity": "sha512-MpY/o8/8kj+EcnxwvrP4aTJSWw/aZ7JIGR4aBeZkZw5B7/Jn+tY9/VNwtcoGmdT7GfggGIU4kygOMSbYnOrAbg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
+ "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
+ "dev": true,
+ "dependencies": {
+ "camelcase": "^5.3.1",
+ "find-up": "^4.1.0",
+ "get-package-type": "^0.1.0",
+ "js-yaml": "^3.13.1",
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
+ "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "sprintf-js": "~1.0.2"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/camelcase": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
+ "version": "3.14.2",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.2.tgz",
+ "integrity": "sha512-PMSmkqxr106Xa156c2M265Z+FTrPl+oxd/rgOQy2tijQeK5TxQ43psO1ZCwhVOSdnn+RzkzlRz/eY4BgJBYVpg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^1.0.7",
+ "esprima": "^4.0.0"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/console": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/console/-/console-29.7.0.tgz",
+ "integrity": "sha512-5Ni4CU7XHQi32IJ398EEP4RrB8eV09sXP2ROqD4bksHrnTree52PsxvX8tpL8LvTZ3pFzXyPbNQReSN41CAhOg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/console/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/core": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/core/-/core-29.7.0.tgz",
+ "integrity": "sha512-n7aeXWKMnGtDA48y8TLWJPJmLmmZ642Ceo78cYWEpiD7FzDgmNDV/GCVRorPABdXLJZ/9wzzgZAlHjXjxDHGsg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/reporters": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-changed-files": "^29.7.0",
+ "jest-config": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-resolve-dependencies": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/core/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@jest/core/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/core/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/environment": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/environment/-/environment-29.7.0.tgz",
+ "integrity": "sha512-aQIfHDq33ExsN4jP1NWGXhxgQ/wixs60gDiKO+XVMd8Mn0NWPWgc34ZQDTb2jKaUWQ7MuwoitXAsN2XVXNMpAw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-8uMeAMycttpva3P1lBHB8VciS9V0XAr3GymPpipdyQXbBcuhkLQOSe8E/p92RyAdToS6ZD1tFkX+CkhoECE0dQ==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.7.0",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/expect-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/expect-utils/-/expect-utils-29.7.0.tgz",
+ "integrity": "sha512-GlsNBWiFQFCVi9QVSx7f5AgMeLxe9YCCs5PuP2O2LdjDAA8Jh9eX7lA1Jq/xdXw3Wb3hyvlFNfZIfcRetSzYcA==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.6.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/fake-timers": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/fake-timers/-/fake-timers-29.7.0.tgz",
+ "integrity": "sha512-q4DH1Ha4TTFPdxLsqDXK1d3+ioSL7yL5oCMJZgDYm6i+6CygW5E5xVr/D1HdsGxjt1ZWSfUAs9OxSB/BNelWrQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@sinonjs/fake-timers": "^10.0.2",
+ "@types/node": "*",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/globals": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/globals/-/globals-29.7.0.tgz",
+ "integrity": "sha512-mpiz3dutLbkW2MNFubUGUEVLkTGiqW6yLVTA+JbP6fI6J5iL9Y0Nlg8k95pcF8ctKwCS7WVxteBs29hhfAotzQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "jest-mock": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/reporters": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/reporters/-/reporters-29.7.0.tgz",
+ "integrity": "sha512-DApq0KJbJOEzAFYjHADNNxAE3KbhxQB1y5Kplb5Waqw6zVbuWatSnMjE5gs8FUgEPmNsnZA3NCWl9NG0ia04Pg==",
+ "dev": true,
+ "dependencies": {
+ "@bcoe/v8-coverage": "^0.2.3",
+ "@jest/console": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "exit": "^0.1.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "istanbul-lib-coverage": "^3.0.0",
+ "istanbul-lib-instrument": "^6.0.0",
+ "istanbul-lib-report": "^3.0.0",
+ "istanbul-lib-source-maps": "^4.0.0",
+ "istanbul-reports": "^3.1.3",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "slash": "^3.0.0",
+ "string-length": "^4.0.1",
+ "strip-ansi": "^6.0.0",
+ "v8-to-istanbul": "^9.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@jest/reporters/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/source-map": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/source-map/-/source-map-29.6.3.tgz",
+ "integrity": "sha512-MHjT95QuipcPrpLM+8JMSzFx6eHp5Bm+4XeFDJlwsvVBjmKNiIAvasGK2fxz2WbGRlnvqehFbh07MMa7n3YJnw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "callsites": "^3.0.0",
+ "graceful-fs": "^4.2.9"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-result": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-result/-/test-result-29.7.0.tgz",
+ "integrity": "sha512-Fdx+tv6x1zlkJPcWXmMDAG2HBnaR9XPSd5aDWQVsfrZmLVT3lU1cwyxLgRmXR9yrq4NBoEm9BMsfgFzTQAbJYA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "collect-v8-coverage": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/test-sequencer/-/test-sequencer-29.7.0.tgz",
+ "integrity": "sha512-GQwJ5WZVrKnOJuiYiAF52UNUJXgTZx1NHjFSEB0qEMmSZKAkdMoIzw/Cj6x6NF4AvV23AUqDpFzQkN/eYCYTxw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/test-sequencer/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/transform": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.7.0.tgz",
+ "integrity": "sha512-ok/BTPFzFKVMwO5eOHRrvnBVHdRy9IrsrW1GpMaQ9MCnilNLXQKmAX8s1YXDFaai9xJpac2ySzV0YeRRECr2Vw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/types": "^29.6.3",
+ "@jridgewell/trace-mapping": "^0.3.18",
+ "babel-plugin-istanbul": "^6.1.1",
+ "chalk": "^4.0.0",
+ "convert-source-map": "^2.0.0",
+ "fast-json-stable-stringify": "^2.1.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "pirates": "^4.0.4",
+ "slash": "^3.0.0",
+ "write-file-atomic": "^4.0.2"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/transform/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.6",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.6.tgz",
+ "integrity": "sha512-1ZJTZebgqllO79ue2bm3rIGud/bOe0pP5BjSRCRxxYkEZS8STV7zN84UBbiYu7jy+eCKSnVIUgoWWE/tt+shMQ==",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@jsdevtools/ono": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
+ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==",
+ "dev": true
+ },
+ "node_modules/@jsonjoy.com/base64": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/base64/-/base64-1.1.2.tgz",
+ "integrity": "sha512-q6XAnWQDIMA3+FTiOYajoYqySkO+JSat0ytXGSuRdq9uXE7o92gzuQwQM14xaCRlBLGq3v5miDGC4vkVTn54xA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/streamich"
+ },
+ "peerDependencies": {
+ "tslib": "2"
+ }
+ },
+ "node_modules/@jsonjoy.com/json-pack": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/json-pack/-/json-pack-1.1.0.tgz",
+ "integrity": "sha512-zlQONA+msXPPwHWZMKFVS78ewFczIll5lXiVPwFPCZUsrOKdxc2AvxU1HoNBmMRhqDZUR9HkC3UOm+6pME6Xsg==",
+ "dev": true,
+ "dependencies": {
+ "@jsonjoy.com/base64": "^1.1.1",
+ "@jsonjoy.com/util": "^1.1.2",
+ "hyperdyperid": "^1.2.0",
+ "thingies": "^1.20.0"
+ },
+ "engines": {
+ "node": ">=10.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/streamich"
+ },
+ "peerDependencies": {
+ "tslib": "2"
+ }
+ },
+ "node_modules/@jsonjoy.com/util": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jsonjoy.com/util/-/util-1.5.0.tgz",
+ "integrity": "sha512-ojoNsrIuPI9g6o8UxhraZQSyF2ByJanAY4cTFbc8Mf2AXEF4aQRGY1dJxyJpuyav8r9FGflEt/Ff3u5Nt6YMPA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/streamich"
+ },
+ "peerDependencies": {
+ "tslib": "2"
+ }
+ },
+ "node_modules/@juggle/resize-observer": {
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/@juggle/resize-observer/-/resize-observer-3.4.0.tgz",
+ "integrity": "sha512-dfLbk+PwWvFzSxwk3n5ySL0hfBog779o8h68wK/7/APo/7cgyWp5jcXockbxdk5kFRkbeXWm4Fbi9FrdN381sA=="
+ },
+ "node_modules/@leichtgewicht/ip-codec": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
+ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==",
+ "dev": true
+ },
+ "node_modules/@nicolo-ribaudo/chokidar-2": {
+ "version": "2.1.8-no-fsevents.3",
+ "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/chokidar-2/-/chokidar-2-2.1.8-no-fsevents.3.tgz",
+ "integrity": "sha512-s88O1aVtXftvp5bCPB7WnmXc5IwOZZ7YPuwNPt+GtOOXpPvad1LfbmjYv+qII7zP6RU2QGnqve27dnLycEnyEQ==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/@noble/hashes": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@noble/hashes/-/hashes-1.4.0.tgz",
+ "integrity": "sha512-V1JJ1WTRUqHHrOSh597hURcMqVKVGL/ea3kv0gSnEdsEZ0/+VyPghM1lMNGc00z7CIQorSvbKpuJkxvuHbvdbg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@oazapfts/runtime": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@oazapfts/runtime/-/runtime-1.0.3.tgz",
+ "integrity": "sha512-8tKiYffhwTGHSHYGnZ3oneLGCjX0po/XAXQ5Ng9fqKkvIdl/xz8+Vh8i+6xjzZqvZ2pLVpUcuSfnvNI/x67L0g==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@parcel/watcher": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher/-/watcher-2.4.1.tgz",
+ "integrity": "sha512-HNjmfLQEVRZmHRET336f20H/8kOozUGwk7yajvsonjNxbj2wBTK1WsQuHkD5yYh9RxFGL2EyDHryOihOwUoKDA==",
+ "dev": true,
+ "optional": true,
+ "dependencies": {
+ "detect-libc": "^1.0.3",
+ "is-glob": "^4.0.3",
+ "micromatch": "^4.0.5",
+ "node-addon-api": "^7.0.0"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher-android-arm64": "2.4.1",
+ "@parcel/watcher-darwin-arm64": "2.4.1",
+ "@parcel/watcher-darwin-x64": "2.4.1",
+ "@parcel/watcher-freebsd-x64": "2.4.1",
+ "@parcel/watcher-linux-arm-glibc": "2.4.1",
+ "@parcel/watcher-linux-arm64-glibc": "2.4.1",
+ "@parcel/watcher-linux-arm64-musl": "2.4.1",
+ "@parcel/watcher-linux-x64-glibc": "2.4.1",
+ "@parcel/watcher-linux-x64-musl": "2.4.1",
+ "@parcel/watcher-win32-arm64": "2.4.1",
+ "@parcel/watcher-win32-ia32": "2.4.1",
+ "@parcel/watcher-win32-x64": "2.4.1"
+ }
+ },
+ "node_modules/@parcel/watcher-android-arm64": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-android-arm64/-/watcher-android-arm64-2.4.1.tgz",
+ "integrity": "sha512-LOi/WTbbh3aTn2RYddrO8pnapixAziFl6SMxHM69r3tvdSm94JtCenaKgk1GRg5FJ5wpMCpHeW+7yqPlvZv7kg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-arm64": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-arm64/-/watcher-darwin-arm64-2.4.1.tgz",
+ "integrity": "sha512-ln41eihm5YXIY043vBrrHfn94SIBlqOWmoROhsMVTSXGh0QahKGy77tfEywQ7v3NywyxBBkGIfrWRHm0hsKtzA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-darwin-x64": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-darwin-x64/-/watcher-darwin-x64-2.4.1.tgz",
+ "integrity": "sha512-yrw81BRLjjtHyDu7J61oPuSoeYWR3lDElcPGJyOvIXmor6DEo7/G2u1o7I38cwlcoBHQFULqF6nesIX3tsEXMg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-freebsd-x64": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-freebsd-x64/-/watcher-freebsd-x64-2.4.1.tgz",
+ "integrity": "sha512-TJa3Pex/gX3CWIx/Co8k+ykNdDCLx+TuZj3f3h7eOjgpdKM+Mnix37RYsYU4LHhiYJz3DK5nFCCra81p6g050w==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm-glibc": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm-glibc/-/watcher-linux-arm-glibc-2.4.1.tgz",
+ "integrity": "sha512-4rVYDlsMEYfa537BRXxJ5UF4ddNwnr2/1O4MHM5PjI9cvV2qymvhwZSFgXqbS8YoTk5i/JR0L0JDs69BUn45YA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-glibc": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-glibc/-/watcher-linux-arm64-glibc-2.4.1.tgz",
+ "integrity": "sha512-BJ7mH985OADVLpbrzCLgrJ3TOpiZggE9FMblfO65PlOCdG++xJpKUJ0Aol74ZUIYfb8WsRlUdgrZxKkz3zXWYA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-arm64-musl": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-arm64-musl/-/watcher-linux-arm64-musl-2.4.1.tgz",
+ "integrity": "sha512-p4Xb7JGq3MLgAfYhslU2SjoV9G0kI0Xry0kuxeG/41UfpjHGOhv7UoUDAz/jb1u2elbhazy4rRBL8PegPJFBhA==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-glibc": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-glibc/-/watcher-linux-x64-glibc-2.4.1.tgz",
+ "integrity": "sha512-s9O3fByZ/2pyYDPoLM6zt92yu6P4E39a03zvO0qCHOTjxmt3GHRMLuRZEWhWLASTMSrrnVNWdVI/+pUElJBBBg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-linux-x64-musl": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-linux-x64-musl/-/watcher-linux-x64-musl-2.4.1.tgz",
+ "integrity": "sha512-L2nZTYR1myLNST0O632g0Dx9LyMNHrn6TOt76sYxWLdff3cB22/GZX2UPtJnaqQPdCRoszoY5rcOj4oMTtp5fQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-arm64": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-arm64/-/watcher-win32-arm64-2.4.1.tgz",
+ "integrity": "sha512-Uq2BPp5GWhrq/lcuItCHoqxjULU1QYEcyjSO5jqqOK8RNFDBQnenMMx4gAl3v8GiWa59E9+uDM7yZ6LxwUIfRg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-ia32": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-ia32/-/watcher-win32-ia32-2.4.1.tgz",
+ "integrity": "sha512-maNRit5QQV2kgHFSYwftmPBxiuK5u4DXjbXx7q6eKjq5dsLXZ4FJiVvlcw35QXzk0KrUecJmuVFbj4uV9oYrcw==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@parcel/watcher-win32-x64": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/@parcel/watcher-win32-x64/-/watcher-win32-x64-2.4.1.tgz",
+ "integrity": "sha512-+DvS92F9ezicfswqrvIRM2njcYJbd5mb9CUgtrHCHmvn7pPPa+nMDRu1o1bYYz/l5IB2NVGNJWiH7h1E58IF2A==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/parcel"
+ }
+ },
+ "node_modules/@peculiar/asn1-cms": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-cms/-/asn1-cms-2.6.0.tgz",
+ "integrity": "sha512-2uZqP+ggSncESeUF/9Su8rWqGclEfEiz1SyU02WX5fUONFfkjzS2Z/F1Li0ofSmf4JqYXIOdCAZqIXAIBAT1OA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.6.0",
+ "@peculiar/asn1-x509": "^2.6.0",
+ "@peculiar/asn1-x509-attr": "^2.6.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-csr": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-csr/-/asn1-csr-2.6.0.tgz",
+ "integrity": "sha512-BeWIu5VpTIhfRysfEp73SGbwjjoLL/JWXhJ/9mo4vXnz3tRGm+NGm3KNcRzQ9VMVqwYS2RHlolz21svzRXIHPQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.6.0",
+ "@peculiar/asn1-x509": "^2.6.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-ecc": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-ecc/-/asn1-ecc-2.6.0.tgz",
+ "integrity": "sha512-FF3LMGq6SfAOwUG2sKpPXblibn6XnEIKa+SryvUl5Pik+WR9rmRA3OCiwz8R3lVXnYnyRkSZsSLdml8H3UiOcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.6.0",
+ "@peculiar/asn1-x509": "^2.6.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-pfx": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-pfx/-/asn1-pfx-2.6.0.tgz",
+ "integrity": "sha512-rtUvtf+tyKGgokHHmZzeUojRZJYPxoD/jaN1+VAB4kKR7tXrnDCA/RAWXAIhMJJC+7W27IIRGe9djvxKgsldCQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-cms": "^2.6.0",
+ "@peculiar/asn1-pkcs8": "^2.6.0",
+ "@peculiar/asn1-rsa": "^2.6.0",
+ "@peculiar/asn1-schema": "^2.6.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-pkcs8": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs8/-/asn1-pkcs8-2.6.0.tgz",
+ "integrity": "sha512-KyQ4D8G/NrS7Fw3XCJrngxmjwO/3htnA0lL9gDICvEQ+GJ+EPFqldcJQTwPIdvx98Tua+WjkdKHSC0/Km7T+lA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.6.0",
+ "@peculiar/asn1-x509": "^2.6.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-pkcs9": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-pkcs9/-/asn1-pkcs9-2.6.0.tgz",
+ "integrity": "sha512-b78OQ6OciW0aqZxdzliXGYHASeCvvw5caqidbpQRYW2mBtXIX2WhofNXTEe7NyxTb0P6J62kAAWLwn0HuMF1Fw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-cms": "^2.6.0",
+ "@peculiar/asn1-pfx": "^2.6.0",
+ "@peculiar/asn1-pkcs8": "^2.6.0",
+ "@peculiar/asn1-schema": "^2.6.0",
+ "@peculiar/asn1-x509": "^2.6.0",
+ "@peculiar/asn1-x509-attr": "^2.6.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-rsa": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-rsa/-/asn1-rsa-2.6.0.tgz",
+ "integrity": "sha512-Nu4C19tsrTsCp9fDrH+sdcOKoVfdfoQQ7S3VqjJU6vedR7tY3RLkQ5oguOIB3zFW33USDUuYZnPEQYySlgha4w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.6.0",
+ "@peculiar/asn1-x509": "^2.6.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-schema": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-schema/-/asn1-schema-2.6.0.tgz",
+ "integrity": "sha512-xNLYLBFTBKkCzEZIw842BxytQQATQv+lDTCEMZ8C196iJcJJMBUZxrhSTxLaohMyKK8QlzRNTRkUmanucnDSqg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "asn1js": "^3.0.6",
+ "pvtsutils": "^1.3.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-x509": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509/-/asn1-x509-2.6.0.tgz",
+ "integrity": "sha512-uzYbPEpoQiBoTq0/+jZtpM6Gq6zADBx+JNFP3yqRgziWBxQ/Dt/HcuvRfm9zJTPdRcBqPNdaRHTVwpyiq6iNMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.6.0",
+ "asn1js": "^3.0.6",
+ "pvtsutils": "^1.3.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/asn1-x509-attr": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/@peculiar/asn1-x509-attr/-/asn1-x509-attr-2.6.0.tgz",
+ "integrity": "sha512-MuIAXFX3/dc8gmoZBkwJWxUWOSvG4MMDntXhrOZpJVMkYX+MYc/rUAU2uJOved9iJEoiUx7//3D8oG83a78UJA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-schema": "^2.6.0",
+ "@peculiar/asn1-x509": "^2.6.0",
+ "asn1js": "^3.0.6",
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/@peculiar/x509": {
+ "version": "1.14.3",
+ "resolved": "https://registry.npmjs.org/@peculiar/x509/-/x509-1.14.3.tgz",
+ "integrity": "sha512-C2Xj8FZ0uHWeCXXqX5B4/gVFQmtSkiuOolzAgutjTfseNOHT3pUjljDZsTSxXFGgio54bCzVFqmEOUrIVk8RDA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/asn1-cms": "^2.6.0",
+ "@peculiar/asn1-csr": "^2.6.0",
+ "@peculiar/asn1-ecc": "^2.6.0",
+ "@peculiar/asn1-pkcs9": "^2.6.0",
+ "@peculiar/asn1-rsa": "^2.6.0",
+ "@peculiar/asn1-schema": "^2.6.0",
+ "@peculiar/asn1-x509": "^2.6.0",
+ "pvtsutils": "^1.3.6",
+ "reflect-metadata": "^0.2.2",
+ "tslib": "^2.8.1",
+ "tsyringe": "^4.10.0"
+ },
+ "engines": {
+ "node": ">=20.0.0"
+ }
+ },
+ "node_modules/@pkgr/core": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/@pkgr/core/-/core-0.2.7.tgz",
+ "integrity": "sha512-YLT9Zo3oNPJoBjBc4q8G2mjU4tqIbf5CEOORbUUr48dCD9q3umJ3IPlVqOqDakPfd2HuwccBaqlGhN4Gmr5OWg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.20.0 || ^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/pkgr"
+ }
+ },
+ "node_modules/@pmmmwh/react-refresh-webpack-plugin": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@pmmmwh/react-refresh-webpack-plugin/-/react-refresh-webpack-plugin-0.5.15.tgz",
+ "integrity": "sha512-LFWllMA55pzB9D34w/wXUCf8+c+IYKuJDgxiZ3qMhl64KRMBHYM1I3VdGaD2BV5FNPV2/S2596bppxHbv2ZydQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-html": "^0.0.9",
+ "core-js-pure": "^3.23.3",
+ "error-stack-parser": "^2.0.6",
+ "html-entities": "^2.1.0",
+ "loader-utils": "^2.0.4",
+ "schema-utils": "^4.2.0",
+ "source-map": "^0.7.3"
+ },
+ "engines": {
+ "node": ">= 10.13"
+ },
+ "peerDependencies": {
+ "@types/webpack": "4.x || 5.x",
+ "react-refresh": ">=0.10.0 <1.0.0",
+ "sockjs-client": "^1.4.0",
+ "type-fest": ">=0.17.0 <5.0.0",
+ "webpack": ">=4.43.0 <6.0.0",
+ "webpack-dev-server": "3.x || 4.x || 5.x",
+ "webpack-hot-middleware": "2.x",
+ "webpack-plugin-serve": "0.x || 1.x"
+ },
+ "peerDependenciesMeta": {
+ "@types/webpack": {
+ "optional": true
+ },
+ "sockjs-client": {
+ "optional": true
+ },
+ "type-fest": {
+ "optional": true
+ },
+ "webpack-dev-server": {
+ "optional": true
+ },
+ "webpack-hot-middleware": {
+ "optional": true
+ },
+ "webpack-plugin-serve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@pmmmwh/react-refresh-webpack-plugin/node_modules/loader-utils": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+ "dev": true,
+ "dependencies": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=8.9.0"
+ }
+ },
+ "node_modules/@reduxjs/toolkit": {
+ "version": "1.9.7",
+ "resolved": "https://registry.npmjs.org/@reduxjs/toolkit/-/toolkit-1.9.7.tgz",
+ "integrity": "sha512-t7v8ZPxhhKgOKtU+uyJT13lu4vL7az5aFi4IdoDs/eS548edn2M8Ik9h8fxgvMjGoAUVFSt6ZC1P5cWmQ014QQ==",
+ "dependencies": {
+ "immer": "^9.0.21",
+ "redux": "^4.2.1",
+ "redux-thunk": "^2.4.2",
+ "reselect": "^4.1.8"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17.0.0 || ^18",
+ "react-redux": "^7.2.1 || ^8.0.2"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ },
+ "react-redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@reduxjs/toolkit/node_modules/redux": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
+ "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
+ "dependencies": {
+ "@babel/runtime": "^7.9.2"
+ }
+ },
+ "node_modules/@reduxjs/toolkit/node_modules/redux-thunk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/redux-thunk/-/redux-thunk-2.4.2.tgz",
+ "integrity": "sha512-+P3TjtnP0k/FEjcBL5FZpoovtvrTNT/UXd4/sluaSyrURlSlhLSzEdfsTBW7WsKB6yPvgd7q/iZPICFjW4o57Q==",
+ "peerDependencies": {
+ "redux": "^4"
+ }
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.23.2",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.23.2.tgz",
+ "integrity": "sha512-Ic6m2U/rMjTkhERIa/0ZtXJP17QUi2CbWE7cqx4J58M8aA3QTfW+2UlQ4psvTX9IO1RfNVhK3pcpdjej7L+t2w==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@rtk-query/codegen-openapi": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@rtk-query/codegen-openapi/-/codegen-openapi-2.0.0.tgz",
+ "integrity": "sha512-uIOshfqX6bcsMpiwUMKAC+oFEw2fUxICMruhXunB6wq7tHpUg2b+gz+qGjiWAWw1Ly6g6jjvb3N4HRxWy9Yqew==",
+ "dev": true,
+ "dependencies": {
+ "@apidevtools/swagger-parser": "^10.0.2",
+ "commander": "^6.2.0",
+ "lodash.camelcase": "^4.3.0",
+ "oazapfts": "^6.1.0",
+ "prettier": "^3.2.5",
+ "semver": "^7.3.5",
+ "swagger2openapi": "^7.0.4",
+ "typescript": "^5.5.4"
+ },
+ "bin": {
+ "rtk-query-codegen-openapi": "lib/bin/cli.mjs"
+ }
+ },
+ "node_modules/@rtk-query/codegen-openapi/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.8",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="
+ },
+ "node_modules/@sinonjs/commons": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sinonjs/commons/-/commons-3.0.1.tgz",
+ "integrity": "sha512-K3mCHKQ9sVh8o1C9cxkwxaOmXoAMlDxC1mYyHrjqOWEcBjYr76t96zL2zlj5dUGZ3HSw240X1qgH3Mjf1yJWpQ==",
+ "dev": true,
+ "dependencies": {
+ "type-detect": "4.0.8"
+ }
+ },
+ "node_modules/@sinonjs/fake-timers": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/@sinonjs/fake-timers/-/fake-timers-10.3.0.tgz",
+ "integrity": "sha512-V4BG07kuYSUkTCSBHG8G8TNhM+F19jXFWnQtzj+we8DrkpSBCee9Z3Ms8yiGer/dlmhe35/Xdgyo3/0rQKg7YA==",
+ "dev": true,
+ "dependencies": {
+ "@sinonjs/commons": "^3.0.0"
+ }
+ },
+ "node_modules/@svgr/babel-plugin-add-jsx-attribute": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-add-jsx-attribute/-/babel-plugin-add-jsx-attribute-6.5.1.tgz",
+ "integrity": "sha512-9PYGcXrAxitycIjRmZB+Q0JaN07GZIWaTBIGQzfaZv+qr1n8X1XUEJ5rZ/vx6OVD9RRYlrNnXWExQXcmZeD/BQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@svgr/babel-plugin-remove-jsx-attribute": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-attribute/-/babel-plugin-remove-jsx-attribute-8.0.0.tgz",
+ "integrity": "sha512-BcCkm/STipKvbCl6b7QFrMh/vx00vIP63k2eM66MfHJzPr6O2U0jYEViXkHJWqXqQYjdeA9cuCl5KWmlwjDvbA==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@svgr/babel-plugin-remove-jsx-empty-expression": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-remove-jsx-empty-expression/-/babel-plugin-remove-jsx-empty-expression-8.0.0.tgz",
+ "integrity": "sha512-5BcGCBfBxB5+XSDSWnhTThfI9jcO5f0Ai2V24gZpG+wXF14BzwxxdDb4g6trdOux0rhibGs385BeFMSmxtS3uA==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@svgr/babel-plugin-replace-jsx-attribute-value": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-replace-jsx-attribute-value/-/babel-plugin-replace-jsx-attribute-value-6.5.1.tgz",
+ "integrity": "sha512-8DPaVVE3fd5JKuIC29dqyMB54sA6mfgki2H2+swh+zNJoynC8pMPzOkidqHOSc6Wj032fhl8Z0TVn1GiPpAiJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@svgr/babel-plugin-svg-dynamic-title": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-dynamic-title/-/babel-plugin-svg-dynamic-title-6.5.1.tgz",
+ "integrity": "sha512-FwOEi0Il72iAzlkaHrlemVurgSQRDFbk0OC8dSvD5fSBPHltNh7JtLsxmZUhjYBZo2PpcU/RJvvi6Q0l7O7ogw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@svgr/babel-plugin-svg-em-dimensions": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-svg-em-dimensions/-/babel-plugin-svg-em-dimensions-6.5.1.tgz",
+ "integrity": "sha512-gWGsiwjb4tw+ITOJ86ndY/DZZ6cuXMNE/SjcDRg+HLuCmwpcjOktwRF9WgAiycTqJD/QXqL2f8IzE2Rzh7aVXA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@svgr/babel-plugin-transform-react-native-svg": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-react-native-svg/-/babel-plugin-transform-react-native-svg-6.5.1.tgz",
+ "integrity": "sha512-2jT3nTayyYP7kI6aGutkyfJ7UMGtuguD72OjeGLwVNyfPRBD8zQthlvL+fAbAKk5n9ZNcvFkp/b1lZ7VsYqVJg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@svgr/babel-plugin-transform-svg-component": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/babel-plugin-transform-svg-component/-/babel-plugin-transform-svg-component-6.5.1.tgz",
+ "integrity": "sha512-a1p6LF5Jt33O3rZoVRBqdxL350oge54iZWHNI6LJB5tQ7EelvD/Mb1mfBiZNAan0dt4i3VArkFRjA4iObuNykQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@svgr/babel-preset": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/babel-preset/-/babel-preset-6.5.1.tgz",
+ "integrity": "sha512-6127fvO/FF2oi5EzSQOAjo1LE3OtNVh11R+/8FXa+mHx1ptAaS4cknIjnUA7e6j6fwGGJ17NzaTJFUwOV2zwCw==",
+ "dev": true,
+ "dependencies": {
+ "@svgr/babel-plugin-add-jsx-attribute": "^6.5.1",
+ "@svgr/babel-plugin-remove-jsx-attribute": "*",
+ "@svgr/babel-plugin-remove-jsx-empty-expression": "*",
+ "@svgr/babel-plugin-replace-jsx-attribute-value": "^6.5.1",
+ "@svgr/babel-plugin-svg-dynamic-title": "^6.5.1",
+ "@svgr/babel-plugin-svg-em-dimensions": "^6.5.1",
+ "@svgr/babel-plugin-transform-react-native-svg": "^6.5.1",
+ "@svgr/babel-plugin-transform-svg-component": "^6.5.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@svgr/core": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/core/-/core-6.5.1.tgz",
+ "integrity": "sha512-/xdLSWxK5QkqG524ONSjvg3V/FkNyCv538OIBdQqPNaAta3AsXj/Bd2FbvR87yMbXO2hFSWiAe/Q6IkVPDw+mw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.19.6",
+ "@svgr/babel-preset": "^6.5.1",
+ "@svgr/plugin-jsx": "^6.5.1",
+ "camelcase": "^6.2.0",
+ "cosmiconfig": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ }
+ },
+ "node_modules/@svgr/hast-util-to-babel-ast": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/hast-util-to-babel-ast/-/hast-util-to-babel-ast-6.5.1.tgz",
+ "integrity": "sha512-1hnUxxjd83EAxbL4a0JDJoD3Dao3hmjvyvyEV8PzWmLK3B9m9NPlW7GKjFyoWE8nM7HnXzPcmmSyOW8yOddSXw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.20.0",
+ "entities": "^4.4.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ }
+ },
+ "node_modules/@svgr/plugin-jsx": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/plugin-jsx/-/plugin-jsx-6.5.1.tgz",
+ "integrity": "sha512-+UdQxI3jgtSjCykNSlEMuy1jSRQlGC7pqBCPvkG/2dATdWo082zHTTK3uhnAju2/6XpE6B5mZ3z4Z8Ns01S8Gw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.19.6",
+ "@svgr/babel-preset": "^6.5.1",
+ "@svgr/hast-util-to-babel-ast": "^6.5.1",
+ "svg-parser": "^2.0.4"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@svgr/core": "^6.0.0"
+ }
+ },
+ "node_modules/@svgr/plugin-svgo": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/plugin-svgo/-/plugin-svgo-6.5.1.tgz",
+ "integrity": "sha512-omvZKf8ixP9z6GWgwbtmP9qQMPX4ODXi+wzbVZgomNFsUIlHA1sf4fThdwTWSsZGgvGAG6yE+b/F5gWUkcZ/iQ==",
+ "dev": true,
+ "dependencies": {
+ "cosmiconfig": "^7.0.1",
+ "deepmerge": "^4.2.2",
+ "svgo": "^2.8.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ },
+ "peerDependencies": {
+ "@svgr/core": "*"
+ }
+ },
+ "node_modules/@svgr/webpack": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/@svgr/webpack/-/webpack-6.5.1.tgz",
+ "integrity": "sha512-cQ/AsnBkXPkEK8cLbv4Dm7JGXq2XrumKnL1dRpJD9rIO2fTIlJI9a1uCciYG1F2aUsox/hJQyNGbt3soDxSRkA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.19.6",
+ "@babel/plugin-transform-react-constant-elements": "^7.18.12",
+ "@babel/preset-env": "^7.19.4",
+ "@babel/preset-react": "^7.18.6",
+ "@babel/preset-typescript": "^7.18.6",
+ "@svgr/core": "^6.5.1",
+ "@svgr/plugin-jsx": "^6.5.1",
+ "@svgr/plugin-svgo": "^6.5.1"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ }
+ },
+ "node_modules/@testing-library/dom": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/@testing-library/dom/-/dom-10.4.0.tgz",
+ "integrity": "sha512-pemlzrSESWbdAloYml3bAJMEfNh1Z7EduzqPKprCH5S341frlpYnUEW0H72dLxa6IsYr+mPno20GiSm+h9dEdQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.10.4",
+ "@babel/runtime": "^7.12.5",
+ "@types/aria-query": "^5.0.1",
+ "aria-query": "5.3.0",
+ "chalk": "^4.1.0",
+ "dom-accessibility-api": "^0.5.9",
+ "lz-string": "^1.5.0",
+ "pretty-format": "^27.0.2"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/@testing-library/jest-dom": {
+ "version": "6.6.3",
+ "resolved": "https://registry.npmjs.org/@testing-library/jest-dom/-/jest-dom-6.6.3.tgz",
+ "integrity": "sha512-IteBhl4XqYNkM54f4ejhLRJiZNqcSCoXUOG2CPK7qbD322KjQozM4kHQOfkG2oln9b9HTYqs+Sae8vBATubxxA==",
+ "dev": true,
+ "dependencies": {
+ "@adobe/css-tools": "^4.4.0",
+ "aria-query": "^5.0.0",
+ "chalk": "^3.0.0",
+ "css.escape": "^1.5.1",
+ "dom-accessibility-api": "^0.6.3",
+ "lodash": "^4.17.21",
+ "redent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=14",
+ "npm": ">=6",
+ "yarn": ">=1"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/chalk": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/@testing-library/jest-dom/node_modules/dom-accessibility-api": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.6.3.tgz",
+ "integrity": "sha512-7ZgogeTnjuHbo+ct10G9Ffp0mif17idi0IyWNVA/wcwcm7NPOD/WEHVP3n7n3MhXqxoIYm8d6MuZohYWIZ4T3w==",
+ "dev": true
+ },
+ "node_modules/@testing-library/react": {
+ "version": "16.0.1",
+ "resolved": "https://registry.npmjs.org/@testing-library/react/-/react-16.0.1.tgz",
+ "integrity": "sha512-dSmwJVtJXmku+iocRhWOUFbrERC76TX2Mnf0ATODz8brzAZrMBbzLwQixlBSanZxR6LddK3eiwpSFZgDET1URg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.12.5"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": "^10.0.0",
+ "@types/react": "^18.0.0",
+ "@types/react-dom": "^18.0.0",
+ "react": "^18.0.0",
+ "react-dom": "^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@testing-library/user-event": {
+ "version": "14.5.2",
+ "resolved": "https://registry.npmjs.org/@testing-library/user-event/-/user-event-14.5.2.tgz",
+ "integrity": "sha512-YAh82Wh4TIrxYLmfGcixwD18oIjyC1pFQC2Y01F2lzV2HTMiYrI0nze0FD0ocB//CKS/7jIUgae+adPqxK5yCQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12",
+ "npm": ">=6"
+ },
+ "peerDependencies": {
+ "@testing-library/dom": ">=7.21.4"
+ }
+ },
+ "node_modules/@trysound/sax": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz",
+ "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/@tsconfig/node10": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node10/-/node10-1.0.11.tgz",
+ "integrity": "sha512-DcRjDCujK/kCk/cUe8Xz8ZSpm8mS3mNNpta+jGCA6USEDfktlNvm1+IuZ9eTcDbNk41BHwpHHeW+N1lKCz4zOw==",
+ "dev": true
+ },
+ "node_modules/@tsconfig/node12": {
+ "version": "1.0.11",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node12/-/node12-1.0.11.tgz",
+ "integrity": "sha512-cqefuRsh12pWyGsIoBKJA9luFu3mRxCA+ORZvA4ktLSzIuCUtWVxGIuXigEwO5/ywWFMZ2QEGKWvkZG1zDMTag==",
+ "dev": true
+ },
+ "node_modules/@tsconfig/node14": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node14/-/node14-1.0.3.tgz",
+ "integrity": "sha512-ysT8mhdixWK6Hw3i1V2AeRqZ5WfXg1G43mqoYlM2nc6388Fq5jcXyr5mRsqViLx/GJYdoL0bfXD8nmF+Zn/Iow==",
+ "dev": true
+ },
+ "node_modules/@tsconfig/node16": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/@tsconfig/node16/-/node16-1.0.4.tgz",
+ "integrity": "sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==",
+ "dev": true
+ },
+ "node_modules/@types/aria-query": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/@types/aria-query/-/aria-query-5.0.4.tgz",
+ "integrity": "sha512-rfT93uj5s0PRL7EzccGMs3brplhcrghnDoV26NqKhCAS1hVo+WdNsPvE/yb6ilfr5hi2MEk6d5EWJTKdxg8jVw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@types/axios": {
+ "version": "0.14.4",
+ "resolved": "https://registry.npmjs.org/@types/axios/-/axios-0.14.4.tgz",
+ "integrity": "sha512-9JgOaunvQdsQ/qW2OPmE5+hCeUB52lQSolecrFrthct55QekhmXEwT203s20RL+UHtCQc15y3VXpby9E7Kkh/g==",
+ "deprecated": "This is a stub types definition. axios provides its own type definitions, so you do not need this installed.",
+ "dev": true,
+ "dependencies": {
+ "axios": "*"
+ }
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.8",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
+ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.6",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
+ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/body-parser": {
+ "version": "1.19.5",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.5.tgz",
+ "integrity": "sha512-fB3Zu92ucau0iQ0JMCFQE7b/dv8Ot07NI3KaZIkIUNXq82k4eBAqUaneXfleGY9JWskeS9y+u0nXMyspcuQrCg==",
+ "dev": true,
+ "dependencies": {
+ "@types/connect": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/bonjour": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz",
+ "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/cheerio": {
+ "version": "0.22.35",
+ "resolved": "https://registry.npmjs.org/@types/cheerio/-/cheerio-0.22.35.tgz",
+ "integrity": "sha512-yD57BchKRvTV+JD53UZ6PD8KWY5g5rvvMLRnZR3EQBCZXiDT/HR+pKpMzFGlWNhFrXlo7VPZXtKvIEwZkAWOIA==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect": {
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/connect-history-api-fallback": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz",
+ "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==",
+ "dev": true,
+ "dependencies": {
+ "@types/express-serve-static-core": "*",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/date-fns": {
+ "version": "2.6.3",
+ "resolved": "https://registry.npmjs.org/@types/date-fns/-/date-fns-2.6.3.tgz",
+ "integrity": "sha512-Ke1lw2Ni1t/wMUoLtKFmSNCLozcTBd6vmMqFP4hRzXn6qzkNt97bPAX0x5Y/c15DP43kKvwW1ycStD5+43jVQA==",
+ "deprecated": "This is a stub types definition. date-fns provides its own type definitions, so you do not need this installed.",
+ "dev": true,
+ "dependencies": {
+ "date-fns": "*"
+ }
+ },
+ "node_modules/@types/enzyme": {
+ "version": "3.10.18",
+ "resolved": "https://registry.npmjs.org/@types/enzyme/-/enzyme-3.10.18.tgz",
+ "integrity": "sha512-RaO/TyyHZvXkpzinbMTZmd/S5biU4zxkvDsn22ujC29t9FMSzq8tnn8f2MxQ2P8GVhFRG5jTAL05DXKyTtpEQQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/cheerio": "*",
+ "@types/react": "^16"
+ }
+ },
+ "node_modules/@types/enzyme/node_modules/@types/react": {
+ "version": "16.14.62",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-16.14.62.tgz",
+ "integrity": "sha512-BWf7hqninZav6nerxXj+NeZT/mTpDeG6Lk2zREHAy63CrnXoOGPGtNqTFYFN/sqpSaREDP5otVV88axIXmKfGA==",
+ "dev": true,
+ "dependencies": {
+ "@types/prop-types": "*",
+ "@types/scheduler": "^0.16",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/eslint": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-9.6.1.tgz",
+ "integrity": "sha512-FXx2pKgId/WyYo2jXw63kk7/+TY7u7AziEJxJAnSFzHlqTAS3Ync6SvgYAN/k4/PQpnnVuzoMuVnByKK2qp0ag==",
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/eslint-scope": {
+ "version": "3.7.7",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+ "dependencies": {
+ "@types/eslint": "*",
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw=="
+ },
+ "node_modules/@types/express": {
+ "version": "4.17.25",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
+ "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/body-parser": "*",
+ "@types/express-serve-static-core": "^4.17.33",
+ "@types/qs": "*",
+ "@types/serve-static": "^1"
+ }
+ },
+ "node_modules/@types/express-serve-static-core": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.0.1.tgz",
+ "integrity": "sha512-CRICJIl0N5cXDONAdlTv5ShATZ4HEwk6kDDIW2/w9qOWKg+NU/5F8wYRWCrONad0/UKkloNSmmyN/wX4rtpbVA==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/express/node_modules/@types/express-serve-static-core": {
+ "version": "4.19.6",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.6.tgz",
+ "integrity": "sha512-N4LZ2xG7DatVqhCZzOGb1Yi5lMbXSZcmdLDe9EzSndPV2HpWYWzRbaerl2n27irrm94EPpprqa8KpskPT085+A==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/graceful-fs": {
+ "version": "4.1.9",
+ "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz",
+ "integrity": "sha512-olP3sd1qOEe5dXTSaFvQG+02VdRXcdytWLAZsAq1PecU8uqQAhkrnbli7DagjtXKW/Bl7YJbUsa8MPcuc8LHEQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/history": {
+ "version": "4.7.11",
+ "resolved": "https://registry.npmjs.org/@types/history/-/history-4.7.11.tgz",
+ "integrity": "sha512-qjDJRrmvBMiTx+jyLxvLfJU7UznFuokDv4f3WRuriHKERccVpFU+8XMQUAbDzoiJCsmexxRExQeMwwCdamSKDA==",
+ "dev": true
+ },
+ "node_modules/@types/hoist-non-react-statics": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.5.tgz",
+ "integrity": "sha512-SbcrWzkKBw2cdwRTwQAswfpB9g9LJWfjtUeW/jvNwbhC8cpmmNYVePa+ncbUe0rGTQ7G3Ff6mYUN2VMfLVr+Sg==",
+ "dependencies": {
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0"
+ }
+ },
+ "node_modules/@types/html-minifier-terser": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
+ "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==",
+ "dev": true
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.4.tgz",
+ "integrity": "sha512-D0CFMMtydbJAegzOyHjtiKPLlvnm3iTZyZRSZoLq2mRhDdmLfIWOCYPfQJ4cu2erKghU++QvjcUjp/5h7hESpA==",
+ "dev": true
+ },
+ "node_modules/@types/http-proxy": {
+ "version": "1.17.15",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.15.tgz",
+ "integrity": "sha512-25g5atgiVNTIv0LBDTg1H74Hvayx0ajtJPLLcYE3whFv75J0pWNtOBzaXJQgDTmrX1bx5U9YC2w/n65BN1HwRQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w=="
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
+ "node_modules/@types/jest": {
+ "version": "29.5.14",
+ "resolved": "https://registry.npmjs.org/@types/jest/-/jest-29.5.14.tgz",
+ "integrity": "sha512-ZN+4sdnLUbo8EVvVc2ao0GFW6oVrQRPn4K2lglySj7APvSrgzxHiNNK99us4WDMi57xxA2yggblIAMNhXOotLQ==",
+ "dev": true,
+ "dependencies": {
+ "expect": "^29.0.0",
+ "pretty-format": "^29.0.0"
+ }
+ },
+ "node_modules/@types/jest/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/@types/jest/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@types/js-yaml": {
+ "version": "4.0.9",
+ "resolved": "https://registry.npmjs.org/@types/js-yaml/-/js-yaml-4.0.9.tgz",
+ "integrity": "sha512-k4MGaQl5TGo/iipqb2UDG2UwjXziSWkh0uysQelTlJpX1qGlpUZYm8PnO4DxG1qBomtJUdYJ6qR6xdIah10JLg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
+ },
+ "node_modules/@types/lodash": {
+ "version": "4.17.13",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.13.tgz",
+ "integrity": "sha512-lfx+dftrEZcdBPczf9d0Qv0x+j/rfNCMuC6OcfXmO8gkfeNAY88PgKUbvG56whcN23gc27yenwF6oJZXGFpYxg=="
+ },
+ "node_modules/@types/mime": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
+ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
+ "dev": true
+ },
+ "node_modules/@types/node": {
+ "version": "22.10.1",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-22.10.1.tgz",
+ "integrity": "sha512-qKgsUwfHZV2WCWLAnVP1JqnpE6Im6h3Y0+fYgMTasNQ7V++CBX5OT1as0g0f+OyubbFqhf6XVNIsmN4IIhEgGQ==",
+ "dependencies": {
+ "undici-types": "~6.20.0"
+ }
+ },
+ "node_modules/@types/node-fetch": {
+ "version": "2.6.11",
+ "resolved": "https://registry.npmjs.org/@types/node-fetch/-/node-fetch-2.6.11.tgz",
+ "integrity": "sha512-24xFj9R5+rfQJLRyM56qh+wnVSYhyXC2tkoBndtY0U+vubqNsYXGjufB2nn8Q6gt0LrARwL6UBtMCSVCwl4B1g==",
+ "dependencies": {
+ "@types/node": "*",
+ "form-data": "^4.0.0"
+ }
+ },
+ "node_modules/@types/parse-json": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
+ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
+ "dev": true
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.13",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
+ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA=="
+ },
+ "node_modules/@types/qs": {
+ "version": "6.9.16",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.16.tgz",
+ "integrity": "sha512-7i+zxXdPD0T4cKDuxCUXJ4wHcsJLwENa6Z3dCu8cfCK743OGy5Nu1RmAGqDPsoTDINVEcdXKRvR/zre+P2Ku1A==",
+ "dev": true
+ },
+ "node_modules/@types/range-parser": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.12",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
+ "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
+ "devOptional": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-helmet": {
+ "version": "6.1.11",
+ "resolved": "https://registry.npmjs.org/@types/react-helmet/-/react-helmet-6.1.11.tgz",
+ "integrity": "sha512-0QcdGLddTERotCXo3VFlUSWO3ztraw8nZ6e3zJSgG7apwV5xt+pJUS8ewPBqT4NYB1optGLprNQzFleIY84u/g==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-redux": {
+ "version": "7.1.34",
+ "resolved": "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.34.tgz",
+ "integrity": "sha512-GdFaVjEbYv4Fthm2ZLvj1VSCedV7TqE5y1kNwnjSdBOTXuRSgowux6J8TAct15T3CKBr63UMk+2CO7ilRhyrAQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/hoist-non-react-statics": "^3.3.0",
+ "@types/react": "*",
+ "hoist-non-react-statics": "^3.3.0",
+ "redux": "^4.0.0"
+ }
+ },
+ "node_modules/@types/react-redux/node_modules/redux": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz",
+ "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.9.2"
+ }
+ },
+ "node_modules/@types/react-router": {
+ "version": "5.1.20",
+ "resolved": "https://registry.npmjs.org/@types/react-router/-/react-router-5.1.20.tgz",
+ "integrity": "sha512-jGjmu/ZqS7FjSH6owMcD5qpq19+1RS9DeVRqfl1FeBMxTDQAGwlMWOcs52NDoXaNKyG3d1cYQFMs9rCrb88o9Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/history": "^4.7.11",
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-router-dom": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/@types/react-router-dom/-/react-router-dom-5.3.3.tgz",
+ "integrity": "sha512-kpqnYK4wcdm5UaWI3fLcELopqLrHgLqNsdpHauzlQktfkHL3npOSwtj1Uz9oKBAzs7lFtVkV8j83voAz2D8fhw==",
+ "dev": true,
+ "dependencies": {
+ "@types/history": "^4.7.11",
+ "@types/react": "*",
+ "@types/react-router": "*"
+ }
+ },
+ "node_modules/@types/react-test-renderer": {
+ "version": "18.3.0",
+ "resolved": "https://registry.npmjs.org/@types/react-test-renderer/-/react-test-renderer-18.3.0.tgz",
+ "integrity": "sha512-HW4MuEYxfDbOHQsVlY/XtOvNHftCVEPhJF2pQXXwcUiUF+Oyb0usgp48HSgpK5rt8m9KZb22yqOeZm+rrVG8gw==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/retry": {
+ "version": "0.12.2",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.2.tgz",
+ "integrity": "sha512-XISRgDJ2Tc5q4TRqvgJtzsRkFYNJzZrhTdtMoGVBttwzzQJkPnS3WWTFc7kuDRoPtPakl+T+OfdEUjYJj7Jbow==",
+ "dev": true
+ },
+ "node_modules/@types/scheduler": {
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@types/scheduler/-/scheduler-0.16.8.tgz",
+ "integrity": "sha512-WZLiwShhwLRmeV6zH+GkbOFT6Z6VklCItrDioxUnv+u4Ll+8vKeFySoFyK/0ctcRpOmwAicELfmys1sDc/Rw+A==",
+ "dev": true
+ },
+ "node_modules/@types/send": {
+ "version": "0.17.4",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.4.tgz",
+ "integrity": "sha512-x2EM6TJOybec7c52BX0ZspPodMsQUd5L6PRwOunVyVUhXiBSKf3AezDL8Dgvgt5o0UfKNfuA0eMLr2wLT4AiBA==",
+ "dev": true,
+ "dependencies": {
+ "@types/mime": "^1",
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/serve-index": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz",
+ "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==",
+ "dev": true,
+ "dependencies": {
+ "@types/express": "*"
+ }
+ },
+ "node_modules/@types/serve-static": {
+ "version": "1.15.7",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.7.tgz",
+ "integrity": "sha512-W8Ym+h8nhuRwaKPaDw34QUkwsGi6Rc4yYqvKFo5rm2FUEhCFbzVWrxXUxuKK8TASjWsysJY0nsmNCGhCOIsrOw==",
+ "dev": true,
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/sockjs": {
+ "version": "0.3.36",
+ "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz",
+ "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/stack-utils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@types/stack-utils/-/stack-utils-2.0.3.tgz",
+ "integrity": "sha512-9aEbYZ3TbYMznPdcdr3SmIrLXwC/AKZXQeCf9Pgao5CKb8CyHuEX5jzWPTkvregvhRJHcpRO6BFoGW9ycaOkYw==",
+ "dev": true
+ },
+ "node_modules/@types/stylis": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz",
+ "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/@types/use-sync-external-store": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
+ "integrity": "sha512-EwmlvuaxPNej9+T4v5AuBPJa2x2UOJVdjCtDHgcDqitUeOtjnJKJ+apYjVcAoBEMjKW1VVFGZLUb5+qqa09XFA=="
+ },
+ "node_modules/@types/ws": {
+ "version": "8.5.12",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.5.12.tgz",
+ "integrity": "sha512-3tPRkv1EtkDpzlgyKyI8pGsGZAGPEaXeu0DOj5DI25Ja91bdAYddYHbADRYVrZMRbfW+1l5YwXVDKohDJNQxkQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
+ "node_modules/@types/yargs": {
+ "version": "17.0.33",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.33.tgz",
+ "integrity": "sha512-WpxBCKWPLr4xSsHgz511rFJAM+wS28w2zEO1QDNY5zM/S8ok70NNfztH0xwhqKyaK0OHCbN98LDAZuy1ctxDkA==",
+ "dependencies": {
+ "@types/yargs-parser": "*"
+ }
+ },
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ=="
+ },
+ "node_modules/@types/yup": {
+ "version": "0.29.14",
+ "resolved": "https://registry.npmjs.org/@types/yup/-/yup-0.29.14.tgz",
+ "integrity": "sha512-Ynb/CjHhE/Xp/4bhHmQC4U1Ox+I2OpfRYF3dnNgQqn1cHa6LK3H1wJMNPT02tSVZA6FYuXE2ITORfbnb6zBCSA==",
+ "license": "MIT"
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.33.1.tgz",
+ "integrity": "sha512-TDCXj+YxLgtvxvFlAvpoRv9MAncDLBV2oT9Bd7YBGC/b/sEURoOYuIwLI99rjWOfY3QtDzO+mk0n4AmdFExW8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.33.1",
+ "@typescript-eslint/type-utils": "8.33.1",
+ "@typescript-eslint/utils": "8.33.1",
+ "@typescript-eslint/visitor-keys": "8.33.1",
+ "graphemer": "^1.4.0",
+ "ignore": "^7.0.0",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.33.1",
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.9.0"
+ }
+ },
+ "node_modules/@typescript-eslint/eslint-plugin/node_modules/ignore": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-7.0.5.tgz",
+ "integrity": "sha512-Hs59xBNfUIunMFgWAbGX5cq6893IbWg4KnrjbYwX3tx0ztorVgTDA6B2sxf8ejHJ4wz8BqGUMYlnzNBer5NvGg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.33.1.tgz",
+ "integrity": "sha512-qwxv6dq682yVvgKKp2qWwLgRbscDAYktPptK4JPojCwwi3R9cwrvIxS4lvBpzmcqzR4bdn54Z0IG1uHFskW4dA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.33.1",
+ "@typescript-eslint/types": "8.33.1",
+ "@typescript-eslint/typescript-estree": "8.33.1",
+ "@typescript-eslint/visitor-keys": "8.33.1",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.9.0"
+ }
+ },
+ "node_modules/@typescript-eslint/project-service": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/project-service/-/project-service-8.33.1.tgz",
+ "integrity": "sha512-DZR0efeNklDIHHGRpMpR5gJITQpu6tLr9lDJnKdONTC7vvzOlLAG/wcfxcdxEWrbiZApcoBCzXqU/Z458Za5Iw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/tsconfig-utils": "^8.33.1",
+ "@typescript-eslint/types": "^8.33.1",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <5.9.0"
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.33.1.tgz",
+ "integrity": "sha512-dM4UBtgmzHR9bS0Rv09JST0RcHYearoEoo3pG5B6GoTR9XcyeqX87FEhPo+5kTvVfKCvfHaHrcgeJQc6mrDKrA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.33.1",
+ "@typescript-eslint/visitor-keys": "8.33.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/tsconfig-utils": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/tsconfig-utils/-/tsconfig-utils-8.33.1.tgz",
+ "integrity": "sha512-STAQsGYbHCF0/e+ShUQ4EatXQ7ceh3fBCXkNU7/MZVKulrlq1usH7t2FhxvCpuCi5O5oi1vmVaAjrGeL71OK1g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <5.9.0"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.33.1.tgz",
+ "integrity": "sha512-1cG37d9xOkhlykom55WVwG2QRNC7YXlxMaMzqw2uPeJixBFfKWZgaP/hjAObqMN/u3fr5BrTwTnc31/L9jQ2ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "8.33.1",
+ "@typescript-eslint/utils": "8.33.1",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.9.0"
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.33.1.tgz",
+ "integrity": "sha512-xid1WfizGhy/TKMTwhtVOgalHwPtV8T32MS9MaH50Cwvz6x6YqRIPdD2WvW0XaqOzTV9p5xdLY0h/ZusU5Lokg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.33.1.tgz",
+ "integrity": "sha512-+s9LYcT8LWjdYWu7IWs7FvUxpQ/DGkdjZeE/GGulHvv8rvYwQvVaUZ6DE+j5x/prADUgSbbCWZ2nPI3usuVeOA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/project-service": "8.33.1",
+ "@typescript-eslint/tsconfig-utils": "8.33.1",
+ "@typescript-eslint/types": "8.33.1",
+ "@typescript-eslint/visitor-keys": "8.33.1",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.2",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^2.1.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4 <5.9.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree/node_modules/semver": {
+ "version": "7.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.2.tgz",
+ "integrity": "sha512-RF0Fw+rO5AMf9MAyaRXI4AV0Ulj5lMHqVxxdSgiVbixSCXoEmmX/jk0CuJw4+3SqroYO9VoUh+HcuJivvtJemA==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.33.1.tgz",
+ "integrity": "sha512-52HaBiEQUaRYqAXpfzWSR2U3gxk92Kw006+xZpElaPMg3C4PgM+A5LqwoQI1f9E5aZ/qlxAZxzm42WX+vn92SQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.7.0",
+ "@typescript-eslint/scope-manager": "8.33.1",
+ "@typescript-eslint/types": "8.33.1",
+ "@typescript-eslint/typescript-estree": "8.33.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0",
+ "typescript": ">=4.8.4 <5.9.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.33.1",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.33.1.tgz",
+ "integrity": "sha512-3i8NrFcZeeDHJ+7ZUuDkGT+UHq+XoFGsymNK2jZCOHcfEzRQ0BdpRtdpSx/Iyf3MHLWIcLS0COuOPibKQboIiQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@typescript-eslint/types": "8.33.1",
+ "eslint-visitor-keys": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys/node_modules/eslint-visitor-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+ "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@webassemblyjs/ast": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.12.1.tgz",
+ "integrity": "sha512-EKfMUOPRRUTy5UII4qJDGPpqfwjOmZ5jeGFwid9mnoqIFK+e0vqoi1qH56JpmZSzEL53jKnNzScdmftJyG5xWg==",
+ "dependencies": {
+ "@webassemblyjs/helper-numbers": "1.11.6",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6"
+ }
+ },
+ "node_modules/@webassemblyjs/floating-point-hex-parser": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz",
+ "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw=="
+ },
+ "node_modules/@webassemblyjs/helper-api-error": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz",
+ "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q=="
+ },
+ "node_modules/@webassemblyjs/helper-buffer": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.12.1.tgz",
+ "integrity": "sha512-nzJwQw99DNDKr9BVCOZcLuJJUlqkJh+kVzVl6Fmq/tI5ZtEyWT1KZMyOXltXLZJmDtvLCDgwsyrkohEtopTXCw=="
+ },
+ "node_modules/@webassemblyjs/helper-numbers": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz",
+ "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==",
+ "dependencies": {
+ "@webassemblyjs/floating-point-hex-parser": "1.11.6",
+ "@webassemblyjs/helper-api-error": "1.11.6",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz",
+ "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA=="
+ },
+ "node_modules/@webassemblyjs/helper-wasm-section": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.12.1.tgz",
+ "integrity": "sha512-Jif4vfB6FJlUlSbgEMHUyk1j234GTNG9dBJ4XJdOySoj518Xj0oGsNi59cUQF4RRMS9ouBUxDDdyBVfPTypa5g==",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.12.1",
+ "@webassemblyjs/helper-buffer": "1.12.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+ "@webassemblyjs/wasm-gen": "1.12.1"
+ }
+ },
+ "node_modules/@webassemblyjs/ieee754": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz",
+ "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==",
+ "dependencies": {
+ "@xtuc/ieee754": "^1.2.0"
+ }
+ },
+ "node_modules/@webassemblyjs/leb128": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz",
+ "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==",
+ "dependencies": {
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webassemblyjs/utf8": {
+ "version": "1.11.6",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz",
+ "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA=="
+ },
+ "node_modules/@webassemblyjs/wasm-edit": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.12.1.tgz",
+ "integrity": "sha512-1DuwbVvADvS5mGnXbE+c9NfA8QRcZ6iKquqjjmR10k6o+zzsRVesil54DKexiowcFCPdr/Q0qaMgB01+SQ1u6g==",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.12.1",
+ "@webassemblyjs/helper-buffer": "1.12.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+ "@webassemblyjs/helper-wasm-section": "1.12.1",
+ "@webassemblyjs/wasm-gen": "1.12.1",
+ "@webassemblyjs/wasm-opt": "1.12.1",
+ "@webassemblyjs/wasm-parser": "1.12.1",
+ "@webassemblyjs/wast-printer": "1.12.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-gen": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.12.1.tgz",
+ "integrity": "sha512-TDq4Ojh9fcohAw6OIMXqiIcTq5KUXTGRkVxbSo1hQnSy6lAM5GSdfwWeSxpAo0YzgsgF182E/U0mDNhuA0tW7w==",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.12.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+ "@webassemblyjs/ieee754": "1.11.6",
+ "@webassemblyjs/leb128": "1.11.6",
+ "@webassemblyjs/utf8": "1.11.6"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-opt": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.12.1.tgz",
+ "integrity": "sha512-Jg99j/2gG2iaz3hijw857AVYekZe2SAskcqlWIZXjji5WStnOpVoat3gQfT/Q5tb2djnCjBtMocY/Su1GfxPBg==",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.12.1",
+ "@webassemblyjs/helper-buffer": "1.12.1",
+ "@webassemblyjs/wasm-gen": "1.12.1",
+ "@webassemblyjs/wasm-parser": "1.12.1"
+ }
+ },
+ "node_modules/@webassemblyjs/wasm-parser": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.12.1.tgz",
+ "integrity": "sha512-xikIi7c2FHXysxXe3COrVUPSheuBtpcfhbpFj4gmu7KRLYOzANztwUU0IbsqvMqzuNK2+glRGWCEqZo1WCLyAQ==",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.12.1",
+ "@webassemblyjs/helper-api-error": "1.11.6",
+ "@webassemblyjs/helper-wasm-bytecode": "1.11.6",
+ "@webassemblyjs/ieee754": "1.11.6",
+ "@webassemblyjs/leb128": "1.11.6",
+ "@webassemblyjs/utf8": "1.11.6"
+ }
+ },
+ "node_modules/@webassemblyjs/wast-printer": {
+ "version": "1.12.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.12.1.tgz",
+ "integrity": "sha512-+X4WAlOisVWQMikjbcvY2e0rwPsKQ9F688lksZhBcPycBBuii3O7m8FACbDMWDojpAqvjIncrG8J0XHKyQfVeA==",
+ "dependencies": {
+ "@webassemblyjs/ast": "1.12.1",
+ "@xtuc/long": "4.2.2"
+ }
+ },
+ "node_modules/@webpack-cli/configtest": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/configtest/-/configtest-2.1.1.tgz",
+ "integrity": "sha512-wy0mglZpDSiSS0XHrVR+BAdId2+yxPSoJW8fsna3ZpYSlufjvxnP4YbKTCBZnNIcGN4r6ZPXV55X4mYExOfLmw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x",
+ "webpack-cli": "5.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/info": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/info/-/info-2.0.2.tgz",
+ "integrity": "sha512-zLHQdI/Qs1UyT5UBdWNqsARasIA+AaF8t+4u2aS2nEpBQh2mWIVb8qAklq0eUENnC5mOItrIB4LiS9xMtph18A==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x",
+ "webpack-cli": "5.x.x"
+ }
+ },
+ "node_modules/@webpack-cli/serve": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@webpack-cli/serve/-/serve-2.0.5.tgz",
+ "integrity": "sha512-lqaoKnRYBdo1UgDX8uF24AfGMifWK19TxPmM5FHc2vAGxrJ/qtyUyFBWoY1tISZdelsQ5fBcOusifo5o5wSJxQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x",
+ "webpack-cli": "5.x.x"
+ },
+ "peerDependenciesMeta": {
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@xtuc/ieee754": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
+ "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
+ },
+ "node_modules/@xtuc/long": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
+ "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
+ },
+ "node_modules/abort-controller": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/abort-controller/-/abort-controller-3.0.0.tgz",
+ "integrity": "sha512-h8lQ8tacZYnR3vNQTgibj+tODHI5/+l06Au2Pcriv/Gmet0eaj4TwWH41sO9wnHDiQsEj19q0drzdWdeAHtweg==",
+ "dependencies": {
+ "event-target-shim": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=6.5"
+ }
+ },
+ "node_modules/accepts": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
+ "dev": true,
+ "dependencies": {
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/ace-builds": {
+ "version": "1.36.3",
+ "resolved": "https://registry.npmjs.org/ace-builds/-/ace-builds-1.36.3.tgz",
+ "integrity": "sha512-YcdwV2IIaJSfjkWAR1NEYN5IxBiXefTgwXsJ//UlaFrjXDX5hQpvPFvEePHz2ZBUfvO54RjHeRUQGX8MS5HaMQ=="
+ },
+ "node_modules/acorn": {
+ "version": "8.15.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz",
+ "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/acorn-walk": {
+ "version": "8.3.4",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.4.tgz",
+ "integrity": "sha512-ueEepnujpqee2o5aIYnvHU6C0A42MNdsIDeqy5BydrkuC5R1ZuUFnm27EeFJGoEHJQgn3uleRvmTXaJgfXbt4g==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/address": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz",
+ "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/adjust-sourcemap-loader": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/adjust-sourcemap-loader/-/adjust-sourcemap-loader-4.0.0.tgz",
+ "integrity": "sha512-OXwN5b9pCUXNQHJpwwD2qP40byEmSgzj8B4ydSN0uMNYWiFmJ6x6KwUllMmfk8Rwu/HJDFR7U8ubsWBoN0Xp0A==",
+ "dev": true,
+ "dependencies": {
+ "loader-utils": "^2.0.0",
+ "regex-parser": "^2.2.11"
+ },
+ "engines": {
+ "node": ">=8.9"
+ }
+ },
+ "node_modules/adjust-sourcemap-loader/node_modules/loader-utils": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+ "dev": true,
+ "dependencies": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=8.9.0"
+ }
+ },
+ "node_modules/agentkeepalive": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/agentkeepalive/-/agentkeepalive-4.5.0.tgz",
+ "integrity": "sha512-5GG/5IbQQpC9FpkRGsSvZI5QYeSCzlJHdpBQntCsuTOxhKD8lqKhrleg2Yi7yvMIf82Ycmmqln9U8V9qwEiJew==",
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 8.0.0"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "8.17.1",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.17.1.tgz",
+ "integrity": "sha512-B/gBuNg5SiMTrPkC+A2+cW0RszwxYmn6VYxB/inlBStS5nx6xHIt/ehKRhIMhqusl7a8LjQoZnjCs5vhwxOQ1g==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-draft-04": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/ajv-draft-04/-/ajv-draft-04-1.0.0.tgz",
+ "integrity": "sha512-mv00Te6nmYbRp5DCwclxtt7yV/joXJPGS7nM+97GdxvuttCOfgI3K4U25zboyeX0O+myI8ERluxQe5wljMmVIw==",
+ "dev": true,
+ "peerDependencies": {
+ "ajv": "^8.5.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependencies": {
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/ansi-escapes": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
+ "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "dev": true,
+ "dependencies": {
+ "type-fest": "^0.21.3"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/ansi-html": {
+ "version": "0.0.9",
+ "resolved": "https://registry.npmjs.org/ansi-html/-/ansi-html-0.0.9.tgz",
+ "integrity": "sha512-ozbS3LuenHVxNRh/wdnN16QapUHzauqSomAl1jwwJRRsGwFwtj644lIhxfWu0Fy0acCij2+AEgHvjscq3dlVXg==",
+ "dev": true,
+ "engines": [
+ "node >= 0.8.0"
+ ],
+ "bin": {
+ "ansi-html": "bin/ansi-html"
+ }
+ },
+ "node_modules/ansi-html-community": {
+ "version": "0.0.8",
+ "resolved": "https://registry.npmjs.org/ansi-html-community/-/ansi-html-community-0.0.8.tgz",
+ "integrity": "sha512-1APHAyr3+PCamwNw3bXCPp4HFLONZt/yIH0sZp0/469KWNTEy+qN5jQ3GVX6DMZ1UXAi34yVwtTeaG/HpBuuzw==",
+ "dev": true,
+ "engines": [
+ "node >= 0.8.0"
+ ],
+ "bin": {
+ "ansi-html": "bin/ansi-html"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-4.1.3.tgz",
+ "integrity": "sha512-58S9QDqG0Xx27YwPSt9fJxivjYl432YCwfDMfZ+71RAqUrZef7LrKQZ3LHLOwCS4FLNBplP533Zx895SeOCHvA==",
+ "dev": true
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
+ "license": "Python-2.0"
+ },
+ "node_modules/aria-query": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.0.tgz",
+ "integrity": "sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==",
+ "dev": true,
+ "dependencies": {
+ "dequal": "^2.0.3"
+ }
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.2.tgz",
+ "integrity": "sha512-LHE+8BuR7RYGDKvnrmcuSq3tDcKv9OFEXQt/HpbZhY7V6h0zlUXutnAD82GiFx9rdieCMjkvtcsPqBwgUl1Iiw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "is-array-buffer": "^3.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-flatten": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.9",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.9.tgz",
+ "integrity": "sha512-FmeCCAenzH0KH381SPT5FZmiA/TmpndpcaShhfgEN9eCVjnFBqq3l1xrI42y8+PPLI6hypzou4GXw00WHmPBLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.0",
+ "es-object-atoms": "^1.1.1",
+ "get-intrinsic": "^1.3.0",
+ "is-string": "^1.1.1",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-union": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/array.prototype.filter": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.filter/-/array.prototype.filter-1.0.4.tgz",
+ "integrity": "sha512-r+mCJ7zXgXElgR4IRC+fkvNCeoaavWBs6EdCso5Tbcf+iEMKzBU/His60lt34WEZ9vlb8wDkZvQGcVI5GwkfoQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-array-method-boxes-properly": "^1.0.0",
+ "es-object-atoms": "^1.0.0",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlast": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlast/-/array.prototype.findlast-1.2.5.tgz",
+ "integrity": "sha512-CVvd6FHg1Z3POpBLxO6E6zr+rSKEQ9L6rZHAaY7lLfhKsWYUBBOuMs0e9o24oopj6H+geRCX0YJ+TJLBK2eHyQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.3.tgz",
+ "integrity": "sha512-rwG/ja1neyLqCuGZ5YYrznA62D4mZXg0i1cIskIUKSiqF3Cje9/wXAls9B9s1Wa2fomMsIv8czB8jZcPmxCXFg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.3.tgz",
+ "integrity": "sha512-Y7Wt51eKJSyi80hFrJCePGGNo5ktJCslFuboqJsbf57CCPcm5zztluPlc4/aD8sWsKvlwatezpV4U1efk8kpjg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.tosorted": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/array.prototype.tosorted/-/array.prototype.tosorted-1.1.4.tgz",
+ "integrity": "sha512-p6Fx8B7b7ZhL/gmUsAy0D15WhvDccw3mnGNbZpi3pmeJdxtWsj2jEaI4Y6oo3XiHfzuSgPwKc04MYt6KgvC/wA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.3",
+ "es-errors": "^1.3.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.4.tgz",
+ "integrity": "sha512-BNoCY6SXXPQ7gF2opIP4GBE+Xw7U+pHMYKuzjgCN3GwiaIR09UUeKfheyIry77QtrCBlC0KK0q5/TER/tYh3PQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/asn1js": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/asn1js/-/asn1js-3.0.7.tgz",
+ "integrity": "sha512-uLvq6KJu04qoQM6gvBfKFjlh6Gl0vOKQuR5cJMDHQkmwfMOQeN3F3SHCv9SNYSL+CRoHvOGFfllDlVz03GQjvQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "pvtsutils": "^1.3.6",
+ "pvutils": "^1.1.3",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/async": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
+ "dev": true
+ },
+ "node_modules/async-function": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/async-function/-/async-function-1.0.0.tgz",
+ "integrity": "sha512-hsU18Ae8CDTR6Kgu9DYf0EbCr/a5iGL0rytQDobUcdpYOKokk8LEjVphnXkDkgpi0wYVsqrXuP0bZxJaTqdgoA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/author-regex": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/author-regex/-/author-regex-1.0.0.tgz",
+ "integrity": "sha512-KbWgR8wOYRAPekEmMXrYYdc7BRyhn2Ftk7KWfMUnQ43hFdojWEFRxhhRUm3/OFEdPa1r0KAvTTg9YQK57xTe0g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.20",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
+ "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "browserslist": "^4.23.3",
+ "caniuse-lite": "^1.0.30001646",
+ "fraction.js": "^4.3.7",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.13.2.tgz",
+ "integrity": "sha512-VPk9ebNqPcy5lRGuSlKx752IlDatOjT9paPlm8A7yOuW2Fbvp4X3JznJtT4f0GzGLLiWE9W8onz51SqLYwzGaA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.4",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/babel-helper-evaluate-path": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-evaluate-path/-/babel-helper-evaluate-path-0.5.0.tgz",
+ "integrity": "sha512-mUh0UhS607bGh5wUMAQfOpt2JX2ThXMtppHRdRU1kL7ZLRWIXxoV2UIV1r2cAeeNeU1M5SB5/RSUgUxrK8yOkA==",
+ "dev": true
+ },
+ "node_modules/babel-helper-flip-expressions": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-flip-expressions/-/babel-helper-flip-expressions-0.4.3.tgz",
+ "integrity": "sha512-rSrkRW4YQ2ETCWww9gbsWk4N0x1BOtln349Tk0dlCS90oT68WMLyGR7WvaMp3eAnsVrCqdUtC19lo1avyGPejA==",
+ "dev": true
+ },
+ "node_modules/babel-helper-is-nodes-equiv": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/babel-helper-is-nodes-equiv/-/babel-helper-is-nodes-equiv-0.0.1.tgz",
+ "integrity": "sha512-ri/nsMFVRqXn7IyT5qW4/hIAGQxuYUFHa3qsxmPtbk6spZQcYlyDogfVpNm2XYOslH/ULS4VEJGUqQX5u7ACQw==",
+ "dev": true
+ },
+ "node_modules/babel-helper-is-void-0": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-is-void-0/-/babel-helper-is-void-0-0.4.3.tgz",
+ "integrity": "sha512-07rBV0xPRM3TM5NVJEOQEkECX3qnHDjaIbFvWYPv+T1ajpUiVLiqTfC+MmiZxY5KOL/Ec08vJdJD9kZiP9UkUg==",
+ "dev": true
+ },
+ "node_modules/babel-helper-mark-eval-scopes": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-mark-eval-scopes/-/babel-helper-mark-eval-scopes-0.4.3.tgz",
+ "integrity": "sha512-+d/mXPP33bhgHkdVOiPkmYoeXJ+rXRWi7OdhwpyseIqOS8CmzHQXHUp/+/Qr8baXsT0kjGpMHHofHs6C3cskdA==",
+ "dev": true
+ },
+ "node_modules/babel-helper-remove-or-void": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-remove-or-void/-/babel-helper-remove-or-void-0.4.3.tgz",
+ "integrity": "sha512-eYNceYtcGKpifHDir62gHJadVXdg9fAhuZEXiRQnJJ4Yi4oUTpqpNY//1pM4nVyjjDMPYaC2xSf0I+9IqVzwdA==",
+ "dev": true
+ },
+ "node_modules/babel-helper-to-multiple-sequence-expressions": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/babel-helper-to-multiple-sequence-expressions/-/babel-helper-to-multiple-sequence-expressions-0.5.0.tgz",
+ "integrity": "sha512-m2CvfDW4+1qfDdsrtf4dwOslQC3yhbgyBFptncp4wvtdrDHqueW7slsYv4gArie056phvQFhT2nRcGS4bnm6mA==",
+ "dev": true
+ },
+ "node_modules/babel-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.7.0.tgz",
+ "integrity": "sha512-BrvGY3xZSwEcCzKvKsCi2GgHqDqsYkOP4/by5xCgIwGXQxIEh+8ew3gmrE1y7XRR6LHZIj6yLYnUi/mm2KXKBg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/transform": "^29.7.0",
+ "@types/babel__core": "^7.1.14",
+ "babel-plugin-istanbul": "^6.1.1",
+ "babel-preset-jest": "^29.6.3",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.8.0"
+ }
+ },
+ "node_modules/babel-jest/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-loader": {
+ "version": "9.2.1",
+ "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-9.2.1.tgz",
+ "integrity": "sha512-fqe8naHt46e0yIdkjUZYqddSXfej3AHajX+CSO5X7oy0EmPc6o5Xh+RClNoHjnieWz9AW4kZxW9yyFMhVB1QLA==",
+ "dev": true,
+ "dependencies": {
+ "find-cache-dir": "^4.0.0",
+ "schema-utils": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.12.0",
+ "webpack": ">=5"
+ }
+ },
+ "node_modules/babel-loader/node_modules/find-cache-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-4.0.0.tgz",
+ "integrity": "sha512-9ZonPT4ZAK4a+1pUPVPZJapbi7O5qbbJPdYw/NOQWZZbVLdDTYM3A4R9z/DpAM08IDaFGsvPgiGZ82WEwUDWjg==",
+ "dev": true,
+ "dependencies": {
+ "common-path-prefix": "^3.0.0",
+ "pkg-dir": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/babel-loader/node_modules/find-up": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-6.3.0.tgz",
+ "integrity": "sha512-v2ZsoEuVHYy8ZIlYqwPe/39Cy+cFDzp4dXPaxNvkEuouymu+2Jbz0PxpKarJHYJTmv2HWT3O382qY8l4jMWthw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^7.1.0",
+ "path-exists": "^5.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/babel-loader/node_modules/locate-path": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-7.2.0.tgz",
+ "integrity": "sha512-gvVijfZvn7R+2qyPX8mAuKcFGDf6Nc61GdvGafQsHL0sBIxfKzA+usWn4GFC/bk+QdwPUD4kWFJLhElipq+0VA==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^6.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/babel-loader/node_modules/p-limit": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-4.0.0.tgz",
+ "integrity": "sha512-5b0R4txpzjPWVw/cXXUResoD4hb6U/x9BH08L7nw+GN1sezDzPdxeRvpc9c433fZhBan/wusjbCsqwqm4EIBIQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^1.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/babel-loader/node_modules/p-locate": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-6.0.0.tgz",
+ "integrity": "sha512-wPrq66Llhl7/4AGC6I+cqxT07LhXvWL08LNXz1fENOw0Ap4sRZZ/gZpTTJ5jpurzzzfS2W/Ge9BY3LgLjCShcw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/babel-loader/node_modules/path-exists": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-5.0.0.tgz",
+ "integrity": "sha512-RjhtfwJOxzcFmNOi6ltcbcu4Iu+FL3zEj83dk4kAS+fVpTxXLO1b38RvJgT/0QwvV/L3aY9TAnyv0EOqW4GoMQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ }
+ },
+ "node_modules/babel-loader/node_modules/pkg-dir": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-7.0.0.tgz",
+ "integrity": "sha512-Ie9z/WINcxxLp27BKOCHGde4ITq9UklYKDzVo1nhk5sqGEXU3FpkwP5GM2voTGJkGd9B3Otl+Q4uwSOeSUtOBA==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/babel-loader/node_modules/yocto-queue": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-1.1.1.tgz",
+ "integrity": "sha512-b4JR1PFR10y1mKjhHY9LaGo6tmrgjit7hxVIeAmyMw3jegXR4dhYqLaQF5zMXZxY7tLpMyJeLjr1C4rLmkVe8g==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.20"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/babel-plugin-istanbul": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
+ "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.0.0",
+ "@istanbuljs/load-nyc-config": "^1.0.0",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-instrument": "^5.0.4",
+ "test-exclude": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-istanbul/node_modules/istanbul-lib-instrument": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
+ "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.12.3",
+ "@babel/parser": "^7.14.7",
+ "@istanbuljs/schema": "^0.1.2",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^6.3.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/babel-plugin-jest-hoist": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.6.3.tgz",
+ "integrity": "sha512-ESAc/RJvGTFEzRwOTT4+lNDk/GNHMkKbNzsvT0qKRfDyyYTskxB5rnU2njIDYVxXCBHHEI1c0YwHob3WaYujOg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.3.3",
+ "@babel/types": "^7.3.3",
+ "@types/babel__core": "^7.1.14",
+ "@types/babel__traverse": "^7.0.6"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/babel-plugin-minify-builtins": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-builtins/-/babel-plugin-minify-builtins-0.5.0.tgz",
+ "integrity": "sha512-wpqbN7Ov5hsNwGdzuzvFcjgRlzbIeVv1gMIlICbPj0xkexnfoIDe7q+AZHMkQmAE/F9R5jkrB6TLfTegImlXag==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-minify-constant-folding": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-constant-folding/-/babel-plugin-minify-constant-folding-0.5.0.tgz",
+ "integrity": "sha512-Vj97CTn/lE9hR1D+jKUeHfNy+m1baNiJ1wJvoGyOBUx7F7kJqDZxr9nCHjO/Ad+irbR3HzR6jABpSSA29QsrXQ==",
+ "dev": true,
+ "dependencies": {
+ "babel-helper-evaluate-path": "^0.5.0"
+ }
+ },
+ "node_modules/babel-plugin-minify-dead-code-elimination": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-dead-code-elimination/-/babel-plugin-minify-dead-code-elimination-0.5.2.tgz",
+ "integrity": "sha512-krq9Lwi0QIzyAlcNBXTL4usqUvevB4BzktdEsb8srcXC1AaYqRJiAQw6vdKdJSaXbz6snBvziGr6ch/aoRCfpA==",
+ "dev": true,
+ "dependencies": {
+ "babel-helper-evaluate-path": "^0.5.0",
+ "babel-helper-mark-eval-scopes": "^0.4.3",
+ "babel-helper-remove-or-void": "^0.4.3",
+ "lodash": "^4.17.11"
+ }
+ },
+ "node_modules/babel-plugin-minify-flip-comparisons": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-flip-comparisons/-/babel-plugin-minify-flip-comparisons-0.4.3.tgz",
+ "integrity": "sha512-8hNwgLVeJzpeLVOVArag2DfTkbKodzOHU7+gAZ8mGBFGPQHK6uXVpg3jh5I/F6gfi5Q5usWU2OKcstn1YbAV7A==",
+ "dev": true,
+ "dependencies": {
+ "babel-helper-is-void-0": "^0.4.3"
+ }
+ },
+ "node_modules/babel-plugin-minify-guarded-expressions": {
+ "version": "0.4.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-guarded-expressions/-/babel-plugin-minify-guarded-expressions-0.4.4.tgz",
+ "integrity": "sha512-RMv0tM72YuPPfLT9QLr3ix9nwUIq+sHT6z8Iu3sLbqldzC1Dls8DPCywzUIzkTx9Zh1hWX4q/m9BPoPed9GOfA==",
+ "dev": true,
+ "dependencies": {
+ "babel-helper-evaluate-path": "^0.5.0",
+ "babel-helper-flip-expressions": "^0.4.3"
+ }
+ },
+ "node_modules/babel-plugin-minify-infinity": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-infinity/-/babel-plugin-minify-infinity-0.4.3.tgz",
+ "integrity": "sha512-X0ictxCk8y+NvIf+bZ1HJPbVZKMlPku3lgYxPmIp62Dp8wdtbMLSekczty3MzvUOlrk5xzWYpBpQprXUjDRyMA==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-minify-mangle-names": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-mangle-names/-/babel-plugin-minify-mangle-names-0.5.1.tgz",
+ "integrity": "sha512-8KMichAOae2FHlipjNDTo2wz97MdEb2Q0jrn4NIRXzHH7SJ3c5TaNNBkeTHbk9WUsMnqpNUx949ugM9NFWewzw==",
+ "dev": true,
+ "dependencies": {
+ "babel-helper-mark-eval-scopes": "^0.4.3"
+ }
+ },
+ "node_modules/babel-plugin-minify-numeric-literals": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-numeric-literals/-/babel-plugin-minify-numeric-literals-0.4.3.tgz",
+ "integrity": "sha512-5D54hvs9YVuCknfWywq0eaYDt7qYxlNwCqW9Ipm/kYeS9gYhJd0Rr/Pm2WhHKJ8DC6aIlDdqSBODSthabLSX3A==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-minify-replace": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-replace/-/babel-plugin-minify-replace-0.5.0.tgz",
+ "integrity": "sha512-aXZiaqWDNUbyNNNpWs/8NyST+oU7QTpK7J9zFEFSA0eOmtUNMU3fczlTTTlnCxHmq/jYNFEmkkSG3DDBtW3Y4Q==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-minify-simplify": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-simplify/-/babel-plugin-minify-simplify-0.5.1.tgz",
+ "integrity": "sha512-OSYDSnoCxP2cYDMk9gxNAed6uJDiDz65zgL6h8d3tm8qXIagWGMLWhqysT6DY3Vs7Fgq7YUDcjOomhVUb+xX6A==",
+ "dev": true,
+ "dependencies": {
+ "babel-helper-evaluate-path": "^0.5.0",
+ "babel-helper-flip-expressions": "^0.4.3",
+ "babel-helper-is-nodes-equiv": "^0.0.1",
+ "babel-helper-to-multiple-sequence-expressions": "^0.5.0"
+ }
+ },
+ "node_modules/babel-plugin-minify-type-constructors": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-minify-type-constructors/-/babel-plugin-minify-type-constructors-0.4.3.tgz",
+ "integrity": "sha512-4ADB0irJ/6BeXWHubjCJmrPbzhxDgjphBMjIjxCc25n4NGJ00NsYqwYt+F/OvE9RXx8KaSW7cJvp+iZX436tnQ==",
+ "dev": true,
+ "dependencies": {
+ "babel-helper-is-void-0": "^0.4.3"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.4.11",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.11.tgz",
+ "integrity": "sha512-sMEJ27L0gRHShOh5G54uAAPaiCOygY/5ratXuiyb2G46FmlSpc9eFCzYVyDiPxfNbwzA7mYahmjQc5q+CZQ09Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.22.6",
+ "@babel/helper-define-polyfill-provider": "^0.6.2",
+ "semver": "^6.3.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.10.6",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.10.6.tgz",
+ "integrity": "sha512-b37+KR2i/khY5sKmWNVQAnitvquQbNdWy6lJdsr0kmquCKEEUgMKK4SboVM3HtfnZilfjr4MMQ7vY58FVWDtIA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.2",
+ "core-js-compat": "^3.38.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-polyfill-regenerator": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.2.tgz",
+ "integrity": "sha512-2R25rQZWP63nGwaAswvDazbPXfrM3HwVoBXK6HcqeKrSrL/JqcC/rDcf95l4r7LXLyxDXc8uQDa064GubtCABg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.2"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
+ }
+ },
+ "node_modules/babel-plugin-transform-inline-consecutive-adds": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-inline-consecutive-adds/-/babel-plugin-transform-inline-consecutive-adds-0.4.3.tgz",
+ "integrity": "sha512-8D104wbzzI5RlxeVPYeQb9QsUyepiH1rAO5hpPpQ6NPRgQLpIVwkS/Nbx944pm4K8Z+rx7CgjPsFACz/VCBN0Q==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-transform-member-expression-literals": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-member-expression-literals/-/babel-plugin-transform-member-expression-literals-6.9.4.tgz",
+ "integrity": "sha512-Xq9/Rarpj+bjOZSl1nBbZYETsNEDDJSrb6Plb1sS3/36FukWFLLRysgecva5KZECjUJTrJoQqjJgtWToaflk5Q==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-transform-merge-sibling-variables": {
+ "version": "6.9.5",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-merge-sibling-variables/-/babel-plugin-transform-merge-sibling-variables-6.9.5.tgz",
+ "integrity": "sha512-xj/KrWi6/uP+DrD844h66Qh2cZN++iugEIgH8QcIxhmZZPNP6VpOE9b4gP2FFW39xDAY43kCmYMM6U0QNKN8fw==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-transform-minify-booleans": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-minify-booleans/-/babel-plugin-transform-minify-booleans-6.9.4.tgz",
+ "integrity": "sha512-9pW9ePng6DZpzGPalcrULuhSCcauGAbn8AeU3bE34HcDkGm8Ldt0ysjGkyb64f0K3T5ilV4mriayOVv5fg0ASA==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-transform-property-literals": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-property-literals/-/babel-plugin-transform-property-literals-6.9.4.tgz",
+ "integrity": "sha512-Pf8JHTjTPxecqVyL6KSwD/hxGpoTZjiEgV7nCx0KFQsJYM0nuuoCajbg09KRmZWeZbJ5NGTySABYv8b/hY1eEA==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ }
+ },
+ "node_modules/babel-plugin-transform-regexp-constructors": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-regexp-constructors/-/babel-plugin-transform-regexp-constructors-0.4.3.tgz",
+ "integrity": "sha512-JjymDyEyRNhAoNFp09y/xGwYVYzT2nWTGrBrWaL6eCg2m+B24qH2jR0AA8V8GzKJTgC8NW6joJmc6nabvWBD/g==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-transform-remove-console": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-console/-/babel-plugin-transform-remove-console-6.9.4.tgz",
+ "integrity": "sha512-88blrUrMX3SPiGkT1GnvVY8E/7A+k6oj3MNvUtTIxJflFzXTw1bHkuJ/y039ouhFMp2prRn5cQGzokViYi1dsg==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-transform-remove-debugger": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-debugger/-/babel-plugin-transform-remove-debugger-6.9.4.tgz",
+ "integrity": "sha512-Kd+eTBYlXfwoFzisburVwrngsrz4xh9I0ppoJnU/qlLysxVBRgI4Pj+dk3X8F5tDiehp3hhP8oarRMT9v2Z3lw==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-transform-remove-undefined": {
+ "version": "0.5.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-remove-undefined/-/babel-plugin-transform-remove-undefined-0.5.0.tgz",
+ "integrity": "sha512-+M7fJYFaEE/M9CXa0/IRkDbiV3wRELzA1kKQFCJ4ifhrzLKn/9VCCgj9OFmYWwBd8IB48YdgPkHYtbYq+4vtHQ==",
+ "dev": true,
+ "dependencies": {
+ "babel-helper-evaluate-path": "^0.5.0"
+ }
+ },
+ "node_modules/babel-plugin-transform-simplify-comparison-operators": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-simplify-comparison-operators/-/babel-plugin-transform-simplify-comparison-operators-6.9.4.tgz",
+ "integrity": "sha512-GLInxhGAQWJ9YIdjwF6dAFlmh4U+kN8pL6Big7nkDzHoZcaDQOtBm28atEhQJq6m9GpAovbiGEShKqXv4BSp0A==",
+ "dev": true
+ },
+ "node_modules/babel-plugin-transform-undefined-to-void": {
+ "version": "6.9.4",
+ "resolved": "https://registry.npmjs.org/babel-plugin-transform-undefined-to-void/-/babel-plugin-transform-undefined-to-void-6.9.4.tgz",
+ "integrity": "sha512-D2UbwxawEY1xVc9svYAUZQM2xarwSNXue2qDIx6CeV2EuMGaes/0su78zlIDIAgE7BvnMw4UpmSo9fDy+znghg==",
+ "dev": true
+ },
+ "node_modules/babel-preset-current-node-syntax": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.1.0.tgz",
+ "integrity": "sha512-ldYss8SbBlWva1bs28q78Ju5Zq1F+8BrqBZZ0VFhLBvhh6lCpC2o3gDJi/5DRLs9FgYZCnmPYIVFU4lRXCkyUw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/plugin-syntax-async-generators": "^7.8.4",
+ "@babel/plugin-syntax-bigint": "^7.8.3",
+ "@babel/plugin-syntax-class-properties": "^7.12.13",
+ "@babel/plugin-syntax-class-static-block": "^7.14.5",
+ "@babel/plugin-syntax-import-attributes": "^7.24.7",
+ "@babel/plugin-syntax-import-meta": "^7.10.4",
+ "@babel/plugin-syntax-json-strings": "^7.8.3",
+ "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
+ "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
+ "@babel/plugin-syntax-numeric-separator": "^7.10.4",
+ "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
+ "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
+ "@babel/plugin-syntax-optional-chaining": "^7.8.3",
+ "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
+ "@babel/plugin-syntax-top-level-await": "^7.14.5"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-jest": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.6.3.tgz",
+ "integrity": "sha512-0B3bhxR6snWXJZtR/RliHTDPRgn1sNHOR0yVtq/IiQFyuOVjFS+wuio/R4gSNkyYmKmJB4wGZv2NZanmKmTnNA==",
+ "dev": true,
+ "dependencies": {
+ "babel-plugin-jest-hoist": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/babel-preset-minify": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/babel-preset-minify/-/babel-preset-minify-0.5.2.tgz",
+ "integrity": "sha512-v4GL+kk0TfovbRIKZnC3HPbu2cAGmPAby7BsOmuPdMJfHV+4FVdsGXTH/OOGQRKYdjemBuL1+MsE6mobobhe9w==",
+ "dev": true,
+ "dependencies": {
+ "babel-plugin-minify-builtins": "^0.5.0",
+ "babel-plugin-minify-constant-folding": "^0.5.0",
+ "babel-plugin-minify-dead-code-elimination": "^0.5.2",
+ "babel-plugin-minify-flip-comparisons": "^0.4.3",
+ "babel-plugin-minify-guarded-expressions": "^0.4.4",
+ "babel-plugin-minify-infinity": "^0.4.3",
+ "babel-plugin-minify-mangle-names": "^0.5.1",
+ "babel-plugin-minify-numeric-literals": "^0.4.3",
+ "babel-plugin-minify-replace": "^0.5.0",
+ "babel-plugin-minify-simplify": "^0.5.1",
+ "babel-plugin-minify-type-constructors": "^0.4.3",
+ "babel-plugin-transform-inline-consecutive-adds": "^0.4.3",
+ "babel-plugin-transform-member-expression-literals": "^6.9.4",
+ "babel-plugin-transform-merge-sibling-variables": "^6.9.5",
+ "babel-plugin-transform-minify-booleans": "^6.9.4",
+ "babel-plugin-transform-property-literals": "^6.9.4",
+ "babel-plugin-transform-regexp-constructors": "^0.4.3",
+ "babel-plugin-transform-remove-console": "^6.9.4",
+ "babel-plugin-transform-remove-debugger": "^6.9.4",
+ "babel-plugin-transform-remove-undefined": "^0.5.0",
+ "babel-plugin-transform-simplify-comparison-operators": "^6.9.4",
+ "babel-plugin-transform-undefined-to-void": "^6.9.4",
+ "lodash": "^4.17.11"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/batch": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
+ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
+ "dev": true
+ },
+ "node_modules/big.js": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
+ "integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/body-parser": {
+ "version": "1.20.4",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.4.tgz",
+ "integrity": "sha512-ZTgYYLMOXY9qKU/57FAo8F+HA2dGX7bqGc71txDRC1rS4frdFI5R7NhluHxH6M0YItAP0sHB4uqAOcYKxO6uGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "content-type": "~1.0.5",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "~1.2.0",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "on-finished": "~2.4.1",
+ "qs": "~6.14.0",
+ "raw-body": "~2.5.3",
+ "type-is": "~1.6.18",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/body-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/body-parser/node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/body-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/bonjour-service": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.2.1.tgz",
+ "integrity": "sha512-oSzCS2zV14bh2kji6vNe7vrpJYCHGvcZnlffFQ1MEoX/WOeQ/teD8SYWKR942OI3INjq8OMNJlbPK5LLLUxFDw==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "multicast-dns": "^7.2.5"
+ }
+ },
+ "node_modules/boolbase": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww=="
+ },
+ "node_modules/brace-expansion": {
+ "version": "1.1.12",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.12.tgz",
+ "integrity": "sha512-9T9UjW3r0UW5c1Q7GTwllptXwhvYmEzFhzMfZ9H7FQWt+uZePjZPjBP/W1ZEyZ1twGWom5/56TF4lPcqjnDHcg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.24.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
+ "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001669",
+ "electron-to-chromium": "^1.5.41",
+ "node-releases": "^2.0.18",
+ "update-browserslist-db": "^1.1.1"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/bs-logger": {
+ "version": "0.2.6",
+ "resolved": "https://registry.npmjs.org/bs-logger/-/bs-logger-0.2.6.tgz",
+ "integrity": "sha512-pd8DCoxmbgc7hyPKOvxtqNcjYoOsABPQdcCUjGp3d42VR2CX1ORhk2A87oqqu5R1kk+76nsxZupkmyd+MVtCog==",
+ "dev": true,
+ "dependencies": {
+ "fast-json-stable-stringify": "2.x"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/bser": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
+ "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
+ "dev": true,
+ "dependencies": {
+ "node-int64": "^0.4.0"
+ }
+ },
+ "node_modules/buffer-from": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
+ },
+ "node_modules/bundle-name": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz",
+ "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==",
+ "dev": true,
+ "dependencies": {
+ "run-applescript": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/bytes": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/bytestreamjs": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/bytestreamjs/-/bytestreamjs-2.0.1.tgz",
+ "integrity": "sha512-U1Z/ob71V/bXfVABvNr/Kumf5VyeQRBEm6Txb0PQ6S7V5GpBM3w4Cbqz/xPDicR5tN0uvDifng8C+5qECeGwyQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.8.tgz",
+ "integrity": "sha512-oKlSFMcMwpUg2ednkhQ454wfWiU/ul3CkJe/PEHcTKuiX6RpbehUiFMXu13HalGZxfUwCQzZG747YXBn1im9ww==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-bind-apply-helpers": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz",
+ "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/call-me-maybe": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.2.tgz",
+ "integrity": "sha512-HpX65o1Hnr9HH25ojC1YGs7HCQLq0GCOibSaWER0eNpgJ/Z1MZv2mTc7+xh6WOPxbRVcmgbv4hGU+uSQ/2xFZQ==",
+ "dev": true
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camel-case": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
+ "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
+ "dev": true,
+ "dependencies": {
+ "pascal-case": "^3.1.2",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/camelize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "dev": true,
+ "peer": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/caniuse-api": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
+ "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==",
+ "dependencies": {
+ "browserslist": "^4.0.0",
+ "caniuse-lite": "^1.0.0",
+ "lodash.memoize": "^4.1.2",
+ "lodash.uniq": "^4.5.0"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001675",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001675.tgz",
+ "integrity": "sha512-/wV1bQwPrkLiQMjaJF5yUMVM/VdRPOCU8QZ+PmG6uW6DvYSrNY1bpwHI/3mOcUosLaJCzYDi5o91IQB51ft6cg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/char-regex": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/char-regex/-/char-regex-1.0.2.tgz",
+ "integrity": "sha512-kWWXztvZ5SBQV+eRgKFeh8q5sLuZY2+8WUIzlxWVTg+oGwY14qylx1KbKzHd8P6ZYkAg0xyIDU9JMHhyJMZ1jw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/charenc": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/charenc/-/charenc-0.0.2.tgz",
+ "integrity": "sha512-yrLQ/yVUFXkzg7EDQsPieE/53+0RlaWTs+wBrvW36cyilJ2SaDWfl4Yj7MtLTXleV9uEKefbAGUPv2/iWSooRA==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/cheerio": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/cheerio/-/cheerio-1.0.0.tgz",
+ "integrity": "sha512-quS9HgjQpdaXOvsZz82Oz7uxtXiy6UIsIQcpBj7HRw2M63Skasm9qlDocAM7jNuaxdhpPU7c4kJN+gA5MCu4ww==",
+ "dev": true,
+ "dependencies": {
+ "cheerio-select": "^2.1.0",
+ "dom-serializer": "^2.0.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.1.0",
+ "encoding-sniffer": "^0.2.0",
+ "htmlparser2": "^9.1.0",
+ "parse5": "^7.1.2",
+ "parse5-htmlparser2-tree-adapter": "^7.0.0",
+ "parse5-parser-stream": "^7.1.2",
+ "undici": "^6.19.5",
+ "whatwg-mimetype": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=18.17"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/cheerio?sponsor=1"
+ }
+ },
+ "node_modules/cheerio-select": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cheerio-select/-/cheerio-select-2.1.0.tgz",
+ "integrity": "sha512-9v9kG0LvzrlcungtnJtpGNxY+fzECQKhK4EGJX2vByejiMX84MFNQw4UxPJl3bFbTMw+Dfs37XaIkCwTZfLh4g==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-select": "^5.1.0",
+ "css-what": "^6.1.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chrome-trace-event": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
+ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+ "engines": {
+ "node": ">=6.0"
+ }
+ },
+ "node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/circular-dependency-plugin": {
+ "version": "5.2.2",
+ "resolved": "https://registry.npmjs.org/circular-dependency-plugin/-/circular-dependency-plugin-5.2.2.tgz",
+ "integrity": "sha512-g38K9Cm5WRwlaH6g03B9OEz/0qRizI+2I7n+Gz+L5DxXJAPAiWQvwlYNm1V1jkdpUv95bOe/ASm2vfi/G560jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.0.0"
+ },
+ "peerDependencies": {
+ "webpack": ">=4.0.1"
+ }
+ },
+ "node_modules/cjs-module-lexer": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/cjs-module-lexer/-/cjs-module-lexer-1.4.1.tgz",
+ "integrity": "sha512-cuSVIHi9/9E/+821Qjdvngor+xpnlwnuwIyZOaLmHBVdXL+gP+I6QQB9VkO7RI77YIcTV+S1W9AreJ5eN63JBA==",
+ "dev": true
+ },
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
+ },
+ "node_modules/clean-css": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz",
+ "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==",
+ "dev": true,
+ "dependencies": {
+ "source-map": "~0.6.0"
+ },
+ "engines": {
+ "node": ">= 10.0"
+ }
+ },
+ "node_modules/clean-css/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/cli-cursor": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz",
+ "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "restore-cursor": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-truncate": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz",
+ "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "slice-ansi": "^5.0.0",
+ "string-width": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-truncate/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/cli-truncate/node_modules/emoji-regex": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
+ "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/cli-truncate/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/cli-truncate/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/cliui": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-8.0.1.tgz",
+ "integrity": "sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^4.2.0",
+ "strip-ansi": "^6.0.1",
+ "wrap-ansi": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
+ "dev": true,
+ "dependencies": {
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/clsx": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-1.2.1.tgz",
+ "integrity": "sha512-EcR6r5a8bj6pu3ycsa/E/cKVGuTgZJZdsyUYHOksG/UHIiKfjxzRxYJpyVBwYaQeOvghal9fcc4PidlgzugAQg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/co": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz",
+ "integrity": "sha512-QVb0dM5HvG+uaxitm8wONl7jltx8dqhfU33DcqtOZcLSVIKSDDLDi7+0LbAKiyI8hD9u42m2YxXSkMGWThaecQ==",
+ "dev": true,
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/collect-v8-coverage": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/collect-v8-coverage/-/collect-v8-coverage-1.0.2.tgz",
+ "integrity": "sha512-lHl4d5/ONEbLlJvaJNtsF/Lz+WvB07u2ycqTYbdrq7UypDXailES4valYb2eWiJFxZlVmpGekfqoxQhzyFdT4Q==",
+ "dev": true
+ },
+ "node_modules/color": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/color/-/color-4.2.3.tgz",
+ "integrity": "sha512-1rXeuUUiGGrykh+CeBdu5Ie7OJwinCgQY0bc7GCRxy5xVHy+moaqkpL/jqQq0MtQOeYcrqEz4abc5f0KtU7W4A==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1",
+ "color-string": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=12.5.0"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA=="
+ },
+ "node_modules/color-string": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.1.tgz",
+ "integrity": "sha512-shrVawQFojnZv6xM40anx4CkoDP+fZsw/ZerEMsW/pyzsRbElpsL/DBVW7q3ExxwusdNXI3lXpuhEZkzs8p5Eg==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "^1.0.0",
+ "simple-swizzle": "^0.2.2"
+ }
+ },
+ "node_modules/colord": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
+ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw=="
+ },
+ "node_modules/colorette": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+ "dev": true
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-6.2.1.tgz",
+ "integrity": "sha512-U7VdrJFnJgo4xjrHpTzu0yrHPGImdsmD95ZlgYSEajAn2JKzDhDTPG9kBTefmObL2w/ngeZnilk+OV9CG3d7UA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/common-path-prefix": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/common-path-prefix/-/common-path-prefix-3.0.0.tgz",
+ "integrity": "sha512-QE33hToZseCH3jS0qN96O/bSh3kaw/h+Tq7ngyY9eWDUnTlTNUyqfqvCXioLe5Na5jFsL78ra/wuBU4iuEgd4w==",
+ "dev": true
+ },
+ "node_modules/commondir": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
+ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+ "dev": true
+ },
+ "node_modules/compressible": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
+ "integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": ">= 1.43.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/compression": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
+ "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "3.1.2",
+ "compressible": "~2.0.18",
+ "debug": "2.6.9",
+ "negotiator": "~0.6.4",
+ "on-headers": "~1.1.0",
+ "safe-buffer": "5.2.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/compression/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/compression/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/compression/node_modules/negotiator": {
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
+ "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/connect-history-api-fallback": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+ "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/content-disposition": {
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "5.2.1"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/content-type": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true
+ },
+ "node_modules/cookie": {
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/cookie-signature": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
+ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/copy-webpack-plugin": {
+ "version": "11.0.0",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-11.0.0.tgz",
+ "integrity": "sha512-fX2MWpamkW0hZxMEg0+mYnA40LTosOSa5TqZ9GYIBzyJa9C3QUaMPSE2xAi/buNr8u89SfD9wHSQVBzrRa/SOQ==",
+ "dev": true,
+ "dependencies": {
+ "fast-glob": "^3.2.11",
+ "glob-parent": "^6.0.1",
+ "globby": "^13.1.1",
+ "normalize-path": "^3.0.0",
+ "schema-utils": "^4.0.0",
+ "serialize-javascript": "^6.0.0"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.1.0"
+ }
+ },
+ "node_modules/copy-webpack-plugin/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/copy-webpack-plugin/node_modules/globby": {
+ "version": "13.2.2",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-13.2.2.tgz",
+ "integrity": "sha512-Y1zNGV+pzQdh7H39l9zgB4PJqjRNqydvdYCDG4HFXM4XuvSaQQlEc91IU1yALL8gUTDomgBAfz3XJdmUS+oo0w==",
+ "dev": true,
+ "dependencies": {
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.3.0",
+ "ignore": "^5.2.4",
+ "merge2": "^1.4.1",
+ "slash": "^4.0.0"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/copy-webpack-plugin/node_modules/slash": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-4.0.0.tgz",
+ "integrity": "sha512-3dOsAHXXUkQTpOYcoAxLIorMTp4gIQr5IW3iVb7A7lFIp0VHhnynm9izx6TssdrIcVIESAlVjtnO2K8bg+Coew==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/core-js-compat": {
+ "version": "3.38.1",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.38.1.tgz",
+ "integrity": "sha512-JRH6gfXxGmrzF3tZ57lFx97YARxCXPaMzPo6jELZhv88pBH5VXpQ+y0znKGlFnzuaihqhLbefxSJxWJMPtfDzw==",
+ "dev": true,
+ "dependencies": {
+ "browserslist": "^4.23.3"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/core-js-pure": {
+ "version": "3.38.1",
+ "resolved": "https://registry.npmjs.org/core-js-pure/-/core-js-pure-3.38.1.tgz",
+ "integrity": "sha512-BY8Etc1FZqdw1glX0XNOq2FDwfrg/VGqoZOZCdaL+UmdaqDwQwYXkMJT4t6In+zfEfOJDcM9T0KdbBeJg8KKCQ==",
+ "hasInstallScript": true,
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/core-js"
+ }
+ },
+ "node_modules/core-util-is": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "dev": true
+ },
+ "node_modules/cosmiconfig": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+ "dev": true,
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/create-jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/create-jest/-/create-jest-29.7.0.tgz",
+ "integrity": "sha512-Adz2bdH0Vq3F53KEMJOoftQFutWCukm6J24wbPWRO4k1kMY7gS7ds/uoJkNuV8wDCtWWnuwGcJwpWcih+zEW1Q==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "exit": "^0.1.2",
+ "graceful-fs": "^4.2.9",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "prompts": "^2.0.1"
+ },
+ "bin": {
+ "create-jest": "bin/create-jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/create-require": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/create-require/-/create-require-1.1.1.tgz",
+ "integrity": "sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==",
+ "dev": true
+ },
+ "node_modules/cross-env": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
+ "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.1"
+ },
+ "bin": {
+ "cross-env": "src/bin/cross-env.js",
+ "cross-env-shell": "src/bin/cross-env-shell.js"
+ },
+ "engines": {
+ "node": ">=10.14",
+ "npm": ">=6",
+ "yarn": ">=1"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/crypt": {
+ "version": "0.0.2",
+ "resolved": "https://registry.npmjs.org/crypt/-/crypt-0.0.2.tgz",
+ "integrity": "sha512-mCxBlsHFYh9C+HVpiEacem8FEBnMXgU9gy4zmNC+SXAZNB/1idgp/aulFJ4FgCi7GPEVbfyng092GqL2k2rmow==",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/css-blank-pseudo": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/css-blank-pseudo/-/css-blank-pseudo-3.0.3.tgz",
+ "integrity": "sha512-VS90XWtsHGqoM0t4KpH053c4ehxZ2E6HtGI7x68YFV0pTo/QmkV/YFA+NnlvK8guxZVNWGQhVNJGC39Q8XF4OQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.9"
+ },
+ "bin": {
+ "css-blank-pseudo": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/css-color-keywords": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/css-declaration-sorter": {
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz",
+ "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==",
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.9"
+ }
+ },
+ "node_modules/css-has-pseudo": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/css-has-pseudo/-/css-has-pseudo-3.0.4.tgz",
+ "integrity": "sha512-Vse0xpR1K9MNlp2j5w1pgWIJtm1a8qS0JwS9goFYcImjlHEmywP9VUF05aGBXzGpDJF86QXk4L0ypBmwPhGArw==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.9"
+ },
+ "bin": {
+ "css-has-pseudo": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/css-loader": {
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz",
+ "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==",
+ "dev": true,
+ "dependencies": {
+ "icss-utils": "^5.1.0",
+ "postcss": "^8.4.33",
+ "postcss-modules-extract-imports": "^3.1.0",
+ "postcss-modules-local-by-default": "^4.0.5",
+ "postcss-modules-scope": "^3.2.0",
+ "postcss-modules-values": "^4.0.0",
+ "postcss-value-parser": "^4.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "@rspack/core": "0.x || 1.x",
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/core": {
+ "optional": true
+ },
+ "webpack": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/css-loader/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/css-minimizer-webpack-plugin": {
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-4.2.2.tgz",
+ "integrity": "sha512-s3Of/4jKfw1Hj9CxEO1E5oXhQAxlayuHO2y/ML+C6I9sQ7FdzfEV6QgMLN3vI+qFsjJGIAFLKtQK7t8BOXAIyA==",
+ "dependencies": {
+ "cssnano": "^5.1.8",
+ "jest-worker": "^29.1.2",
+ "postcss": "^8.4.17",
+ "schema-utils": "^4.0.0",
+ "serialize-javascript": "^6.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@parcel/css": {
+ "optional": true
+ },
+ "@swc/css": {
+ "optional": true
+ },
+ "clean-css": {
+ "optional": true
+ },
+ "csso": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/css-minimizer-webpack-plugin/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/css-prefers-color-scheme": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/css-prefers-color-scheme/-/css-prefers-color-scheme-6.0.3.tgz",
+ "integrity": "sha512-4BqMbZksRkJQx2zAjrokiGMd07RqOa2IxIrrN10lyBe9xhn9DEvjUK79J6jkeiv9D9hQFXKb6g1jwU62jziJZA==",
+ "dev": true,
+ "bin": {
+ "css-prefers-color-scheme": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/css-select": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-5.1.0.tgz",
+ "integrity": "sha512-nwoRF1rvRRnnCqqY7updORDsuqKzqYJ28+oSMaJMMgOauh3fvwHqMS7EZpIPqK8GL+g9mKxF1vP/ZjSeNjEVHg==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.1.0",
+ "domhandler": "^5.0.2",
+ "domutils": "^3.0.1",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css-selector-tokenizer": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
+ "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "fastparse": "^1.1.2"
+ }
+ },
+ "node_modules/css-to-react-native": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
+ "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "camelize": "^1.0.0",
+ "css-color-keywords": "^1.0.0",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
+ "node_modules/css-tree": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
+ "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
+ "dependencies": {
+ "mdn-data": "2.0.14",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/css-tree/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/css-what": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.1.0.tgz",
+ "integrity": "sha512-HTUrgRJ7r4dsZKU6GjmpfRK1O76h97Z8MfS1G0FozR+oF2kG6Vfe8JE6zwrkbxigziPHinCJ+gCPjA9EaBDtRw==",
+ "engines": {
+ "node": ">= 6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/css.escape": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/css.escape/-/css.escape-1.5.1.tgz",
+ "integrity": "sha512-YUifsXXuknHlUsmlgyY0PKzgPOr7/FjCePfHNt0jxm83wHZi44VDMQ7/fGNkjY3/jV1MC+1CmZbaHzugyeRtpg=="
+ },
+ "node_modules/cssdb": {
+ "version": "7.11.2",
+ "resolved": "https://registry.npmjs.org/cssdb/-/cssdb-7.11.2.tgz",
+ "integrity": "sha512-lhQ32TFkc1X4eTefGfYPvgovRSzIMofHkigfH8nWtyRL4XJLsRhJFreRvEgKzept7x1rjBuy3J/MurXLaFxW/A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/csstools"
+ }
+ ]
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/cssnano": {
+ "version": "5.1.15",
+ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz",
+ "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==",
+ "dependencies": {
+ "cssnano-preset-default": "^5.2.14",
+ "lilconfig": "^2.0.3",
+ "yaml": "^1.10.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/cssnano"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/cssnano-preset-default": {
+ "version": "5.2.14",
+ "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz",
+ "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==",
+ "dependencies": {
+ "css-declaration-sorter": "^6.3.1",
+ "cssnano-utils": "^3.1.0",
+ "postcss-calc": "^8.2.3",
+ "postcss-colormin": "^5.3.1",
+ "postcss-convert-values": "^5.1.3",
+ "postcss-discard-comments": "^5.1.2",
+ "postcss-discard-duplicates": "^5.1.0",
+ "postcss-discard-empty": "^5.1.1",
+ "postcss-discard-overridden": "^5.1.0",
+ "postcss-merge-longhand": "^5.1.7",
+ "postcss-merge-rules": "^5.1.4",
+ "postcss-minify-font-values": "^5.1.0",
+ "postcss-minify-gradients": "^5.1.1",
+ "postcss-minify-params": "^5.1.4",
+ "postcss-minify-selectors": "^5.2.1",
+ "postcss-normalize-charset": "^5.1.0",
+ "postcss-normalize-display-values": "^5.1.0",
+ "postcss-normalize-positions": "^5.1.1",
+ "postcss-normalize-repeat-style": "^5.1.1",
+ "postcss-normalize-string": "^5.1.0",
+ "postcss-normalize-timing-functions": "^5.1.0",
+ "postcss-normalize-unicode": "^5.1.1",
+ "postcss-normalize-url": "^5.1.0",
+ "postcss-normalize-whitespace": "^5.1.1",
+ "postcss-ordered-values": "^5.1.3",
+ "postcss-reduce-initial": "^5.1.2",
+ "postcss-reduce-transforms": "^5.1.0",
+ "postcss-svgo": "^5.1.0",
+ "postcss-unique-selectors": "^5.1.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/cssnano-utils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz",
+ "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==",
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/csso": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz",
+ "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==",
+ "dependencies": {
+ "css-tree": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+ },
+ "node_modules/d3-path": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
+ "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
+ },
+ "node_modules/d3-shape": {
+ "version": "1.3.7",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
+ "integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
+ "dependencies": {
+ "d3-path": "1"
+ }
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.2.tgz",
+ "integrity": "sha512-EmKO5V3OLXh1rtK2wgXRansaK1/mtVdTUEiEI0W8RkvgT05kfxaH29PliLnpLP73yYO6142Q72QNa8Wx/A5CqQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.2.tgz",
+ "integrity": "sha512-tuhGbE6CfTM9+5ANGf+oQb72Ky/0+s3xKUpHvShfiz2RxMFgFPjsXuRLBVMtvMs15awe45SRb83D6wH4ew6wlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/inspect-js"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.1.tgz",
+ "integrity": "sha512-BS8PfmtDGnrgYdOonGZQdLZslWIeCGFP9tpan0hi1Co2Zr2NKADsvGYA8XxuG/4UWgJ6Cjtv+YJnB6MM69QGlQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/date-fns": {
+ "version": "2.30.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-2.30.0.tgz",
+ "integrity": "sha512-fnULvOpxnC5/Vg3NCiWelDsLiUc9bRwAPs/+LfTLNvetFCtCTN+yQz15C/fs4AwX1R9K5GLtLfn8QW+dWisaAw==",
+ "dependencies": {
+ "@babel/runtime": "^7.21.0"
+ },
+ "engines": {
+ "node": ">=0.11"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/date-fns"
+ }
+ },
+ "node_modules/debug": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.1.tgz",
+ "integrity": "sha512-KcKCqiftBJcZr++7ykoDIEwSa3XWowTfNPo92BYxjXiyYEVrUQh2aLyhxBCwww+heortUFxEJYcRzosstTEBYQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/dedent": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/dedent/-/dedent-1.5.3.tgz",
+ "integrity": "sha512-NHQtfOOW68WD8lgypbLA5oT+Bt0xXJhiYvoR6SmmNXZfpzOGXwdKWmcwG8N7PwVVWV3eF/68nmD9BaJSsTBhyQ==",
+ "dev": true,
+ "peerDependencies": {
+ "babel-plugin-macros": "^3.1.0"
+ },
+ "peerDependenciesMeta": {
+ "babel-plugin-macros": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/deepmerge": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz",
+ "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/default-browser": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.2.1.tgz",
+ "integrity": "sha512-WY/3TUME0x3KPYdRRxEJJvXRHV4PyPoUsxtZa78lwItwRQRHhd2U9xOscaT/YTf8uCXIAjeJOFBVEh/7FtD8Xg==",
+ "dev": true,
+ "dependencies": {
+ "bundle-name": "^4.1.0",
+ "default-browser-id": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/default-browser-id": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.0.tgz",
+ "integrity": "sha512-A6p/pu/6fyBcA1TRz/GqWYPViplrftcW2gZC9q79ngNCKAeR/X3gcEdXQHl4KNXV+3wgIJ1CPkJQ3IHM6lcsyA==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/depd": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/dequal": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/dequal/-/dequal-2.0.3.tgz",
+ "integrity": "sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
+ }
+ },
+ "node_modules/detect-libc": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz",
+ "integrity": "sha512-pGjwhsmsp4kL2RTz08wcOlGN83otlqHeD/Z5T8GXZB+/YcpQ/dgo+lbU8ZsGxV0HIvqqxo9l7mqYwyYMD9bKDg==",
+ "dev": true,
+ "optional": true,
+ "bin": {
+ "detect-libc": "bin/detect-libc.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/detect-newline": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/detect-newline/-/detect-newline-3.1.0.tgz",
+ "integrity": "sha512-TLz+x/vEXm/Y7P7wn1EJFNLxYpUD4TgMosxY6fAVJUnJMbupHBOncxyWUG9OpTaH9EBD7uFI5LfEgmMOc54DsA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/detect-node": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
+ "integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
+ "dev": true
+ },
+ "node_modules/detect-port-alt": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/detect-port-alt/-/detect-port-alt-1.1.6.tgz",
+ "integrity": "sha512-5tQykt+LqfJFBEYaDITx7S7cR7mJ/zQmLXZ2qt5w04ainYZw6tBf9dBunMjVeVOdYVRUzUOE4HkY5J7+uttb5Q==",
+ "dev": true,
+ "dependencies": {
+ "address": "^1.0.1",
+ "debug": "^2.6.0"
+ },
+ "bin": {
+ "detect": "bin/detect-port",
+ "detect-port": "bin/detect-port"
+ },
+ "engines": {
+ "node": ">= 4.2.1"
+ }
+ },
+ "node_modules/detect-port-alt/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/detect-port-alt/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true
+ },
+ "node_modules/diff": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/diff/-/diff-4.0.4.tgz",
+ "integrity": "sha512-X07nttJQkwkfKfvTPG/KSnE2OMdcUCao6+eXF3wmnIQRn2aPAHH3VxDbDOdegkd6JbPsXqShpvEOHfAT+nCNwQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.3.1"
+ }
+ },
+ "node_modules/diff-sequences": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/diff-sequences/-/diff-sequences-29.6.3.tgz",
+ "integrity": "sha512-EjePK1srD3P08o2j4f0ExnylqRs5B9tJjcp9t1krH2qRi8CCdsYfwe9JgSLurFBWwq4uOlipzfk5fHNvwFKr8Q==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/dir-glob": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
+ "dev": true,
+ "dependencies": {
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/discontinuous-range": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/discontinuous-range/-/discontinuous-range-1.0.0.tgz",
+ "integrity": "sha512-c68LpLbO+7kP/b1Hr1qs8/BJ09F5khZGTxqxZuhzxpmwJKOgRFHJWIb9/KmqnqHhLdO55aOxFH/EGBvUQbL/RQ==",
+ "dev": true
+ },
+ "node_modules/dns-packet": {
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
+ "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
+ "dev": true,
+ "dependencies": {
+ "@leichtgewicht/ip-codec": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dom-accessibility-api": {
+ "version": "0.5.16",
+ "resolved": "https://registry.npmjs.org/dom-accessibility-api/-/dom-accessibility-api-0.5.16.tgz",
+ "integrity": "sha512-X7BJ2yElsnOJ30pZF4uIIDfBEVgF4XEBxL9Bxhy6dnrm5hkzqmsWHGTiHqRiITNhMyFLyAiWndIJP7Z1NTteDg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/dom-align": {
+ "version": "1.12.4",
+ "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz",
+ "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw=="
+ },
+ "node_modules/dom-converter": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
+ "integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
+ "dev": true,
+ "dependencies": {
+ "utila": "~0.4"
+ }
+ },
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/dom-serializer": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-2.0.0.tgz",
+ "integrity": "sha512-wIkAryiqt/nV5EQKqQpo3SToSOV9J0DnbJqwK7Wv/Trc92zIAYZ4FlMu+JPFW1DfGFt81ZTCGgDEabffXeLyJg==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.2",
+ "entities": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/domelementtype": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ]
+ },
+ "node_modules/domhandler": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-5.0.3.tgz",
+ "integrity": "sha512-cgwlv/1iFQiFnU96XXgROh8xTeetsnJiDsTc7TYCLFd9+/WNkIqPTxiM/8pSd8VIrhXGTf1Ny1q1hquVqDJB5w==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.3.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/domutils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz",
+ "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==",
+ "dev": true,
+ "dependencies": {
+ "dom-serializer": "^2.0.0",
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/dot-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
+ "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
+ "dev": true,
+ "dependencies": {
+ "no-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/dunder-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
+ "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.2.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/duplexer": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
+ "integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
+ "dev": true
+ },
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "dev": true
+ },
+ "node_modules/ejs": {
+ "version": "3.1.10",
+ "resolved": "https://registry.npmjs.org/ejs/-/ejs-3.1.10.tgz",
+ "integrity": "sha512-UeJmFfOrAQS8OJWPZ4qtgHyWExa088/MtK5UEyoJGFH67cDEXkZSviOiKRCZ4Xij0zxI3JECgYs3oKx+AizQBA==",
+ "dev": true,
+ "dependencies": {
+ "jake": "^10.8.5"
+ },
+ "bin": {
+ "ejs": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.49",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.49.tgz",
+ "integrity": "sha512-ZXfs1Of8fDb6z7WEYZjXpgIRF6MEu8JdeGA0A40aZq6OQbS+eJpnnV49epZRna2DU/YsEjSQuGtQPPtvt6J65A=="
+ },
+ "node_modules/emittery": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/emittery/-/emittery-0.13.1.tgz",
+ "integrity": "sha512-DeWwawk6r5yR9jFgnDKYt4sLS0LmHJJi3ZOnb5/JdbYwj3nW+FxQnHIjhBKz8YLC7oRNPVM9NQ47I3CVx34eqQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/emittery?sponsor=1"
+ }
+ },
+ "node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/emojis-list": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
+ "integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/encodeurl": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/encoding-sniffer": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/encoding-sniffer/-/encoding-sniffer-0.2.0.tgz",
+ "integrity": "sha512-ju7Wq1kg04I3HtiYIOrUrdfdDvkyO9s5XM8QAj/bN61Yo/Vb4vgJxy5vi4Yxk01gWHbrofpPtpxM8bKger9jhg==",
+ "dev": true,
+ "dependencies": {
+ "iconv-lite": "^0.6.3",
+ "whatwg-encoding": "^3.1.1"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/encoding-sniffer?sponsor=1"
+ }
+ },
+ "node_modules/enhanced-resolve": {
+ "version": "5.17.1",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.1.tgz",
+ "integrity": "sha512-LMHl3dXhTcfv8gM4kEzIUeTQ+7fpdA0l2tUf34BddXPkz2A5xJ5L/Pchd5BL6rdccM9QGvu0sWZzK1Z1t4wwyg==",
+ "dependencies": {
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/entities": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-4.5.0.tgz",
+ "integrity": "sha512-V0hjH4dGPh9Ao5p0MoRY6BVqtwCjhz6vI5LT8AJ55H+4g9/4vbHx1I54fS0XuclLhDHArPQCiMjDxjaL8fPxhw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/envinfo": {
+ "version": "7.14.0",
+ "resolved": "https://registry.npmjs.org/envinfo/-/envinfo-7.14.0.tgz",
+ "integrity": "sha512-CO40UI41xDQzhLB1hWyqUKgFhs250pNcGbyGKe1l/e4FSaI/+YE4IMG76GDt0In67WLPACIITC+sOi08x4wIvg==",
+ "dev": true,
+ "bin": {
+ "envinfo": "dist/cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/environment": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz",
+ "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/enzyme": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/enzyme/-/enzyme-3.11.0.tgz",
+ "integrity": "sha512-Dw8/Gs4vRjxY6/6i9wU0V+utmQO9kvh9XLnz3LIudviOnVYDEe2ec+0k+NQoMamn1VrjKgCUOWj5jG/5M5M0Qw==",
+ "dev": true,
+ "dependencies": {
+ "array.prototype.flat": "^1.2.3",
+ "cheerio": "^1.0.0-rc.3",
+ "enzyme-shallow-equal": "^1.0.1",
+ "function.prototype.name": "^1.1.2",
+ "has": "^1.0.3",
+ "html-element-map": "^1.2.0",
+ "is-boolean-object": "^1.0.1",
+ "is-callable": "^1.1.5",
+ "is-number-object": "^1.0.4",
+ "is-regex": "^1.0.5",
+ "is-string": "^1.0.5",
+ "is-subset": "^0.1.1",
+ "lodash.escape": "^4.0.1",
+ "lodash.isequal": "^4.5.0",
+ "object-inspect": "^1.7.0",
+ "object-is": "^1.0.2",
+ "object.assign": "^4.1.0",
+ "object.entries": "^1.1.1",
+ "object.values": "^1.1.1",
+ "raf": "^3.4.1",
+ "rst-selector-parser": "^2.2.3",
+ "string.prototype.trim": "^1.2.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/enzyme-shallow-equal": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/enzyme-shallow-equal/-/enzyme-shallow-equal-1.0.7.tgz",
+ "integrity": "sha512-/um0GFqUXnpM9SvKtje+9Tjoz3f1fpBC3eXRFrNs8kpYn69JljciYP7KZTqM/YQbUY9KUjvKB4jo/q+L6WGGvg==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.0",
+ "object-is": "^1.1.5"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/error-stack-parser": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
+ "dev": true,
+ "dependencies": {
+ "stackframe": "^1.3.4"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.24.1",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.24.1.tgz",
+ "integrity": "sha512-zHXBLhP+QehSSbsS9Pt23Gg964240DPd6QCf8WpkqEXxQ7fhdZzYsocOr5u7apWonsS5EjZDmTF+/slGMyasvw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.2",
+ "arraybuffer.prototype.slice": "^1.0.4",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "data-view-buffer": "^1.0.2",
+ "data-view-byte-length": "^1.0.2",
+ "data-view-byte-offset": "^1.0.1",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "es-set-tostringtag": "^2.1.0",
+ "es-to-primitive": "^1.3.0",
+ "function.prototype.name": "^1.1.8",
+ "get-intrinsic": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "get-symbol-description": "^1.1.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.1.0",
+ "is-array-buffer": "^3.0.5",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.2",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.2.1",
+ "is-set": "^2.0.3",
+ "is-shared-array-buffer": "^1.0.4",
+ "is-string": "^1.1.1",
+ "is-typed-array": "^1.1.15",
+ "is-weakref": "^1.1.1",
+ "math-intrinsics": "^1.1.0",
+ "object-inspect": "^1.13.4",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.7",
+ "own-keys": "^1.0.1",
+ "regexp.prototype.flags": "^1.5.4",
+ "safe-array-concat": "^1.1.3",
+ "safe-push-apply": "^1.0.0",
+ "safe-regex-test": "^1.1.0",
+ "set-proto": "^1.0.0",
+ "stop-iteration-iterator": "^1.1.0",
+ "string.prototype.trim": "^1.2.10",
+ "string.prototype.trimend": "^1.0.9",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.3",
+ "typed-array-byte-length": "^1.0.3",
+ "typed-array-byte-offset": "^1.0.4",
+ "typed-array-length": "^1.0.7",
+ "unbox-primitive": "^1.1.0",
+ "which-typed-array": "^1.1.19"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-array-method-boxes-properly": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-array-method-boxes-properly/-/es-array-method-boxes-properly-1.0.0.tgz",
+ "integrity": "sha512-wd6JXUmyHmt8T5a2xreUwKcGPq6f1f+WwIJkijUqiGcJz1qqnZgP6XIK+QyIWU5lT7imeNxUll48bziG+TSYcA==",
+ "dev": true
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz",
+ "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-iterator-helpers": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/es-iterator-helpers/-/es-iterator-helpers-1.2.2.tgz",
+ "integrity": "sha512-BrUQ0cPTB/IwXj23HtwHjS9n7O4h9FX94b4xc5zlTHxeLgTAdzYUDyy6KdExAl9lbN5rtfe44xpjpmj9grxs5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.24.1",
+ "es-errors": "^1.3.0",
+ "es-set-tostringtag": "^2.1.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.3.0",
+ "globalthis": "^1.0.4",
+ "gopd": "^1.2.0",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "iterator.prototype": "^1.1.5",
+ "safe-array-concat": "^1.1.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-module-lexer": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.5.4.tgz",
+ "integrity": "sha512-MVNK56NiMrOwitFB7cqDwq0CQutbw+0BvLshJSse0MUNU+y1FC3bUS/AQg7oUng+/wKrrki7JfmwtVHkVfPLlw=="
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
+ "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.1.0.tgz",
+ "integrity": "sha512-j6vWzfrGVfyXxge+O0x5sh6cvxAog0a/4Rdd2K36zCMV5eJ+/+tOAngRO8cODMNWbVRdVlmGZQL2YS3yR8bIUA==",
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.1.0.tgz",
+ "integrity": "sha512-d9T8ucsEhh8Bi1woXCf+TIKDIROLG5WCkxg8geBCbvk22kzwC5G2OnXVMO6FUsvQlgUUXQ2itephWDLqDzbeCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.3.0.tgz",
+ "integrity": "sha512-w+5mJ3GuFL+NjVtJlvydShqE1eN3h3PbI7/5LAsYJP/2qtuMXjfL2LpHSRqo4b4eSF5K/DH1JXKUAHSB2UW50g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7",
+ "is-date-object": "^1.0.5",
+ "is-symbol": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es6-promise": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/es6-promise/-/es6-promise-3.3.1.tgz",
+ "integrity": "sha512-SOp9Phqvqn7jtEUxPWdWfWoLmyt2VaJ6MpvP9Comy1MceMXqE6bxvaTu4iaxpYYPzhny28Lc+M87/c2cPK6lDg==",
+ "dev": true
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-html": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "dev": true
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.39.2",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.2.tgz",
+ "integrity": "sha512-LEyamqS7W5HB3ujJyvi0HQK/dtVINZvd5mAAp9eT5S/ujByGjiZLCzPcHVzuXbpJDJF/cxwHlfceVUDZ2lnSTw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.1",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "9.39.2",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-config-prettier": {
+ "version": "10.1.5",
+ "resolved": "https://registry.npmjs.org/eslint-config-prettier/-/eslint-config-prettier-10.1.5.tgz",
+ "integrity": "sha512-zc1UmCpNltmVY34vuLRV61r1K27sWuX39E+uyUnY8xS2Bex88VV9cugG+UZbRSRGtGyFboj+D8JODyme1plMpw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "eslint-config-prettier": "bin/cli.js"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-config-prettier"
+ },
+ "peerDependencies": {
+ "eslint": ">=7.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-i18n": {
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-i18n/-/eslint-plugin-i18n-2.4.0.tgz",
+ "integrity": "sha512-6RpPoj+lr0xk6SNljziOjGfDtuQSN6cw/gdds248N5MvCQUrPxo5+0s7b7TQsEl1qLr5OVnCMxsaRBy/4T62cg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-prettier": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-prettier/-/eslint-plugin-prettier-5.4.1.tgz",
+ "integrity": "sha512-9dF+KuU/Ilkq27A8idRP7N2DH8iUR6qXcjF3FR2wETY21PZdBrIjwCau8oboyGj9b7etWmTGEeM8e7oOed6ZWg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "prettier-linter-helpers": "^1.0.0",
+ "synckit": "^0.11.7"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint-plugin-prettier"
+ },
+ "peerDependencies": {
+ "@types/eslint": ">=8.0.0",
+ "eslint": ">=8.0.0",
+ "eslint-config-prettier": ">= 7.0.0 <10.0.0 || >=10.1.0",
+ "prettier": ">=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/eslint": {
+ "optional": true
+ },
+ "eslint-config-prettier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-plugin-react": {
+ "version": "7.37.5",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react/-/eslint-plugin-react-7.37.5.tgz",
+ "integrity": "sha512-Qteup0SqU15kdocexFNAJMvCJEfa2xUKNV4CC1xsVMrIIqEy3SQ/rqyxCWNzfrd3/ldy6HMlD2e0JDVpDg2qIA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.8",
+ "array.prototype.findlast": "^1.2.5",
+ "array.prototype.flatmap": "^1.3.3",
+ "array.prototype.tosorted": "^1.1.4",
+ "doctrine": "^2.1.0",
+ "es-iterator-helpers": "^1.2.1",
+ "estraverse": "^5.3.0",
+ "hasown": "^2.0.2",
+ "jsx-ast-utils": "^2.4.1 || ^3.0.0",
+ "minimatch": "^3.1.2",
+ "object.entries": "^1.1.9",
+ "object.fromentries": "^2.0.8",
+ "object.values": "^1.2.1",
+ "prop-types": "^15.8.1",
+ "resolve": "^2.0.0-next.5",
+ "semver": "^6.3.1",
+ "string.prototype.matchall": "^4.0.12",
+ "string.prototype.repeat": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^3 || ^4 || ^5 || ^6 || ^7 || ^8 || ^9.7"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint-plugin-react/node_modules/resolve": {
+ "version": "2.0.0-next.5",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-2.0.0-next.5.tgz",
+ "integrity": "sha512-U7WjGVG9sH8tvjW5SmGbQuui75FiyjAX72HX15DwBBwF9dNiQZRQAg9nnPhYy+TUnE0+VcrttuvNI8oSxZcocA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/eslint-plugin-simple-import-sort": {
+ "version": "12.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-simple-import-sort/-/eslint-plugin-simple-import-sort-12.1.1.tgz",
+ "integrity": "sha512-6nuzu4xwQtE3332Uz0to+TxDQYRLTKRESSc2hefVT48Zc8JthmN23Gx9lnYhu0FtkRSL1oxny3kJ2aveVhmOVA==",
+ "dev": true,
+ "license": "MIT",
+ "peerDependencies": {
+ "eslint": ">=5.0.0"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
+ "integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^4.1.1"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/eslint/node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/eslint/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/espree": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esprima": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
+ "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "bin": {
+ "esparse": "bin/esparse.js",
+ "esvalidate": "bin/esvalidate.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esquery/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esrecurse/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
+ "integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/etag": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/event-target-shim": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/event-target-shim/-/event-target-shim-5.0.1.tgz",
+ "integrity": "sha512-i/2XbnSz/uxRCU6+NdVJgKWDTM427+MqYbkQzD321DuCQJUqOuJKIA0IM2+W2xtYHdKOmZ4dR6fExsd4SXL+WQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
+ "dev": true
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/execa": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
+ "is-stream": "^2.0.0",
+ "merge-stream": "^2.0.0",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
+ "strip-final-newline": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
+ }
+ },
+ "node_modules/exit": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/exit/-/exit-0.1.2.tgz",
+ "integrity": "sha512-Zk/eNKV2zbjpKzrsQ+n1G6poVbErQxJ0LBOJXaKZ1EViLzH+hrLu9cdXI4zw9dBQJslwBEpbQ2P1oS7nDxs6jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/expect": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/expect/-/expect-29.7.0.tgz",
+ "integrity": "sha512-2Zks0hf1VLFYI1kbh0I5jP3KHHyCHpkfyHBzsSXRFgl/Bg9mWYfMW8oD+PdMPlEwy5HNsR9JutYy6pMeOh61nw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/expect-utils": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/express": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
+ "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "~1.20.3",
+ "content-disposition": "~0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "~0.7.1",
+ "cookie-signature": "~1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.3.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "~2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "~0.1.12",
+ "proxy-addr": "~2.0.7",
+ "qs": "~6.14.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "~0.19.0",
+ "serve-static": "~1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "~2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/express/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/express/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q=="
+ },
+ "node_modules/fast-diff": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.3.0.tgz",
+ "integrity": "sha512-VxPP4NqbUjj6MaAOafWeUn2cXWLcCtljklUtZf0Ind4XQ+QPtmA0b18zZy0jIQx+ExRVCR/ZQpBmik5lXshNsw==",
+ "dev": true
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fast-safe-stringify": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.1.1.tgz",
+ "integrity": "sha512-W+KJc2dmILlPplD/H4K9l9LcAHAfPtP6BY84uVLXQ6Evcz9Lcg33Y2z1IVblT6xdY54PXYVHEv+0Wpq8Io6zkA==",
+ "dev": true
+ },
+ "node_modules/fast-uri": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.0.3.tgz",
+ "integrity": "sha512-aLrHthzCjH5He4Z2H9YZ+v6Ujb9ocRuW6ZzkJQOrTxleEijANq4v1TsaPaVG1PZcuurEzrLcWRyYBYXD5cEiaw=="
+ },
+ "node_modules/fastest-levenshtein": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/fastest-levenshtein/-/fastest-levenshtein-1.0.16.tgz",
+ "integrity": "sha512-eRnCtTTtGZFpQCwhJiUOuxPQWRXVKYDn0b2PeHfXL6/Zi53SLAzAHfVhVWK2AryC/WH05kGfxhFIPvTF0SXQzg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4.9.1"
+ }
+ },
+ "node_modules/fastparse": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ=="
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/favicons": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/favicons/-/favicons-7.2.0.tgz",
+ "integrity": "sha512-k/2rVBRIRzOeom3wI9jBPaSEvoTSQEW4iM0EveBmBBKFxO8mSyyRWtDlfC3VnEfu0avmjrMzy8/ZFPSe6F71Hw==",
+ "dev": true,
+ "dependencies": {
+ "escape-html": "^1.0.3",
+ "sharp": "^0.33.1",
+ "xml2js": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/favicons-webpack-plugin": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/favicons-webpack-plugin/-/favicons-webpack-plugin-6.0.1.tgz",
+ "integrity": "sha512-Gl0Co4zIZq74EKXdpfe8FaoJqbuf0undV4UgpsL34vqICRAYUDwQdp3D+z+uxEOV0i9o+vHDn7Q6jaSxRiDJUA==",
+ "dev": true,
+ "dependencies": {
+ "find-root": "^1.1.0",
+ "parse-author": "^2.0.0",
+ "parse5": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "optionalDependencies": {
+ "html-webpack-plugin": "^5.5.0"
+ },
+ "peerDependencies": {
+ "favicons": "^7.0.1",
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "dev": true,
+ "dependencies": {
+ "websocket-driver": ">=0.5.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/fb-watchman": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
+ "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
+ "dev": true,
+ "dependencies": {
+ "bser": "2.1.1"
+ }
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/file-loader": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-6.2.0.tgz",
+ "integrity": "sha512-qo3glqyTa61Ytg4u73GultjHGjdRyig3tG6lPtyX/jOEJvHif9uB0/OCI2Kif6ctF3caQTW2G5gym21oAsI4pw==",
+ "dev": true,
+ "dependencies": {
+ "loader-utils": "^2.0.0",
+ "schema-utils": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^4.0.0 || ^5.0.0"
+ }
+ },
+ "node_modules/file-loader/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/file-loader/node_modules/ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+ "dev": true,
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/file-loader/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/file-loader/node_modules/loader-utils": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+ "dev": true,
+ "dependencies": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=8.9.0"
+ }
+ },
+ "node_modules/file-loader/node_modules/schema-utils": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/filelist": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/filelist/-/filelist-1.0.4.tgz",
+ "integrity": "sha512-w1cEuf3S+DrLCQL7ET6kz+gmlJdbq9J7yXCSjK/OZCPA+qEN1WyF4ZAf0YYJa4/shHJra2t/d/r8SV4Ji+x+8Q==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^5.0.1"
+ }
+ },
+ "node_modules/filelist/node_modules/brace-expansion": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz",
+ "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/filelist/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/filesize": {
+ "version": "8.0.7",
+ "resolved": "https://registry.npmjs.org/filesize/-/filesize-8.0.7.tgz",
+ "integrity": "sha512-pjmC+bkIF8XI7fWaH8KxHcZL3DPybs1roSKP4rKDvy20tAWwIObE4+JIseG2byfGKhud5ZnM4YSGKBz7Sh0ndQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
+ "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "on-finished": "~2.4.1",
+ "parseurl": "~1.3.3",
+ "statuses": "~2.0.2",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/finalhandler/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/finalhandler/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/find-cache-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
+ "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
+ "dev": true,
+ "dependencies": {
+ "commondir": "^1.0.1",
+ "make-dir": "^2.0.0",
+ "pkg-dir": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng==",
+ "dev": true
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
+ "dev": true,
+ "bin": {
+ "flat": "cli.js"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.3.tgz",
+ "integrity": "sha512-GX+ysw4PBCz0PzosHDepZGANEuFCMLrnRTiEy9McGjmkCQYwRq4A/X786G/fjM/+OjsWSU1ZrY5qyARZmO/uwg==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.5.tgz",
+ "integrity": "sha512-dKx12eRCVIzqCxFGplyFKJMPvLEWgmNtUrpTiJIR5u97zEhRG8ySrtboPHZXx7daLxQVrl643cTzbab2tkQjxg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/fork-ts-checker-webpack-plugin": {
+ "version": "6.5.3",
+ "resolved": "https://registry.npmjs.org/fork-ts-checker-webpack-plugin/-/fork-ts-checker-webpack-plugin-6.5.3.tgz",
+ "integrity": "sha512-SbH/l9ikmMWycd5puHJKTkZJKddF4iRLyW3DeZ08HTI7NGyLS38MXd/KGgeWumQO7YNQbW2u/NtPT2YowbPaGQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.8.3",
+ "@types/json-schema": "^7.0.5",
+ "chalk": "^4.1.0",
+ "chokidar": "^3.4.2",
+ "cosmiconfig": "^6.0.0",
+ "deepmerge": "^4.2.2",
+ "fs-extra": "^9.0.0",
+ "glob": "^7.1.6",
+ "memfs": "^3.1.2",
+ "minimatch": "^3.0.4",
+ "schema-utils": "2.7.0",
+ "semver": "^7.3.2",
+ "tapable": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=10",
+ "yarn": ">=1.0.0"
+ },
+ "peerDependencies": {
+ "eslint": ">= 6",
+ "typescript": ">= 2.7",
+ "vue-template-compiler": "*",
+ "webpack": ">= 4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ },
+ "vue-template-compiler": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/fork-ts-checker-webpack-plugin/node_modules/ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+ "dev": true,
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/fork-ts-checker-webpack-plugin/node_modules/cosmiconfig": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-6.0.0.tgz",
+ "integrity": "sha512-xb3ZL6+L8b9JLLCx3ZdoZy4+2ECphCMo2PwqgP1tlfVq6M6YReyzBJtvWWtbDSpNr9hn96pkCiZqUcFEc+54Qg==",
+ "dev": true,
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.1.0",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.7.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/fork-ts-checker-webpack-plugin/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/fork-ts-checker-webpack-plugin/node_modules/schema-utils": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.0.tgz",
+ "integrity": "sha512-0ilKFI6QQF5nxDZLFn2dMjvc4hjg/Wkg7rHd3jK6/A4a1Hl9VFdQWvgB1UMGoU94pad1P/8N7fMcEnLnSiju8A==",
+ "dev": true,
+ "dependencies": {
+ "@types/json-schema": "^7.0.4",
+ "ajv": "^6.12.2",
+ "ajv-keywords": "^3.4.1"
+ },
+ "engines": {
+ "node": ">= 8.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/fork-ts-checker-webpack-plugin/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fork-ts-checker-webpack-plugin/node_modules/tapable": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
+ "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/form-data-encoder": {
+ "version": "1.7.2",
+ "resolved": "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.7.2.tgz",
+ "integrity": "sha512-qfqtYan3rxrnCk1VYaA4H+Ms9xdpPqvLZa6xmMgFvhO32x7/3J/ExcTd6qpxM0vH2GdMI+poehyBZvqfMTto8A=="
+ },
+ "node_modules/formdata-node": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/formdata-node/-/formdata-node-4.4.1.tgz",
+ "integrity": "sha512-0iirZp3uVDjVGt9p49aTaqjk84TrglENEDuqfdlZQ1roC9CWlPk6Avf8EEnZNcAqPonwkG35x4n3ww/1THYAeQ==",
+ "dependencies": {
+ "node-domexception": "1.0.0",
+ "web-streams-polyfill": "4.0.0-beta.3"
+ },
+ "engines": {
+ "node": ">= 12.20"
+ }
+ },
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fraction.js": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
+ "dev": true,
+ "dependencies": {
+ "at-least-node": "^1.0.0",
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/fs-monkey": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.0.6.tgz",
+ "integrity": "sha512-b1FMfwetIKymC0eioW7mTywihSQE4oLzQn1dB6rZB5fx/3NpNEdAWeCSMB+60/AeT0TCXsxzAlcYVEFCTAksWg==",
+ "dev": true
+ },
+ "node_modules/fs-readdir-recursive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fs-readdir-recursive/-/fs-readdir-recursive-1.1.0.tgz",
+ "integrity": "sha512-GNanXlVr2pf02+sPN40XN8HG+ePaNcvM0q5mZBd668Obwb0yD5GiUbZOFgwn8kGMY6I3mdyDJzieUy3PTYyTRA==",
+ "dev": true
+ },
+ "node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.8",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.8.tgz",
+ "integrity": "sha512-e5iwyodOHhbMr/yNrc7fDYG4qlbIvI5gajyzPnb5TCwyhjApznQh1BMFou9b30SevY43gCJKXycoCBjMbsuW0Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "functions-have-names": "^1.2.3",
+ "hasown": "^2.0.2",
+ "is-callable": "^1.2.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/generator-function": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/generator-function/-/generator-function-2.0.1.tgz",
+ "integrity": "sha512-SFdFmIJi+ybC0vjlHN0ZGVGHc3lgE0DxPAT0djjVg+kjOnSqclqmj0KQ7ykTOLP6YxoqOvuAODGdcHJn+43q3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-caller-file": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
+ "integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
+ "dev": true,
+ "engines": {
+ "node": "6.* || 8.* || >= 10.*"
+ }
+ },
+ "node_modules/get-east-asian-width": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.3.0.tgz",
+ "integrity": "sha512-vpeMIQKxczTD/0s2CdEWHcb0eeJe6TFjxb+J5xgX7hScxqrGuyjmv4c1D4A/gelKfyox0gJJwIHF+fLjeaM8kQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz",
+ "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==",
+ "license": "MIT",
+ "dependencies": {
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.1.1",
+ "function-bind": "^1.1.2",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "hasown": "^2.0.2",
+ "math-intrinsics": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-package-type": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
+ "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/get-proto": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz",
+ "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==",
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/get-stream": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.1.0.tgz",
+ "integrity": "sha512-w9UMqWwJxHNOvoNzSJ2oPF5wvYcvP7jUvYzhp67yEhTi17ZDBBC1z9pTdGuzjD+EFIqLSYRweZjqfiPzQ06Ebg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Glob versions prior to v9 are no longer supported",
+ "dev": true,
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.1.1",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/glob-to-regexp": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw=="
+ },
+ "node_modules/global-modules": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/global-modules/-/global-modules-2.0.0.tgz",
+ "integrity": "sha512-NGbfmJBp9x8IxyJSd1P+otYK8vonoJactOogrVfFRIAEY1ukil8RSKDz2Yo7wh1oihl51l/r6W4epkeKJHqL8A==",
+ "dev": true,
+ "dependencies": {
+ "global-prefix": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/global-prefix": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-3.0.0.tgz",
+ "integrity": "sha512-awConJSVCHVGND6x3tmMaKcQvwXLhjdkmomy2W+Goaui8YPgYgXJZewhg3fWC+DlfqqQuWg8AwqjGTD2nAPVWg==",
+ "dev": true,
+ "dependencies": {
+ "ini": "^1.3.5",
+ "kind-of": "^6.0.2",
+ "which": "^1.3.1"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/global-prefix/node_modules/which": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
+ "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
+ "dev": true,
+ "dependencies": {
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/globby/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/gopd": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
+ "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/gzip-size": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
+ "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==",
+ "dev": true,
+ "dependencies": {
+ "duplexer": "^0.1.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/handle-thing": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
+ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
+ "dev": true
+ },
+ "node_modules/harmony-reflect": {
+ "version": "1.6.2",
+ "resolved": "https://registry.npmjs.org/harmony-reflect/-/harmony-reflect-1.6.2.tgz",
+ "integrity": "sha512-HIp/n38R9kQjDEziXyDTuW3vvoxxyxjxFzXLrBr18uB47GnSt+G9D29fqrpM5ZkspMcPICud3XsBJQ4Y2URg8g==",
+ "dev": true
+ },
+ "node_modules/has": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/has/-/has-1.0.4.tgz",
+ "integrity": "sha512-qdSAmqLF6209RFj4VVItywPMbm3vWylknmB3nvNiUIs72xAimcM8nVYxYr7ncvZq5qzk9MKIZR8ijqD/1QuYjQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.1.0.tgz",
+ "integrity": "sha512-R3pbpkcIqv2Pm3dUwgjclDRVmWpTJW2DcMzcIhEXEx1oh/CEMObMm3KLmRJOdvhM7o4uQBnwr8pzRK2sJWIqfg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.2.0.tgz",
+ "integrity": "sha512-KIL7eQPfHQRC8+XluaIw7BHUwwqL19bQn4hzNgdr+1wXoU0KKj6rufu47lhY7KbJR2C6T6+PfyN0Ea7wkSS+qQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
+ "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "dev": true,
+ "bin": {
+ "he": "bin/he"
+ }
+ },
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hoist-non-react-statics/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/hpack.js": {
+ "version": "2.1.6",
+ "resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
+ "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "obuf": "^1.0.0",
+ "readable-stream": "^2.0.1",
+ "wbuf": "^1.1.0"
+ }
+ },
+ "node_modules/hpack.js/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true
+ },
+ "node_modules/hpack.js/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dev": true,
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/hpack.js/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true
+ },
+ "node_modules/hpack.js/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/html-element-map": {
+ "version": "1.3.1",
+ "resolved": "https://registry.npmjs.org/html-element-map/-/html-element-map-1.3.1.tgz",
+ "integrity": "sha512-6XMlxrAFX4UEEGxctfFnmrFaaZFNf9i5fNuV5wZ3WWQ4FVaNP1aX1LkX9j2mfEx1NpjeE/rL3nmgEn23GdFmrg==",
+ "dev": true,
+ "dependencies": {
+ "array.prototype.filter": "^1.0.0",
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/html-entities": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.5.2.tgz",
+ "integrity": "sha512-K//PSRMQk4FZ78Kyau+mZurHn3FH0Vwr+H36eE0rPbeYkRRi9YxceYPhuN60UwWorxyKHhqoAJl2OFKa4BVtaA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/mdevils"
+ },
+ {
+ "type": "patreon",
+ "url": "https://patreon.com/mdevils"
+ }
+ ]
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true
+ },
+ "node_modules/html-minifier-terser": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
+ "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==",
+ "dev": true,
+ "dependencies": {
+ "camel-case": "^4.1.2",
+ "clean-css": "^5.2.2",
+ "commander": "^8.3.0",
+ "he": "^1.2.0",
+ "param-case": "^3.0.4",
+ "relateurl": "^0.2.7",
+ "terser": "^5.10.0"
+ },
+ "bin": {
+ "html-minifier-terser": "cli.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/html-minifier-terser/node_modules/commander": {
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/html-parse-stringify": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/html-parse-stringify/-/html-parse-stringify-3.0.1.tgz",
+ "integrity": "sha512-KknJ50kTInJ7qIScF3jeaFRpMpE8/lfiTdzf/twXyPBLAGrLRTmkz3AdTnKeh40X8k9L2fdYwEp/42WGXIRGcg==",
+ "dependencies": {
+ "void-elements": "3.1.0"
+ }
+ },
+ "node_modules/html-webpack-plugin": {
+ "version": "5.6.3",
+ "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.3.tgz",
+ "integrity": "sha512-QSf1yjtSAsmf7rYBV7XX86uua4W/vkhIt0xNXKbsi2foEeW7vjJQz4bhnpL3xH+l1ryl1680uNv968Z+X6jSYg==",
+ "dev": true,
+ "dependencies": {
+ "@types/html-minifier-terser": "^6.0.0",
+ "html-minifier-terser": "^6.0.2",
+ "lodash": "^4.17.21",
+ "pretty-error": "^4.0.0",
+ "tapable": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/html-webpack-plugin"
+ },
+ "peerDependencies": {
+ "@rspack/core": "0.x || 1.x",
+ "webpack": "^5.20.0"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/core": {
+ "optional": true
+ },
+ "webpack": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/htmlparser2": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-9.1.0.tgz",
+ "integrity": "sha512-5zfg6mHUoaer/97TxnGpxmbR7zJtPwIYFMZ/H5ucTlPZhKvtum05yiPK3Mgai3a0DyVxv7qYqoweaEd2nrYQzQ==",
+ "dev": true,
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.3.0",
+ "domhandler": "^5.0.3",
+ "domutils": "^3.1.0",
+ "entities": "^4.5.0"
+ }
+ },
+ "node_modules/http-deceiver": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
+ "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
+ "dev": true
+ },
+ "node_modules/http-errors": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
+ }
+ },
+ "node_modules/http-parser-js": {
+ "version": "0.5.8",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.8.tgz",
+ "integrity": "sha512-SGeBX54F94Wgu5RH3X5jsDtf4eHyRogWX1XGT3b4HuW3tQPM4AaBzoUji/4AAJNXCEOWZ5O0DgZmJw1947gD5Q==",
+ "dev": true
+ },
+ "node_modules/http-proxy": {
+ "version": "1.18.1",
+ "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
+ "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
+ "dev": true,
+ "dependencies": {
+ "eventemitter3": "^4.0.0",
+ "follow-redirects": "^1.0.0",
+ "requires-port": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8.0.0"
+ }
+ },
+ "node_modules/http-proxy-middleware": {
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz",
+ "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-proxy": "^1.17.8",
+ "http-proxy": "^1.18.1",
+ "is-glob": "^4.0.1",
+ "is-plain-obj": "^3.0.0",
+ "micromatch": "^4.0.2"
+ },
+ "engines": {
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "@types/express": "^4.17.13"
+ },
+ "peerDependenciesMeta": {
+ "@types/express": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/http2-client": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/http2-client/-/http2-client-1.3.5.tgz",
+ "integrity": "sha512-EC2utToWl4RKfs5zd36Mxq7nzHHBuomZboI0yYL6Y0RmBgT7Sgkq4rQ0ezFTYoIsSs7Tm9SJe+o2FcAg6GBhGA==",
+ "dev": true
+ },
+ "node_modules/human-signals": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.17.0"
+ }
+ },
+ "node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/humanize-ms/-/humanize-ms-1.2.1.tgz",
+ "integrity": "sha512-Fl70vYtsAFb/C06PTS9dZBo7ihau+Tu/DNCk/OyHhea07S+aeMWpFFkUaXRa8fI+ScZbEI8dfSxwY7gxZ9SAVQ==",
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/hyperdyperid": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/hyperdyperid/-/hyperdyperid-1.2.0.tgz",
+ "integrity": "sha512-Y93lCzHYgGWdrJ66yIktxiaGULYc6oGiABxhcO5AufBeOyoIdZF7bIfLaOrbM0iGIOXQQgxxRrFEnb+Y6w1n4A==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.18"
+ }
+ },
+ "node_modules/i18next": {
+ "version": "24.0.2",
+ "resolved": "https://registry.npmjs.org/i18next/-/i18next-24.0.2.tgz",
+ "integrity": "sha512-D88xyIGcWAKwBTAs4RSqASi8NXR/NhCVSTM4LDbdoU8qb/5dcEZjNCLDhtQBB7Epw/Cp1w2vH/3ujoTbqLSs5g==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://locize.com"
+ },
+ {
+ "type": "individual",
+ "url": "https://locize.com/i18next.html"
+ },
+ {
+ "type": "individual",
+ "url": "https://www.i18next.com/how-to/faq#i18next-is-awesome.-how-can-i-support-the-project"
+ }
+ ],
+ "dependencies": {
+ "@babel/runtime": "^7.23.2"
+ },
+ "peerDependencies": {
+ "typescript": "^5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dev": true,
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/icss-utils": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
+ "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
+ "dev": true,
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/identity-obj-proxy": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/identity-obj-proxy/-/identity-obj-proxy-3.0.0.tgz",
+ "integrity": "sha512-00n6YnVHKrinT9t0d9+5yZC6UBNJANpYEQvL2LlX6Ab9lnmxzIRcEmTPuyGScvl1+jKuCICX1Z0Ab1pPKKdikA==",
+ "dev": true,
+ "dependencies": {
+ "harmony-reflect": "^1.4.6"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/immer": {
+ "version": "9.0.21",
+ "resolved": "https://registry.npmjs.org/immer/-/immer-9.0.21.tgz",
+ "integrity": "sha512-bc4NBHqOqSfRW7POMkHd51LvClaeMXpm8dx0e8oE2GORbq5aRK7Bxl4FyzVLdGtLmvLKL7BTDBG5ACQm4HWjTA==",
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/immer"
+ }
+ },
+ "node_modules/immutable": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/immutable/-/immutable-5.0.3.tgz",
+ "integrity": "sha512-P8IdPQHq3lA1xVeBRi5VPqUm5HDgKnx0Ru51wZz5mjxHr5n3RWhjIpOFU7ybkUxfB+5IToy+OLaHYDBIWsv+uw==",
+ "dev": true
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dev": true,
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-local": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/import-local/-/import-local-3.2.0.tgz",
+ "integrity": "sha512-2SPlun1JUPWoM6t3F0dw0FkCF/jWY8kttcY4f599GLTSjh2OCuuhdTkJQsEcZzBqbXZGKMK2OqW1oZsjtf/gQA==",
+ "dev": true,
+ "dependencies": {
+ "pkg-dir": "^4.2.0",
+ "resolve-cwd": "^3.0.0"
+ },
+ "bin": {
+ "import-local-fixture": "fixtures/cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-local/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/import-local/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/import-local/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/import-local/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/import-local/node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/indent-string": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/indent-string/-/indent-string-4.0.0.tgz",
+ "integrity": "sha512-EdDDZu4A2OyIK7Lr/2zG+w5jmbuk1DVBnEwREQvBzspBJkCEbRa8GxU1lghYcaGJCnRWibjDXlq779X1/y5xwg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/inflight": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
+ "dev": true,
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/inherits": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "dev": true
+ },
+ "node_modules/ini": {
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.8.tgz",
+ "integrity": "sha512-JV/yugV2uzW5iMRSiZAyDtQd+nxtUnjeLt0acNdw98kKLrvuRVyB80tsREOE7yvGVgalhZ6RNXCmEHkUKBKxew==",
+ "dev": true
+ },
+ "node_modules/internal-slot": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.1.0.tgz",
+ "integrity": "sha512-4gd7VpWNQNB4UKKCFFVcp1AVv+FMOgs9NKzjHKusc8jTMhd5eL1NqQqOpE0KzMds804/yHlglp3uxgluOqAPLw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/interpret": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/interpret/-/interpret-3.1.1.tgz",
+ "integrity": "sha512-6xwYfHbajpoF0xLW+iwLkhwgvLoZDfjYfoFNu8ftMoXINzwuymNLd9u/KmwtdT2GbR+/Cz66otEGEVVUHX9QLQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/intl-messageformat": {
+ "version": "10.7.3",
+ "resolved": "https://registry.npmjs.org/intl-messageformat/-/intl-messageformat-10.7.3.tgz",
+ "integrity": "sha512-AAo/3oyh7ROfPhDuh7DxTTydh97OC+lv7h1Eq5LuHWuLsUMKOhtzTYuyXlUReuwZ9vANDHo4CS1bGRrn7TZRtg==",
+ "dependencies": {
+ "@formatjs/ecma402-abstract": "2.2.1",
+ "@formatjs/fast-memoize": "2.2.2",
+ "@formatjs/icu-messageformat-parser": "2.9.1",
+ "tslib": "2"
+ }
+ },
+ "node_modules/ipaddr.js": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.2.0.tgz",
+ "integrity": "sha512-Ag3wB2o37wslZS19hZqorUnrnzSkpOVy+IiiDEiTqNubEYpYuHWIf6K4psgN2ZWKExS4xhVCrRVfb/wfW8fWJA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.5.tgz",
+ "integrity": "sha512-DDfANUiiG2wC1qawP66qlTugJeL5HyzMpfr8lLK+jMQirGzNod0B12cFB/9q838Ru27sBwfw78/rdoU7RERz6A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
+ "dev": true
+ },
+ "node_modules/is-async-function": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-async-function/-/is-async-function-2.1.1.tgz",
+ "integrity": "sha512-9dgM/cZBnNvjzaMYHVoxxfPj2QXt22Ev7SuuPrs+xav0ukGB0S6d4ydZdEiM48kLx5kDV+QBPrpVnFyefL8kkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "async-function": "^1.0.0",
+ "call-bound": "^1.0.3",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-bigint": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.1.0.tgz",
+ "integrity": "sha512-n4ZT37wG78iz03xPRKJrHTdZbe3IicyucEtdRsV5yglwc3GyUfbAfpSeD0FJ41NbUNSt5wbhqfp1fS+BgnvDFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-bigints": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.2.2.tgz",
+ "integrity": "sha512-wa56o2/ElJMYqjCjGkXri7it5FbebW5usLw/nPmCMs5DeZ7eziSYZhSmPRn0txqeW4LnAmQQU7FgqLpsEFKM4A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-buffer": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
+ "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w=="
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.16.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz",
+ "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.2.tgz",
+ "integrity": "sha512-RKtWF8pGmS87i2D6gqQu/l7EYRlVdfzemCJN/P3UOs//x1QE7mfhvzHIApBTRf7axvT6DMGwSwBXYCT0nfB9xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.1.0.tgz",
+ "integrity": "sha512-PwwhEakHVKTdRNVOw+/Gyh0+MzlCl4R6qKvkhuvLtPMggI1WAHt9sOwZxQLSGpUaDnrdyDsomoRgNnCfKNSXXg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-docker": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
+ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-finalizationregistry": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-finalizationregistry/-/is-finalizationregistry-1.1.1.tgz",
+ "integrity": "sha512-1pC6N8qWJbWoPtEjgcL2xyhQOP491EQjeUo3qTKcmV8YSDDJrOepfG8pcC7h/QgnQHYSv0mJ3Z/ZWxmatVrysg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-generator-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-generator-fn/-/is-generator-fn-2.1.0.tgz",
+ "integrity": "sha512-cTIB4yPYL/Grw0EaSzASzg6bBy9gqCofvWN8okThAYIxKJZC+udlRAmGbM0XLeniEJSs8uEgHPGuHSe1XsOLSQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-generator-function": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-generator-function/-/is-generator-function-1.1.2.tgz",
+ "integrity": "sha512-upqt1SkGkODW9tsGNG5mtXTXtECizwtS2kA161M+gJPc1xdb/Ax629af6YrTwcOeQHbewrPNlE5Dx7kzvXTizA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.4",
+ "generator-function": "^2.0.0",
+ "get-proto": "^1.0.1",
+ "has-tostringtag": "^1.0.2",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-inside-container": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz",
+ "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^3.0.0"
+ },
+ "bin": {
+ "is-inside-container": "cli.js"
+ },
+ "engines": {
+ "node": ">=14.16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-inside-container/node_modules/is-docker": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz",
+ "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==",
+ "dev": true,
+ "bin": {
+ "is-docker": "cli.js"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-map": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-map/-/is-map-2.0.3.tgz",
+ "integrity": "sha512-1Qed0/Hr2m+YqxnM09CjA2d/i6YZNfF6R2oRAOj36eUdS6qIV/huPJNSEpKbupewFs+ZsJlxsjjPbc0/afW6Lw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-network-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-network-error/-/is-network-error-1.1.0.tgz",
+ "integrity": "sha512-tUdRRAnhT+OtCZR/LxZelH/C7QtjtFrTu5tXCA8pl55eTUElUHT+GPYV8MBMBvea/j+NxQqVt3LbWMRir7Gx9g==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.1.1.tgz",
+ "integrity": "sha512-lZhclumE1G6VYD8VHe35wFaIif+CTy5SJIi5+3y4psDgWu4wPDoBhF8NxUOinEc7pHgiTsT6MaBb92rKhhD+Xw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-plain-obj": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
+ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-plain-object": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
+ "integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
+ "dev": true,
+ "dependencies": {
+ "isobject": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.2.1.tgz",
+ "integrity": "sha512-MjYsKHO5O7mCsmRGxWcLWheFqN9DJ/2TmngvjKXihe6efViPqc274+Fx/4fYj/r03+ESvBdTXK0V6tA3rgez1g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-retina": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-retina/-/is-retina-1.0.3.tgz",
+ "integrity": "sha512-/tCmbIETZwCd8uHWO+GvbRa7jxwHFHdfetHfiwoP0aN9UDf3prUJMtKn7iBFYipYhqY1bSTjur8hC/Dakt8eyw=="
+ },
+ "node_modules/is-root": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz",
+ "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/is-set": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.3.tgz",
+ "integrity": "sha512-iPAjerrse27/ygGLxw+EBR9agv9Y6uLeYVJMu+QNCoouJ1/1ri0mGrcWpfCqFZuzzx3WjtwxG098X+n4OuRkPg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.4.tgz",
+ "integrity": "sha512-ISWac8drv4ZGfwKl5slpHG9OwPNty4jOWPRIhBpxOoD+hqITiwuipOQ2bNthAzwA3B4fIjO4Nln74N0S9byq8A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-stream": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
+ "integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.1.1.tgz",
+ "integrity": "sha512-BtEeSsoaQjlSPBemMQIrY1MY0uM6vnS1g5fmufYOtnxLGUZM2178PKbhsk7Ffv58IX+ZtcvoGwccYsh0PglkAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-subset": {
+ "version": "0.1.1",
+ "resolved": "https://registry.npmjs.org/is-subset/-/is-subset-0.1.1.tgz",
+ "integrity": "sha512-6Ybun0IkarhmEqxXCNw/C0bna6Zb/TkfUX9UbwJtK6ObwAVCxmAP308WWTHviM/zAqXk05cdhYsUsZeGQh99iw==",
+ "dev": true
+ },
+ "node_modules/is-symbol": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.1.1.tgz",
+ "integrity": "sha512-9gGx6GTtCQM73BgmHQXfDmLtfjjTUDSyoxTCbp5WtoixAhfgsDirWIcVQ/IHpvI5Vgd5i/J5F7B9cN/WlVbC/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "safe-regex-test": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.15.tgz",
+ "integrity": "sha512-p3EcsicXjit7SaskXHs1hA91QxgTw46Fv6EFKKGS5DRFLD8yKnohjF3hxoju94b/OcMZoQukzpPpBE9uLVKzgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakmap": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakmap/-/is-weakmap-2.0.2.tgz",
+ "integrity": "sha512-K5pXYOm9wqY1RgjpL3YTkF39tni1XajUIkawTLUo9EZEVUFga5gSQJF8nNS7ZwJQ02y+1YCNYcMh+HIf1ZqE+w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.1.1.tgz",
+ "integrity": "sha512-6i9mGWSlqzNMEqpCp93KwRS1uUOodk2OJ6b+sq7ZPDSy2WuI5NFIxp/254TytR8ftefexkWn5xNiHUNpPOfSew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakset": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/is-weakset/-/is-weakset-2.0.4.tgz",
+ "integrity": "sha512-mfcwb6IzQyOKTs84CQMrOwW4gQcaTOAWJ0zzJCl2WSPDrWk/OzDaImWFH3djXhb24g4eudZfLRozAvPGw4d9hQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "get-intrinsic": "^1.2.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-wsl": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
+ "integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
+ "dev": true,
+ "dependencies": {
+ "is-docker": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true
+ },
+ "node_modules/isobject": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/istanbul-lib-coverage": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
+ "integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/istanbul-lib-instrument": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-6.0.3.tgz",
+ "integrity": "sha512-Vtgk7L/R2JHyyGW07spoFlB8/lpjiOLTjMdms6AFMraYt3BaJauod/NGrfnVG/y4Ix1JEuMRPDPEj2ua+zz1/Q==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.23.9",
+ "@babel/parser": "^7.23.9",
+ "@istanbuljs/schema": "^0.1.3",
+ "istanbul-lib-coverage": "^3.2.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-instrument/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-report/-/istanbul-lib-report-3.0.1.tgz",
+ "integrity": "sha512-GCfE1mtsHGOELCU8e/Z7YWzpmybrx/+dSTfLrvY8qRmaY6zXTKWn6WQIjaAFw069icm6GVMNkgu0NzI4iPZUNw==",
+ "dev": true,
+ "dependencies": {
+ "istanbul-lib-coverage": "^3.0.0",
+ "make-dir": "^4.0.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-report/node_modules/make-dir": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-4.0.0.tgz",
+ "integrity": "sha512-hXdUTZYIVOt1Ex//jAQi+wTZZpUpwBj/0QsOzqegb3rGMMeJiSEu5xLHnYfBrRV4RH2+OCSOO95Is/7x1WJ4bw==",
+ "dev": true,
+ "dependencies": {
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/istanbul-lib-report/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/istanbul-lib-source-maps/-/istanbul-lib-source-maps-4.0.1.tgz",
+ "integrity": "sha512-n3s8EwkdFIJCG3BPKBYvskgXGoy88ARzvegkitk60NxRdwltLOTaH7CUiMRXvwYorl0Q712iEjcWB+fK/MrWVw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.1",
+ "istanbul-lib-coverage": "^3.0.0",
+ "source-map": "^0.6.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/istanbul-lib-source-maps/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/istanbul-reports": {
+ "version": "3.1.7",
+ "resolved": "https://registry.npmjs.org/istanbul-reports/-/istanbul-reports-3.1.7.tgz",
+ "integrity": "sha512-BewmUXImeuRk2YY0PVbxgKAysvhRPUQE0h5QRM++nVWyubKGV0l8qQ5op8+B2DOmwSe63Jivj0BjkPQVf8fP5g==",
+ "dev": true,
+ "dependencies": {
+ "html-escaper": "^2.0.0",
+ "istanbul-lib-report": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/iterator.prototype": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/iterator.prototype/-/iterator.prototype-1.1.5.tgz",
+ "integrity": "sha512-H0dkQoCa3b2VEeKQBOxFph+JAbcrQdE7KC0UkqwpLmv2EC4P41QXP+rqo9wYodACiG5/WM5s9oDApTU8utwj9g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "get-proto": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/jake": {
+ "version": "10.9.2",
+ "resolved": "https://registry.npmjs.org/jake/-/jake-10.9.2.tgz",
+ "integrity": "sha512-2P4SQ0HrLQ+fw6llpLnOaGAvN2Zu6778SJMrCUwns4fOoG9ayrTiZk3VV8sCPkVZF8ab0zksVpS8FDY5pRCNBA==",
+ "dev": true,
+ "dependencies": {
+ "async": "^3.2.3",
+ "chalk": "^4.0.2",
+ "filelist": "^1.0.4",
+ "minimatch": "^3.1.2"
+ },
+ "bin": {
+ "jake": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest/-/jest-29.7.0.tgz",
+ "integrity": "sha512-NIy3oAFp9shda19hy4HK0HRTWKtPJmGdnvywu01nOqNC2vZg+Z+fvJDxpMQA88eb2I9EcafcdjYgsDthnYTvGw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "import-local": "^3.0.2",
+ "jest-cli": "^29.7.0"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-changed-files": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-changed-files/-/jest-changed-files-29.7.0.tgz",
+ "integrity": "sha512-fEArFiwf1BpQ+4bXSprcDc3/x4HSzL4al2tozwVpDFpsxALjLYdyiIK4e5Vz66GQJIbXJ82+35PtysofptNX2w==",
+ "dev": true,
+ "dependencies": {
+ "execa": "^5.0.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-circus/-/jest-circus-29.7.0.tgz",
+ "integrity": "sha512-3E1nCMgipcTkCocFwM90XXQab9bS+GMsjdpmPrlelaxwD93Ad8iVEjX/vvHPdLPnFf+L40u+5+iutRdA1N9myw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/expect": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "co": "^4.6.0",
+ "dedent": "^1.0.0",
+ "is-generator-fn": "^2.0.0",
+ "jest-each": "^29.7.0",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "pretty-format": "^29.7.0",
+ "pure-rand": "^6.0.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-circus/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-circus/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-cli": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-cli/-/jest-cli-29.7.0.tgz",
+ "integrity": "sha512-OVVobw2IubN/GSYsxETi+gOe7Ka59EFMR/twOU3Jb2GnKKeMGJB5SGUUrEz3SFVmJASUdZUzy83sLNNQ2gZslg==",
+ "dev": true,
+ "dependencies": {
+ "@jest/core": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "create-jest": "^29.7.0",
+ "exit": "^0.1.2",
+ "import-local": "^3.0.2",
+ "jest-config": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "yargs": "^17.3.1"
+ },
+ "bin": {
+ "jest": "bin/jest.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "node-notifier": "^8.0.1 || ^9.0.0 || ^10.0.0"
+ },
+ "peerDependenciesMeta": {
+ "node-notifier": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-config/-/jest-config-29.7.0.tgz",
+ "integrity": "sha512-uXbpfeQ7R6TZBqI3/TxCU4q4ttk3u0PJeC+E0zbfSoSjq6bJ7buBPxzQPL0ifrkY4DNu4JUdk0ImlBUYi840eQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@jest/test-sequencer": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-jest": "^29.7.0",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "deepmerge": "^4.2.2",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-circus": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-runner": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "parse-json": "^5.2.0",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "peerDependencies": {
+ "@types/node": "*",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-config/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-config/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-config/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-diff": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-diff/-/jest-diff-29.7.0.tgz",
+ "integrity": "sha512-LMIgiIrhigmPrs03JHpxUh2yISK3vLFPkAodPeo0+BuF7wA2FoQbkEg1u8gBYBThncu7e1oEDUfIXVuTqLRUjw==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "diff-sequences": "^29.6.3",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-diff/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-diff/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-docblock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-docblock/-/jest-docblock-29.7.0.tgz",
+ "integrity": "sha512-q617Auw3A612guyaFgsbFeYpNP5t2aoUNLwBUbc/0kD1R4t9ixDbyFTHd1nok4epoVFpr7PmeWHrhvuV3XaJ4g==",
+ "dev": true,
+ "dependencies": {
+ "detect-newline": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-each/-/jest-each-29.7.0.tgz",
+ "integrity": "sha512-gns+Er14+ZrEoC5fhOfYCY1LOHHr0TI+rQUHZS8Ttw2l7gl+80eHc/gFf2Ktkw0+SIACDTeWvpFcv3B04VembQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-each/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-each/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-environment-node": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-environment-node/-/jest-environment-node-29.7.0.tgz",
+ "integrity": "sha512-DOSwCRqXirTOyheM+4d5YZOrWcdu0LNZ87ewUoywbcb2XR4wKgqiG8vNeYwhjFMbEkfju7wx2GYH0P2gevGvFw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-mock": "^29.7.0",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-get-type": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-get-type/-/jest-get-type-29.6.3.tgz",
+ "integrity": "sha512-zrteXnqYxfQh7l5FHyL38jL39di8H8rHoecLH3JNxH3BwOrBsNeabdap5e0I23lD4HHI8W5VFBZqG4Eaq5LNcw==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-haste-map": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.7.0.tgz",
+ "integrity": "sha512-fP8u2pyfqx0K1rGn1R9pyE0/KTn+G7PxktWidOBTqFPLYX0b9ksaMFkhK5vrS3DVun09pckLdlx90QthlW7AmA==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/graceful-fs": "^4.1.3",
+ "@types/node": "*",
+ "anymatch": "^3.0.3",
+ "fb-watchman": "^2.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-regex-util": "^29.6.3",
+ "jest-util": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.4",
+ "walker": "^1.0.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ },
+ "optionalDependencies": {
+ "fsevents": "^2.3.2"
+ }
+ },
+ "node_modules/jest-leak-detector": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-leak-detector/-/jest-leak-detector-29.7.0.tgz",
+ "integrity": "sha512-kYA8IJcSYtST2BY9I+SMC32nDpBT3J2NvWJx8+JCuCdl/CR1I4EKUJROiP8XtCcxqgTTBGJNdbB1A8XRKbTetw==",
+ "dev": true,
+ "dependencies": {
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-leak-detector/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-leak-detector/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-matcher-utils/-/jest-matcher-utils-29.7.0.tgz",
+ "integrity": "sha512-sBkD+Xi9DtcChsI3L3u0+N0opgPYnCRPtGcQYrgXmR+hmt/fYfWAL0xRXYU8eWOdfuLgBe0YCW3AFtnRLagq/g==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-matcher-utils/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-matcher-utils/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-message-util/-/jest-message-util-29.7.0.tgz",
+ "integrity": "sha512-GBEV4GRADeP+qtB2+6u61stea8mGcOT4mCtrYISZwfu9/ISHFJ/5zOMXYbpBE9RsS5+Gb63DW4FgmnKJ79Kf6w==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.12.13",
+ "@jest/types": "^29.6.3",
+ "@types/stack-utils": "^2.0.0",
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "micromatch": "^4.0.4",
+ "pretty-format": "^29.7.0",
+ "slash": "^3.0.0",
+ "stack-utils": "^2.0.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-message-util/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-message-util/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-mock": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-mock/-/jest-mock-29.7.0.tgz",
+ "integrity": "sha512-ITOMZn+UkYS4ZFh83xYAOzWStloNzJFO2s8DWrE4lhtGD+AorgnbkiKERe4wQVBydIGPx059g6riW5Btp6Llnw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "jest-util": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-pnp-resolver": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/jest-pnp-resolver/-/jest-pnp-resolver-1.2.3.tgz",
+ "integrity": "sha512-+3NpwQEnRoIBtx4fyhblQDPgJI0H1IEIkX7ShLUjPGA7TtUTvI1oiKi3SR4oBR0hQhQR80l4WAe5RrXBwWMA8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ },
+ "peerDependencies": {
+ "jest-resolve": "*"
+ },
+ "peerDependenciesMeta": {
+ "jest-resolve": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/jest-regex-util": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.6.3.tgz",
+ "integrity": "sha512-KJJBsRCyyLNWCNBOvZyRDnAIfUiRJ8v+hOBQYGn8gDyF3UegwiP4gwRR3/SDa42g1YbVycTidUF3rKjyLFDWbg==",
+ "dev": true,
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve/-/jest-resolve-29.7.0.tgz",
+ "integrity": "sha512-IOVhZSrg+UvVAshDSDtHyFCCBUl/Q3AAJv8iZ6ZjnZ74xzvwuzLXid9IIIPgTnY62SJjfuupMKZsZQRsCvxEgA==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.0.0",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-pnp-resolver": "^1.2.2",
+ "jest-util": "^29.7.0",
+ "jest-validate": "^29.7.0",
+ "resolve": "^1.20.0",
+ "resolve.exports": "^2.0.0",
+ "slash": "^3.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve-dependencies": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-resolve-dependencies/-/jest-resolve-dependencies-29.7.0.tgz",
+ "integrity": "sha512-un0zD/6qxJ+S0et7WxeI3H5XSe9lTBBR7bOHCHXkKR6luG5mwDDlIzVQ0V5cZCuoTgEdcdwzTghYkTWfubi+nA==",
+ "dev": true,
+ "dependencies": {
+ "jest-regex-util": "^29.6.3",
+ "jest-snapshot": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-resolve/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-runner": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runner/-/jest-runner-29.7.0.tgz",
+ "integrity": "sha512-fsc4N6cPCAahybGBfTRcq5wFR6fpLznMg47sY5aDpsoejOcVYFb07AHuSnR0liMcPTgBsA3ZJL6kFOjPdoNipQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/console": "^29.7.0",
+ "@jest/environment": "^29.7.0",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "graceful-fs": "^4.2.9",
+ "jest-docblock": "^29.7.0",
+ "jest-environment-node": "^29.7.0",
+ "jest-haste-map": "^29.7.0",
+ "jest-leak-detector": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-resolve": "^29.7.0",
+ "jest-runtime": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "jest-watcher": "^29.7.0",
+ "jest-worker": "^29.7.0",
+ "p-limit": "^3.1.0",
+ "source-map-support": "0.5.13"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runner/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/jest-runner/node_modules/source-map-support": {
+ "version": "0.5.13",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.13.tgz",
+ "integrity": "sha512-SHSKFHadjVA5oR4PPqhtAVdcBWwRYVd6g6cAXnIbRiIwc2EhPrTuKUBdSLvlEKyIP3GCf89fltvcZiP9MMFA1w==",
+ "dev": true,
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/jest-runtime": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-runtime/-/jest-runtime-29.7.0.tgz",
+ "integrity": "sha512-gUnLjgwdGqW7B4LvOIkbKs9WGbn+QLqRQQ9juC6HndeDiezIwhDP+mhMwHWCEcfQ5RUXa6OPnFF8BJh5xegwwQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/environment": "^29.7.0",
+ "@jest/fake-timers": "^29.7.0",
+ "@jest/globals": "^29.7.0",
+ "@jest/source-map": "^29.6.3",
+ "@jest/test-result": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "cjs-module-lexer": "^1.0.0",
+ "collect-v8-coverage": "^1.0.0",
+ "glob": "^7.1.3",
+ "graceful-fs": "^4.2.9",
+ "jest-haste-map": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-mock": "^29.7.0",
+ "jest-regex-util": "^29.6.3",
+ "jest-resolve": "^29.7.0",
+ "jest-snapshot": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "slash": "^3.0.0",
+ "strip-bom": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-runtime/node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-snapshot": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-snapshot/-/jest-snapshot-29.7.0.tgz",
+ "integrity": "sha512-Rm0BMWtxBcioHr1/OX5YCP8Uov4riHvKPknOGs804Zg9JGZgmIBkbtlxJC/7Z4msKYVbIJtfU+tKb8xlYNfdkw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.11.6",
+ "@babel/generator": "^7.7.2",
+ "@babel/plugin-syntax-jsx": "^7.7.2",
+ "@babel/plugin-syntax-typescript": "^7.7.2",
+ "@babel/types": "^7.3.3",
+ "@jest/expect-utils": "^29.7.0",
+ "@jest/transform": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "babel-preset-current-node-syntax": "^1.0.0",
+ "chalk": "^4.0.0",
+ "expect": "^29.7.0",
+ "graceful-fs": "^4.2.9",
+ "jest-diff": "^29.7.0",
+ "jest-get-type": "^29.6.3",
+ "jest-matcher-utils": "^29.7.0",
+ "jest-message-util": "^29.7.0",
+ "jest-util": "^29.7.0",
+ "natural-compare": "^1.4.0",
+ "pretty-format": "^29.7.0",
+ "semver": "^7.5.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-snapshot/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/jest-styled-components": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/jest-styled-components/-/jest-styled-components-7.2.0.tgz",
+ "integrity": "sha512-gwyyveNjvuRA0pyhbQoydXZllLZESs2VuL5fXCabzh0buHPAOUfANtW7n5YMPmdC0sH3VB7h2eUGZ23+tjvaBA==",
+ "dev": true,
+ "dependencies": {
+ "@adobe/css-tools": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 12"
+ },
+ "peerDependencies": {
+ "styled-components": ">= 5"
+ }
+ },
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-validate/-/jest-validate-29.7.0.tgz",
+ "integrity": "sha512-ZB7wHqaRGVw/9hST/OuFUReG7M8vKeq0/J2egIGLdvjHCmYqGARhzXmtgi+gVeZ5uXFF219aOc3Ls2yLg27tkw==",
+ "dev": true,
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "camelcase": "^6.2.0",
+ "chalk": "^4.0.0",
+ "jest-get-type": "^29.6.3",
+ "leven": "^3.1.0",
+ "pretty-format": "^29.7.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-validate/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/jest-validate/node_modules/pretty-format": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-29.7.0.tgz",
+ "integrity": "sha512-Pdlw/oPxN+aXdmM9R00JVC9WVFoCLTKJvDVLgmJ+qAffBMxsV85l/Lu7sNx4zSzPyoL2euImuEwHhOXdEgNFZQ==",
+ "dev": true,
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^18.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-watcher": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-watcher/-/jest-watcher-29.7.0.tgz",
+ "integrity": "sha512-49Fg7WXkU3Vl2h6LbLtMQ/HyB6rXSIX7SqvBLQmssRBGN9I0PNvPmAmCWSOY6SOvrjhI/F7/bGAv9RtnsPA03g==",
+ "dev": true,
+ "dependencies": {
+ "@jest/test-result": "^29.7.0",
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "ansi-escapes": "^4.2.1",
+ "chalk": "^4.0.0",
+ "emittery": "^0.13.1",
+ "jest-util": "^29.7.0",
+ "string-length": "^4.0.1"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
+ "dependencies": {
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.21.6",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
+ "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
+ "dev": true,
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
+ "license": "MIT",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "dev": true,
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug=="
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dev": true,
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/jsx-ast-utils": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/jsx-ast-utils/-/jsx-ast-utils-3.3.5.tgz",
+ "integrity": "sha512-ZZow9HBI5O6EPgSJLUb8n2NKgmVWTwCvHGwFuJlMjvLFqlGG6pjirPhtdsseaLZjSibD8eegzmYpUZwoIlj2cQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "array-includes": "^3.1.6",
+ "array.prototype.flat": "^1.3.1",
+ "object.assign": "^4.1.4",
+ "object.values": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/kind-of": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
+ "integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/kleur": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/kleur/-/kleur-3.0.3.tgz",
+ "integrity": "sha512-eTIzlVOSUR+JxdDFepEYcBMtZ9Qqdef+rnzWdRZuMbOywu5tO2w2N7rqjoANZ5k9vywhL6Br1VRjUIgTQx4E8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/launch-editor": {
+ "version": "2.9.1",
+ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.9.1.tgz",
+ "integrity": "sha512-Gcnl4Bd+hRO9P9icCP/RVVT2o8SFlPXofuCxvA2SaZuH45whSvf5p8x5oih5ftLiVhEI4sp5xDY+R+b3zJBh5w==",
+ "dev": true,
+ "dependencies": {
+ "picocolors": "^1.0.0",
+ "shell-quote": "^1.8.1"
+ }
+ },
+ "node_modules/leven": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/leven/-/leven-3.1.0.tgz",
+ "integrity": "sha512-qsda+H8jTaUaN/x5vzW2rzc+8Rw4TAQ/4KjB46IwK5VH+IlVeeeje/EoZRpiXvIqjFgK84QffqPztGI3VBLG1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
+ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
+ "dev": true
+ },
+ "node_modules/lint-staged": {
+ "version": "16.1.2",
+ "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-16.1.2.tgz",
+ "integrity": "sha512-sQKw2Si2g9KUZNY3XNvRuDq4UJqpHwF0/FQzZR2M7I5MvtpWvibikCjUVJzZdGE0ByurEl3KQNvsGetd1ty1/Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^5.4.1",
+ "commander": "^14.0.0",
+ "debug": "^4.4.1",
+ "lilconfig": "^3.1.3",
+ "listr2": "^8.3.3",
+ "micromatch": "^4.0.8",
+ "nano-spawn": "^1.0.2",
+ "pidtree": "^0.6.0",
+ "string-argv": "^0.3.2",
+ "yaml": "^2.8.0"
+ },
+ "bin": {
+ "lint-staged": "bin/lint-staged.js"
+ },
+ "engines": {
+ "node": ">=20.17"
+ },
+ "funding": {
+ "url": "https://opencollective.com/lint-staged"
+ }
+ },
+ "node_modules/lint-staged/node_modules/chalk": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.4.1.tgz",
+ "integrity": "sha512-zgVZuo2WcZgfUEmsn6eO3kINexW8RAE4maiQ8QNs8CtpPCSyMiYsULR3HQYkm3w8FIA3SberyMJMSldGsW+U3w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.17.0 || ^14.13 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/lint-staged/node_modules/commander": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.0.tgz",
+ "integrity": "sha512-2uM9rYjPvyq39NwLRqaiLtWHyDC1FvryJDa2ATTVims5YAS4PupsEQsDvP14FqhFr0P49CYDugi59xaxJlTXRA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20"
+ }
+ },
+ "node_modules/lint-staged/node_modules/lilconfig": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
+ "node_modules/lint-staged/node_modules/yaml": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.0.tgz",
+ "integrity": "sha512-4lLa/EcQCB0cJkyts+FpIRx5G/llPxfP6VQU5KByHEhLxY3IJCH0f0Hy1MHI8sClTvsIb8qwRJ6R/ZdlDJ/leQ==",
+ "dev": true,
+ "license": "ISC",
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14.6"
+ }
+ },
+ "node_modules/listr2": {
+ "version": "8.3.3",
+ "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz",
+ "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cli-truncate": "^4.0.0",
+ "colorette": "^2.0.20",
+ "eventemitter3": "^5.0.1",
+ "log-update": "^6.1.0",
+ "rfdc": "^1.4.1",
+ "wrap-ansi": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/listr2/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/listr2/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/listr2/node_modules/emoji-regex": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
+ "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/listr2/node_modules/eventemitter3": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz",
+ "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/listr2/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/listr2/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/listr2/node_modules/wrap-ansi": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+ "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/loader-runner": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz",
+ "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==",
+ "engines": {
+ "node": ">=6.11.5"
+ }
+ },
+ "node_modules/loader-utils": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz",
+ "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 12.13.0"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.23",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.23.tgz",
+ "integrity": "sha512-LgVTMpQtIopCi79SJeDiP0TfWi5CNEc/L/aRdTh3yIvmZXTnheWpKjSZhnvMl8iXbC1tFg9gdHHDMLoV7CnG+w==",
+ "license": "MIT"
+ },
+ "node_modules/lodash-es": {
+ "version": "4.17.23",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.23.tgz",
+ "integrity": "sha512-kVI48u3PZr38HdYz98UmfPnXl2DXrpdctLrFLCd3kOx1xUkOmpFPx7gCWWM5MPkL/fD8zb+Ph0QzjGFs4+hHWg==",
+ "license": "MIT"
+ },
+ "node_modules/lodash.camelcase": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz",
+ "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==",
+ "dev": true
+ },
+ "node_modules/lodash.debounce": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "dev": true
+ },
+ "node_modules/lodash.escape": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/lodash.escape/-/lodash.escape-4.0.1.tgz",
+ "integrity": "sha512-nXEOnb/jK9g0DYMr1/Xvq6l5xMD7GDG55+GSYIYmS0G4tBk/hURD4JR9WCavs04t33WmJx9kCyp9vJ+mr4BOUw==",
+ "dev": true
+ },
+ "node_modules/lodash.flattendeep": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.flattendeep/-/lodash.flattendeep-4.4.0.tgz",
+ "integrity": "sha512-uHaJFihxmJcEX3kT4I23ABqKKalJ/zDrDg0lsFtc1h+3uw49SIJ5beyhx5ExVRti3AvKoOJngIj7xz3oylPdWQ==",
+ "dev": true
+ },
+ "node_modules/lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+ "dev": true
+ },
+ "node_modules/lodash.memoize": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag=="
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/lodash.uniq": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
+ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ=="
+ },
+ "node_modules/log-update": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz",
+ "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-escapes": "^7.0.0",
+ "cli-cursor": "^5.0.0",
+ "slice-ansi": "^7.1.0",
+ "strip-ansi": "^7.1.0",
+ "wrap-ansi": "^9.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/ansi-escapes": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.0.0.tgz",
+ "integrity": "sha512-GdYO7a61mR0fOlAsvC9/rIHf7L96sBc6dEWzeOu+KAea5bZyQRPIpojrVoI4AXGJS/ycu/fBTdLrUkA4ODrvjw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "environment": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/emoji-regex": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.4.0.tgz",
+ "integrity": "sha512-EC+0oUMY1Rqm4O6LLrgjtYDvcVYTy7chDnM4Q7030tP4Kwj3u/pR6gP9ygnp2CJMK5Gq+9Q2oqmrFJAz01DXjw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/log-update/node_modules/is-fullwidth-code-point": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz",
+ "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-east-asian-width": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/slice-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz",
+ "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "is-fullwidth-code-point": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/string-width": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz",
+ "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "emoji-regex": "^10.3.0",
+ "get-east-asian-width": "^1.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/log-update/node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/log-update/node_modules/wrap-ansi": {
+ "version": "9.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz",
+ "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.2.1",
+ "string-width": "^7.0.0",
+ "strip-ansi": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lower-case": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
+ "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
+ "dev": true,
+ "dependencies": {
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/lz-string": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/lz-string/-/lz-string-1.5.0.tgz",
+ "integrity": "sha512-h5bgJWpxJNswbU7qCrV0tIKQCaS3blPDrqKWx+QxzuzL1zGUzij9XCWLrSLsJPu5t+eWA/ycetzYAO5IOMcWAQ==",
+ "dev": true,
+ "peer": true,
+ "bin": {
+ "lz-string": "bin/bin.js"
+ }
+ },
+ "node_modules/make-dir": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
+ "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^4.0.1",
+ "semver": "^5.6.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/make-dir/node_modules/semver": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz",
+ "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/make-error": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/make-error/-/make-error-1.3.6.tgz",
+ "integrity": "sha512-s8UhlNe7vPKomQhC1qFelMokr/Sc3AgNbso3n74mVPA5LTZwkB9NlXf4XPamLxJE8h0gh73rM94xvwRT2CVInw==",
+ "dev": true
+ },
+ "node_modules/makeerror": {
+ "version": "1.0.12",
+ "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
+ "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
+ "dev": true,
+ "dependencies": {
+ "tmpl": "1.0.5"
+ }
+ },
+ "node_modules/math-intrinsics": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
+ "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/md5": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/md5/-/md5-2.3.0.tgz",
+ "integrity": "sha512-T1GITYmFaKuO91vxyoQMFETst+O71VUPEU3ze5GNzDm0OWdP8v1ziTaAEPUr/3kLsY3Sftgz242A1SetQiDL7g==",
+ "dependencies": {
+ "charenc": "0.0.2",
+ "crypt": "0.0.2",
+ "is-buffer": "~1.1.6"
+ }
+ },
+ "node_modules/mdn-data": {
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
+ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow=="
+ },
+ "node_modules/media-typer": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/memfs": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
+ "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
+ "dev": true,
+ "dependencies": {
+ "fs-monkey": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/merge-descriptors": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/merge-stream": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/methods": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "mime": "cli.js"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
+ "integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/mimic-function": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz",
+ "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/min-indent": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz",
+ "integrity": "sha512-I9jwMn07Sy/IwOj3zVkVik2JTvgpaykDZEigL6Rx6N9LbMywwUSMtxET+7lVoDLLd3O3IXwJwvuuns8UB/HeAg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/mini-css-extract-plugin": {
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.9.2.tgz",
+ "integrity": "sha512-GJuACcS//jtq4kCtd5ii/M0SZf7OZRH+BxdqXZHaJfb8TJiVl+NgQRPwiYt2EuqeSkNydn/7vP+bcE27C5mb9w==",
+ "dev": true,
+ "dependencies": {
+ "schema-utils": "^4.0.0",
+ "tapable": "^2.2.1"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/minimalistic-assert": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
+ "integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
+ "dev": true
+ },
+ "node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/mitt": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/mitt/-/mitt-3.0.1.tgz",
+ "integrity": "sha512-vKivATfr97l2/QBCYAkXYDbrIWPM2IIKEl7YPhjCvKlG3kE2gm+uBo6nEXK3M5/Ffh/FLpKExzOQ3JJoJGFKBw==",
+ "license": "MIT"
+ },
+ "node_modules/mnth": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/mnth/-/mnth-2.0.0.tgz",
+ "integrity": "sha512-3ZH4UWBGpAwCKdfjynLQpUDVZWMe6vRHwarIpMdGLUp89CVR9hjzgyWERtMyqx+fPEqQ/PsAxFwvwPxLFxW40A==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.0"
+ },
+ "engines": {
+ "node": ">=12.13.0"
+ }
+ },
+ "node_modules/moo": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/moo/-/moo-0.5.2.tgz",
+ "integrity": "sha512-iSAJLHYKnX41mKcJKjqvnAN9sf0LMDTXDEvFv+ffuRR9a1MIuXLjMNL6EsnDHSkKLTWNqQQ5uo61P4EbU4NU+Q==",
+ "dev": true
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/multicast-dns": {
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
+ "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
+ "dev": true,
+ "dependencies": {
+ "dns-packet": "^5.2.2",
+ "thunky": "^1.0.2"
+ },
+ "bin": {
+ "multicast-dns": "cli.js"
+ }
+ },
+ "node_modules/nano-spawn": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/nano-spawn/-/nano-spawn-1.0.2.tgz",
+ "integrity": "sha512-21t+ozMQDAL/UGgQVBbZ/xXvNO10++ZPuTmKRO8k9V3AClVRht49ahtDjfY8l1q6nSHOrE5ASfthzH3ol6R/hg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=20.17"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/nano-spawn?sponsor=1"
+ }
+ },
+ "node_modules/nanoclone": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
+ "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.11",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz",
+ "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/nearley": {
+ "version": "2.20.1",
+ "resolved": "https://registry.npmjs.org/nearley/-/nearley-2.20.1.tgz",
+ "integrity": "sha512-+Mc8UaAebFzgV+KpI5n7DasuuQCHA89dmwm7JXw3TV43ukfNQ9DnBH3Mdb2g/I4Fdxc26pwimBWvjIw0UAILSQ==",
+ "dev": true,
+ "dependencies": {
+ "commander": "^2.19.0",
+ "moo": "^0.5.0",
+ "railroad-diagrams": "^1.0.0",
+ "randexp": "0.4.6"
+ },
+ "bin": {
+ "nearley-railroad": "bin/nearley-railroad.js",
+ "nearley-test": "bin/nearley-test.js",
+ "nearley-unparse": "bin/nearley-unparse.js",
+ "nearleyc": "bin/nearleyc.js"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://nearley.js.org/#give-to-nearley"
+ }
+ },
+ "node_modules/nearley/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "dev": true
+ },
+ "node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
+ },
+ "node_modules/no-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
+ "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
+ "dev": true,
+ "dependencies": {
+ "lower-case": "^2.0.2",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/node-addon-api": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/node-addon-api/-/node-addon-api-7.1.1.tgz",
+ "integrity": "sha512-5m3bsyrjFWE1xf7nz7YXdN4udnVtXK6/Yfgn5qnahL6bCkf2yKt4k3nuTKAtT4r3IG8JNR2ncsIMdZuAzJjHQQ==",
+ "dev": true,
+ "optional": true
+ },
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/node-fetch-h2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/node-fetch-h2/-/node-fetch-h2-2.3.0.tgz",
+ "integrity": "sha512-ofRW94Ab0T4AOh5Fk8t0h8OBWrmjb0SSB20xh1H8YnPV9EJ+f5AMoYSUQ2zgJ4Iq2HAK0I2l5/Nequ8YzFS3Hg==",
+ "dev": true,
+ "dependencies": {
+ "http2-client": "^1.2.5"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ }
+ },
+ "node_modules/node-int64": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
+ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==",
+ "dev": true
+ },
+ "node_modules/node-readfiles": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/node-readfiles/-/node-readfiles-0.2.0.tgz",
+ "integrity": "sha512-SU00ZarexNlE4Rjdm83vglt5Y9yiQ+XI1XpflWlb7q7UTN1JUItm69xMeiQCTxtTfnzt+83T8Cx+vI2ED++VDA==",
+ "dev": true,
+ "dependencies": {
+ "es6-promise": "^3.2.1"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
+ "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g=="
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-url": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
+ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/npm-run-path": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
+ "integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
+ "dev": true,
+ "dependencies": {
+ "path-key": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/npx": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/npx/-/npx-10.2.2.tgz",
+ "integrity": "sha512-eImmySusyeWphzs5iNh791XbZnZG0FSNvM4KSah34pdQQIDsdTDhIwg1sjN3AIVcjGLpbQ/YcfqHPshKZQK1fA==",
+ "bundleDependencies": [
+ "npm",
+ "libnpx"
+ ],
+ "deprecated": "This package is now part of the npm CLI.",
+ "dev": true,
+ "dependencies": {
+ "libnpx": "10.2.2",
+ "npm": "5.1.0"
+ },
+ "bin": {
+ "npx": "index.js"
+ }
+ },
+ "node_modules/npx/node_modules/ansi-align": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-convert": "^1.9.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/balanced-match": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/boxen": {
+ "version": "1.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-align": "^2.0.0",
+ "camelcase": "^4.0.0",
+ "chalk": "^2.0.1",
+ "cli-boxes": "^1.0.0",
+ "string-width": "^2.0.0",
+ "term-size": "^1.2.0",
+ "widest-line": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/builtins": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/camelcase": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/capture-stack-trace": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/chalk": {
+ "version": "2.4.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/ci-info": {
+ "version": "1.6.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/cli-boxes": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/cliui": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0",
+ "wrap-ansi": "^2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/code-point-at": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/color-convert": {
+ "version": "1.9.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "1.1.3"
+ }
+ },
+ "node_modules/npx/node_modules/color-name": {
+ "version": "1.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/concat-map": {
+ "version": "0.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/configstore": {
+ "version": "3.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dot-prop": "^4.1.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^1.0.0",
+ "unique-string": "^1.0.0",
+ "write-file-atomic": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/create-error-class": {
+ "version": "3.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "capture-stack-trace": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/cross-spawn": {
+ "version": "5.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "lru-cache": "^4.0.1",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ }
+ },
+ "node_modules/npx/node_modules/crypto-random-string": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/decamelize": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/deep-extend": {
+ "version": "0.6.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/dot-prop": {
+ "version": "4.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-obj": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/dotenv": {
+ "version": "5.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.6.0"
+ }
+ },
+ "node_modules/npx/node_modules/duplexer3": {
+ "version": "0.1.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/npx/node_modules/end-of-stream": {
+ "version": "1.4.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/npx/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/npx/node_modules/execa": {
+ "version": "0.7.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^5.0.1",
+ "get-stream": "^3.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/find-up": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/get-caller-file": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/get-stream": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/glob": {
+ "version": "7.1.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/npx/node_modules/global-dirs": {
+ "version": "0.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ini": "^1.3.4"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/got": {
+ "version": "6.7.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "create-error-class": "^3.0.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "is-redirect": "^1.0.0",
+ "is-retry-allowed": "^1.0.0",
+ "is-stream": "^1.0.0",
+ "lowercase-keys": "^1.0.0",
+ "safe-buffer": "^5.0.1",
+ "timed-out": "^4.0.0",
+ "unzip-response": "^2.0.1",
+ "url-parse-lax": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/graceful-fs": {
+ "version": "4.2.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/has-flag": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/hosted-git-info": {
+ "version": "2.8.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/import-lazy": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/npx/node_modules/inflight": {
+ "version": "1.0.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/npx/node_modules/inherits": {
+ "version": "2.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/ini": {
+ "version": "1.3.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/invert-kv": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/is-ci": {
+ "version": "1.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ci-info": "^1.5.0"
+ },
+ "bin": {
+ "is-ci": "bin.js"
+ }
+ },
+ "node_modules/npx/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/is-installed-globally": {
+ "version": "0.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "global-dirs": "^0.1.0",
+ "is-path-inside": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/is-npm": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/is-obj": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/is-path-inside": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-is-inside": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/is-redirect": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/is-retry-allowed": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/is-stream": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/isexe": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/latest-version": {
+ "version": "3.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "package-json": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/lcid": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "invert-kv": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npx/node_modules/libnpx": {
+ "version": "10.2.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "dotenv": "^5.0.1",
+ "npm-package-arg": "^6.0.0",
+ "rimraf": "^2.6.2",
+ "safe-buffer": "^5.1.0",
+ "update-notifier": "^2.3.0",
+ "which": "^1.3.0",
+ "y18n": "^4.0.0",
+ "yargs": "^11.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/locate-path": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-locate": "^2.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/lowercase-keys": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/lru-cache": {
+ "version": "4.1.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/npx/node_modules/make-dir": {
+ "version": "1.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/map-age-cleaner": {
+ "version": "0.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-defer": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npx/node_modules/mem": {
+ "version": "4.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "map-age-cleaner": "^0.1.1",
+ "mimic-fn": "^2.0.0",
+ "p-is-promise": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npx/node_modules/mimic-fn": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npx/node_modules/minimatch": {
+ "version": "3.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/minimist": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/nice-try": {
+ "version": "1.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm": {
+ "version": "5.1.0",
+ "bundleDependencies": [
+ "abbrev",
+ "ansi-regex",
+ "ansicolors",
+ "ansistyles",
+ "aproba",
+ "archy",
+ "cacache",
+ "call-limit",
+ "bluebird",
+ "chownr",
+ "cmd-shim",
+ "columnify",
+ "config-chain",
+ "debuglog",
+ "detect-indent",
+ "dezalgo",
+ "editor",
+ "fs-vacuum",
+ "fs-write-stream-atomic",
+ "fstream",
+ "fstream-npm",
+ "glob",
+ "graceful-fs",
+ "has-unicode",
+ "hosted-git-info",
+ "iferr",
+ "imurmurhash",
+ "inflight",
+ "inherits",
+ "ini",
+ "init-package-json",
+ "JSONStream",
+ "lazy-property",
+ "lockfile",
+ "lodash._baseindexof",
+ "lodash._baseuniq",
+ "lodash._bindcallback",
+ "lodash._cacheindexof",
+ "lodash._createcache",
+ "lodash._getnative",
+ "lodash.clonedeep",
+ "lodash.restparam",
+ "lodash.union",
+ "lodash.uniq",
+ "lodash.without",
+ "lru-cache",
+ "mkdirp",
+ "mississippi",
+ "move-concurrently",
+ "node-gyp",
+ "nopt",
+ "normalize-package-data",
+ "npm-cache-filename",
+ "npm-install-checks",
+ "npm-package-arg",
+ "npm-registry-client",
+ "npm-user-validate",
+ "npmlog",
+ "once",
+ "opener",
+ "osenv",
+ "pacote",
+ "path-is-inside",
+ "promise-inflight",
+ "read",
+ "read-cmd-shim",
+ "read-installed",
+ "read-package-json",
+ "read-package-tree",
+ "readable-stream",
+ "readdir-scoped-modules",
+ "request",
+ "retry",
+ "rimraf",
+ "semver",
+ "sha",
+ "slide",
+ "sorted-object",
+ "sorted-union-stream",
+ "ssri",
+ "strip-ansi",
+ "tar",
+ "text-table",
+ "uid-number",
+ "umask",
+ "unique-filename",
+ "unpipe",
+ "update-notifier",
+ "uuid",
+ "validate-npm-package-license",
+ "validate-npm-package-name",
+ "which",
+ "wrappy",
+ "write-file-atomic",
+ "safe-buffer",
+ "worker-farm"
+ ],
+ "dev": true,
+ "inBundle": true,
+ "license": "Artistic-2.0",
+ "dependencies": {
+ "abbrev": "~1.1.0",
+ "ansi-regex": "~3.0.0",
+ "ansicolors": "~0.3.2",
+ "ansistyles": "~0.1.3",
+ "aproba": "~1.1.2",
+ "archy": "~1.0.0",
+ "bluebird": "~3.5.0",
+ "cacache": "~9.2.9",
+ "call-limit": "~1.1.0",
+ "chownr": "~1.0.1",
+ "cmd-shim": "~2.0.2",
+ "columnify": "~1.5.4",
+ "config-chain": "~1.1.11",
+ "debuglog": "*",
+ "detect-indent": "~5.0.0",
+ "dezalgo": "~1.0.3",
+ "editor": "~1.0.0",
+ "fs-vacuum": "~1.2.10",
+ "fs-write-stream-atomic": "~1.0.10",
+ "fstream": "~1.0.11",
+ "fstream-npm": "~1.2.1",
+ "glob": "~7.1.2",
+ "graceful-fs": "~4.1.11",
+ "has-unicode": "~2.0.1",
+ "hosted-git-info": "~2.5.0",
+ "iferr": "~0.1.5",
+ "imurmurhash": "*",
+ "inflight": "~1.0.6",
+ "inherits": "~2.0.3",
+ "ini": "~1.3.4",
+ "init-package-json": "~1.10.1",
+ "JSONStream": "~1.3.1",
+ "lazy-property": "~1.0.0",
+ "lockfile": "~1.0.3",
+ "lodash._baseindexof": "*",
+ "lodash._baseuniq": "~4.6.0",
+ "lodash._bindcallback": "*",
+ "lodash._cacheindexof": "*",
+ "lodash._createcache": "*",
+ "lodash._getnative": "*",
+ "lodash.clonedeep": "~4.5.0",
+ "lodash.restparam": "*",
+ "lodash.union": "~4.6.0",
+ "lodash.uniq": "~4.5.0",
+ "lodash.without": "~4.4.0",
+ "lru-cache": "~4.1.1",
+ "mississippi": "~1.3.0",
+ "mkdirp": "~0.5.1",
+ "move-concurrently": "~1.0.1",
+ "node-gyp": "~3.6.2",
+ "nopt": "~4.0.1",
+ "normalize-package-data": "~2.4.0",
+ "npm-cache-filename": "~1.0.2",
+ "npm-install-checks": "~3.0.0",
+ "npm-package-arg": "~5.1.2",
+ "npm-registry-client": "~8.4.0",
+ "npm-user-validate": "~1.0.0",
+ "npmlog": "~4.1.2",
+ "once": "~1.4.0",
+ "opener": "~1.4.3",
+ "osenv": "~0.1.4",
+ "pacote": "~2.7.38",
+ "path-is-inside": "~1.0.2",
+ "promise-inflight": "~1.0.1",
+ "read": "~1.0.7",
+ "read-cmd-shim": "~1.0.1",
+ "read-installed": "~4.0.3",
+ "read-package-json": "~2.0.9",
+ "read-package-tree": "~5.1.6",
+ "readable-stream": "~2.3.2",
+ "readdir-scoped-modules": "*",
+ "request": "~2.81.0",
+ "retry": "~0.10.1",
+ "rimraf": "~2.6.1",
+ "safe-buffer": "~5.1.1",
+ "semver": "~5.3.0",
+ "sha": "~2.0.1",
+ "slide": "~1.1.6",
+ "sorted-object": "~2.0.1",
+ "sorted-union-stream": "~2.1.3",
+ "ssri": "~4.1.6",
+ "strip-ansi": "~4.0.0",
+ "tar": "~2.2.1",
+ "text-table": "~0.2.0",
+ "uid-number": "0.0.6",
+ "umask": "~1.1.0",
+ "unique-filename": "~1.1.0",
+ "unpipe": "~1.0.0",
+ "update-notifier": "~2.2.0",
+ "uuid": "~3.1.0",
+ "validate-npm-package-license": "*",
+ "validate-npm-package-name": "~3.0.0",
+ "which": "~1.2.14",
+ "worker-farm": "~1.3.1",
+ "wrappy": "~1.0.2",
+ "write-file-atomic": "~2.1.0"
+ },
+ "bin": {
+ "npm": "bin/npm-cli.js"
+ }
+ },
+ "node_modules/npx/node_modules/npm-package-arg": {
+ "version": "6.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "hosted-git-info": "^2.7.1",
+ "osenv": "^0.1.5",
+ "semver": "^5.6.0",
+ "validate-npm-package-name": "^3.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm-run-path": {
+ "version": "2.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/abbrev": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/ansicolors": {
+ "version": "0.3.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/ansistyles": {
+ "version": "0.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/aproba": {
+ "version": "1.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/archy": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/bluebird": {
+ "version": "3.5.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/cacache": {
+ "version": "9.2.9",
+ "dev": true,
+ "inBundle": true,
+ "license": "CC0-1.0",
+ "dependencies": {
+ "bluebird": "^3.5.0",
+ "chownr": "^1.0.1",
+ "glob": "^7.1.2",
+ "graceful-fs": "^4.1.11",
+ "lru-cache": "^4.1.1",
+ "mississippi": "^1.3.0",
+ "mkdirp": "^0.5.1",
+ "move-concurrently": "^1.0.1",
+ "promise-inflight": "^1.0.1",
+ "rimraf": "^2.6.1",
+ "ssri": "^4.1.6",
+ "unique-filename": "^1.1.0",
+ "y18n": "^3.2.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/cacache/node_modules/lru-cache": {
+ "version": "4.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/cacache/node_modules/lru-cache/node_modules/pseudomap": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/cacache/node_modules/lru-cache/node_modules/yallist": {
+ "version": "2.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/cacache/node_modules/y18n": {
+ "version": "3.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/call-limit": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/chownr": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/cmd-shim": {
+ "version": "2.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "mkdirp": "~0.5.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/columnify": {
+ "version": "1.5.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "strip-ansi": "^3.0.0",
+ "wcwidth": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/columnify/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/columnify/node_modules/strip-ansi/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/columnify/node_modules/wcwidth": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "defaults": "^1.0.3"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/columnify/node_modules/wcwidth/node_modules/defaults": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "clone": "^1.0.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/columnify/node_modules/wcwidth/node_modules/defaults/node_modules/clone": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/config-chain": {
+ "version": "1.1.11",
+ "dev": true,
+ "inBundle": true,
+ "dependencies": {
+ "ini": "^1.3.4",
+ "proto-list": "~1.2.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/config-chain/node_modules/proto-list": {
+ "version": "1.2.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/debuglog": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/detect-indent": {
+ "version": "5.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/dezalgo": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "asap": "^2.0.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/dezalgo/node_modules/asap": {
+ "version": "2.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/editor": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/fs-vacuum": {
+ "version": "1.2.10",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "path-is-inside": "^1.0.1",
+ "rimraf": "^2.5.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/fs-write-stream-atomic": {
+ "version": "1.0.10",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "iferr": "^0.1.5",
+ "imurmurhash": "^0.1.4",
+ "readable-stream": "1 || 2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/fstream": {
+ "version": "1.0.11",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "inherits": "~2.0.0",
+ "mkdirp": ">=0.5 0",
+ "rimraf": "2"
+ },
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/fstream-npm": {
+ "version": "1.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "fstream-ignore": "^1.0.0",
+ "inherits": "2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/fstream-npm/node_modules/fstream-ignore": {
+ "version": "1.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "fstream": "^1.0.0",
+ "inherits": "2",
+ "minimatch": "^3.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/fstream-npm/node_modules/fstream-ignore/node_modules/minimatch": {
+ "version": "3.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/fstream-npm/node_modules/fstream-ignore/node_modules/minimatch/node_modules/brace-expansion": {
+ "version": "1.1.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/fstream-npm/node_modules/fstream-ignore/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/fstream-npm/node_modules/fstream-ignore/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map": {
+ "version": "0.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/glob": {
+ "version": "7.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "fs.realpath": "^1.0.0",
+ "inflight": "^1.0.4",
+ "inherits": "2",
+ "minimatch": "^3.0.4",
+ "once": "^1.3.0",
+ "path-is-absolute": "^1.0.0"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/glob/node_modules/fs.realpath": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/glob/node_modules/minimatch": {
+ "version": "3.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion": {
+ "version": "1.1.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/glob/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map": {
+ "version": "0.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/glob/node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/graceful-fs": {
+ "version": "4.1.11",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/has-unicode": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/hosted-git-info": {
+ "version": "2.5.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/iferr": {
+ "version": "0.1.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/inflight": {
+ "version": "1.0.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "once": "^1.3.0",
+ "wrappy": "1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/inherits": {
+ "version": "2.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/ini": {
+ "version": "1.3.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/init-package-json": {
+ "version": "1.10.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.1",
+ "npm-package-arg": "^4.0.0 || ^5.0.0",
+ "promzard": "^0.3.0",
+ "read": "~1.0.1",
+ "read-package-json": "1 || 2",
+ "semver": "2.x || 3.x || 4 || 5",
+ "validate-npm-package-license": "^3.0.1",
+ "validate-npm-package-name": "^3.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/init-package-json/node_modules/promzard": {
+ "version": "0.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "read": "1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/JSONStream": {
+ "version": "1.3.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "(MIT OR Apache-2.0)",
+ "dependencies": {
+ "jsonparse": "^1.2.0",
+ "through": ">=2.2.7 <3"
+ },
+ "bin": {
+ "JSONStream": "index.js"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/JSONStream/node_modules/jsonparse": {
+ "version": "1.3.1",
+ "dev": true,
+ "engines": [
+ "node >= 0.2.0"
+ ],
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/JSONStream/node_modules/through": {
+ "version": "2.3.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lazy-property": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lockfile": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash._baseindexof": {
+ "version": "3.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash._baseuniq": {
+ "version": "4.6.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "lodash._createset": "~4.0.0",
+ "lodash._root": "~3.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash._baseuniq/node_modules/lodash._createset": {
+ "version": "4.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash._baseuniq/node_modules/lodash._root": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash._bindcallback": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash._cacheindexof": {
+ "version": "3.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash._createcache": {
+ "version": "3.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "lodash._getnative": "^3.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash._getnative": {
+ "version": "3.9.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash.clonedeep": {
+ "version": "4.5.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash.restparam": {
+ "version": "3.6.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash.union": {
+ "version": "4.6.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash.uniq": {
+ "version": "4.5.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lodash.without": {
+ "version": "4.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lru-cache": {
+ "version": "4.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "pseudomap": "^1.0.2",
+ "yallist": "^2.1.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lru-cache/node_modules/pseudomap": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/lru-cache/node_modules/yallist": {
+ "version": "2.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi": {
+ "version": "1.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "concat-stream": "^1.5.0",
+ "duplexify": "^3.4.2",
+ "end-of-stream": "^1.1.0",
+ "flush-write-stream": "^1.0.0",
+ "from2": "^2.1.0",
+ "parallel-transform": "^1.1.0",
+ "pump": "^1.0.0",
+ "pumpify": "^1.3.3",
+ "stream-each": "^1.1.0",
+ "through2": "^2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/concat-stream": {
+ "version": "1.6.0",
+ "dev": true,
+ "engines": [
+ "node >= 0.8"
+ ],
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/concat-stream/node_modules/typedarray": {
+ "version": "0.0.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/duplexify": {
+ "version": "3.5.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "1.0.0",
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/duplexify/node_modules/end-of-stream": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "once": "~1.3.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/duplexify/node_modules/end-of-stream/node_modules/once": {
+ "version": "1.3.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/duplexify/node_modules/stream-shift": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/end-of-stream": {
+ "version": "1.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/flush-write-stream": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/from2": {
+ "version": "2.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/parallel-transform": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "cyclist": "~0.2.2",
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.1.5"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/parallel-transform/node_modules/cyclist": {
+ "version": "0.2.2",
+ "dev": true,
+ "inBundle": true
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/pump": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/pumpify": {
+ "version": "1.3.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "duplexify": "^3.1.2",
+ "inherits": "^2.0.1",
+ "pump": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/stream-each": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/stream-each/node_modules/stream-shift": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/through2": {
+ "version": "2.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "^2.1.5",
+ "xtend": "~4.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mississippi/node_modules/through2/node_modules/xtend": {
+ "version": "4.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mkdirp": {
+ "version": "0.5.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "minimist": "0.0.8"
+ },
+ "bin": {
+ "mkdirp": "bin/cmd.js"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/mkdirp/node_modules/minimist": {
+ "version": "0.0.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/move-concurrently": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^1.1.1",
+ "copy-concurrently": "^1.0.0",
+ "fs-write-stream-atomic": "^1.0.8",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.3"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/move-concurrently/node_modules/copy-concurrently": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^1.1.1",
+ "fs-write-stream-atomic": "^1.0.8",
+ "iferr": "^0.1.5",
+ "mkdirp": "^0.5.1",
+ "rimraf": "^2.5.4",
+ "run-queue": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/move-concurrently/node_modules/run-queue": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^1.1.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/node-gyp": {
+ "version": "3.6.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "fstream": "^1.0.0",
+ "glob": "^7.0.3",
+ "graceful-fs": "^4.1.2",
+ "minimatch": "^3.0.2",
+ "mkdirp": "^0.5.0",
+ "nopt": "2 || 3",
+ "npmlog": "0 || 1 || 2 || 3 || 4",
+ "osenv": "0",
+ "request": "2",
+ "rimraf": "2",
+ "semver": "~5.3.0",
+ "tar": "^2.0.0",
+ "which": "1"
+ },
+ "bin": {
+ "node-gyp": "bin/node-gyp.js"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/node-gyp/node_modules/minimatch": {
+ "version": "3.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/node-gyp/node_modules/minimatch/node_modules/brace-expansion": {
+ "version": "1.1.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/node-gyp/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/node-gyp/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map": {
+ "version": "0.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/node-gyp/node_modules/nopt": {
+ "version": "3.0.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "1"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/nopt": {
+ "version": "4.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "abbrev": "1",
+ "osenv": "^0.1.4"
+ },
+ "bin": {
+ "nopt": "bin/nopt.js"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/normalize-package-data": {
+ "version": "2.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "hosted-git-info": "^2.1.4",
+ "is-builtin-module": "^1.0.0",
+ "semver": "2 || 3 || 4 || 5",
+ "validate-npm-package-license": "^3.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/normalize-package-data/node_modules/is-builtin-module": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "builtin-modules": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/normalize-package-data/node_modules/is-builtin-module/node_modules/builtin-modules": {
+ "version": "1.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npm-cache-filename": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npm-install-checks": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "semver": "^2.3.0 || 3.x || 4 || 5"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npm-package-arg": {
+ "version": "5.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "hosted-git-info": "^2.4.2",
+ "osenv": "^0.1.4",
+ "semver": "^5.1.0",
+ "validate-npm-package-name": "^3.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npm-registry-client": {
+ "version": "8.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "concat-stream": "^1.5.2",
+ "graceful-fs": "^4.1.6",
+ "normalize-package-data": "~1.0.1 || ^2.0.0",
+ "npm-package-arg": "^3.0.0 || ^4.0.0 || ^5.0.0",
+ "once": "^1.3.3",
+ "request": "^2.74.0",
+ "retry": "^0.10.0",
+ "semver": "2 >=2.2.1 || 3.x || 4 || 5",
+ "slide": "^1.1.3",
+ "ssri": "^4.1.2"
+ },
+ "optionalDependencies": {
+ "npmlog": "2 || ^3.1.0 || ^4.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npm-registry-client/node_modules/concat-stream": {
+ "version": "1.6.0",
+ "dev": true,
+ "engines": [
+ "node >= 0.8"
+ ],
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "readable-stream": "^2.2.2",
+ "typedarray": "^0.0.6"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npm-registry-client/node_modules/concat-stream/node_modules/typedarray": {
+ "version": "0.0.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npm-user-validate": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog": {
+ "version": "4.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "are-we-there-yet": "~1.1.2",
+ "console-control-strings": "~1.1.0",
+ "gauge": "~2.7.3",
+ "set-blocking": "~2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/are-we-there-yet": {
+ "version": "1.1.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "delegates": "^1.0.0",
+ "readable-stream": "^2.0.6"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/are-we-there-yet/node_modules/delegates": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/console-control-strings": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge": {
+ "version": "2.7.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "aproba": "^1.0.3",
+ "console-control-strings": "^1.0.0",
+ "has-unicode": "^2.0.0",
+ "object-assign": "^4.1.0",
+ "signal-exit": "^3.0.0",
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1",
+ "wide-align": "^1.1.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge/node_modules/object-assign": {
+ "version": "4.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge/node_modules/signal-exit": {
+ "version": "3.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge/node_modules/string-width": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge/node_modules/string-width/node_modules/code-point-at": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge/node_modules/string-width/node_modules/is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge/node_modules/string-width/node_modules/is-fullwidth-code-point/node_modules/number-is-nan": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge/node_modules/strip-ansi/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/gauge/node_modules/wide-align": {
+ "version": "1.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^1.0.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/npmlog/node_modules/set-blocking": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/once": {
+ "version": "1.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/opener": {
+ "version": "1.4.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "(WTFPL OR MIT)",
+ "bin": {
+ "opener": "opener.js"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/osenv": {
+ "version": "0.1.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/osenv/node_modules/os-homedir": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/osenv/node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote": {
+ "version": "2.7.38",
+ "dev": true,
+ "inBundle": true,
+ "license": "CC0-1.0",
+ "dependencies": {
+ "bluebird": "^3.5.0",
+ "cacache": "^9.2.9",
+ "glob": "^7.1.2",
+ "lru-cache": "^4.1.1",
+ "make-fetch-happen": "^2.4.13",
+ "minimatch": "^3.0.4",
+ "mississippi": "^1.2.0",
+ "normalize-package-data": "^2.4.0",
+ "npm-package-arg": "^5.1.2",
+ "npm-pick-manifest": "^1.0.4",
+ "osenv": "^0.1.4",
+ "promise-inflight": "^1.0.1",
+ "promise-retry": "^1.1.1",
+ "protoduck": "^4.0.0",
+ "safe-buffer": "^5.1.1",
+ "semver": "^5.3.0",
+ "ssri": "^4.1.6",
+ "tar-fs": "^1.15.3",
+ "tar-stream": "^1.5.4",
+ "unique-filename": "^1.1.0",
+ "which": "^1.2.12"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen": {
+ "version": "2.4.13",
+ "dev": true,
+ "inBundle": true,
+ "license": "CC0-1.0",
+ "dependencies": {
+ "agentkeepalive": "^3.3.0",
+ "cacache": "^9.2.9",
+ "http-cache-semantics": "^3.7.3",
+ "http-proxy-agent": "^2.0.0",
+ "https-proxy-agent": "^2.0.0",
+ "lru-cache": "^4.1.1",
+ "mississippi": "^1.2.0",
+ "node-fetch-npm": "^2.0.1",
+ "promise-retry": "^1.1.1",
+ "socks-proxy-agent": "^3.0.0",
+ "ssri": "^4.1.6"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/agentkeepalive": {
+ "version": "3.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "humanize-ms": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/agentkeepalive/node_modules/humanize-ms": {
+ "version": "1.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "^2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/agentkeepalive/node_modules/humanize-ms/node_modules/ms": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/http-cache-semantics": {
+ "version": "3.7.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/http-proxy-agent": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "4",
+ "debug": "2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/http-proxy-agent/node_modules/agent-base": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "es6-promisify": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/http-proxy-agent/node_modules/agent-base/node_modules/es6-promisify": {
+ "version": "5.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/http-proxy-agent/node_modules/agent-base/node_modules/es6-promisify/node_modules/es6-promise": {
+ "version": "4.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/http-proxy-agent/node_modules/debug": {
+ "version": "2.6.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/http-proxy-agent/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/https-proxy-agent": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^4.1.0",
+ "debug": "^2.4.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/https-proxy-agent/node_modules/agent-base": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "es6-promisify": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/https-proxy-agent/node_modules/agent-base/node_modules/es6-promisify": {
+ "version": "5.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/https-proxy-agent/node_modules/agent-base/node_modules/es6-promisify/node_modules/es6-promise": {
+ "version": "4.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/https-proxy-agent/node_modules/debug": {
+ "version": "2.6.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/https-proxy-agent/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/node-fetch-npm": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "encoding": "^0.1.11",
+ "json-parse-helpfulerror": "^1.0.3",
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/node-fetch-npm/node_modules/encoding": {
+ "version": "0.1.12",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "iconv-lite": "~0.4.13"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/node-fetch-npm/node_modules/encoding/node_modules/iconv-lite": {
+ "version": "0.4.18",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/node-fetch-npm/node_modules/json-parse-helpfulerror": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "jju": "^1.1.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/node-fetch-npm/node_modules/json-parse-helpfulerror/node_modules/jju": {
+ "version": "1.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "WTFPL"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/socks-proxy-agent": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "agent-base": "^4.0.1",
+ "socks": "^1.1.10"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/socks-proxy-agent/node_modules/agent-base": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "es6-promisify": "^5.0.0"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/socks-proxy-agent/node_modules/agent-base/node_modules/es6-promisify": {
+ "version": "5.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "es6-promise": "^4.0.3"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/socks-proxy-agent/node_modules/agent-base/node_modules/es6-promisify/node_modules/es6-promise": {
+ "version": "4.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/socks-proxy-agent/node_modules/socks": {
+ "version": "1.1.10",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ip": "^1.1.4",
+ "smart-buffer": "^1.0.13"
+ },
+ "engines": {
+ "node": ">= 0.10.0",
+ "npm": ">= 1.3.5"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/socks-proxy-agent/node_modules/socks/node_modules/ip": {
+ "version": "1.1.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/make-fetch-happen/node_modules/socks-proxy-agent/node_modules/socks/node_modules/smart-buffer": {
+ "version": "1.1.15",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10.15",
+ "npm": ">= 1.3.5"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/minimatch": {
+ "version": "3.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/minimatch/node_modules/brace-expansion": {
+ "version": "1.1.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/minimatch/node_modules/brace-expansion/node_modules/balanced-match": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/minimatch/node_modules/brace-expansion/node_modules/concat-map": {
+ "version": "0.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/npm-pick-manifest": {
+ "version": "1.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "CC0-1.0",
+ "dependencies": {
+ "npm-package-arg": "^5.1.2",
+ "semver": "^5.3.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/promise-retry": {
+ "version": "1.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "err-code": "^1.0.0",
+ "retry": "^0.10.0"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/promise-retry/node_modules/err-code": {
+ "version": "1.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/protoduck": {
+ "version": "4.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "CC0-1.0",
+ "dependencies": {
+ "genfun": "^4.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/protoduck/node_modules/genfun": {
+ "version": "4.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "CC0-1.0"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/tar-fs": {
+ "version": "1.15.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "chownr": "^1.0.1",
+ "mkdirp": "^0.5.1",
+ "pump": "^1.0.0",
+ "tar-stream": "^1.1.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/tar-fs/node_modules/pump": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/tar-fs/node_modules/pump/node_modules/end-of-stream": {
+ "version": "1.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/tar-stream": {
+ "version": "1.5.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "bl": "^1.0.0",
+ "end-of-stream": "^1.0.0",
+ "readable-stream": "^2.0.0",
+ "xtend": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/tar-stream/node_modules/bl": {
+ "version": "1.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "^2.0.5"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/tar-stream/node_modules/end-of-stream": {
+ "version": "1.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "once": "^1.4.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/pacote/node_modules/tar-stream/node_modules/xtend": {
+ "version": "4.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/path-is-inside": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "(WTFPL OR MIT)"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/promise-inflight": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/read": {
+ "version": "1.0.7",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "mute-stream": "~0.0.4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/read-cmd-shim": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "graceful-fs": "^4.1.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/read-installed": {
+ "version": "4.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "debuglog": "^1.0.1",
+ "read-package-json": "^2.0.0",
+ "readdir-scoped-modules": "^1.0.0",
+ "semver": "2 || 3 || 4 || 5",
+ "slide": "~1.1.3",
+ "util-extend": "^1.0.1"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/read-installed/node_modules/util-extend": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/read-package-json": {
+ "version": "2.0.9",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.1",
+ "json-parse-helpfulerror": "^1.0.2",
+ "normalize-package-data": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/read-package-json/node_modules/json-parse-helpfulerror": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "jju": "^1.1.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/read-package-json/node_modules/json-parse-helpfulerror/node_modules/jju": {
+ "version": "1.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "WTFPL"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/read-package-tree": {
+ "version": "5.1.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "debuglog": "^1.0.1",
+ "dezalgo": "^1.0.0",
+ "once": "^1.3.0",
+ "read-package-json": "^2.0.0",
+ "readdir-scoped-modules": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/read/node_modules/mute-stream": {
+ "version": "0.0.7",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/readable-stream": {
+ "version": "2.3.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~1.0.6",
+ "safe-buffer": "~5.1.0",
+ "string_decoder": "~1.0.0",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/readable-stream/node_modules/core-util-is": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/readable-stream/node_modules/isarray": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/readable-stream/node_modules/process-nextick-args": {
+ "version": "1.0.7",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/readable-stream/node_modules/string_decoder": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/readable-stream/node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/readdir-scoped-modules": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "debuglog": "^1.0.1",
+ "dezalgo": "^1.0.0",
+ "graceful-fs": "^4.1.2",
+ "once": "^1.3.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request": {
+ "version": "2.81.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "aws-sign2": "~0.6.0",
+ "aws4": "^1.2.1",
+ "caseless": "~0.12.0",
+ "combined-stream": "~1.0.5",
+ "extend": "~3.0.0",
+ "forever-agent": "~0.6.1",
+ "form-data": "~2.1.1",
+ "har-validator": "~4.2.1",
+ "hawk": "~3.1.3",
+ "http-signature": "~1.1.0",
+ "is-typedarray": "~1.0.0",
+ "isstream": "~0.1.2",
+ "json-stringify-safe": "~5.0.1",
+ "mime-types": "~2.1.7",
+ "oauth-sign": "~0.8.1",
+ "performance-now": "^0.2.0",
+ "qs": "~6.4.0",
+ "safe-buffer": "^5.0.1",
+ "stringstream": "~0.0.4",
+ "tough-cookie": "~2.3.0",
+ "tunnel-agent": "^0.6.0",
+ "uuid": "^3.0.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/aws-sign2": {
+ "version": "0.6.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/aws4": {
+ "version": "1.6.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/caseless": {
+ "version": "0.12.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/combined-stream": {
+ "version": "1.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/combined-stream/node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/extend": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/forever-agent": {
+ "version": "0.6.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/form-data": {
+ "version": "2.1.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.5",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 0.12"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/form-data/node_modules/asynckit": {
+ "version": "0.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/har-validator": {
+ "version": "4.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "ajv": "^4.9.1",
+ "har-schema": "^1.0.5"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/har-validator/node_modules/ajv": {
+ "version": "4.11.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "co": "^4.6.0",
+ "json-stable-stringify": "^1.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/har-validator/node_modules/ajv/node_modules/co": {
+ "version": "4.6.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">= 1.0.0",
+ "node": ">= 0.12.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/har-validator/node_modules/ajv/node_modules/json-stable-stringify": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "jsonify": "~0.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/har-validator/node_modules/ajv/node_modules/json-stable-stringify/node_modules/jsonify": {
+ "version": "0.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "Public Domain",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/har-validator/node_modules/har-schema": {
+ "version": "1.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/hawk": {
+ "version": "3.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "boom": "2.x.x",
+ "cryptiles": "2.x.x",
+ "hoek": "2.x.x",
+ "sntp": "1.x.x"
+ },
+ "engines": {
+ "node": ">=0.10.32"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/hawk/node_modules/boom": {
+ "version": "2.10.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "hoek": "2.x.x"
+ },
+ "engines": {
+ "node": ">=0.10.40"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/hawk/node_modules/cryptiles": {
+ "version": "2.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "boom": "2.x.x"
+ },
+ "engines": {
+ "node": ">=0.10.40"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/hawk/node_modules/hoek": {
+ "version": "2.16.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.10.40"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/hawk/node_modules/sntp": {
+ "version": "1.0.9",
+ "dev": true,
+ "inBundle": true,
+ "dependencies": {
+ "hoek": "2.x.x"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature": {
+ "version": "1.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "assert-plus": "^0.2.0",
+ "jsprim": "^1.2.2",
+ "sshpk": "^1.7.0"
+ },
+ "engines": {
+ "node": ">=0.8",
+ "npm": ">=1.3.7"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/assert-plus": {
+ "version": "0.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/jsprim": {
+ "version": "1.4.0",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "assert-plus": "1.0.0",
+ "extsprintf": "1.0.2",
+ "json-schema": "0.2.3",
+ "verror": "1.3.6"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/assert-plus": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/extsprintf": {
+ "version": "1.0.2",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "inBundle": true
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/json-schema": {
+ "version": "0.2.3",
+ "dev": true,
+ "inBundle": true
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/jsprim/node_modules/verror": {
+ "version": "1.3.6",
+ "dev": true,
+ "engines": [
+ "node >=0.6.0"
+ ],
+ "inBundle": true,
+ "dependencies": {
+ "extsprintf": "1.0.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk": {
+ "version": "1.13.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "asn1": "~0.2.3",
+ "assert-plus": "^1.0.0",
+ "dashdash": "^1.12.0",
+ "getpass": "^0.1.1"
+ },
+ "bin": {
+ "sshpk-conv": "bin/sshpk-conv",
+ "sshpk-sign": "bin/sshpk-sign",
+ "sshpk-verify": "bin/sshpk-verify"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "optionalDependencies": {
+ "bcrypt-pbkdf": "^1.0.0",
+ "ecc-jsbn": "~0.1.1",
+ "jsbn": "~0.1.0",
+ "tweetnacl": "~0.14.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/node_modules/asn1": {
+ "version": "0.2.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/node_modules/assert-plus": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/node_modules/bcrypt-pbkdf": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "optional": true,
+ "dependencies": {
+ "tweetnacl": "^0.14.3"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/node_modules/dashdash": {
+ "version": "1.14.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/node_modules/ecc-jsbn": {
+ "version": "0.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true,
+ "dependencies": {
+ "jsbn": "~0.1.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/node_modules/getpass": {
+ "version": "0.1.7",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "assert-plus": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/node_modules/jsbn": {
+ "version": "0.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "optional": true
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/http-signature/node_modules/sshpk/node_modules/tweetnacl": {
+ "version": "0.14.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "Unlicense",
+ "optional": true
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/is-typedarray": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/isstream": {
+ "version": "0.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/json-stringify-safe": {
+ "version": "5.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/mime-types": {
+ "version": "2.1.15",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "mime-db": "~1.27.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/mime-types/node_modules/mime-db": {
+ "version": "1.27.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/oauth-sign": {
+ "version": "0.8.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/performance-now": {
+ "version": "0.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/qs": {
+ "version": "6.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/stringstream": {
+ "version": "0.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/tough-cookie": {
+ "version": "2.3.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "punycode": "^1.4.1"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/tough-cookie/node_modules/punycode": {
+ "version": "1.4.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/request/node_modules/tunnel-agent": {
+ "version": "0.6.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "safe-buffer": "^5.0.1"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/retry": {
+ "version": "0.10.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/rimraf": {
+ "version": "2.6.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.0.5"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/safe-buffer": {
+ "version": "5.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/semver": {
+ "version": "5.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sha": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "(BSD-2-Clause OR MIT)",
+ "dependencies": {
+ "graceful-fs": "^4.1.2",
+ "readable-stream": "^2.0.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/slide": {
+ "version": "1.1.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sorted-object": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "(WTFPL OR MIT)"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sorted-union-stream": {
+ "version": "2.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "from2": "^1.3.0",
+ "stream-iterate": "^1.1.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sorted-union-stream/node_modules/from2": {
+ "version": "1.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "inherits": "~2.0.1",
+ "readable-stream": "~1.1.10"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sorted-union-stream/node_modules/from2/node_modules/readable-stream": {
+ "version": "1.1.14",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.1",
+ "isarray": "0.0.1",
+ "string_decoder": "~0.10.x"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sorted-union-stream/node_modules/from2/node_modules/readable-stream/node_modules/core-util-is": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sorted-union-stream/node_modules/from2/node_modules/readable-stream/node_modules/isarray": {
+ "version": "0.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sorted-union-stream/node_modules/from2/node_modules/readable-stream/node_modules/string_decoder": {
+ "version": "0.10.31",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sorted-union-stream/node_modules/stream-iterate": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "^2.1.5",
+ "stream-shift": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/sorted-union-stream/node_modules/stream-iterate/node_modules/stream-shift": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/ssri": {
+ "version": "4.1.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "CC0-1.0",
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/strip-ansi/node_modules/ansi-regex": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/tar": {
+ "version": "2.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "block-stream": "*",
+ "fstream": "^1.0.2",
+ "inherits": "2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/tar/node_modules/block-stream": {
+ "version": "0.0.9",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "inherits": "~2.0.0"
+ },
+ "engines": {
+ "node": "0.4 || >=0.5.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/text-table": {
+ "version": "0.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/uid-number": {
+ "version": "0.0.6",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/umask": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/unique-filename": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "unique-slug": "^2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/unique-filename/node_modules/unique-slug": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "imurmurhash": "^0.1.4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/unpipe": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier": {
+ "version": "2.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boxen": "^1.0.0",
+ "chalk": "^1.0.0",
+ "configstore": "^3.0.0",
+ "import-lazy": "^2.1.0",
+ "is-npm": "^1.0.0",
+ "latest-version": "^3.0.0",
+ "semver-diff": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-align": "^2.0.0",
+ "camelcase": "^4.0.0",
+ "chalk": "^1.1.1",
+ "cli-boxes": "^1.0.0",
+ "string-width": "^2.0.0",
+ "term-size": "^0.1.0",
+ "widest-line": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/ansi-align": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "string-width": "^2.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/camelcase": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/cli-boxes": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/string-width": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/string-width/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/string-width/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/term-size": {
+ "version": "0.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/term-size/node_modules/execa": {
+ "version": "0.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn-async": "^2.1.1",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "path-key": "^1.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/term-size/node_modules/execa/node_modules/cross-spawn-async": {
+ "version": "2.2.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "lru-cache": "^4.0.0",
+ "which": "^1.2.8"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/term-size/node_modules/execa/node_modules/is-stream": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/term-size/node_modules/execa/node_modules/npm-run-path": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "path-key": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/term-size/node_modules/execa/node_modules/object-assign": {
+ "version": "4.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/term-size/node_modules/execa/node_modules/path-key": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/term-size/node_modules/execa/node_modules/strip-eof": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/widest-line": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/widest-line/node_modules/string-width": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/widest-line/node_modules/string-width/node_modules/code-point-at": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/widest-line/node_modules/string-width/node_modules/is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/widest-line/node_modules/string-width/node_modules/is-fullwidth-code-point/node_modules/number-is-nan": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/widest-line/node_modules/string-width/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/boxen/node_modules/widest-line/node_modules/string-width/node_modules/strip-ansi/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/chalk": {
+ "version": "1.1.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^2.2.1",
+ "escape-string-regexp": "^1.0.2",
+ "has-ansi": "^2.0.0",
+ "strip-ansi": "^3.0.0",
+ "supports-color": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/chalk/node_modules/ansi-styles": {
+ "version": "2.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/chalk/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/chalk/node_modules/has-ansi": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/chalk/node_modules/has-ansi/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/chalk/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/chalk/node_modules/strip-ansi/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/chalk/node_modules/supports-color": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/configstore": {
+ "version": "3.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "dot-prop": "^4.1.0",
+ "graceful-fs": "^4.1.2",
+ "make-dir": "^1.0.0",
+ "unique-string": "^1.0.0",
+ "write-file-atomic": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/configstore/node_modules/dot-prop": {
+ "version": "4.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-obj": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/configstore/node_modules/dot-prop/node_modules/is-obj": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/configstore/node_modules/make-dir": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^2.3.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/configstore/node_modules/make-dir/node_modules/pify": {
+ "version": "2.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/configstore/node_modules/unique-string": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "crypto-random-string": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/configstore/node_modules/unique-string/node_modules/crypto-random-string": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/import-lazy": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/is-npm": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version": {
+ "version": "3.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "package-json": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json": {
+ "version": "4.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "got": "^6.7.1",
+ "registry-auth-token": "^3.0.1",
+ "registry-url": "^3.0.3",
+ "semver": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got": {
+ "version": "6.7.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "create-error-class": "^3.0.0",
+ "duplexer3": "^0.1.4",
+ "get-stream": "^3.0.0",
+ "is-redirect": "^1.0.0",
+ "is-retry-allowed": "^1.0.0",
+ "is-stream": "^1.0.0",
+ "lowercase-keys": "^1.0.0",
+ "safe-buffer": "^5.0.1",
+ "timed-out": "^4.0.0",
+ "unzip-response": "^2.0.1",
+ "url-parse-lax": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/create-error-class": {
+ "version": "3.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "capture-stack-trace": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/create-error-class/node_modules/capture-stack-trace": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/duplexer3": {
+ "version": "0.1.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/get-stream": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/is-redirect": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/is-retry-allowed": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/is-stream": {
+ "version": "1.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/lowercase-keys": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/timed-out": {
+ "version": "4.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/unzip-response": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/url-parse-lax": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "prepend-http": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/got/node_modules/url-parse-lax/node_modules/prepend-http": {
+ "version": "1.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-auth-token": {
+ "version": "3.3.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "rc": "^1.1.6",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-auth-token/node_modules/rc": {
+ "version": "1.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "~0.4.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "index.js"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-auth-token/node_modules/rc/node_modules/deep-extend": {
+ "version": "0.4.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-auth-token/node_modules/rc/node_modules/minimist": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-auth-token/node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-url": {
+ "version": "3.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "rc": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-url/node_modules/rc": {
+ "version": "1.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "~0.4.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "index.js"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-url/node_modules/rc/node_modules/deep-extend": {
+ "version": "0.4.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-url/node_modules/rc/node_modules/minimist": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/latest-version/node_modules/package-json/node_modules/registry-url/node_modules/rc/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/semver-diff": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^5.0.3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/update-notifier/node_modules/xdg-basedir": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/uuid": {
+ "version": "3.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "bin": {
+ "uuid": "bin/uuid"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/validate-npm-package-license": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-correct": "~1.0.0",
+ "spdx-expression-parse": "~1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-correct": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "spdx-license-ids": "^1.0.2"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-correct/node_modules/spdx-license-ids": {
+ "version": "1.2.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "Unlicense"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/validate-npm-package-license/node_modules/spdx-expression-parse": {
+ "version": "1.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "(MIT AND CC-BY-3.0)"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/validate-npm-package-name": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "builtins": "^1.0.3"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/validate-npm-package-name/node_modules/builtins": {
+ "version": "1.0.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/which": {
+ "version": "1.2.14",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/which/node_modules/isexe": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/worker-farm": {
+ "version": "1.3.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "errno": ">=0.1.1 <0.2.0-0",
+ "xtend": ">=4.0.0 <4.1.0-0"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/worker-farm/node_modules/errno": {
+ "version": "0.1.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "prr": "~0.0.0"
+ },
+ "bin": {
+ "errno": "cli.js"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/worker-farm/node_modules/errno/node_modules/prr": {
+ "version": "0.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/worker-farm/node_modules/xtend": {
+ "version": "4.0.1",
+ "dev": true,
+ "inBundle": true,
+ "engines": {
+ "node": ">=0.4"
+ }
+ },
+ "node_modules/npx/node_modules/npm/node_modules/wrappy": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/npm/node_modules/write-file-atomic": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "slide": "^1.1.5"
+ }
+ },
+ "node_modules/npx/node_modules/number-is-nan": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/once": {
+ "version": "1.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/npx/node_modules/os-homedir": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/os-locale": {
+ "version": "3.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^1.0.0",
+ "lcid": "^2.0.0",
+ "mem": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npx/node_modules/os-locale/node_modules/cross-spawn": {
+ "version": "6.0.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "nice-try": "^1.0.4",
+ "path-key": "^2.0.1",
+ "semver": "^5.5.0",
+ "shebang-command": "^1.2.0",
+ "which": "^1.2.9"
+ },
+ "engines": {
+ "node": ">=4.8"
+ }
+ },
+ "node_modules/npx/node_modules/os-locale/node_modules/execa": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "cross-spawn": "^6.0.0",
+ "get-stream": "^4.0.0",
+ "is-stream": "^1.1.0",
+ "npm-run-path": "^2.0.0",
+ "p-finally": "^1.0.0",
+ "signal-exit": "^3.0.0",
+ "strip-eof": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npx/node_modules/os-locale/node_modules/get-stream": {
+ "version": "4.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "pump": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npx/node_modules/os-tmpdir": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/osenv": {
+ "version": "0.1.5",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "os-homedir": "^1.0.0",
+ "os-tmpdir": "^1.0.0"
+ }
+ },
+ "node_modules/npx/node_modules/p-defer": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/p-finally": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/p-is-promise": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/npx/node_modules/p-limit": {
+ "version": "1.3.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-try": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/p-locate": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/p-try": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/package-json": {
+ "version": "4.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "got": "^6.7.1",
+ "registry-auth-token": "^3.0.1",
+ "registry-url": "^3.0.3",
+ "semver": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/path-exists": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/path-is-inside": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "(WTFPL OR MIT)"
+ },
+ "node_modules/npx/node_modules/path-key": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/pify": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/prepend-http": {
+ "version": "1.0.4",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/pseudomap": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/pump": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
+ }
+ },
+ "node_modules/npx/node_modules/rc": {
+ "version": "1.2.8",
+ "dev": true,
+ "inBundle": true,
+ "license": "(BSD-2-Clause OR MIT OR Apache-2.0)",
+ "dependencies": {
+ "deep-extend": "^0.6.0",
+ "ini": "~1.3.0",
+ "minimist": "^1.2.0",
+ "strip-json-comments": "~2.0.1"
+ },
+ "bin": {
+ "rc": "cli.js"
+ }
+ },
+ "node_modules/npx/node_modules/registry-auth-token": {
+ "version": "3.4.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "rc": "^1.1.6",
+ "safe-buffer": "^5.0.1"
+ }
+ },
+ "node_modules/npx/node_modules/registry-url": {
+ "version": "3.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "rc": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/require-directory": {
+ "version": "2.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/require-main-filename": {
+ "version": "1.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/rimraf": {
+ "version": "2.7.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "glob": "^7.1.3"
+ },
+ "bin": {
+ "rimraf": "bin.js"
+ }
+ },
+ "node_modules/npx/node_modules/safe-buffer": {
+ "version": "5.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT"
+ },
+ "node_modules/npx/node_modules/semver": {
+ "version": "5.7.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "bin": {
+ "semver": "bin/semver"
+ }
+ },
+ "node_modules/npx/node_modules/semver-diff": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "semver": "^5.0.3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/set-blocking": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/shebang-command": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "shebang-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/shebang-regex": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/signal-exit": {
+ "version": "3.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/string-width": {
+ "version": "2.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/strip-eof": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/strip-json-comments": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/supports-color": {
+ "version": "5.5.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/term-size": {
+ "version": "1.2.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "execa": "^0.7.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/timed-out": {
+ "version": "4.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/unique-string": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "crypto-random-string": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/unzip-response": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/update-notifier": {
+ "version": "2.5.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "BSD-2-Clause",
+ "dependencies": {
+ "boxen": "^1.2.1",
+ "chalk": "^2.0.1",
+ "configstore": "^3.0.0",
+ "import-lazy": "^2.1.0",
+ "is-ci": "^1.0.10",
+ "is-installed-globally": "^0.1.0",
+ "is-npm": "^1.0.0",
+ "latest-version": "^3.0.0",
+ "semver-diff": "^2.0.0",
+ "xdg-basedir": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/url-parse-lax": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "prepend-http": "^1.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/validate-npm-package-name": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "builtins": "^1.0.3"
+ }
+ },
+ "node_modules/npx/node_modules/which": {
+ "version": "1.3.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "which": "bin/which"
+ }
+ },
+ "node_modules/npx/node_modules/which-module": {
+ "version": "2.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/widest-line": {
+ "version": "2.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/wrap-ansi": {
+ "version": "2.1.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^1.0.1",
+ "strip-ansi": "^3.0.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/wrap-ansi/node_modules/ansi-regex": {
+ "version": "2.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/wrap-ansi/node_modules/is-fullwidth-code-point": {
+ "version": "1.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "number-is-nan": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/wrap-ansi/node_modules/string-width": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "code-point-at": "^1.0.0",
+ "is-fullwidth-code-point": "^1.0.0",
+ "strip-ansi": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/wrap-ansi/node_modules/strip-ansi": {
+ "version": "3.0.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/npx/node_modules/wrappy": {
+ "version": "1.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/write-file-atomic": {
+ "version": "2.4.3",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "graceful-fs": "^4.1.11",
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.2"
+ }
+ },
+ "node_modules/npx/node_modules/xdg-basedir": {
+ "version": "3.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/npx/node_modules/y18n": {
+ "version": "4.0.0",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/yallist": {
+ "version": "2.1.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/npx/node_modules/yargs": {
+ "version": "11.1.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "MIT",
+ "dependencies": {
+ "cliui": "^4.0.0",
+ "decamelize": "^1.1.1",
+ "find-up": "^2.1.0",
+ "get-caller-file": "^1.0.1",
+ "os-locale": "^3.1.0",
+ "require-directory": "^2.1.1",
+ "require-main-filename": "^1.0.1",
+ "set-blocking": "^2.0.0",
+ "string-width": "^2.0.0",
+ "which-module": "^2.0.0",
+ "y18n": "^3.2.1",
+ "yargs-parser": "^9.0.2"
+ }
+ },
+ "node_modules/npx/node_modules/yargs-parser": {
+ "version": "9.0.2",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC",
+ "dependencies": {
+ "camelcase": "^4.1.0"
+ }
+ },
+ "node_modules/npx/node_modules/yargs/node_modules/y18n": {
+ "version": "3.2.1",
+ "dev": true,
+ "inBundle": true,
+ "license": "ISC"
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
+ "dependencies": {
+ "boolbase": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/nth-check?sponsor=1"
+ }
+ },
+ "node_modules/oas-kit-common": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/oas-kit-common/-/oas-kit-common-1.0.8.tgz",
+ "integrity": "sha512-pJTS2+T0oGIwgjGpw7sIRU8RQMcUoKCDWFLdBqKB2BNmGpbBMH2sdqAaOXUg8OzonZHU0L7vfJu1mJFEiYDWOQ==",
+ "dev": true,
+ "dependencies": {
+ "fast-safe-stringify": "^2.0.7"
+ }
+ },
+ "node_modules/oas-linter": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/oas-linter/-/oas-linter-3.2.2.tgz",
+ "integrity": "sha512-KEGjPDVoU5K6swgo9hJVA/qYGlwfbFx+Kg2QB/kd7rzV5N8N5Mg6PlsoCMohVnQmo+pzJap/F610qTodKzecGQ==",
+ "dev": true,
+ "dependencies": {
+ "@exodus/schemasafe": "^1.0.0-rc.2",
+ "should": "^13.2.1",
+ "yaml": "^1.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/Mermade/oas-kit?sponsor=1"
+ }
+ },
+ "node_modules/oas-resolver": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/oas-resolver/-/oas-resolver-2.5.6.tgz",
+ "integrity": "sha512-Yx5PWQNZomfEhPPOphFbZKi9W93CocQj18NlD2Pa4GWZzdZpSJvYwoiuurRI7m3SpcChrnO08hkuQDL3FGsVFQ==",
+ "dev": true,
+ "dependencies": {
+ "node-fetch-h2": "^2.3.0",
+ "oas-kit-common": "^1.0.8",
+ "reftools": "^1.1.9",
+ "yaml": "^1.10.0",
+ "yargs": "^17.0.1"
+ },
+ "bin": {
+ "resolve": "resolve.js"
+ },
+ "funding": {
+ "url": "https://github.com/Mermade/oas-kit?sponsor=1"
+ }
+ },
+ "node_modules/oas-schema-walker": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/oas-schema-walker/-/oas-schema-walker-1.1.5.tgz",
+ "integrity": "sha512-2yucenq1a9YPmeNExoUa9Qwrt9RFkjqaMAA1X+U7sbb0AqBeTIdMHky9SQQ6iN94bO5NW0W4TRYXerG+BdAvAQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/Mermade/oas-kit?sponsor=1"
+ }
+ },
+ "node_modules/oas-validator": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/oas-validator/-/oas-validator-5.0.8.tgz",
+ "integrity": "sha512-cu20/HE5N5HKqVygs3dt94eYJfBi0TsZvPVXDhbXQHiEityDN+RROTleefoKRKKJ9dFAF2JBkDHgvWj0sjKGmw==",
+ "dev": true,
+ "dependencies": {
+ "call-me-maybe": "^1.0.1",
+ "oas-kit-common": "^1.0.8",
+ "oas-linter": "^3.2.2",
+ "oas-resolver": "^2.5.6",
+ "oas-schema-walker": "^1.1.5",
+ "reftools": "^1.1.9",
+ "should": "^13.2.1",
+ "yaml": "^1.10.0"
+ },
+ "funding": {
+ "url": "https://github.com/Mermade/oas-kit?sponsor=1"
+ }
+ },
+ "node_modules/oazapfts": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/oazapfts/-/oazapfts-6.1.0.tgz",
+ "integrity": "sha512-+E0db72jn0AMJ36ZzEXF3qCZ+T4pnOem/tmiJVql1Kx4qkWBE4YGeiUicp3gkzLJ/OrmpvSyAufI8eZ7sODCYg==",
+ "dev": true,
+ "dependencies": {
+ "@apidevtools/swagger-parser": "^10.1.0",
+ "lodash": "^4.17.21",
+ "minimist": "^1.2.8",
+ "swagger2openapi": "^7.0.8",
+ "tapable": "^2.2.1",
+ "typescript": "^5.4.5"
+ },
+ "bin": {
+ "oazapfts": "cli.js"
+ },
+ "peerDependencies": {
+ "@oazapfts/runtime": "*"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-is": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.6.tgz",
+ "integrity": "sha512-F8cZ+KfGlSGi09lJT7/Nd6KJZ9ygtvYC0/UYYLI9nmQKLMnydpB9yvbv9K1uSkEu7FU9vYPmVwLg328tX+ot3Q==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.entries": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/object.entries/-/object.entries-1.1.9.tgz",
+ "integrity": "sha512-8u/hfXFRBD1O0hPUjioLhoWFHRmt6tKA4/vZPyckBr18l1KE9uHrFaFaUi8MDRTpi4uak2goyPTSNJLXX2k2Hw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.1.tgz",
+ "integrity": "sha512-gXah6aZrcUxjWg2zR2MwouP2eHlCBzdV4pygudehaKXSGW4v2AsRQUK+lwwXhii6KFZcunEnmSUoYp5CXibxtA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/obuf": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
+ "integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
+ "dev": true
+ },
+ "node_modules/on-finished": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
+ "dev": true,
+ "dependencies": {
+ "ee-first": "1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/on-headers": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
+ "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/once": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "dev": true,
+ "dependencies": {
+ "wrappy": "1"
+ }
+ },
+ "node_modules/onetime": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
+ "integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
+ "dev": true,
+ "dependencies": {
+ "mimic-fn": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/open": {
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
+ "dev": true,
+ "dependencies": {
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/openai": {
+ "version": "4.68.4",
+ "resolved": "https://registry.npmjs.org/openai/-/openai-4.68.4.tgz",
+ "integrity": "sha512-LRinV8iU9VQplkr25oZlyrsYGPGasIwYN8KFMAAFTHHLHjHhejtJ5BALuLFrkGzY4wfbKhOhuT+7lcHZ+F3iEA==",
+ "dependencies": {
+ "@types/node": "^18.11.18",
+ "@types/node-fetch": "^2.6.4",
+ "abort-controller": "^3.0.0",
+ "agentkeepalive": "^4.2.1",
+ "form-data-encoder": "1.7.2",
+ "formdata-node": "^4.3.2",
+ "node-fetch": "^2.6.7"
+ },
+ "bin": {
+ "openai": "bin/cli"
+ },
+ "peerDependencies": {
+ "zod": "^3.23.8"
+ },
+ "peerDependenciesMeta": {
+ "zod": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/openai/node_modules/@types/node": {
+ "version": "18.19.61",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-18.19.61.tgz",
+ "integrity": "sha512-z8fH66NcVkDzBItOao+Nyh0fiy7CYdxIyxnNCcZ60aY0I+EA/y4TSi/S/W9i8DIQvwVo7a0pgzAxmDeNnqrpkw==",
+ "dependencies": {
+ "undici-types": "~5.26.4"
+ }
+ },
+ "node_modules/openai/node_modules/undici-types": {
+ "version": "5.26.5",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-5.26.5.tgz",
+ "integrity": "sha512-JlCMO+ehdEIKqlFxk6IfVoAUVmgz7cU7zD/h9XZ0qzeosSHmUJVOzSQvvYSYWXkFXC+IfLKSIffhv0sVZup6pA=="
+ },
+ "node_modules/openapi-types": {
+ "version": "12.1.3",
+ "resolved": "https://registry.npmjs.org/openapi-types/-/openapi-types-12.1.3.tgz",
+ "integrity": "sha512-N4YtSYJqghVu4iek2ZUvcN/0aqH1kRDuNqzcycDxhOUpg7GdvLa2F3DgS6yBNhInhv2r/6I0Flkn7CqL8+nIcw==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/own-keys": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/own-keys/-/own-keys-1.0.1.tgz",
+ "integrity": "sha512-qFOyK5PjiWZd+QQIh+1jhdb9LpxTF0qs7Pm8o5QHYZ0M3vKqSqzsZaEB6oWlxZ+q2sJBMI/Ktgd2N5ZwQoRHfg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "get-intrinsic": "^1.2.6",
+ "object-keys": "^1.1.1",
+ "safe-push-apply": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-retry": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-6.2.1.tgz",
+ "integrity": "sha512-hEt02O4hUct5wtwg4H4KcWgDdm+l1bOaEy/hWzd8xtXB9BqxTWBBhb+2ImAtH4Cv4rPjV76xN3Zumqk3k3AhhQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/retry": "0.12.2",
+ "is-network-error": "^1.0.0",
+ "retry": "^0.13.1"
+ },
+ "engines": {
+ "node": ">=16.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-try": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
+ "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/param-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
+ "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
+ "dev": true,
+ "dependencies": {
+ "dot-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dev": true,
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-author": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/parse-author/-/parse-author-2.0.0.tgz",
+ "integrity": "sha512-yx5DfvkN8JsHL2xk2Os9oTia467qnvRgey4ahSm2X8epehBLx/gWLcy5KI+Y36ful5DzGbCS6RazqZGgy1gHNw==",
+ "dev": true,
+ "dependencies": {
+ "author-regex": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/parse5": {
+ "version": "7.2.1",
+ "resolved": "https://registry.npmjs.org/parse5/-/parse5-7.2.1.tgz",
+ "integrity": "sha512-BuBYQYlv1ckiPdQi/ohiivi9Sagc9JG+Ozs0r7b/0iK3sKmrb0b9FdWdBbOdx6hBCM/F9Ir82ofnBhtZOjCRPQ==",
+ "dev": true,
+ "dependencies": {
+ "entities": "^4.5.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-htmlparser2-tree-adapter": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-7.1.0.tgz",
+ "integrity": "sha512-ruw5xyKs6lrpo9x9rCZqZZnIUntICjQAd0Wsmp396Ul9lN/h+ifgVV1x1gZHi8euej6wTfpqX8j+BFQxF0NS/g==",
+ "dev": true,
+ "dependencies": {
+ "domhandler": "^5.0.3",
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parse5-parser-stream": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/parse5-parser-stream/-/parse5-parser-stream-7.1.2.tgz",
+ "integrity": "sha512-JyeQc9iwFLn5TbvvqACIF/VXG6abODeB3Fwmv/TGdLk2LfbWkaySGY72at4+Ty7EkPZj854u4CrICqNk2qIbow==",
+ "dev": true,
+ "dependencies": {
+ "parse5": "^7.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/inikulin/parse5?sponsor=1"
+ }
+ },
+ "node_modules/parseurl": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
+ "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/pascal-case": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
+ "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
+ "dev": true,
+ "dependencies": {
+ "no-case": "^3.0.4",
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-is-absolute": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "dev": true
+ },
+ "node_modules/path-to-regexp": {
+ "version": "0.1.12",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.12.tgz",
+ "integrity": "sha512-RA1GjUVMnvYFxuqovrEqZoxxW5NUZqbwKtYz/Tt7nXerk0LbLblQmrsgdeOxV5SFHf0UDggjS/bSeOZwt1pmEQ==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+ "dev": true
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pidtree": {
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/pidtree/-/pidtree-0.6.0.tgz",
+ "integrity": "sha512-eG2dWTVw5bzqGRztnHExczNxt5VGsE6OwTeCG3fdUf9KBsZzO3R5OIIIzWR+iZA0NtZ+RDVdaoE2dK1cn6jH4g==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "pidtree": "bin/pidtree.js"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/pify": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
+ "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
+ "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pkg-up": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/pkg-up/-/pkg-up-3.1.0.tgz",
+ "integrity": "sha512-nDywThFk1i4BQK4twPQ6TA4RT8bDY96yeuCVBWL3ePARCiEKDRSrNGbFIgUJpLp+XeIR65v8ra7WuJOFUBtkMA==",
+ "dev": true,
+ "dependencies": {
+ "find-up": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/pkg-up/node_modules/find-up": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
+ "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-up/node_modules/locate-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
+ "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^3.0.0",
+ "path-exists": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-up/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "dev": true,
+ "dependencies": {
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-up/node_modules/p-locate": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
+ "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pkg-up/node_modules/path-exists": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
+ "integrity": "sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/pkijs": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/pkijs/-/pkijs-3.3.3.tgz",
+ "integrity": "sha512-+KD8hJtqQMYoTuL1bbGOqxb4z+nZkTAwVdNtWwe8Tc2xNbEmdJYIYoc6Qt0uF55e6YW6KuTHw1DjQ18gMhzepw==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@noble/hashes": "1.4.0",
+ "asn1js": "^3.0.6",
+ "bytestreamjs": "^2.0.1",
+ "pvtsutils": "^1.3.6",
+ "pvutils": "^1.1.3",
+ "tslib": "^2.8.1"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.1.0.tgz",
+ "integrity": "sha512-/+5VFTchJDoVj3bhoqi6UeymcD00DAwb1nJwamzPvHEszJ4FpF6SNNbUbOS8yI56qHzdV8eK0qEfOSiodkTdxg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.49",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.49.tgz",
+ "integrity": "sha512-OCVPnIObs4N29kxTjzLfUryOkvZEq+pf8jTF0lg8E7uETuWHA+v7j3c/xJmiqpX450191LlmZfUKkXxkTry7nA==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-attribute-case-insensitive": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-attribute-case-insensitive/-/postcss-attribute-case-insensitive-5.0.2.tgz",
+ "integrity": "sha512-XIidXV8fDr0kKt28vqki84fRK8VW8eTuIa4PChv2MqKuT6C9UjmSKzen6KaWhWEoYvwxFCa7n/tC1SZ3tyq4SQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-calc": {
+ "version": "8.2.4",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz",
+ "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.9",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.2"
+ }
+ },
+ "node_modules/postcss-clamp": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-clamp/-/postcss-clamp-4.1.0.tgz",
+ "integrity": "sha512-ry4b1Llo/9zz+PKC+030KUnPITTJAHeOwjfAyyB60eT0AorGLdzp52s31OsPRHRf8NchkgFoG2y6fCfn1IV1Ow==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": ">=7.6.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.6"
+ }
+ },
+ "node_modules/postcss-color-functional-notation": {
+ "version": "4.2.4",
+ "resolved": "https://registry.npmjs.org/postcss-color-functional-notation/-/postcss-color-functional-notation-4.2.4.tgz",
+ "integrity": "sha512-2yrTAUZUab9s6CpxkxC4rVgFEVaR6/2Pipvi6qcgvnYiVqZcbDHEoBDhrXzyb7Efh2CCfHQNtcqWcIruDTIUeg==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-color-hex-alpha": {
+ "version": "8.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-color-hex-alpha/-/postcss-color-hex-alpha-8.0.4.tgz",
+ "integrity": "sha512-nLo2DCRC9eE4w2JmuKgVA3fGL3d01kGq752pVALF68qpGLmx2Qrk91QTKkdUqqp45T1K1XV8IhQpcu1hoAQflQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-color-rebeccapurple": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-color-rebeccapurple/-/postcss-color-rebeccapurple-7.1.1.tgz",
+ "integrity": "sha512-pGxkuVEInwLHgkNxUc4sdg4g3py7zUeCQ9sMfwyHAT+Ezk8a4OaaVZ8lIY5+oNqA/BXXgLyXv0+5wHP68R79hg==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-colormin": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz",
+ "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==",
+ "dependencies": {
+ "browserslist": "^4.21.4",
+ "caniuse-api": "^3.0.0",
+ "colord": "^2.9.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-convert-values": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz",
+ "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==",
+ "dependencies": {
+ "browserslist": "^4.21.4",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-custom-media": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-custom-media/-/postcss-custom-media-8.0.2.tgz",
+ "integrity": "sha512-7yi25vDAoHAkbhAzX9dHx2yc6ntS4jQvejrNcC+csQJAXjj15e7VcWfMgLqBNAbOvqi5uIa9huOVwdHbf+sKqg==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.3"
+ }
+ },
+ "node_modules/postcss-custom-properties": {
+ "version": "12.1.11",
+ "resolved": "https://registry.npmjs.org/postcss-custom-properties/-/postcss-custom-properties-12.1.11.tgz",
+ "integrity": "sha512-0IDJYhgU8xDv1KY6+VgUwuQkVtmYzRwu+dMjnmdMafXYv86SWqfxkc7qdDvWS38vsjaEtv8e0vGOUQrAiMBLpQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-custom-selectors": {
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/postcss-custom-selectors/-/postcss-custom-selectors-6.0.3.tgz",
+ "integrity": "sha512-fgVkmyiWDwmD3JbpCmB45SvvlCD6z9CG6Ie6Iere22W5aHea6oWa7EM2bpnv2Fj3I94L3VbtvX9KqwSi5aFzSg==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.4"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.3"
+ }
+ },
+ "node_modules/postcss-dir-pseudo-class": {
+ "version": "6.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-dir-pseudo-class/-/postcss-dir-pseudo-class-6.0.5.tgz",
+ "integrity": "sha512-eqn4m70P031PF7ZQIvSgy9RSJ5uI2171O/OO/zcRNYpJbvaeKFUlar1aJ7rmgiQtbm0FSPsRewjpdS0Oew7MPA==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-discard-comments": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz",
+ "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==",
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-discard-duplicates": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz",
+ "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==",
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-discard-empty": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz",
+ "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==",
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-discard-overridden": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz",
+ "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==",
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-double-position-gradients": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-double-position-gradients/-/postcss-double-position-gradients-3.1.2.tgz",
+ "integrity": "sha512-GX+FuE/uBR6eskOK+4vkXgT6pDkexLokPaz/AbJna9s5Kzp/yl488pKPjhy0obB475ovfT1Wv8ho7U/cHNaRgQ==",
+ "dev": true,
+ "dependencies": {
+ "@csstools/postcss-progressive-custom-properties": "^1.1.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-env-function": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/postcss-env-function/-/postcss-env-function-4.0.6.tgz",
+ "integrity": "sha512-kpA6FsLra+NqcFnL81TnsU+Z7orGtDTxcOhl6pwXeEq1yFPpRMkCDpHhrz8CFQDr/Wfm0jLiNQ1OsGGPjlqPwA==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-focus-visible": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-focus-visible/-/postcss-focus-visible-6.0.4.tgz",
+ "integrity": "sha512-QcKuUU/dgNsstIK6HELFRT5Y3lbrMLEOwG+A4s5cA+fx3A3y/JTq3X9LaOj3OC3ALH0XqyrgQIgey/MIZ8Wczw==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.9"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-focus-within": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-focus-within/-/postcss-focus-within-5.0.4.tgz",
+ "integrity": "sha512-vvjDN++C0mu8jz4af5d52CB184ogg/sSxAFS+oUJQq2SuCe7T5U2iIsVJtsCp2d6R4j0jr5+q3rPkBVZkXD9fQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.9"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-font-variant": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-font-variant/-/postcss-font-variant-5.0.0.tgz",
+ "integrity": "sha512-1fmkBaCALD72CK2a9i468mA/+tr9/1cBxRRMXOUaZqO43oWPR5imcyPjXwuv7PXbCid4ndlP5zWhidQVVa3hmA==",
+ "dev": true,
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-gap-properties": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-gap-properties/-/postcss-gap-properties-3.0.5.tgz",
+ "integrity": "sha512-IuE6gKSdoUNcvkGIqdtjtcMtZIFyXZhmFd5RUlg97iVEvp1BZKV5ngsAjCjrVy+14uhGBQl9tzmi1Qwq4kqVOg==",
+ "dev": true,
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-image-set-function": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/postcss-image-set-function/-/postcss-image-set-function-4.0.7.tgz",
+ "integrity": "sha512-9T2r9rsvYzm5ndsBE8WgtrMlIT7VbtTfE7b3BQnudUqnBcBo7L758oc+o+pdj/dUV0l5wjwSdjeOH2DZtfv8qw==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-initial": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-initial/-/postcss-initial-4.0.1.tgz",
+ "integrity": "sha512-0ueD7rPqX8Pn1xJIjay0AZeIuDoF+V+VvMt/uOnn+4ezUKhZM/NokDeP6DwMNyIoYByuN/94IQnt5FEkaN59xQ==",
+ "dev": true,
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-lab-function": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-lab-function/-/postcss-lab-function-4.2.1.tgz",
+ "integrity": "sha512-xuXll4isR03CrQsmxyz92LJB2xX9n+pZJ5jE9JgcnmsCammLyKdlzrBin+25dy6wIjfhJpKBAN80gsTlCgRk2w==",
+ "dev": true,
+ "dependencies": {
+ "@csstools/postcss-progressive-custom-properties": "^1.1.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-loader": {
+ "version": "7.3.4",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-7.3.4.tgz",
+ "integrity": "sha512-iW5WTTBSC5BfsBJ9daFMPVrLT36MrNiC6fqOZTTaHjBNX6Pfd5p+hSBqe/fEeNd7pc13QiAyGt7VdGMw4eRC4A==",
+ "dev": true,
+ "dependencies": {
+ "cosmiconfig": "^8.3.5",
+ "jiti": "^1.20.0",
+ "semver": "^7.5.4"
+ },
+ "engines": {
+ "node": ">= 14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "postcss": "^7.0.0 || ^8.0.1",
+ "webpack": "^5.0.0"
+ }
+ },
+ "node_modules/postcss-loader/node_modules/cosmiconfig": {
+ "version": "8.3.6",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-8.3.6.tgz",
+ "integrity": "sha512-kcZ6+W5QzcJ3P1Mt+83OUv/oHFqZHIx8DuxG6eZ5RGMERoLqp4BuGjhHLYGK+Kf5XVkQvqBSmAy/nGWN3qDgEA==",
+ "dev": true,
+ "dependencies": {
+ "import-fresh": "^3.3.0",
+ "js-yaml": "^4.1.0",
+ "parse-json": "^5.2.0",
+ "path-type": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/d-fischer"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.9.5"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-loader/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/postcss-logical": {
+ "version": "5.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-logical/-/postcss-logical-5.0.4.tgz",
+ "integrity": "sha512-RHXxplCeLh9VjinvMrZONq7im4wjWGlRJAqmAVLXyZaXwfDWP73/oq4NdIp+OZwhQUMj0zjqDfM5Fj7qby+B4g==",
+ "dev": true,
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4"
+ }
+ },
+ "node_modules/postcss-media-minmax": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-media-minmax/-/postcss-media-minmax-5.0.0.tgz",
+ "integrity": "sha512-yDUvFf9QdFZTuCUg0g0uNSHVlJ5X1lSzDZjPSFaiCWvjgsvu8vEVxtahPrLMinIDEEGnx6cBe6iqdx5YWz08wQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-merge-longhand": {
+ "version": "5.1.7",
+ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz",
+ "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0",
+ "stylehacks": "^5.1.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-merge-rules": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz",
+ "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==",
+ "dependencies": {
+ "browserslist": "^4.21.4",
+ "caniuse-api": "^3.0.0",
+ "cssnano-utils": "^3.1.0",
+ "postcss-selector-parser": "^6.0.5"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-minify-font-values": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz",
+ "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-minify-gradients": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz",
+ "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==",
+ "dependencies": {
+ "colord": "^2.9.1",
+ "cssnano-utils": "^3.1.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-minify-params": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz",
+ "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==",
+ "dependencies": {
+ "browserslist": "^4.21.4",
+ "cssnano-utils": "^3.1.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-minify-selectors": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz",
+ "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.5"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-modules-extract-imports": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz",
+ "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==",
+ "dev": true,
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-modules-local-by-default": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.5.tgz",
+ "integrity": "sha512-6MieY7sIfTK0hYfafw1OMEG+2bg8Q1ocHCpoWLqOKj3JXlKu4G7btkmM/B7lFubYkYWmRSPLZi5chid63ZaZYw==",
+ "dev": true,
+ "dependencies": {
+ "icss-utils": "^5.0.0",
+ "postcss-selector-parser": "^6.0.2",
+ "postcss-value-parser": "^4.1.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-modules-scope": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.0.tgz",
+ "integrity": "sha512-oq+g1ssrsZOsx9M96c5w8laRmvEu9C3adDSjI8oTcbfkrTE8hx/zfyobUoWIxaKPO8bt6S62kxpw5GqypEw1QQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.4"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-modules-values": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
+ "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
+ "dev": true,
+ "dependencies": {
+ "icss-utils": "^5.0.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/postcss-nesting": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nesting/-/postcss-nesting-10.2.0.tgz",
+ "integrity": "sha512-EwMkYchxiDiKUhlJGzWsD9b2zvq/r2SSubcRrgP+jujMXFzqvANLt16lJANC+5uZ6hjI7lpRmI6O8JIl+8l1KA==",
+ "dev": true,
+ "dependencies": {
+ "@csstools/selector-specificity": "^2.0.0",
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-normalize-charset": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz",
+ "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==",
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-normalize-display-values": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz",
+ "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-normalize-positions": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz",
+ "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-normalize-repeat-style": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz",
+ "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-normalize-string": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz",
+ "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-normalize-timing-functions": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz",
+ "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-normalize-unicode": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz",
+ "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==",
+ "dependencies": {
+ "browserslist": "^4.21.4",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-normalize-url": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz",
+ "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==",
+ "dependencies": {
+ "normalize-url": "^6.0.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-normalize-whitespace": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz",
+ "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-opacity-percentage": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/postcss-opacity-percentage/-/postcss-opacity-percentage-1.1.3.tgz",
+ "integrity": "sha512-An6Ba4pHBiDtyVpSLymUUERMo2cU7s+Obz6BTrS+gxkbnSBNKSuD0AVUc+CpBMrpVPKKfoVz0WQCX+Tnst0i4A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "kofi",
+ "url": "https://ko-fi.com/mrcgrtz"
+ },
+ {
+ "type": "liberapay",
+ "url": "https://liberapay.com/mrcgrtz"
+ }
+ ],
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-ordered-values": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz",
+ "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==",
+ "dependencies": {
+ "cssnano-utils": "^3.1.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-overflow-shorthand": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-overflow-shorthand/-/postcss-overflow-shorthand-3.0.4.tgz",
+ "integrity": "sha512-otYl/ylHK8Y9bcBnPLo3foYFLL6a6Ak+3EQBPOTR7luMYCOsiVTUk1iLvNf6tVPNGXcoL9Hoz37kpfriRIFb4A==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-page-break": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/postcss-page-break/-/postcss-page-break-3.0.4.tgz",
+ "integrity": "sha512-1JGu8oCjVXLa9q9rFTo4MbeeA5FMe00/9C7lN4va606Rdb+HkxXtXsmEDrIraQ11fGz/WvKWa8gMuCKkrXpTsQ==",
+ "dev": true,
+ "peerDependencies": {
+ "postcss": "^8"
+ }
+ },
+ "node_modules/postcss-place": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/postcss-place/-/postcss-place-7.0.5.tgz",
+ "integrity": "sha512-wR8igaZROA6Z4pv0d+bvVrvGY4GVHihBCBQieXFY3kuSuMyOmEnnfFzHl/tQuqHZkfkIVBEbDvYcFfHmpSet9g==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-preset-env": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/postcss-preset-env/-/postcss-preset-env-7.8.3.tgz",
+ "integrity": "sha512-T1LgRm5uEVFSEF83vHZJV2z19lHg4yJuZ6gXZZkqVsqv63nlr6zabMH3l4Pc01FQCyfWVrh2GaUeCVy9Po+Aag==",
+ "dev": true,
+ "dependencies": {
+ "@csstools/postcss-cascade-layers": "^1.1.1",
+ "@csstools/postcss-color-function": "^1.1.1",
+ "@csstools/postcss-font-format-keywords": "^1.0.1",
+ "@csstools/postcss-hwb-function": "^1.0.2",
+ "@csstools/postcss-ic-unit": "^1.0.1",
+ "@csstools/postcss-is-pseudo-class": "^2.0.7",
+ "@csstools/postcss-nested-calc": "^1.0.0",
+ "@csstools/postcss-normalize-display-values": "^1.0.1",
+ "@csstools/postcss-oklab-function": "^1.1.1",
+ "@csstools/postcss-progressive-custom-properties": "^1.3.0",
+ "@csstools/postcss-stepped-value-functions": "^1.0.1",
+ "@csstools/postcss-text-decoration-shorthand": "^1.0.0",
+ "@csstools/postcss-trigonometric-functions": "^1.0.2",
+ "@csstools/postcss-unset-value": "^1.0.2",
+ "autoprefixer": "^10.4.13",
+ "browserslist": "^4.21.4",
+ "css-blank-pseudo": "^3.0.3",
+ "css-has-pseudo": "^3.0.4",
+ "css-prefers-color-scheme": "^6.0.3",
+ "cssdb": "^7.1.0",
+ "postcss-attribute-case-insensitive": "^5.0.2",
+ "postcss-clamp": "^4.1.0",
+ "postcss-color-functional-notation": "^4.2.4",
+ "postcss-color-hex-alpha": "^8.0.4",
+ "postcss-color-rebeccapurple": "^7.1.1",
+ "postcss-custom-media": "^8.0.2",
+ "postcss-custom-properties": "^12.1.10",
+ "postcss-custom-selectors": "^6.0.3",
+ "postcss-dir-pseudo-class": "^6.0.5",
+ "postcss-double-position-gradients": "^3.1.2",
+ "postcss-env-function": "^4.0.6",
+ "postcss-focus-visible": "^6.0.4",
+ "postcss-focus-within": "^5.0.4",
+ "postcss-font-variant": "^5.0.0",
+ "postcss-gap-properties": "^3.0.5",
+ "postcss-image-set-function": "^4.0.7",
+ "postcss-initial": "^4.0.1",
+ "postcss-lab-function": "^4.2.1",
+ "postcss-logical": "^5.0.4",
+ "postcss-media-minmax": "^5.0.0",
+ "postcss-nesting": "^10.2.0",
+ "postcss-opacity-percentage": "^1.1.2",
+ "postcss-overflow-shorthand": "^3.0.4",
+ "postcss-page-break": "^3.0.4",
+ "postcss-place": "^7.0.5",
+ "postcss-pseudo-class-any-link": "^7.1.6",
+ "postcss-replace-overflow-wrap": "^4.0.0",
+ "postcss-selector-not": "^6.0.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-pseudo-class-any-link": {
+ "version": "7.1.6",
+ "resolved": "https://registry.npmjs.org/postcss-pseudo-class-any-link/-/postcss-pseudo-class-any-link-7.1.6.tgz",
+ "integrity": "sha512-9sCtZkO6f/5ML9WcTLcIyV1yz9D1rf0tWc+ulKcvV30s0iZKS/ONyETvoWsr6vnrmW+X+KmuK3gV/w5EWnT37w==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-reduce-initial": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz",
+ "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==",
+ "dependencies": {
+ "browserslist": "^4.21.4",
+ "caniuse-api": "^3.0.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-reduce-transforms": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz",
+ "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-replace-overflow-wrap": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/postcss-replace-overflow-wrap/-/postcss-replace-overflow-wrap-4.0.0.tgz",
+ "integrity": "sha512-KmF7SBPphT4gPPcKZc7aDkweHiKEEO8cla/GjcBK+ckKxiZslIu3C4GCRW3DNfL0o7yW7kMQu9xlZ1kXRXLXtw==",
+ "dev": true,
+ "peerDependencies": {
+ "postcss": "^8.0.3"
+ }
+ },
+ "node_modules/postcss-selector-not": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-not/-/postcss-selector-not-6.0.1.tgz",
+ "integrity": "sha512-1i9affjAe9xu/y9uqWH+tD4r6/hDaXJruk8xn2x1vzxC2U3J3LKO3zJW4CyxlNhA56pADJ/djpEwpH1RClI2rQ==",
+ "dev": true,
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.10"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >=16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/csstools"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-svgo": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz",
+ "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0",
+ "svgo": "^2.7.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-unique-selectors": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz",
+ "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==",
+ "dependencies": {
+ "postcss-selector-parser": "^6.0.5"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prettier": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.5.3.tgz",
+ "integrity": "sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==",
+ "dev": true,
+ "license": "MIT",
+ "bin": {
+ "prettier": "bin/prettier.cjs"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
+ }
+ },
+ "node_modules/prettier-linter-helpers": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/prettier-linter-helpers/-/prettier-linter-helpers-1.0.0.tgz",
+ "integrity": "sha512-GbK2cP9nraSSUF9N2XwUwqfzlAFlMNYYl+ShE/V+H8a9uNl/oUqB1w2EL54Jh0OlyRSd8RfWYJ3coVS4TROP2w==",
+ "dev": true,
+ "dependencies": {
+ "fast-diff": "^1.1.2"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/pretty-error": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
+ "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==",
+ "dev": true,
+ "dependencies": {
+ "lodash": "^4.17.20",
+ "renderkid": "^3.0.0"
+ }
+ },
+ "node_modules/pretty-format": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/pretty-format/-/pretty-format-27.5.1.tgz",
+ "integrity": "sha512-Qb1gy5OrP5+zDf2Bvnzdl3jsTf1qXVMazbvCoKhtKqVs4/YK4ozX4gKQJJVyNe+cajNPn0KoC0MC3FUmaHWEmQ==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1",
+ "ansi-styles": "^5.0.0",
+ "react-is": "^17.0.1"
+ },
+ "engines": {
+ "node": "^10.13.0 || ^12.13.0 || ^14.15.0 || >=15.0.0"
+ }
+ },
+ "node_modules/pretty-format/node_modules/ansi-styles": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-5.2.0.tgz",
+ "integrity": "sha512-Cxwpt2SfTzTtXcfOlzGEee8O+c+MmUgGrNiBcXnuWxuFJHe6a5Hz7qwhwe5OgaSYI0IJvkLqWX1ASG+cJOkEiA==",
+ "dev": true,
+ "peer": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/pretty-format/node_modules/react-is": {
+ "version": "17.0.2",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
+ "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/prismjs": {
+ "version": "1.30.0",
+ "resolved": "https://registry.npmjs.org/prismjs/-/prismjs-1.30.0.tgz",
+ "integrity": "sha512-DEvV2ZF2r2/63V+tK8hQvrR2ZGn10srHbXviTlcv7Kpzw8jWiNTqbVgjO3IY8RxrrOUF8VPMQQFysYYYv0YZxw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "dev": true
+ },
+ "node_modules/prompts": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/prompts/-/prompts-2.4.2.tgz",
+ "integrity": "sha512-NxNv/kLguCA7p3jE8oL2aEBsrJWgAakBpgmgK6lpPWV+WuOmY6r2/zbAVnP+T8bQlA0nzHXSJSJW0Hq7ylaD2Q==",
+ "dev": true,
+ "dependencies": {
+ "kleur": "^3.0.3",
+ "sisteransi": "^1.0.5"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/prop-types/node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/property-expr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
+ "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA=="
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-addr/node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
+ "dev": true
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/pure-rand": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/pure-rand/-/pure-rand-6.1.0.tgz",
+ "integrity": "sha512-bVWawvoZoBYpp6yIoQtQXHZjmz35RSVHnUOTefl8Vcjr8snTPY1wnpSPMWekcFwbxI6gtmT7rSYPFvz71ldiOA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/dubzzz"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fast-check"
+ }
+ ]
+ },
+ "node_modules/pvtsutils": {
+ "version": "1.3.6",
+ "resolved": "https://registry.npmjs.org/pvtsutils/-/pvtsutils-1.3.6.tgz",
+ "integrity": "sha512-PLgQXQ6H2FWCaeRak8vvk1GW462lMxB5s3Jm673N82zI4vqtVUPuZdffdZbPDFRoU8kAhItWFtPCWiPpp4/EDg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.8.1"
+ }
+ },
+ "node_modules/pvutils": {
+ "version": "1.1.5",
+ "resolved": "https://registry.npmjs.org/pvutils/-/pvutils-1.1.5.tgz",
+ "integrity": "sha512-KTqnxsgGiQ6ZAzZCVlJH5eOjSnvlyEgx1m8bkRJfOhmGRqfo5KLvmAlACQkrjEtOQ4B7wF9TdSLIs9O90MX9xA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/qs": {
+ "version": "6.14.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.1.tgz",
+ "integrity": "sha512-4EK3+xJl8Ts67nLYNwqw/dsFVnCf+qR7RgXSK9jEEm9unao3njwMDdmsdvoKBKHzxd7tCYz5e5M+SnMjdtXGQQ==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/raf": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
+ "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+ "dev": true,
+ "dependencies": {
+ "performance-now": "^2.1.0"
+ }
+ },
+ "node_modules/railroad-diagrams": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/railroad-diagrams/-/railroad-diagrams-1.0.0.tgz",
+ "integrity": "sha512-cz93DjNeLY0idrCNOH6PviZGRN9GJhsdm9hpn1YCS879fj4W+x5IFJhhkRZcwVgMmFF7R82UA/7Oh+R8lLZg6A==",
+ "dev": true
+ },
+ "node_modules/randexp": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/randexp/-/randexp-0.4.6.tgz",
+ "integrity": "sha512-80WNmd9DA0tmZrw9qQa62GPPWfuXJknrmVmLcxvq4uZBdYqb1wYoKTmnlGUchvVWe0XiLupYkBoXVOxz3C8DYQ==",
+ "dev": true,
+ "dependencies": {
+ "discontinuous-range": "1.0.0",
+ "ret": "~0.1.10"
+ },
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/randombytes": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
+ "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
+ "dependencies": {
+ "safe-buffer": "^5.1.0"
+ }
+ },
+ "node_modules/range-parser": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
+ "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/raw-body": {
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
+ "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "unpipe": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/raw-body/node_modules/iconv-lite": {
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rc-align": {
+ "version": "4.0.15",
+ "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-4.0.15.tgz",
+ "integrity": "sha512-wqJtVH60pka/nOX7/IspElA8gjPNQKIx/ZqJ6heATCkXpe1Zg4cPVrMD2vC96wjsFFL8WsmhPbx9tdMo1qqlIA==",
+ "dependencies": {
+ "@babel/runtime": "^7.10.1",
+ "classnames": "2.x",
+ "dom-align": "^1.7.0",
+ "rc-util": "^5.26.0",
+ "resize-observer-polyfill": "^1.5.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-motion": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/rc-motion/-/rc-motion-2.9.3.tgz",
+ "integrity": "sha512-rkW47ABVkic7WEB0EKJqzySpvDqwl60/tdkY7hWP7dYnh5pm0SzJpo54oW3TDUGXV5wfxXFmMkxrzRRbotQ0+w==",
+ "dependencies": {
+ "@babel/runtime": "^7.11.1",
+ "classnames": "^2.2.1",
+ "rc-util": "^5.43.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-tooltip": {
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-5.3.1.tgz",
+ "integrity": "sha512-e6H0dMD38EPaSPD2XC8dRfct27VvT2TkPdoBSuNl3RRZ5tspiY/c5xYEmGC0IrABvMBgque4Mr2SMZuliCvoiQ==",
+ "dependencies": {
+ "@babel/runtime": "^7.11.2",
+ "classnames": "^2.3.1",
+ "rc-trigger": "^5.3.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-trigger": {
+ "version": "5.3.4",
+ "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-5.3.4.tgz",
+ "integrity": "sha512-mQv+vas0TwKcjAO2izNPkqR4j86OemLRmvL2nOzdP9OWNWA1ivoTt5hzFqYNW9zACwmTezRiN8bttrC7cZzYSw==",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "classnames": "^2.2.6",
+ "rc-align": "^4.0.0",
+ "rc-motion": "^2.0.0",
+ "rc-util": "^5.19.2"
+ },
+ "engines": {
+ "node": ">=8.x"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/rc-util": {
+ "version": "5.43.0",
+ "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-5.43.0.tgz",
+ "integrity": "sha512-AzC7KKOXFqAdIBqdGWepL9Xn7cm3vnAmjlHqUnoQaTMZYhM4VlXGLkkHHxj/BZ7Td0+SOPKB4RGPboBVKT9htw==",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "react-is": "^18.2.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.9.0",
+ "react-dom": ">=16.9.0"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-avatar": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/react-avatar/-/react-avatar-5.0.3.tgz",
+ "integrity": "sha512-DNc+qkWH9QehSEZqHBhqpXWsPY+rU9W7kD68QFHfu8Atfsvx/3ML0DzAePgTUd96nCXQQ3KZMcC3LKYT8FiBIg==",
+ "dependencies": {
+ "is-retina": "^1.0.3",
+ "md5": "^2.0.0"
+ },
+ "peerDependencies": {
+ "@babel/runtime": ">=7",
+ "core-js-pure": ">=3",
+ "prop-types": "^15.0.0 || ^16.0.0",
+ "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-bus": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/react-bus/-/react-bus-4.0.1.tgz",
+ "integrity": "sha512-tzPWE23WN0U9v3YaGKAlLW7GXYv1YkCUgWcnzm8HDtfBeD2vDvK8PYHkJVrwMdzg5BleHcxejtdKYfIYZxD7PQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/react": "^18.0.8",
+ "mitt": "^3.0.1"
+ },
+ "peerDependencies": {
+ "react": ">=17.0.0 || ^19.0.0-0"
+ }
+ },
+ "node_modules/react-dev-utils": {
+ "version": "12.0.1",
+ "resolved": "https://registry.npmjs.org/react-dev-utils/-/react-dev-utils-12.0.1.tgz",
+ "integrity": "sha512-84Ivxmr17KjUupyqzFode6xKhjwuEJDROWKJy/BthkL7Wn6NJ8h4WE6k/exAv6ImS+0oZLRRW5j/aINMHyeGeQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.16.0",
+ "address": "^1.1.2",
+ "browserslist": "^4.18.1",
+ "chalk": "^4.1.2",
+ "cross-spawn": "^7.0.3",
+ "detect-port-alt": "^1.1.6",
+ "escape-string-regexp": "^4.0.0",
+ "filesize": "^8.0.6",
+ "find-up": "^5.0.0",
+ "fork-ts-checker-webpack-plugin": "^6.5.0",
+ "global-modules": "^2.0.0",
+ "globby": "^11.0.4",
+ "gzip-size": "^6.0.0",
+ "immer": "^9.0.7",
+ "is-root": "^2.1.0",
+ "loader-utils": "^3.2.0",
+ "open": "^8.4.0",
+ "pkg-up": "^3.1.0",
+ "prompts": "^2.4.2",
+ "react-error-overlay": "^6.0.11",
+ "recursive-readdir": "^2.2.2",
+ "shell-quote": "^1.7.3",
+ "strip-ansi": "^6.0.1",
+ "text-table": "^0.2.0"
+ },
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-error-overlay": {
+ "version": "6.0.11",
+ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz",
+ "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==",
+ "dev": true
+ },
+ "node_modules/react-fast-compare": {
+ "version": "3.2.2",
+ "resolved": "https://registry.npmjs.org/react-fast-compare/-/react-fast-compare-3.2.2.tgz",
+ "integrity": "sha512-nsO+KSNgo1SbJqJEYRE9ERzo7YtYbou/OqjSQKxV7jcKox7+usiUVZOAC+XnDOABXggQTno0Y1CpVnuWEc1boQ=="
+ },
+ "node_modules/react-helmet": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/react-helmet/-/react-helmet-6.1.0.tgz",
+ "integrity": "sha512-4uMzEY9nlDlgxr61NL3XbKRy1hEkXmKNXhjbAIOVw5vcFrsdYbH2FEwcNyWvWinl103nXgzYNlns9ca+8kFiWw==",
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "prop-types": "^15.7.2",
+ "react-fast-compare": "^3.1.1",
+ "react-side-effect": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.3.0"
+ }
+ },
+ "node_modules/react-hook-form": {
+ "version": "7.53.1",
+ "resolved": "https://registry.npmjs.org/react-hook-form/-/react-hook-form-7.53.1.tgz",
+ "integrity": "sha512-6aiQeBda4zjcuaugWvim9WsGqisoUk+etmFEsSUMm451/Ic8L/UAb7sRtMj3V+Hdzm6mMjU1VhiSzYUZeBm0Vg==",
+ "engines": {
+ "node": ">=18.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-hook-form"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17 || ^18 || ^19"
+ }
+ },
+ "node_modules/react-i18next": {
+ "version": "12.3.1",
+ "resolved": "https://registry.npmjs.org/react-i18next/-/react-i18next-12.3.1.tgz",
+ "integrity": "sha512-5v8E2XjZDFzK7K87eSwC7AJcAkcLt5xYZ4+yTPDAW1i7C93oOY1dnr4BaQM7un4Hm+GmghuiPvevWwlca5PwDA==",
+ "dependencies": {
+ "@babel/runtime": "^7.20.6",
+ "html-parse-stringify": "^3.0.1"
+ },
+ "peerDependencies": {
+ "i18next": ">= 19.0.0",
+ "react": ">= 16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+ },
+ "node_modules/react-keyed-flatten-children": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/react-keyed-flatten-children/-/react-keyed-flatten-children-2.2.1.tgz",
+ "integrity": "sha512-6yBLVO6suN8c/OcJk1mzIrUHdeEzf5rtRVBhxEXAHO49D7SlJ70cG4xrSJrBIAG7MMeQ+H/T151mM2dRDNnFaA==",
+ "license": "MIT",
+ "dependencies": {
+ "react-is": "^18.2.0"
+ },
+ "peerDependencies": {
+ "react": ">=15.0.0"
+ }
+ },
+ "node_modules/react-redux": {
+ "version": "8.1.3",
+ "resolved": "https://registry.npmjs.org/react-redux/-/react-redux-8.1.3.tgz",
+ "integrity": "sha512-n0ZrutD7DaX/j9VscF+uTALI3oUPa/pO4Z3soOBIjuRn/FzVu6aehhysxZCLi6y7duMf52WNZGMl7CtuK5EnRw==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.1",
+ "@types/hoist-non-react-statics": "^3.3.1",
+ "@types/use-sync-external-store": "^0.0.3",
+ "hoist-non-react-statics": "^3.3.2",
+ "react-is": "^18.0.0",
+ "use-sync-external-store": "^1.0.0"
+ },
+ "peerDependencies": {
+ "@types/react": "^16.8 || ^17.0 || ^18.0",
+ "@types/react-dom": "^16.8 || ^17.0 || ^18.0",
+ "react": "^16.8 || ^17.0 || ^18.0",
+ "react-dom": "^16.8 || ^17.0 || ^18.0",
+ "react-native": ">=0.59",
+ "redux": "^4 || ^5.0.0-beta.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "@types/react-dom": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ },
+ "redux": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
+ "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "6.30.3",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.30.3.tgz",
+ "integrity": "sha512-XRnlbKMTmktBkjCLE8/XcZFlnHvr2Ltdr1eJX4idL55/9BbORzyZEaIkBFDhFGCEWBBItsVrDxwx3gnisMitdw==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.23.2"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.30.3",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.30.3.tgz",
+ "integrity": "sha512-pxPcv1AczD4vso7G4Z3TKcvlxK7g7TNt3/FNGMhfqyntocvYKj+GCatfigGDjbLozC4baguJ0ReCigoDJXb0ag==",
+ "license": "MIT",
+ "dependencies": {
+ "@remix-run/router": "1.23.2",
+ "react-router": "6.30.3"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/react-shallow-renderer": {
+ "version": "16.15.0",
+ "resolved": "https://registry.npmjs.org/react-shallow-renderer/-/react-shallow-renderer-16.15.0.tgz",
+ "integrity": "sha512-oScf2FqQ9LFVQgA73vr86xl2NaOIX73rh+YFqcOp68CWj56tSfgtGKrEbyhCj0rSijyG9M1CYprTh39fBi5hzA==",
+ "dev": true,
+ "dependencies": {
+ "object-assign": "^4.1.1",
+ "react-is": "^16.12.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-side-effect": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/react-side-effect/-/react-side-effect-2.1.2.tgz",
+ "integrity": "sha512-PVjOcvVOyIILrYoyGEpDN3vmYNLdy1CajSFNt4TDsVQC5KpTijDvWVoR+/7Rz2xT978D8/ZtFceXxzsPwZEDvw==",
+ "peerDependencies": {
+ "react": "^16.3.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-string-replace": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/react-string-replace/-/react-string-replace-1.1.1.tgz",
+ "integrity": "sha512-26TUbLzLfHQ5jO5N7y3Mx88eeKo0Ml0UjCQuX4BMfOd/JX+enQqlKpL1CZnmjeBRvQE8TR+ds9j1rqx9CxhKHQ==",
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/react-test-renderer": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-test-renderer/-/react-test-renderer-18.3.1.tgz",
+ "integrity": "sha512-KkAgygexHUkQqtvvx/otwxtuFu5cVjfzTCtjXLH9boS19/Nbtg84zS7wIQn39G8IlrhThBpQsMKkq5ZHZIYFXA==",
+ "dev": true,
+ "dependencies": {
+ "react-is": "^18.3.1",
+ "react-shallow-renderer": "^16.15.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
+ "dev": true,
+ "dependencies": {
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/rechoir": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.8.0.tgz",
+ "integrity": "sha512-/vxpCXddiX8NGfGO/mTafwjq4aFa/71pvamip0++IQk3zG8cbCj0fifNPrjjF1XMXUne91jL9OoxmdykoEtifQ==",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.20.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/recursive-readdir": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/recursive-readdir/-/recursive-readdir-2.2.3.tgz",
+ "integrity": "sha512-8HrF5ZsXk5FAH9dgsx3BlUer73nIhuj+9OrQwEbLTPOBzGkL1lsFCR01am+v+0m2Cmbs1nP12hLDl5FA7EszKA==",
+ "dev": true,
+ "dependencies": {
+ "minimatch": "^3.0.5"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/redent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/redent/-/redent-3.0.0.tgz",
+ "integrity": "sha512-6tDA8g98We0zd0GvVeMT9arEOnTw9qM03L9cJXaCjrip1OO764RDBLBfrB4cwzNGDj5OA5ioymC9GkizgWJDUg==",
+ "dev": true,
+ "dependencies": {
+ "indent-string": "^4.0.0",
+ "strip-indent": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/redux": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/redux/-/redux-5.0.1.tgz",
+ "integrity": "sha512-M9/ELqF6fy8FwmkpnF0S3YKOqMyoWJ4+CS5Efg2ct3oY9daQvd/Pc71FpGZsVsbl3Cpb+IIcjBDUnnyBdQbq4w=="
+ },
+ "node_modules/reflect-metadata": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/reflect-metadata/-/reflect-metadata-0.2.2.tgz",
+ "integrity": "sha512-urBwgfrvVP/eAyXx4hluJivBKzuEbSQs9rKWCrCkbSxNv8mxPcUZKeuoF3Uy4mJl3Lwprp6yy5/39VWigZ4K6Q==",
+ "dev": true,
+ "license": "Apache-2.0"
+ },
+ "node_modules/reflect.getprototypeof": {
+ "version": "1.0.10",
+ "resolved": "https://registry.npmjs.org/reflect.getprototypeof/-/reflect.getprototypeof-1.0.10.tgz",
+ "integrity": "sha512-00o4I+DVrefhv+nX0ulyi3biSHCPDe+yLv5o/p6d/UVlirijB8E16FtfwSAi4g3tcqrQ4lRAqQSoFEZJehYEcw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.9",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.7",
+ "get-proto": "^1.0.1",
+ "which-builtin-type": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/reftools": {
+ "version": "1.1.9",
+ "resolved": "https://registry.npmjs.org/reftools/-/reftools-1.1.9.tgz",
+ "integrity": "sha512-OVede/NQE13xBQ+ob5CKd5KyeJYU2YInb1bmV4nRoOfquZPkAkxuOXicSe1PvqIuZZ4kD13sPKBbR7UFDmli6w==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/Mermade/oas-kit?sponsor=1"
+ }
+ },
+ "node_modules/regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+ "dev": true
+ },
+ "node_modules/regenerate-unicode-properties": {
+ "version": "10.2.0",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.0.tgz",
+ "integrity": "sha512-DqHn3DwbmmPVzeKj9woBadqmXxLvQoQIwu7nopMc72ztvxVmVk2SBhSnx67zuye5TP+lJsb/TBQsjLKhnDf3MA==",
+ "dev": true,
+ "dependencies": {
+ "regenerate": "^1.4.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regenerator-transform": {
+ "version": "0.15.2",
+ "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.15.2.tgz",
+ "integrity": "sha512-hfMp2BoF0qOk3uc5V20ALGDS2ddjQaLrdl7xrGXvAIow7qeWRM2VA2HuCHkUKk9slq3VwEwLNK3DFBqDfPGYtg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/runtime": "^7.8.4"
+ }
+ },
+ "node_modules/regex-parser": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/regex-parser/-/regex-parser-2.3.0.tgz",
+ "integrity": "sha512-TVILVSz2jY5D47F4mA4MppkBrafEaiUWJO/TcZHEIuI13AqoZMkK1WMA4Om1YkYbTx+9Ki1/tSUXbceyr9saRg==",
+ "dev": true
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.4.tgz",
+ "integrity": "sha512-dYqgNSZbDwkaJ2ceRd9ojCGjBq+mOm9LmtXnAnEGyHhN/5R7iDW2TRw3h+o/jCFxus3P2LfWIIiwowAjANm7IA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/regexpu-core": {
+ "version": "6.1.1",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.1.1.tgz",
+ "integrity": "sha512-k67Nb9jvwJcJmVpw0jPttR1/zVfnKf8Km0IPatrU/zJ5XeG3+Slx0xLXs9HByJSzXzrlz5EDvN6yLNMDc2qdnw==",
+ "dev": true,
+ "dependencies": {
+ "regenerate": "^1.4.2",
+ "regenerate-unicode-properties": "^10.2.0",
+ "regjsgen": "^0.8.0",
+ "regjsparser": "^0.11.0",
+ "unicode-match-property-ecmascript": "^2.0.0",
+ "unicode-match-property-value-ecmascript": "^2.1.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/regjsgen": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz",
+ "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==",
+ "dev": true
+ },
+ "node_modules/regjsparser": {
+ "version": "0.11.2",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.11.2.tgz",
+ "integrity": "sha512-3OGZZ4HoLJkkAZx/48mTXJNlmqTGOzc0o9OWQPuWpkOlXXPbyN6OafCcoXUnBqE2D3f/T5L+pWc1kdEmnfnRsA==",
+ "dev": true,
+ "dependencies": {
+ "jsesc": "~3.0.2"
+ },
+ "bin": {
+ "regjsparser": "bin/parser"
+ }
+ },
+ "node_modules/relateurl": {
+ "version": "0.2.7",
+ "resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
+ "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/renderkid": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
+ "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==",
+ "dev": true,
+ "dependencies": {
+ "css-select": "^4.1.3",
+ "dom-converter": "^0.2.0",
+ "htmlparser2": "^6.1.0",
+ "lodash": "^4.17.21",
+ "strip-ansi": "^6.0.1"
+ }
+ },
+ "node_modules/renderkid/node_modules/css-select": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
+ "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
+ "dev": true,
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.0.1",
+ "domhandler": "^4.3.1",
+ "domutils": "^2.8.0",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/renderkid/node_modules/dom-serializer": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
+ "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^4.2.0",
+ "entities": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/renderkid/node_modules/domhandler": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
+ "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
+ "dev": true,
+ "dependencies": {
+ "domelementtype": "^2.2.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/renderkid/node_modules/domutils": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
+ "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
+ "dev": true,
+ "dependencies": {
+ "dom-serializer": "^1.0.1",
+ "domelementtype": "^2.2.0",
+ "domhandler": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/renderkid/node_modules/entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/renderkid/node_modules/htmlparser2": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/htmlparser2/-/htmlparser2-6.1.0.tgz",
+ "integrity": "sha512-gyyPk6rgonLFEDGoeRgQNaEUvdJ4ktTmmUh/h2t7s+M8oPpIPxgNACWa+6ESR57kXstwqPiCut0V8NRpcwgU7A==",
+ "dev": true,
+ "funding": [
+ "https://github.com/fb55/htmlparser2?sponsor=1",
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fb55"
+ }
+ ],
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^4.0.0",
+ "domutils": "^2.5.2",
+ "entities": "^2.0.0"
+ }
+ },
+ "node_modules/require-directory": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/requires-port": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true
+ },
+ "node_modules/reselect": {
+ "version": "4.1.8",
+ "resolved": "https://registry.npmjs.org/reselect/-/reselect-4.1.8.tgz",
+ "integrity": "sha512-ab9EmR80F/zQTMNeneUr4cv+jSwPJgIlvEmVwLerwrWVbpLlBuls9XHzIeTFy4cegU2NHBp3va0LKOzU5qFEYQ=="
+ },
+ "node_modules/resize-observer-polyfill": {
+ "version": "1.5.1",
+ "resolved": "https://registry.npmjs.org/resize-observer-polyfill/-/resize-observer-polyfill-1.5.1.tgz",
+ "integrity": "sha512-LwZrotdHOo12nQuZlHEmtuXdqGoOD0OhaxopaNFxWzInpEgaLWoVuAMbTzixuosCx2nEG58ngzW3vxdWoxIgdg=="
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dev": true,
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-cwd": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-3.0.0.tgz",
+ "integrity": "sha512-OrZaX2Mb+rJCpH/6CpSqt9xFVpN++x01XnN2ie9g6P5/3xelLAkXWVADpdz1IHD/KFfEXyE6V0U01OQ3UO2rEg==",
+ "dev": true,
+ "dependencies": {
+ "resolve-from": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-cwd/node_modules/resolve-from": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
+ "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/resolve-url-loader": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-url-loader/-/resolve-url-loader-5.0.0.tgz",
+ "integrity": "sha512-uZtduh8/8srhBoMx//5bwqjQ+rfYOUq8zC9NrMUGtjBiGTtFJM42s58/36+hTqeqINcnYe08Nj3LkK9lW4N8Xg==",
+ "dev": true,
+ "dependencies": {
+ "adjust-sourcemap-loader": "^4.0.0",
+ "convert-source-map": "^1.7.0",
+ "loader-utils": "^2.0.0",
+ "postcss": "^8.2.14",
+ "source-map": "0.6.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/resolve-url-loader/node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A==",
+ "dev": true
+ },
+ "node_modules/resolve-url-loader/node_modules/loader-utils": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+ "dev": true,
+ "dependencies": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=8.9.0"
+ }
+ },
+ "node_modules/resolve-url-loader/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve.exports": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.2.tgz",
+ "integrity": "sha512-X2UW6Nw3n/aMgDVy+0rSqgHlv39WZAlZrXCdnbyEiKm17DSqHX4MmQMaST3FbeWR5FTuRcUwYAziZajji0Y7mg==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/restore-cursor": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz",
+ "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^7.0.0",
+ "signal-exit": "^4.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/onetime": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz",
+ "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "mimic-function": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/restore-cursor/node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/ret": {
+ "version": "0.1.15",
+ "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
+ "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12"
+ }
+ },
+ "node_modules/retry": {
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/rfdc": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz",
+ "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/rst-selector-parser": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/rst-selector-parser/-/rst-selector-parser-2.2.3.tgz",
+ "integrity": "sha512-nDG1rZeP6oFTLN6yNDV/uiAvs1+FS/KlrEwh7+y7dpuApDBy6bI2HTBcc0/V8lv9OTqfyD34eF7au2pm8aBbhA==",
+ "dev": true,
+ "dependencies": {
+ "lodash.flattendeep": "^4.4.0",
+ "nearley": "^2.7.10"
+ }
+ },
+ "node_modules/run-applescript": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.0.0.tgz",
+ "integrity": "sha512-9by4Ij99JUr/MCFBUkDKLWK3G9HVXmabKz9U5MlIAIuvuzkiOicRYs8XJLxX+xahD+mLiiCYDqF9dKAgtzKP1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.3.tgz",
+ "integrity": "sha512-AURm5f0jYEOydBj7VQlVvDrjeFgthDdEF5H1dP+6mNpoXOMo1quQqJ4wvJDyRZ9+pO3kGWoOdmV08cSv2aJV6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "get-intrinsic": "^1.2.6",
+ "has-symbols": "^1.1.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-buffer": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/safe-push-apply": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/safe-push-apply/-/safe-push-apply-1.0.0.tgz",
+ "integrity": "sha512-iKE9w/Z7xCzUMIZqdBsp6pEQvwuEebH4vdpjcDWnyzaI6yl6O9FHvVpmGelvEHNsoY6wGblkxR6Zty/h00WiSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.1.0.tgz",
+ "integrity": "sha512-x/+Cz4YrimQxQccJf5mKEbIa1NzeCRNI5Ecl/ekmlYaampdNLPalVyIcCZNNH3MvmqBugV5TMYZXv0ljslUlaw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safer-buffer": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "dev": true
+ },
+ "node_modules/sass": {
+ "version": "1.81.0",
+ "resolved": "https://registry.npmjs.org/sass/-/sass-1.81.0.tgz",
+ "integrity": "sha512-Q4fOxRfhmv3sqCLoGfvrC9pRV8btc0UtqL9mN6Yrv6Qi9ScL55CVH1vlPP863ISLEEMNLLuu9P+enCeGHlnzhA==",
+ "dev": true,
+ "dependencies": {
+ "chokidar": "^4.0.0",
+ "immutable": "^5.0.2",
+ "source-map-js": ">=0.6.2 <2.0.0"
+ },
+ "bin": {
+ "sass": "sass.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "optionalDependencies": {
+ "@parcel/watcher": "^2.4.1"
+ }
+ },
+ "node_modules/sass-loader": {
+ "version": "16.0.3",
+ "resolved": "https://registry.npmjs.org/sass-loader/-/sass-loader-16.0.3.tgz",
+ "integrity": "sha512-gosNorT1RCkuCMyihv6FBRR7BMV06oKRAs+l4UMp1mlcVg9rWN6KMmUj3igjQwmYys4mDP3etEYJgiHRbgHCHA==",
+ "dev": true,
+ "dependencies": {
+ "neo-async": "^2.6.2"
+ },
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "@rspack/core": "0.x || 1.x",
+ "node-sass": "^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0",
+ "sass": "^1.3.0",
+ "sass-embedded": "*",
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/core": {
+ "optional": true
+ },
+ "node-sass": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "webpack": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/sass/node_modules/chokidar": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.1.tgz",
+ "integrity": "sha512-n8enUVCED/KVRQlab1hr3MVpcVMvxtZjmEa956u+4YijlmQED223XMSYj2tLuKvr4jcCTzNNMpQDUer72MMmzA==",
+ "dev": true,
+ "dependencies": {
+ "readdirp": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/sass/node_modules/readdirp": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.0.2.tgz",
+ "integrity": "sha512-yDMz9g+VaZkqBYS/ozoBJwaBhTbZo3UNYQHNRw1D3UFQB8oHB4uS/tAODO+ZLjGWmUbKnIlOWO+aaIiAxrUWHA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 14.16.0"
+ },
+ "funding": {
+ "type": "individual",
+ "url": "https://paulmillr.com/funding/"
+ }
+ },
+ "node_modules/sax": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.4.1.tgz",
+ "integrity": "sha512-+aWOz7yVScEGoKNd4PA10LZ8sk0A/z5+nXQG5giUO5rprX9jgYsTdov9qCchZiPIZezbZH+jRut8nPodFAX4Jg==",
+ "dev": true
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/schema-utils": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.2.0.tgz",
+ "integrity": "sha512-L0jRsrPpjdckP3oPug3/VxNKt2trR8TcabrM6FOAAlvC/9Phcmm+cuAgTlxBqdBR1WJx7Naj9WHw+aOmheSVbw==",
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/select-hose": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
+ "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
+ "dev": true
+ },
+ "node_modules/selfsigned": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-5.5.0.tgz",
+ "integrity": "sha512-ftnu3TW4+3eBfLRFnDEkzGxSF/10BJBkaLJuBHZX0kiPS7bRdlpZGu6YGt4KngMkdTwJE6MbjavFpqHvqVt+Ew==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@peculiar/x509": "^1.14.2",
+ "pkijs": "^3.3.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/send": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
+ "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.1",
+ "mime": "1.6.0",
+ "ms": "2.1.3",
+ "on-finished": "~2.4.1",
+ "range-parser": "~1.2.1",
+ "statuses": "~2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/send/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/send/node_modules/debug/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/serialize-javascript": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
+ "dependencies": {
+ "randombytes": "^2.1.0"
+ }
+ },
+ "node_modules/serve-index": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
+ "integrity": "sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
+ "dev": true,
+ "dependencies": {
+ "accepts": "~1.3.4",
+ "batch": "0.6.1",
+ "debug": "2.6.9",
+ "escape-html": "~1.0.3",
+ "http-errors": "~1.6.2",
+ "mime-types": "~2.1.17",
+ "parseurl": "~1.3.2"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/serve-index/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "dev": true,
+ "dependencies": {
+ "ms": "2.0.0"
+ }
+ },
+ "node_modules/serve-index/node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-index/node_modules/http-errors": {
+ "version": "1.6.3",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
+ "integrity": "sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
+ "dev": true,
+ "dependencies": {
+ "depd": "~1.1.2",
+ "inherits": "2.0.3",
+ "setprototypeof": "1.1.0",
+ "statuses": ">= 1.4.0 < 2"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-index/node_modules/inherits": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
+ "integrity": "sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
+ "dev": true
+ },
+ "node_modules/serve-index/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true
+ },
+ "node_modules/serve-index/node_modules/setprototypeof": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
+ "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
+ "dev": true
+ },
+ "node_modules/serve-index/node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/serve-static": {
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
+ "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "parseurl": "~1.3.3",
+ "send": "~0.19.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-proto": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/set-proto/-/set-proto-1.0.0.tgz",
+ "integrity": "sha512-RJRdvCo6IAnPdsvP/7m6bsQqNnn1FCBX5ZNtFL98MmFF/4xAIJTIg1YbHW5DC2W5SKZanrC6i4HsJqlajw/dZw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "dunder-proto": "^1.0.1",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/setprototypeof": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
+ "dev": true,
+ "dependencies": {
+ "kind-of": "^6.0.2"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shallowequal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/sharp": {
+ "version": "0.33.5",
+ "resolved": "https://registry.npmjs.org/sharp/-/sharp-0.33.5.tgz",
+ "integrity": "sha512-haPVm1EkS9pgvHrQ/F3Xy+hgcuMV0Wm9vfIBSiwZ05k+xgb0PkBQpGsAA/oWdDobNaZTH5ppvHtzCFbnSEwHVw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "dependencies": {
+ "color": "^4.2.3",
+ "detect-libc": "^2.0.3",
+ "semver": "^7.6.3"
+ },
+ "engines": {
+ "node": "^18.17.0 || ^20.3.0 || >=21.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/libvips"
+ },
+ "optionalDependencies": {
+ "@img/sharp-darwin-arm64": "0.33.5",
+ "@img/sharp-darwin-x64": "0.33.5",
+ "@img/sharp-libvips-darwin-arm64": "1.0.4",
+ "@img/sharp-libvips-darwin-x64": "1.0.4",
+ "@img/sharp-libvips-linux-arm": "1.0.5",
+ "@img/sharp-libvips-linux-arm64": "1.0.4",
+ "@img/sharp-libvips-linux-s390x": "1.0.4",
+ "@img/sharp-libvips-linux-x64": "1.0.4",
+ "@img/sharp-libvips-linuxmusl-arm64": "1.0.4",
+ "@img/sharp-libvips-linuxmusl-x64": "1.0.4",
+ "@img/sharp-linux-arm": "0.33.5",
+ "@img/sharp-linux-arm64": "0.33.5",
+ "@img/sharp-linux-s390x": "0.33.5",
+ "@img/sharp-linux-x64": "0.33.5",
+ "@img/sharp-linuxmusl-arm64": "0.33.5",
+ "@img/sharp-linuxmusl-x64": "0.33.5",
+ "@img/sharp-wasm32": "0.33.5",
+ "@img/sharp-win32-ia32": "0.33.5",
+ "@img/sharp-win32-x64": "0.33.5"
+ }
+ },
+ "node_modules/sharp/node_modules/detect-libc": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.0.3.tgz",
+ "integrity": "sha512-bwy0MGW55bG41VqxxypOsdSdGqLwXPI/focwgTYCFMbdUiBAxLg9CFzG08sz2aqzknwiX7Hkl0bQENjg8iLByw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/sharp/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dev": true,
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shell-quote": {
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.1.tgz",
+ "integrity": "sha512-6j1W9l1iAs/4xYBI1SYOVZyFcCis9b4KCLQ8fgAGG07QvzaRLVVRQvAy85yNmmZSjYjg4MWh4gNvlPujU/5LpA==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/should": {
+ "version": "13.2.3",
+ "resolved": "https://registry.npmjs.org/should/-/should-13.2.3.tgz",
+ "integrity": "sha512-ggLesLtu2xp+ZxI+ysJTmNjh2U0TsC+rQ/pfED9bUZZ4DKefP27D+7YJVVTvKsmjLpIi9jAa7itwDGkDDmt1GQ==",
+ "dev": true,
+ "dependencies": {
+ "should-equal": "^2.0.0",
+ "should-format": "^3.0.3",
+ "should-type": "^1.4.0",
+ "should-type-adaptors": "^1.0.1",
+ "should-util": "^1.0.0"
+ }
+ },
+ "node_modules/should-equal": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/should-equal/-/should-equal-2.0.0.tgz",
+ "integrity": "sha512-ZP36TMrK9euEuWQYBig9W55WPC7uo37qzAEmbjHz4gfyuXrEUgF8cUvQVO+w+d3OMfPvSRQJ22lSm8MQJ43LTA==",
+ "dev": true,
+ "dependencies": {
+ "should-type": "^1.4.0"
+ }
+ },
+ "node_modules/should-format": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/should-format/-/should-format-3.0.3.tgz",
+ "integrity": "sha512-hZ58adtulAk0gKtua7QxevgUaXTTXxIi8t41L3zo9AHvjXO1/7sdLECuHeIN2SRtYXpNkmhoUP2pdeWgricQ+Q==",
+ "dev": true,
+ "dependencies": {
+ "should-type": "^1.3.0",
+ "should-type-adaptors": "^1.0.1"
+ }
+ },
+ "node_modules/should-type": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/should-type/-/should-type-1.4.0.tgz",
+ "integrity": "sha512-MdAsTu3n25yDbIe1NeN69G4n6mUnJGtSJHygX3+oN0ZbO3DTiATnf7XnYJdGT42JCXurTb1JI0qOBR65shvhPQ==",
+ "dev": true
+ },
+ "node_modules/should-type-adaptors": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/should-type-adaptors/-/should-type-adaptors-1.1.0.tgz",
+ "integrity": "sha512-JA4hdoLnN+kebEp2Vs8eBe9g7uy0zbRo+RMcU0EsNy+R+k049Ki+N5tT5Jagst2g7EAja+euFuoXFCa8vIklfA==",
+ "dev": true,
+ "dependencies": {
+ "should-type": "^1.3.0",
+ "should-util": "^1.0.0"
+ }
+ },
+ "node_modules/should-util": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/should-util/-/should-util-1.0.1.tgz",
+ "integrity": "sha512-oXF8tfxx5cDk8r2kYqlkUJzZpDBqVY/II2WhvU0n9Y3XYvAYRmeaf1PvvIvTgPnv4KJ+ES5M0PyDq5Jp+Ygy2g==",
+ "dev": true
+ },
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-list": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz",
+ "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
+ "dev": true
+ },
+ "node_modules/simple-swizzle": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
+ "integrity": "sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "dev": true,
+ "dependencies": {
+ "is-arrayish": "^0.3.1"
+ }
+ },
+ "node_modules/simple-swizzle/node_modules/is-arrayish": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
+ "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
+ "dev": true
+ },
+ "node_modules/sisteransi": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/sisteransi/-/sisteransi-1.0.5.tgz",
+ "integrity": "sha512-bLGGlR1QxBcynn2d5YmDX4MGjlZvy2MRBDRNHLJ8VI6l6+9FUiyTFNJ0IveOSP0bcXgVDPRcfGqA0pjaqUpfVg==",
+ "dev": true
+ },
+ "node_modules/slash": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
+ "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/slice-ansi": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz",
+ "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^6.0.0",
+ "is-fullwidth-code-point": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/slice-ansi?sponsor=1"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz",
+ "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/sockjs": {
+ "version": "0.3.24",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
+ "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
+ "dev": true,
+ "dependencies": {
+ "faye-websocket": "^0.11.3",
+ "uuid": "^8.3.2",
+ "websocket-driver": "^0.7.4"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.4.tgz",
+ "integrity": "sha512-l3BikUxvPOcn5E74dZiq5BGsTb5yEwhaTSzccU6t4sDOH8NWJCstKO5QT2CvtFoK6F0saL7p9xHAqHOlCPJygA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-support": {
+ "version": "0.5.21",
+ "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
+ "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
+ "dependencies": {
+ "buffer-from": "^1.0.0",
+ "source-map": "^0.6.0"
+ }
+ },
+ "node_modules/source-map-support/node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/spdy": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
+ "integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.0",
+ "handle-thing": "^2.0.0",
+ "http-deceiver": "^1.2.7",
+ "select-hose": "^2.0.0",
+ "spdy-transport": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/spdy-transport": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
+ "integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.1.0",
+ "detect-node": "^2.0.4",
+ "hpack.js": "^2.1.6",
+ "obuf": "^1.1.2",
+ "readable-stream": "^3.0.6",
+ "wbuf": "^1.7.3"
+ }
+ },
+ "node_modules/sprintf-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
+ "integrity": "sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/stable": {
+ "version": "0.1.8",
+ "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
+ "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
+ "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility"
+ },
+ "node_modules/stack-utils": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/stack-utils/-/stack-utils-2.0.6.tgz",
+ "integrity": "sha512-XlkWvfIm6RmsWtNJx+uqtKLS8eqFbxUg0ZzLXqY0caEy9l7hruX8IpiDnjsLavoBgqCCR71TqWO8MaXYheJ3RQ==",
+ "dev": true,
+ "dependencies": {
+ "escape-string-regexp": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/stack-utils/node_modules/escape-string-regexp": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-2.0.0.tgz",
+ "integrity": "sha512-UpzcLCXolUWcNu5HtVMHYdXJjArjsF9C0aNnquZYY4uW/Vu0miy5YoWvbV345HauVvcAUnpRuhMMcqTcGOY2+w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/stackframe": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+ "dev": true
+ },
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/stop-iteration-iterator": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/stop-iteration-iterator/-/stop-iteration-iterator-1.1.0.tgz",
+ "integrity": "sha512-eLoXW/DHyl62zxY4SCaIgnRhuMr6ri4juEYARS8E6sCEqzKpOiE521Ucofdx+KnDZl5xmvGYaaKCk5FEOxJCoQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "internal-slot": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/string_decoder": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "dependencies": {
+ "safe-buffer": "~5.2.0"
+ }
+ },
+ "node_modules/string-argv": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/string-argv/-/string-argv-0.3.2.tgz",
+ "integrity": "sha512-aqD2Q0144Z+/RqG52NeHEkZauTAUWJO8c6yTftGJKO3Tja5tUgIfmIl6kExvhtxSDP7fXB6DvzkfMpCd/F3G+Q==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6.19"
+ }
+ },
+ "node_modules/string-length": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/string-length/-/string-length-4.0.2.tgz",
+ "integrity": "sha512-+l6rNN5fYHNhZZy41RXsYptCjA2Igmq4EG7kZAYFQI1E1VTXarr6ZPXBg6eq7Y6eK4FEhY6AJlyuFIb/v/S0VQ==",
+ "dev": true,
+ "dependencies": {
+ "char-regex": "^1.0.2",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string.prototype.matchall": {
+ "version": "4.0.12",
+ "resolved": "https://registry.npmjs.org/string.prototype.matchall/-/string.prototype.matchall-4.0.12.tgz",
+ "integrity": "sha512-6CC9uyBL+/48dYizRf7H7VAYCMCNTBeM78x/VTUe9bFEaxBepPJDa1Ow99LqI/1yF7kuy7Q3cQsYMrcjGUcskA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.6",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.6",
+ "gopd": "^1.2.0",
+ "has-symbols": "^1.1.0",
+ "internal-slot": "^1.1.0",
+ "regexp.prototype.flags": "^1.5.3",
+ "set-function-name": "^2.0.2",
+ "side-channel": "^1.1.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.repeat": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/string.prototype.repeat/-/string.prototype.repeat-1.0.0.tgz",
+ "integrity": "sha512-0u/TldDbKD8bFCQ/4f5+mNRrXwZ8hg2w7ZR8wa16e8z9XpePWl3eGEcUD0OXpEH/VJH/2G3gjUtR3ZOiBe2S/w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "define-properties": "^1.1.3",
+ "es-abstract": "^1.17.5"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.10",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.10.tgz",
+ "integrity": "sha512-Rs66F0P/1kedk5lyYyH9uBzuiI/kNRmwJAR9quK6VOtIpZ2G+hMZd+HQbbv25MgCA6gEffoMZYxlTod4WcdrKA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-data-property": "^1.1.4",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.5",
+ "es-object-atoms": "^1.0.0",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.9.tgz",
+ "integrity": "sha512-G7Ok5C6E/j4SGfyLCloXTrngQIQU3PWtXGst3yM7Bea9FRURf1S42ZHlZZtsNque2FN2PoUhfZXYLNWwEr4dLQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.2",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-4.0.0.tgz",
+ "integrity": "sha512-3xurFv5tEgii33Zi8Jtp55wEIILR9eh34FAW00PZf+JnSsTmV/ioewSgQl97JHvgjoRGwPShsWm+IdrxB35d0w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-final-newline": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
+ "integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/strip-indent": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-3.0.0.tgz",
+ "integrity": "sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==",
+ "dev": true,
+ "dependencies": {
+ "min-indent": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/style-loader": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz",
+ "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.27.0"
+ }
+ },
+ "node_modules/styled-components": {
+ "version": "6.1.13",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.13.tgz",
+ "integrity": "sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==",
+ "dev": true,
+ "peer": true,
+ "dependencies": {
+ "@emotion/is-prop-valid": "1.2.2",
+ "@emotion/unitless": "0.8.1",
+ "@types/stylis": "4.2.5",
+ "css-to-react-native": "3.2.0",
+ "csstype": "3.1.3",
+ "postcss": "8.4.38",
+ "shallowequal": "1.1.0",
+ "stylis": "4.3.2",
+ "tslib": "2.6.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/styled-components"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0",
+ "react-dom": ">= 16.8.0"
+ }
+ },
+ "node_modules/styled-components/node_modules/postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "peer": true,
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/styled-components/node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/stylehacks": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz",
+ "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==",
+ "dependencies": {
+ "browserslist": "^4.21.4",
+ "postcss-selector-parser": "^6.0.4"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
+ }
+ },
+ "node_modules/stylis": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
+ "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg==",
+ "dev": true,
+ "peer": true
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/svg-parser": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/svg-parser/-/svg-parser-2.0.4.tgz",
+ "integrity": "sha512-e4hG1hRwoOdRb37cIMSgzNsxyzKfayW6VOflrwvR+/bzrkyxY/31WkbgnQpgtrNp1SdpJvpUAGTa/ZoiPNDuRQ==",
+ "dev": true
+ },
+ "node_modules/svgo": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz",
+ "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==",
+ "dependencies": {
+ "@trysound/sax": "0.2.0",
+ "commander": "^7.2.0",
+ "css-select": "^4.1.3",
+ "css-tree": "^1.1.3",
+ "csso": "^4.2.0",
+ "picocolors": "^1.0.0",
+ "stable": "^0.1.8"
+ },
+ "bin": {
+ "svgo": "bin/svgo"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/svgo/node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
+ "engines": {
+ "node": ">= 10"
+ }
+ },
+ "node_modules/svgo/node_modules/css-select": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
+ "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
+ "dependencies": {
+ "boolbase": "^1.0.0",
+ "css-what": "^6.0.1",
+ "domhandler": "^4.3.1",
+ "domutils": "^2.8.0",
+ "nth-check": "^2.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/fb55"
+ }
+ },
+ "node_modules/svgo/node_modules/dom-serializer": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
+ "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
+ "dependencies": {
+ "domelementtype": "^2.0.1",
+ "domhandler": "^4.2.0",
+ "entities": "^2.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
+ }
+ },
+ "node_modules/svgo/node_modules/domhandler": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
+ "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
+ "dependencies": {
+ "domelementtype": "^2.2.0"
+ },
+ "engines": {
+ "node": ">= 4"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domhandler?sponsor=1"
+ }
+ },
+ "node_modules/svgo/node_modules/domutils": {
+ "version": "2.8.0",
+ "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
+ "integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
+ "dependencies": {
+ "dom-serializer": "^1.0.1",
+ "domelementtype": "^2.2.0",
+ "domhandler": "^4.2.0"
+ },
+ "funding": {
+ "url": "https://github.com/fb55/domutils?sponsor=1"
+ }
+ },
+ "node_modules/svgo/node_modules/entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
+ "node_modules/swagger2openapi": {
+ "version": "7.0.8",
+ "resolved": "https://registry.npmjs.org/swagger2openapi/-/swagger2openapi-7.0.8.tgz",
+ "integrity": "sha512-upi/0ZGkYgEcLeGieoz8gT74oWHA0E7JivX7aN9mAf+Tc7BQoRBvnIGHoPDw+f9TXTW4s6kGYCZJtauP6OYp7g==",
+ "dev": true,
+ "dependencies": {
+ "call-me-maybe": "^1.0.1",
+ "node-fetch": "^2.6.1",
+ "node-fetch-h2": "^2.3.0",
+ "node-readfiles": "^0.2.0",
+ "oas-kit-common": "^1.0.8",
+ "oas-resolver": "^2.5.6",
+ "oas-schema-walker": "^1.1.5",
+ "oas-validator": "^5.0.8",
+ "reftools": "^1.1.9",
+ "yaml": "^1.10.0",
+ "yargs": "^17.0.1"
+ },
+ "bin": {
+ "boast": "boast.js",
+ "oas-validate": "oas-validate.js",
+ "swagger2openapi": "swagger2openapi.js"
+ },
+ "funding": {
+ "url": "https://github.com/Mermade/oas-kit?sponsor=1"
+ }
+ },
+ "node_modules/synckit": {
+ "version": "0.11.8",
+ "resolved": "https://registry.npmjs.org/synckit/-/synckit-0.11.8.tgz",
+ "integrity": "sha512-+XZ+r1XGIJGeQk3VvXhT6xx/VpbHsRzsTkGgF6E5RX9TTXD0118l87puaEBZ566FhqblC6U0d4XnubznJDm30A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@pkgr/core": "^0.2.4"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/synckit"
+ }
+ },
+ "node_modules/tapable": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
+ "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/terser": {
+ "version": "5.36.0",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.36.0.tgz",
+ "integrity": "sha512-IYV9eNMuFAV4THUspIRXkLakHnV6XO7FEdtKjf/mDyrnqUg9LnlOn6/RwRvM9SZjR4GUq8Nk8zj67FzVARr74w==",
+ "dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.8.2",
+ "commander": "^2.20.0",
+ "source-map-support": "~0.5.20"
+ },
+ "bin": {
+ "terser": "bin/terser"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/terser-webpack-plugin": {
+ "version": "5.3.10",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz",
+ "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==",
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.20",
+ "jest-worker": "^27.4.5",
+ "schema-utils": "^3.1.1",
+ "serialize-javascript": "^6.0.1",
+ "terser": "^5.26.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.1.0"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "uglify-js": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/terser-webpack-plugin/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "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"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/terser-webpack-plugin/node_modules/jest-worker": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "node_modules/terser-webpack-plugin/node_modules/schema-utils": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "dependencies": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/terser-webpack-plugin/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/terser/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ=="
+ },
+ "node_modules/test-exclude": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
+ "integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
+ "dependencies": {
+ "@istanbuljs/schema": "^0.1.2",
+ "glob": "^7.1.4",
+ "minimatch": "^3.0.4"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/thingies": {
+ "version": "1.21.0",
+ "resolved": "https://registry.npmjs.org/thingies/-/thingies-1.21.0.tgz",
+ "integrity": "sha512-hsqsJsFMsV+aD4s3CWKk85ep/3I9XzYV/IXaSouJMYIoDlgyi11cBhsqYe9/geRfB0YIikBQg6raRaM+nIMP9g==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.18"
+ },
+ "peerDependencies": {
+ "tslib": "^2"
+ }
+ },
+ "node_modules/thunky": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
+ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
+ "dev": true
+ },
+ "node_modules/tmpl": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
+ "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw==",
+ "dev": true
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toidentifier": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6"
+ }
+ },
+ "node_modules/toposort": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
+ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw=="
+ },
+ "node_modules/tree-dump": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/tree-dump/-/tree-dump-1.0.2.tgz",
+ "integrity": "sha512-dpev9ABuLWdEubk+cIaI9cHwRNNDjkBBLXTwI4UCUFdQ5xXKqNXoK4FEciw/vxf+NQ7Cb7sGUyeUtORvHIdRXQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/streamich"
+ },
+ "peerDependencies": {
+ "tslib": "2"
+ }
+ },
+ "node_modules/ts-api-utils": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-2.1.0.tgz",
+ "integrity": "sha512-CUgTZL1irw8u29bzrOD/nH85jqyc74D6SshFgujOIA7osm2Rz7dYH77agkx7H4FBNxDq7Cjf+IjaX/8zwFW+ZQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.12"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.8.4"
+ }
+ },
+ "node_modules/ts-jest": {
+ "version": "29.2.5",
+ "resolved": "https://registry.npmjs.org/ts-jest/-/ts-jest-29.2.5.tgz",
+ "integrity": "sha512-KD8zB2aAZrcKIdGk4OwpJggeLcH1FgrICqDSROWqlnJXGCXK4Mn6FcdK2B6670Xr73lHMG1kHw8R87A0ecZ+vA==",
+ "dev": true,
+ "dependencies": {
+ "bs-logger": "^0.2.6",
+ "ejs": "^3.1.10",
+ "fast-json-stable-stringify": "^2.1.0",
+ "jest-util": "^29.0.0",
+ "json5": "^2.2.3",
+ "lodash.memoize": "^4.1.2",
+ "make-error": "^1.3.6",
+ "semver": "^7.6.3",
+ "yargs-parser": "^21.1.1"
+ },
+ "bin": {
+ "ts-jest": "cli.js"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || ^18.0.0 || >=20.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": ">=7.0.0-beta.0 <8",
+ "@jest/transform": "^29.0.0",
+ "@jest/types": "^29.0.0",
+ "babel-jest": "^29.0.0",
+ "jest": "^29.0.0",
+ "typescript": ">=4.3 <6"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ },
+ "@jest/transform": {
+ "optional": true
+ },
+ "@jest/types": {
+ "optional": true
+ },
+ "babel-jest": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/ts-jest/node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/ts-node": {
+ "version": "10.9.2",
+ "resolved": "https://registry.npmjs.org/ts-node/-/ts-node-10.9.2.tgz",
+ "integrity": "sha512-f0FFpIdcHgn8zcPSbf1dRevwt047YMnaiJM3u2w2RewrB+fob/zePZcrOyQoLMMO7aBIddLcQIEK5dYjkLnGrQ==",
+ "dev": true,
+ "dependencies": {
+ "@cspotcode/source-map-support": "^0.8.0",
+ "@tsconfig/node10": "^1.0.7",
+ "@tsconfig/node12": "^1.0.7",
+ "@tsconfig/node14": "^1.0.0",
+ "@tsconfig/node16": "^1.0.2",
+ "acorn": "^8.4.1",
+ "acorn-walk": "^8.1.1",
+ "arg": "^4.1.0",
+ "create-require": "^1.1.0",
+ "diff": "^4.0.1",
+ "make-error": "^1.1.1",
+ "v8-compile-cache-lib": "^3.0.1",
+ "yn": "3.1.1"
+ },
+ "bin": {
+ "ts-node": "dist/bin.js",
+ "ts-node-cwd": "dist/bin-cwd.js",
+ "ts-node-esm": "dist/bin-esm.js",
+ "ts-node-script": "dist/bin-script.js",
+ "ts-node-transpile-only": "dist/bin-transpile.js",
+ "ts-script": "dist/bin-script-deprecated.js"
+ },
+ "peerDependencies": {
+ "@swc/core": ">=1.2.50",
+ "@swc/wasm": ">=1.2.50",
+ "@types/node": "*",
+ "typescript": ">=2.7"
+ },
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "@swc/wasm": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
+ },
+ "node_modules/tsyringe": {
+ "version": "4.10.0",
+ "resolved": "https://registry.npmjs.org/tsyringe/-/tsyringe-4.10.0.tgz",
+ "integrity": "sha512-axr3IdNuVIxnaK5XGEUFTu3YmAQ6lllgrvqfEoR16g/HGnYY/6We4oWENtAnzK6/LpJ2ur9PAb80RBt7/U4ugw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^1.9.3"
+ },
+ "engines": {
+ "node": ">= 6.0.0"
+ }
+ },
+ "node_modules/tsyringe/node_modules/tslib": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
+ "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
+ "dev": true,
+ "license": "0BSD"
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-detect": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/type-detect/-/type-detect-4.0.8.tgz",
+ "integrity": "sha512-0fr/mIH1dlO+x7TlcMy+bIDqKPsw/70tVyeHW787goQjhmqaZe10uwLujubK9q9Lg6Fiho1KUKDYz0Z7k7g5/g==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "0.21.3",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
+ "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/type-is": {
+ "version": "1.6.18",
+ "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
+ "integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "media-typer": "0.3.0",
+ "mime-types": "~2.1.24"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nAYYwfY3qnzX30IkA6AQZjVbtK6duGontcQm1WSG1MD94YLqK0515GNApXkoxKOWMusVssAHWLh9SeaoefYFGw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.3.tgz",
+ "integrity": "sha512-BaXgOuIxz8n8pIq3e7Atg/7s+DpiYrxn4vdot3w9KbnBhcRQq6o3xemQdIfynqSeXeDrF32x+WvfzmOjPiY9lg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.4.tgz",
+ "integrity": "sha512-bTlAFB/FBYMcuX81gbL4OcpH5PmlFHqlCCpAl8AlEzMz5k53oNDvN8p1PNOWLEmI2x4orp3raOFB51tv9X+MFQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "for-each": "^0.3.3",
+ "gopd": "^1.2.0",
+ "has-proto": "^1.2.0",
+ "is-typed-array": "^1.1.15",
+ "reflect.getprototypeof": "^1.0.9"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.7.tgz",
+ "integrity": "sha512-3KS2b+kL7fsuk/eJZ7EQdnEmQoaho/r6KUef7hxvltNA5DR8NAUM+8wJMbJyZ4G9/7i3v5zPBIMN5aybAh2/Jg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0",
+ "reflect.getprototypeof": "^1.0.6"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.7.2",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.7.2.tgz",
+ "integrity": "sha512-i5t66RHxDvVN40HfDd1PsEThGNnlMCMT3jMUuoh9/0TaqWevNontacunWyN02LA9/fIbEWlcHZcgTKb9QoaLfg==",
+ "devOptional": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.1.0.tgz",
+ "integrity": "sha512-nWJ91DjeOkej/TA8pXQ3myruKpKEYgqvpw9lz4OPHj/NWFNluYrjbz9j01CJ8yKQd2g4jFoOkINCTW2I5LEEyw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.3",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.1.0",
+ "which-boxed-primitive": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/undici": {
+ "version": "6.23.0",
+ "resolved": "https://registry.npmjs.org/undici/-/undici-6.23.0.tgz",
+ "integrity": "sha512-VfQPToRA5FZs/qJxLIinmU59u0r7LXqoJkCzinq3ckNJp3vKEh7jTWN589YQ5+aoAC/TGRLyJLCPKcLQbM8r9g==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=18.17"
+ }
+ },
+ "node_modules/undici-types": {
+ "version": "6.20.0",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-6.20.0.tgz",
+ "integrity": "sha512-Ny6QZ2Nju20vw1SRHe3d9jVu6gJ+4e3+MMpqu7pqE5HT6WsTSlce++GQmK5UXS8mzV8DSYHrQH+Xrf2jVcuKNg=="
+ },
+ "node_modules/unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
+ "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-ecmascript": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
+ "dev": true,
+ "dependencies": {
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-match-property-value-ecmascript": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.0.tgz",
+ "integrity": "sha512-4IehN3V/+kkr5YeSSDDQG8QLqO26XpL2XP3GQtqwlT/QYSECAwFztxVHjlbh0+gjJ3XmNLS0zDsbgs9jWKExLg==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/unicode-property-aliases-ecmascript": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.1.0.tgz",
+ "integrity": "sha512-6t3foTQI9qne+OZoVQB/8x8rk2k1eVy1gRXhV3oFQ5T6R1dqQ1xtin3XqSlx3+ATBkliTaR/hHyJBm+LVPNM8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
+ "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.2.tgz",
+ "integrity": "sha512-PElTlVMwpblvbNqQ82d2n6RjStvdSoNe9FG28kNfz3WiXilJm4DdNkEzRhCZuIDwY8U08WVihhGR5iRqAwfDiw==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
+ },
+ "node_modules/utila": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
+ "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==",
+ "dev": true
+ },
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4.0"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "dev": true,
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/v8-compile-cache-lib": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/v8-compile-cache-lib/-/v8-compile-cache-lib-3.0.1.tgz",
+ "integrity": "sha512-wa7YjyUGfNZngI/vtK0UHAN+lgDCxBPCylVXGp0zu59Fz5aiGtNXaq3DhIov063MorB+VfufLh3JlF2KdTK3xg==",
+ "dev": true
+ },
+ "node_modules/v8-to-istanbul": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/v8-to-istanbul/-/v8-to-istanbul-9.3.0.tgz",
+ "integrity": "sha512-kiGUalWN+rgBJ/1OHZsBtU4rXZOfj/7rKQxULKlIzwzQSvMJUUNgPwJEEh7gU6xEVxC0ahoOBvN2YI8GH6FNgA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/trace-mapping": "^0.3.12",
+ "@types/istanbul-lib-coverage": "^2.0.1",
+ "convert-source-map": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.12.0"
+ }
+ },
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/void-elements": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/void-elements/-/void-elements-3.1.0.tgz",
+ "integrity": "sha512-Dhxzh5HZuiHQhbvTW9AMetFfBHDMYpo23Uo9btPXgdYP+3T5S+p+jgNy7spra+veYhBP2dCSgxR/i2Y02h5/6w==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/walker": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
+ "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
+ "dev": true,
+ "dependencies": {
+ "makeerror": "1.0.12"
+ }
+ },
+ "node_modules/watchpack": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.2.tgz",
+ "integrity": "sha512-TnbFSbcOCcDgjZ4piURLCbJ3nJhznVh9kw6F6iokjiFPl8ONxe9A6nMDVXDiNbrSfLILs6vB07F7wLBrwPYzJw==",
+ "dependencies": {
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.1.2"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
+ "dev": true,
+ "dependencies": {
+ "minimalistic-assert": "^1.0.0"
+ }
+ },
+ "node_modules/web-streams-polyfill": {
+ "version": "4.0.0-beta.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.3.tgz",
+ "integrity": "sha512-QW95TCTaHmsYfHDybGMwO5IJIM93I/6vTRk+daHTWFPhwh+C8Cg7j7XyKrwrj8Ib6vYXe0ocYNrmzY4xAAN6ug==",
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ=="
+ },
+ "node_modules/webpack": {
+ "version": "5.96.1",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz",
+ "integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==",
+ "dependencies": {
+ "@types/eslint-scope": "^3.7.7",
+ "@types/estree": "^1.0.6",
+ "@webassemblyjs/ast": "^1.12.1",
+ "@webassemblyjs/wasm-edit": "^1.12.1",
+ "@webassemblyjs/wasm-parser": "^1.12.1",
+ "acorn": "^8.14.0",
+ "browserslist": "^4.24.0",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.17.1",
+ "es-module-lexer": "^1.2.1",
+ "eslint-scope": "5.1.1",
+ "events": "^3.2.0",
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.2.11",
+ "json-parse-even-better-errors": "^2.3.1",
+ "loader-runner": "^4.2.0",
+ "mime-types": "^2.1.27",
+ "neo-async": "^2.6.2",
+ "schema-utils": "^3.2.0",
+ "tapable": "^2.1.1",
+ "terser-webpack-plugin": "^5.3.10",
+ "watchpack": "^2.4.1",
+ "webpack-sources": "^3.2.3"
+ },
+ "bin": {
+ "webpack": "bin/webpack.js"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependenciesMeta": {
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/webpack-cli/-/webpack-cli-5.1.4.tgz",
+ "integrity": "sha512-pIDJHIEI9LR0yxHXQ+Qh95k2EvXpWzZ5l+d+jIo+RdSm9MiHfzazIxwwni/p7+x4eJZuvG1AJwgC4TNQ7NRgsg==",
+ "dev": true,
+ "dependencies": {
+ "@discoveryjs/json-ext": "^0.5.0",
+ "@webpack-cli/configtest": "^2.1.1",
+ "@webpack-cli/info": "^2.0.2",
+ "@webpack-cli/serve": "^2.0.5",
+ "colorette": "^2.0.14",
+ "commander": "^10.0.1",
+ "cross-spawn": "^7.0.3",
+ "envinfo": "^7.7.3",
+ "fastest-levenshtein": "^1.0.12",
+ "import-local": "^3.0.2",
+ "interpret": "^3.1.1",
+ "rechoir": "^0.8.0",
+ "webpack-merge": "^5.7.3"
+ },
+ "bin": {
+ "webpack-cli": "bin/cli.js"
+ },
+ "engines": {
+ "node": ">=14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "5.x.x"
+ },
+ "peerDependenciesMeta": {
+ "@webpack-cli/generators": {
+ "optional": true
+ },
+ "webpack-bundle-analyzer": {
+ "optional": true
+ },
+ "webpack-dev-server": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-cli/node_modules/commander": {
+ "version": "10.0.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-10.0.1.tgz",
+ "integrity": "sha512-y4Mg2tXshplEbSGzx7amzPwKKOCGuoSRP/CjEdwwk0FOGlUbq6lKuoyDZTNZkmxHdJtp54hdfY/JUrdL7Xfdug==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/webpack-cli/node_modules/webpack-merge": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz",
+ "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==",
+ "dev": true,
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "flat": "^5.0.2",
+ "wildcard": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/webpack-dev-middleware": {
+ "version": "7.4.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-7.4.2.tgz",
+ "integrity": "sha512-xOO8n6eggxnwYpy1NlzUKpvrjfJTvae5/D6WOK0S2LSo7vjmo5gCM1DbLUmFqrMTJP+W/0YZNctm7jasWvLuBA==",
+ "dev": true,
+ "dependencies": {
+ "colorette": "^2.0.10",
+ "memfs": "^4.6.0",
+ "mime-types": "^2.1.31",
+ "on-finished": "^2.4.1",
+ "range-parser": "^1.2.1",
+ "schema-utils": "^4.0.0"
+ },
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "webpack": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-dev-middleware/node_modules/memfs": {
+ "version": "4.14.0",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-4.14.0.tgz",
+ "integrity": "sha512-JUeY0F/fQZgIod31Ja1eJgiSxLn7BfQlCnqhwXFBzFHEw63OdLK7VJUJ7bnzNsWgCyoUP5tEp1VRY8rDaYzqOA==",
+ "dev": true,
+ "dependencies": {
+ "@jsonjoy.com/json-pack": "^1.0.3",
+ "@jsonjoy.com/util": "^1.3.0",
+ "tree-dump": "^1.0.1",
+ "tslib": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/streamich"
+ }
+ },
+ "node_modules/webpack-dev-server": {
+ "version": "5.2.3",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-5.2.3.tgz",
+ "integrity": "sha512-9Gyu2F7+bg4Vv+pjbovuYDhHX+mqdqITykfzdM9UyKqKHlsE5aAjRhR+oOEfXW5vBeu8tarzlJFIZva4ZjAdrQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/bonjour": "^3.5.13",
+ "@types/connect-history-api-fallback": "^1.5.4",
+ "@types/express": "^4.17.25",
+ "@types/express-serve-static-core": "^4.17.21",
+ "@types/serve-index": "^1.9.4",
+ "@types/serve-static": "^1.15.5",
+ "@types/sockjs": "^0.3.36",
+ "@types/ws": "^8.5.10",
+ "ansi-html-community": "^0.0.8",
+ "bonjour-service": "^1.2.1",
+ "chokidar": "^3.6.0",
+ "colorette": "^2.0.10",
+ "compression": "^1.8.1",
+ "connect-history-api-fallback": "^2.0.0",
+ "express": "^4.22.1",
+ "graceful-fs": "^4.2.6",
+ "http-proxy-middleware": "^2.0.9",
+ "ipaddr.js": "^2.1.0",
+ "launch-editor": "^2.6.1",
+ "open": "^10.0.3",
+ "p-retry": "^6.2.0",
+ "schema-utils": "^4.2.0",
+ "selfsigned": "^5.5.0",
+ "serve-index": "^1.9.1",
+ "sockjs": "^0.3.24",
+ "spdy": "^4.0.2",
+ "webpack-dev-middleware": "^7.4.2",
+ "ws": "^8.18.0"
+ },
+ "bin": {
+ "webpack-dev-server": "bin/webpack-dev-server.js"
+ },
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "webpack": {
+ "optional": true
+ },
+ "webpack-cli": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/webpack-dev-server/node_modules/@types/express-serve-static-core": {
+ "version": "4.19.8",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz",
+ "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/webpack-dev-server/node_modules/define-lazy-prop": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz",
+ "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/webpack-dev-server/node_modules/is-wsl": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz",
+ "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==",
+ "dev": true,
+ "dependencies": {
+ "is-inside-container": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/webpack-dev-server/node_modules/open": {
+ "version": "10.1.0",
+ "resolved": "https://registry.npmjs.org/open/-/open-10.1.0.tgz",
+ "integrity": "sha512-mnkeQ1qP5Ue2wd+aivTD3NHd/lZ96Lu0jgf0pwktLPtx6cTZiH7tyeGRRHs0zX0rbrahXPnXlUnbeXyaBBuIaw==",
+ "dev": true,
+ "dependencies": {
+ "default-browser": "^5.2.1",
+ "define-lazy-prop": "^3.0.0",
+ "is-inside-container": "^1.0.0",
+ "is-wsl": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/webpack-merge": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-6.0.1.tgz",
+ "integrity": "sha512-hXXvrjtx2PLYx4qruKl+kyRSLc52V+cCvMxRjmKwoA+CBbbF5GfIBtR6kCvl0fYGqTUPKB+1ktVmTHqMOzgCBg==",
+ "dev": true,
+ "dependencies": {
+ "clone-deep": "^4.0.1",
+ "flat": "^5.0.2",
+ "wildcard": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=18.0.0"
+ }
+ },
+ "node_modules/webpack-nano": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/webpack-nano/-/webpack-nano-1.1.1.tgz",
+ "integrity": "sha512-3dypjHtWQylpgsYmaovsUgFmXmDBoArq8aNMvDjmhVRpaA8MQsYxMiXgsp09GYL3n5y+1PfscytrFW3IXknlIQ==",
+ "dev": true,
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "import-local": "^3.0.2",
+ "rechoir": "^0.7.0",
+ "yargs-parser": "^20.2.1"
+ },
+ "bin": {
+ "wp": "bin/wp.js"
+ },
+ "engines": {
+ "node": ">= 10.0.0"
+ },
+ "peerDependencies": {
+ "webpack": ">=4.20.2"
+ }
+ },
+ "node_modules/webpack-nano/node_modules/rechoir": {
+ "version": "0.7.1",
+ "resolved": "https://registry.npmjs.org/rechoir/-/rechoir-0.7.1.tgz",
+ "integrity": "sha512-/njmZ8s1wVeR6pjTZ+0nCnv8SpZNRMT2D1RLOJQESlYFDBvwpTA4KWJpZ+sBJ4+vhjILRcK7JIFdGCdxEAAitg==",
+ "dev": true,
+ "dependencies": {
+ "resolve": "^1.9.0"
+ },
+ "engines": {
+ "node": ">= 0.10"
+ }
+ },
+ "node_modules/webpack-nano/node_modules/yargs-parser": {
+ "version": "20.2.9",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
+ "integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/webpack-sources": {
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz",
+ "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==",
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/webpack/node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "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"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/webpack/node_modules/ajv-keywords": {
+ "version": "3.5.2",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
+ "integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
+ "peerDependencies": {
+ "ajv": "^6.9.1"
+ }
+ },
+ "node_modules/webpack/node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg=="
+ },
+ "node_modules/webpack/node_modules/schema-utils": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "dependencies": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
+ },
+ "node_modules/websocket-driver": {
+ "version": "0.7.4",
+ "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
+ "integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
+ "dev": true,
+ "dependencies": {
+ "http-parser-js": ">=0.5.1",
+ "safe-buffer": ">=5.1.0",
+ "websocket-extensions": ">=0.1.1"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/websocket-extensions": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
+ "integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/weekstart": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/weekstart/-/weekstart-1.1.0.tgz",
+ "integrity": "sha512-ZO3I7c7J9nwGN1PZKZeBYAsuwWEsCOZi5T68cQoVNYrzrpp5Br0Bgi0OF4l8kH/Ez7nKfxa5mSsXjsgris3+qg=="
+ },
+ "node_modules/whatwg-encoding": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/whatwg-encoding/-/whatwg-encoding-3.1.1.tgz",
+ "integrity": "sha512-6qN4hJdMwfYBtE3YBTTHhoeuUrDBPZmbQaxWAqSALV/MeEnR5z1xd8UKud2RAkFoPkmB+hli1TZSnyi84xz1vQ==",
+ "dev": true,
+ "dependencies": {
+ "iconv-lite": "0.6.3"
+ },
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-mimetype": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-mimetype/-/whatwg-mimetype-4.0.0.tgz",
+ "integrity": "sha512-QaKxh0eNIi2mE9p2vEdzfagOKHCcj1pJ56EEHGQOVxp8r9/iszLUUV7v89x9O1p/T+NlTM5W7jW6+cz4Fq1YVg==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dev": true,
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.1.1.tgz",
+ "integrity": "sha512-TbX3mj8n0odCBFVlY8AxkqcHASw3L60jIuF8jFP78az3C2YhmGvqbHBpAjTRH2/xqYunrJ9g1jSyjCjpoWzIAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-bigint": "^1.1.0",
+ "is-boolean-object": "^1.2.1",
+ "is-number-object": "^1.1.1",
+ "is-string": "^1.1.1",
+ "is-symbol": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-builtin-type": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/which-builtin-type/-/which-builtin-type-1.2.1.tgz",
+ "integrity": "sha512-6iBczoX+kDQ7a3+YJBnh3T+KZRxM/iYNPXicqk66/Qfm1b93iu+yOImkg0zHbj5LNOcNv1TEADiZ0xa34B4q6Q==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "call-bound": "^1.0.2",
+ "function.prototype.name": "^1.1.6",
+ "has-tostringtag": "^1.0.2",
+ "is-async-function": "^2.0.0",
+ "is-date-object": "^1.1.0",
+ "is-finalizationregistry": "^1.1.0",
+ "is-generator-function": "^1.0.10",
+ "is-regex": "^1.2.1",
+ "is-weakref": "^1.0.2",
+ "isarray": "^2.0.5",
+ "which-boxed-primitive": "^1.1.0",
+ "which-collection": "^1.0.2",
+ "which-typed-array": "^1.1.16"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-collection": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-collection/-/which-collection-1.0.2.tgz",
+ "integrity": "sha512-K4jVyjnBdgvc86Y6BkaLZEN933SwYOuBFkdmBu9ZfkcAbdVbpITnDmjvZ/aQjRXQrv5EPkTnD1s39GiiqbngCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "is-map": "^2.0.3",
+ "is-set": "^2.0.3",
+ "is-weakmap": "^2.0.2",
+ "is-weakset": "^2.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.20",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.20.tgz",
+ "integrity": "sha512-LYfpUkmqwl0h9A2HL09Mms427Q1RZWuOHsukfVcKRq9q95iQxdw0ix1JQrqbcDR9PH1QDwf5Qo8OZb5lksZ8Xg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.4",
+ "for-each": "^0.3.5",
+ "get-proto": "^1.0.1",
+ "gopd": "^1.2.0",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/wildcard": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
+ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
+ "dev": true
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wrap-ansi": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrappy": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "dev": true
+ },
+ "node_modules/write-file-atomic": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
+ "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
+ "dev": true,
+ "dependencies": {
+ "imurmurhash": "^0.1.4",
+ "signal-exit": "^3.0.7"
+ },
+ "engines": {
+ "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
+ }
+ },
+ "node_modules/ws": {
+ "version": "8.18.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.18.0.tgz",
+ "integrity": "sha512-8VbfWfHLbbwu3+N6OKsOMpBdT4kXPDDB9cJk2bJ6mh9ucxdlnNvH1e+roYkKmN9Nxw2yjz7VzeO9oOz2zJ04Pw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/xml2js": {
+ "version": "0.6.2",
+ "resolved": "https://registry.npmjs.org/xml2js/-/xml2js-0.6.2.tgz",
+ "integrity": "sha512-T4rieHaC1EXcES0Kxxj4JWgaUQHDk+qwHcYOCFHfiwKz7tOVPLq7Hjq9dM1WCMhylqMEfP7hMcOIChvotiZegA==",
+ "dev": true,
+ "dependencies": {
+ "sax": ">=0.6.0",
+ "xmlbuilder": "~11.0.0"
+ },
+ "engines": {
+ "node": ">=4.0.0"
+ }
+ },
+ "node_modules/xmlbuilder": {
+ "version": "11.0.1",
+ "resolved": "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-11.0.1.tgz",
+ "integrity": "sha512-fDlsI/kFEx7gLvbecc0/ohLG50fugQp8ryHzMTuW9vSa1GJ0XYWKnhsUx7oie3G98+r56aTQIUB4kht42R3JvA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/y18n": {
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/yargs": {
+ "version": "17.7.2",
+ "resolved": "https://registry.npmjs.org/yargs/-/yargs-17.7.2.tgz",
+ "integrity": "sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==",
+ "dev": true,
+ "dependencies": {
+ "cliui": "^8.0.1",
+ "escalade": "^3.1.1",
+ "get-caller-file": "^2.0.5",
+ "require-directory": "^2.1.1",
+ "string-width": "^4.2.3",
+ "y18n": "^5.0.5",
+ "yargs-parser": "^21.1.1"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yn": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yn/-/yn-3.1.1.tgz",
+ "integrity": "sha512-Ux4ygGWsu2c7isFWe8Yu1YluJmqVhxqK2cLXNQA5AcC3QfbGNpM7fu0Y8b/z16pXLnFxZYvWhd3fhBY9DLmC6Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/yup": {
+ "version": "0.32.11",
+ "resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
+ "integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
+ "dependencies": {
+ "@babel/runtime": "^7.15.4",
+ "@types/lodash": "^4.14.175",
+ "lodash": "^4.17.21",
+ "lodash-es": "^4.17.21",
+ "nanoclone": "^0.2.1",
+ "property-expr": "^2.0.4",
+ "toposort": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ }
+ }
+}
diff --git a/frontend/package.json b/frontend/package.json
new file mode 100644
index 0000000000..f4dfc7c09e
--- /dev/null
+++ b/frontend/package.json
@@ -0,0 +1,139 @@
+{
+ "name": "dstackai",
+ "version": "2.0.0",
+ "main": "src/index.ts",
+ "repository": "git@gitlab.com:dstackai/dstackai-website.git",
+ "author": "Oleg Vavilov",
+ "license": "Apache 2.0",
+ "private": true,
+ "scripts": {
+ "start": "cross-env NODE_ENV=development webpack serve --config webpack.config.js",
+ "start-sky": "cross-env NODE_ENV=development UI_VERSION=sky webpack serve --config webpack.config.js",
+ "build": "cross-env NODE_ENV=production webpack build --config webpack.config.js",
+ "build-sky": "cross-env NODE_ENV=production UI_VERSION=sky webpack build --config webpack.config.js",
+ "eslint": "eslint ./src --ext .js,.jsx,.ts,.tsx",
+ "eslint-fix": "eslint ./src --ext .js,.jsx,.ts,.tsx --fix",
+ "test": "jest",
+ "test:update-snapshots": "jest -u",
+ "generate-api": "npx @rtk-query/codegen-openapi openapi-config.ts",
+ "pre-commit": "lint-staged"
+ },
+ "devDependencies": {
+ "@babel/cli": "^7.25.9",
+ "@babel/core": "^7.26.0",
+ "@babel/plugin-proposal-class-properties": "^7.18.6",
+ "@babel/plugin-transform-runtime": "^7.25.9",
+ "@babel/preset-env": "^7.26.0",
+ "@babel/preset-react": "^7.25.9",
+ "@babel/preset-typescript": "^7.26.0",
+ "@babel/register": "^7.25.9",
+ "@cfaester/enzyme-adapter-react-18": "^0.8.0",
+ "@eslint/eslintrc": "^3.3.1",
+ "@eslint/js": "^9.28.0",
+ "@pmmmwh/react-refresh-webpack-plugin": "^0.5.15",
+ "@rtk-query/codegen-openapi": "^2.0.0",
+ "@svgr/webpack": "^6.5.1",
+ "@testing-library/jest-dom": "^6.6.3",
+ "@testing-library/react": "^16.0.1",
+ "@testing-library/user-event": "^14.5.2",
+ "@types/axios": "^0.14.0",
+ "@types/date-fns": "^2.6.0",
+ "@types/enzyme": "^3.10.18",
+ "@types/jest": "^29.5.14",
+ "@types/js-yaml": "^4.0.9",
+ "@types/lodash": "^4.17.13",
+ "@types/node": "^22.10.1",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@types/react-helmet": "^6.1.11",
+ "@types/react-redux": "^7.1.34",
+ "@types/react-router-dom": "^5.3.3",
+ "@types/react-test-renderer": "^18.3.0",
+ "@typescript-eslint/eslint-plugin": "^8.33.1",
+ "@typescript-eslint/parser": "^8.33.1",
+ "@webpack-cli/serve": "^2.0.5",
+ "babel-loader": "^9.2.1",
+ "babel-preset-minify": "^0.5.2",
+ "circular-dependency-plugin": "^5.2.2",
+ "copy-webpack-plugin": "^11.0.0",
+ "cross-env": "^7.0.3",
+ "css-loader": "^6.7.3",
+ "enzyme": "^3.11.0",
+ "eslint": "^9.39.2",
+ "eslint-config-prettier": "^10.1.5",
+ "eslint-plugin-i18n": "^2.4.0",
+ "eslint-plugin-prettier": "^5.4.1",
+ "eslint-plugin-react": "^7.37.5",
+ "eslint-plugin-simple-import-sort": "^12.1.1",
+ "favicons": "^7.2.0",
+ "favicons-webpack-plugin": "^6.0.1",
+ "file-loader": "^6.2.0",
+ "html-webpack-plugin": "^5.6.3",
+ "http-proxy-middleware": "^2.0.6",
+ "identity-obj-proxy": "^3.0.0",
+ "jest": "^29.7.0",
+ "jest-styled-components": "^7.2.0",
+ "lint-staged": "^16.1.2",
+ "loader-utils": "^3.3.1",
+ "mini-css-extract-plugin": "^2.9.2",
+ "npx": "^10.2.2",
+ "postcss": "^8.4.49",
+ "postcss-loader": "^7.0.2",
+ "postcss-preset-env": "7.8.3",
+ "prettier": "^3.5.3",
+ "react-dev-utils": "^12.0.1",
+ "react-refresh": "^0.14.2",
+ "react-test-renderer": "^18.3.1",
+ "resolve-url-loader": "^5.0.0",
+ "sass": "^1.81.0",
+ "sass-loader": "^16.0.3",
+ "style-loader": "^4.0.0",
+ "ts-jest": "^29.2.5",
+ "ts-node": "^10.9.2",
+ "typescript": "^5.7.2",
+ "webpack": "^5.96.1",
+ "webpack-cli": "^5.1.4",
+ "webpack-dev-server": "^5.1.0",
+ "webpack-merge": "^6.0.1",
+ "webpack-nano": "^1.1.1"
+ },
+ "dependencies": {
+ "@cloudscape-design/chat-components": "^1.0.62",
+ "@cloudscape-design/collection-hooks": "^1.0.74",
+ "@cloudscape-design/component-toolkit": "^1.0.0-beta.120",
+ "@cloudscape-design/components": "^3.0.1188",
+ "@cloudscape-design/design-tokens": "^3.0.60",
+ "@cloudscape-design/global-styles": "^1.0.45",
+ "@hookform/resolvers": "^2.9.10",
+ "@reduxjs/toolkit": "^1.9.1",
+ "@types/yup": "^0.29.14",
+ "ace-builds": "^1.36.3",
+ "classnames": "^2.5.1",
+ "css-minimizer-webpack-plugin": "^4.2.2",
+ "date-fns": "^2.29.3",
+ "i18next": "^24.0.2",
+ "js-yaml": "^4.1.0",
+ "lodash": "^4.17.21",
+ "openai": "^4.33.1",
+ "prismjs": "^1.30.0",
+ "rc-tooltip": "^5.2.2",
+ "react": "^18.3.1",
+ "react-avatar": "^5.0.3",
+ "react-bus": "^4.0.1",
+ "react-dom": "^18.3.1",
+ "react-helmet": "^6.1.0",
+ "react-hook-form": "^7.53.0",
+ "react-i18next": "^12.1.4",
+ "react-redux": "^8.0.5",
+ "react-router-dom": "^6.27.0",
+ "react-string-replace": "^1.1.1",
+ "redux": "^5.0.1",
+ "yup": "^0.32.11"
+ },
+ "lint-staged": {
+ "*.{js,jsx,ts,tsx}": [
+ "eslint --fix --max-warnings=0 --no-warn-ignored",
+ "git add"
+ ]
+ }
+}
diff --git a/frontend/public/index.html b/frontend/public/index.html
new file mode 100644
index 0000000000..c661f9de7b
--- /dev/null
+++ b/frontend/public/index.html
@@ -0,0 +1,43 @@
+
+
+
+
+
+
+
+ <%= htmlWebpackPlugin.options.title %>
+
+
+
+
+
+
+
+ <%= htmlWebpackPlugin.options.customHeadHTML %>
+
+
+ You need to enable JavaScript to run this app.
+
+
+
+
+
+
diff --git a/docs/assets/images/dstack-logo-notext.svg b/frontend/public/logo-notext.svg
similarity index 100%
rename from docs/assets/images/dstack-logo-notext.svg
rename to frontend/public/logo-notext.svg
diff --git a/frontend/public/manifest.json b/frontend/public/manifest.json
new file mode 100644
index 0000000000..fb612dc348
--- /dev/null
+++ b/frontend/public/manifest.json
@@ -0,0 +1,16 @@
+{
+ "short_name": "dstack",
+ "name": "dstack",
+ "icons": [
+ {
+ "src": "favicon.ico",
+ "sizes": "64x64 32x32 24x24 16x16",
+ "type": "image/x-icon"
+ }
+ ],
+ "start_url": ".",
+ "display": "standalone",
+ "theme_color": "#000000",
+ "background_color": "#ffffff",
+ "permissions": ["clipboardWrite", "clipboardRead"]
+}
diff --git a/frontend/public/robots.txt b/frontend/public/robots.txt
new file mode 100644
index 0000000000..e9e57dc4d4
--- /dev/null
+++ b/frontend/public/robots.txt
@@ -0,0 +1,3 @@
+# https://www.robotstxt.org/robotstxt.html
+User-agent: *
+Disallow:
diff --git a/frontend/setupEnzyme.ts b/frontend/setupEnzyme.ts
new file mode 100644
index 0000000000..aedc1b24cf
--- /dev/null
+++ b/frontend/setupEnzyme.ts
@@ -0,0 +1,4 @@
+import { configure } from 'enzyme';
+import Adapter from '@cfaester/enzyme-adapter-react-18';
+
+configure({ adapter: new Adapter() });
diff --git a/frontend/src/App/AuthErrorMessage/index.tsx b/frontend/src/App/AuthErrorMessage/index.tsx
new file mode 100644
index 0000000000..f336f8c665
--- /dev/null
+++ b/frontend/src/App/AuthErrorMessage/index.tsx
@@ -0,0 +1,30 @@
+import React, { PropsWithChildren } from 'react';
+
+import { Box, SpaceBetween } from 'components';
+
+import styles from './styles.module.scss';
+
+export interface Props extends PropsWithChildren {
+ title: string;
+ text?: string;
+}
+
+export const AuthErrorMessage: React.FC = ({ title, text, children }) => {
+ return (
+
+
+
+ {title}
+
+ {text && (
+
+ {text}
+
+ )}
+
+
+
+ {children}
+
+ );
+};
diff --git a/frontend/src/App/AuthErrorMessage/styles.module.scss b/frontend/src/App/AuthErrorMessage/styles.module.scss
new file mode 100644
index 0000000000..bdee5af260
--- /dev/null
+++ b/frontend/src/App/AuthErrorMessage/styles.module.scss
@@ -0,0 +1,3 @@
+.content {
+ margin-top: 20px;
+}
diff --git a/frontend/src/App/Loading/index.tsx b/frontend/src/App/Loading/index.tsx
new file mode 100644
index 0000000000..d6e06913d1
--- /dev/null
+++ b/frontend/src/App/Loading/index.tsx
@@ -0,0 +1,20 @@
+import React from 'react';
+
+import { AppLayout, Spinner } from 'components';
+
+import styles from './styles.module.scss';
+
+export const Loading: React.FC = () => {
+ return (
+
+
+
+ }
+ />
+ );
+};
diff --git a/frontend/src/App/Loading/styles.module.scss b/frontend/src/App/Loading/styles.module.scss
new file mode 100644
index 0000000000..b2a1e1fbe3
--- /dev/null
+++ b/frontend/src/App/Loading/styles.module.scss
@@ -0,0 +1,6 @@
+.spinner {
+ height: 100%;
+ display: flex;
+ align-items: center;
+ justify-content: center;
+}
diff --git a/frontend/src/App/Login/EnterpriseLogin/index.tsx b/frontend/src/App/Login/EnterpriseLogin/index.tsx
new file mode 100644
index 0000000000..7cb9b530af
--- /dev/null
+++ b/frontend/src/App/Login/EnterpriseLogin/index.tsx
@@ -0,0 +1,53 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import cn from 'classnames';
+
+import { Box, NavigateLink, SpaceBetween } from 'components';
+import { UnauthorizedLayout } from 'layouts/UnauthorizedLayout';
+
+import { ROUTES } from 'routes';
+import { useGetEntraInfoQuery, useGetGoogleInfoQuery, useGetOktaInfoQuery } from 'services/auth';
+
+import { LoginByEntraID } from '../EntraID/LoginByEntraID';
+import { LoginByGoogle } from '../LoginByGoogle';
+import { LoginByOkta } from '../LoginByOkta';
+import { LoginByTokenForm } from '../LoginByTokenForm';
+
+import styles from './styles.module.scss';
+
+export const EnterpriseLogin: React.FC = () => {
+ const { t } = useTranslation();
+ const { data: oktaData, isLoading: isLoadingOkta } = useGetOktaInfoQuery();
+ const { data: entraData, isLoading: isLoadingEntra } = useGetEntraInfoQuery();
+ const { data: googleData, isLoading: isLoadingGoogle } = useGetGoogleInfoQuery();
+
+ const oktaEnabled = oktaData?.enabled;
+ const entraEnabled = entraData?.enabled;
+ const googleEnabled = googleData?.enabled;
+
+ const isLoading = isLoadingOkta || isLoadingEntra;
+ const isShowTokenForm = !oktaEnabled && !entraEnabled;
+
+ return (
+
+
+
+
+ {t('auth.sign_in_to_dstack_enterprise')}
+
+
+ {!isLoading && isShowTokenForm && }
+ {!isLoadingOkta && oktaEnabled && }
+ {!isLoadingEntra && entraEnabled && }
+ {!isLoadingGoogle && googleEnabled && }
+
+ {!isLoading && !isShowTokenForm && (
+
+ {t('auth.login_by_token')}
+
+ )}
+
+
+
+ );
+};
diff --git a/frontend/src/App/Login/EnterpriseLogin/styles.module.scss b/frontend/src/App/Login/EnterpriseLogin/styles.module.scss
new file mode 100644
index 0000000000..72a104a848
--- /dev/null
+++ b/frontend/src/App/Login/EnterpriseLogin/styles.module.scss
@@ -0,0 +1,16 @@
+.form {
+ max-width: 440px;
+ width: 100%;
+ margin-left: auto;
+ margin-right: auto;
+ padding-top: 120px;
+}
+.token {
+
+}
+.okta {
+ margin-top: 20px;
+}
+.entra {
+ margin-top: 20px;
+}
diff --git a/frontend/src/App/Login/EntraID/LoginByEntraID/index.tsx b/frontend/src/App/Login/EntraID/LoginByEntraID/index.tsx
new file mode 100644
index 0000000000..c52d14fe10
--- /dev/null
+++ b/frontend/src/App/Login/EntraID/LoginByEntraID/index.tsx
@@ -0,0 +1,39 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import cn from 'classnames';
+
+import { Button } from 'components';
+
+import { goToUrl } from 'libs';
+import { useEntraAuthorizeMutation } from 'services/auth';
+
+import { getBaseUrl } from 'App/helpers';
+
+import { ReactComponent as EntraIdIcon } from 'assets/icons/entraID.svg';
+import styles from './styles.module.scss';
+
+export const LoginByEntraID: React.FC<{ className?: string }> = ({ className }) => {
+ const { t } = useTranslation();
+
+ const [entraAuthorize, { isLoading }] = useEntraAuthorizeMutation();
+
+ const signInClick = () => {
+ entraAuthorize({ base_url: getBaseUrl() })
+ .unwrap()
+ .then((data) => {
+ goToUrl(data.authorization_url);
+ })
+ .catch(console.log);
+ };
+
+ return (
+
+
+
+
+ {t('common.login_entra')}
+
+
+
+ );
+};
diff --git a/frontend/src/App/Login/EntraID/LoginByEntraID/styles.module.scss b/frontend/src/App/Login/EntraID/LoginByEntraID/styles.module.scss
new file mode 100644
index 0000000000..cf258c4c3a
--- /dev/null
+++ b/frontend/src/App/Login/EntraID/LoginByEntraID/styles.module.scss
@@ -0,0 +1,20 @@
+@use '@cloudscape-design/design-tokens/index' as awsui;
+
+.entraSignIn {
+ display: flex;
+ justify-content: center;
+
+ button {
+ .loginButtonInner {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ }
+
+ .loginButtonLabel {
+ height: 20px;
+ line-height: 21px;
+ }
+ }
+}
diff --git a/frontend/src/App/Login/EntraID/LoginByEntraIDCallback/index.tsx b/frontend/src/App/Login/EntraID/LoginByEntraIDCallback/index.tsx
new file mode 100644
index 0000000000..036851c3cf
--- /dev/null
+++ b/frontend/src/App/Login/EntraID/LoginByEntraIDCallback/index.tsx
@@ -0,0 +1,76 @@
+import React, { useEffect, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useNavigate, useSearchParams } from 'react-router-dom';
+
+import { NavigateLink } from 'components';
+import { UnauthorizedLayout } from 'layouts/UnauthorizedLayout';
+
+import { useAppDispatch } from 'hooks';
+import { ROUTES } from 'routes';
+import { useEntraCallbackMutation, useGetNextRedirectMutation } from 'services/auth';
+
+import { AuthErrorMessage } from 'App/AuthErrorMessage';
+import { getBaseUrl } from 'App/helpers';
+import { Loading } from 'App/Loading';
+import { setAuthData } from 'App/slice';
+
+export const LoginByEntraIDCallback: React.FC = () => {
+ const { t } = useTranslation();
+ const [searchParams] = useSearchParams();
+ const navigate = useNavigate();
+ const code = searchParams.get('code');
+ const state = searchParams.get('state');
+ const [isInvalidCode, setIsInvalidCode] = useState(false);
+ const dispatch = useAppDispatch();
+
+ const [getNextRedirect] = useGetNextRedirectMutation();
+ const [entraCallback] = useEntraCallbackMutation();
+
+ const checkCode = () => {
+ if (code && state) {
+ getNextRedirect({ code, state })
+ .unwrap()
+ .then(({ redirect_url }) => {
+ if (redirect_url) {
+ window.location.href = redirect_url;
+ return;
+ }
+ entraCallback({ code, state, base_url: getBaseUrl() })
+ .unwrap()
+ .then(({ creds: { token } }) => {
+ dispatch(setAuthData({ token }));
+ navigate('/');
+ })
+ .catch(() => {
+ setIsInvalidCode(true);
+ });
+ })
+ .catch(() => {
+ setIsInvalidCode(true);
+ });
+ }
+ };
+
+ useEffect(() => {
+ if (code && state) {
+ checkCode();
+ } else {
+ setIsInvalidCode(true);
+ }
+ }, []);
+
+ if (isInvalidCode)
+ return (
+
+
+ {t('auth.try_again')}
+
+
+ );
+
+ return (
+
+ ;
+
+ );
+};
diff --git a/frontend/src/App/Login/LoginByGithub/index.tsx b/frontend/src/App/Login/LoginByGithub/index.tsx
new file mode 100644
index 0000000000..61ce317cc8
--- /dev/null
+++ b/frontend/src/App/Login/LoginByGithub/index.tsx
@@ -0,0 +1,504 @@
+import React from 'react';
+import { createPortal } from 'react-dom';
+import { useTranslation } from 'react-i18next';
+import enMessages from '@cloudscape-design/components/i18n/messages/all.en.json';
+import { Mode } from '@cloudscape-design/global-styles';
+
+import {
+ AnchorNavigation,
+ Box,
+ BreadcrumbGroup,
+ Button,
+ Container,
+ ContentLayout,
+ ExpandableSection,
+ Grid,
+ Header,
+ I18nProvider,
+ Icon,
+ Link,
+ Popover,
+ SpaceBetween,
+ TextContent,
+ TopNavigation,
+} from 'components';
+import { DarkThemeIcon, LightThemeIcon } from 'layouts/AppLayout/themeIcons';
+
+import { DISCORD_URL } from 'consts';
+import { useAppDispatch, useAppSelector } from 'hooks';
+import { goToUrl } from 'libs';
+import { ROUTES } from 'routes';
+import { useGithubAuthorizeMutation } from 'services/auth';
+
+import { selectSystemMode, setSystemMode } from 'App/slice';
+
+import logo from 'assets/images/logo.svg';
+import styles from './styles.module.scss';
+
+type PortalProps = {
+ children: React.ReactNode;
+};
+
+const i18nStrings = {
+ overflowMenuTriggerText: '',
+ overflowMenuTitleText: '',
+ overflowMenuBackIconAriaLabel: '',
+ overflowMenuDismissIconAriaLabel: '',
+};
+
+const THEME_ICON_MAP: Record = {
+ [Mode.Dark]: DarkThemeIcon,
+ [Mode.Light]: LightThemeIcon,
+};
+
+const GitHubIcon: React.FC = () => (
+
+
+
+
+
+);
+
+const askAi = () => {
+ window.document.body.focus();
+ window?.Kapa?.open();
+};
+
+const HeaderPortal = ({ children }: PortalProps) => {
+ const domNode = document.querySelector('#header');
+ if (domNode) return createPortal(children, domNode);
+ return null;
+};
+
+function OnThisPageNavigation({ variant }: { variant: 'mobile' | 'side' }) {
+ const anchorNavigation = (
+
+ );
+
+ return variant === 'side' ? (
+
+
+
+
+ {anchorNavigation}
+
+ ) : (
+
+ {anchorNavigation}
+
+ );
+}
+
+function HeroHeader() {
+ const [githubAuthorize, { isLoading }] = useGithubAuthorizeMutation();
+
+ const signInClick = () => {
+ githubAuthorize()
+ .unwrap()
+ .then((data) => {
+ goToUrl(data.authorization_url);
+ })
+ .catch(console.log);
+ };
+
+ return (
+
+
+
+ Welcome to dstack Sky
+
+ Enjoy the full power of dstack without the hassle of hosting it yourself or managing
+ your own infrastructure.
+ Sign up for dstack Sky to use the cheapest GPUs from our marketplace or connect it to
+ your own cloud accounts.
+
+
+ By clicking Sign up you agree to the{' '}
+
+ Terms
+ {' '}
+ and{' '}
+
+ Privacy policy
+
+
+
+
+
+
+ }
+ >
+ Sign up with GitHub
+
+
+
+ No credit card required
+
+
+
+
+
+
+ }>
+ Sign in with GitHub
+
+
+
+ Sign in with a token
+
+
+
+
+
+ );
+}
+
+function ProductOverview() {
+ return (
+
+
+
+
+
+ dstack is an open-source container orchestrator that lets ML teams easily manage
+ clusters, volumes, dev environments, training, and inference. Its container-native interface boosts
+ productivity, maximizes GPU efficiency, and lowers costs.
+
+
+ dstack Sky adds a managed service, letting you use the cheapest GPUs from our
+ marketplace or connect your own cloud accounts.
+
+
+
+
+
+ Features
+
+
+
+
+
+
+ Open-source
+
+
+ dstack Sky
+
+
+ Bring your own cloud{' '}
+
+
+ Use compute from your own cloud account(s) by providing your credentials.
+
+
+ You pay for compute and storage usage directly to the configured cloud
+ provider(s) through their billing. dstack won't bill or charge you.
+
+ >
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+
+
+ GPU marketplace{' '}
+
+
+ Use compute from multiple cloud providers without needing your own cloud
+ account(s).
+
+
+ You pay for compute and storage usage directly to dstack. You can
+ top up your balance in your dstack user settings.
+
+ When you sign up, you get $5 in credits.
+ >
+ }
+ >
+
+
+
+
+
+
+
+
+
+
+
+ SSH fleets{' '}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ Gateway{' '}
+
+
+
+
+
+
+ Configure your own domain
+
+ Pre-configured *.sky.dstack.ai
+
+
+ Pricing
+ Free
+ Pay only if you use GPU marketplace
+
+
+ Self-hosted
+ Hosted by dstack
+
+
+
+
+
+
+
+
+ Use compute from your own cloud account(s) or through GPU marketplace.
+ Create dev environments, run training tasks, and deploy inference services.
+ Manage volumes and fleets.
+ Manage multiple projects and teams.
+
+
+
+
+
+
+
+
+ Want to learn more about dstack ? Check out the{' '}
+
+ documentation
+
+
+
+
+
+
+ );
+}
+
+function OtherVersions() {
+ return (
+
+
+ Other versions
+
+
+
+
+
+
+ Open-source
+ Self-hosted
+
+ Fully customizable and self-hosted open-source version.
+
+ Installation
+
+
+
+
+
+
+
+
+ dstack Enterprise
+ Self-hosted
+
+ Single sign-on, advanced governance controls, and dedicated support.
+
+ Book a demo
+
+
+
+
+
+
+ );
+}
+
+export const LoginByGithub: React.FC = () => {
+ const { t } = useTranslation();
+ const dispatch = useAppDispatch();
+ const systemMode = useAppSelector(selectSystemMode) ?? '';
+ const ThemeIcon = THEME_ICON_MAP[systemMode];
+
+ const onChangeSystemModeToggle = (event: React.MouseEvent) => {
+ event.preventDefault();
+ switch (systemMode) {
+ case Mode.Light:
+ dispatch(setSystemMode(Mode.Dark));
+ return;
+ default:
+ dispatch(setSystemMode(Mode.Light));
+ }
+ };
+
+ return (
+ <>
+
+
+ goToUrl('https://dstack.ai/docs/', true),
+ },
+ {
+ type: 'button',
+ text: t('common.discord'),
+ external: true,
+ onClick: () => goToUrl(DISCORD_URL, true),
+ },
+ {
+ href: 'theme-button',
+ type: 'button',
+ iconSvg: ,
+ onClick: onChangeSystemModeToggle,
+ },
+ {
+ type: 'button',
+ iconName: 'gen-ai',
+ text: t('common.ask_ai'),
+ title: t('common.ask_ai'),
+ onClick: askAi,
+ },
+ ]}
+ />
+
+
+
+
+
+ }
+ headerVariant="high-contrast"
+ header={ }
+ defaultPadding={true}
+ maxContentWidth={1040}
+ disableOverlap={true}
+ >
+
+
+
+ >
+ );
+};
diff --git a/frontend/src/App/Login/LoginByGithub/styles.module.scss b/frontend/src/App/Login/LoginByGithub/styles.module.scss
new file mode 100644
index 0000000000..d3efe6e389
--- /dev/null
+++ b/frontend/src/App/Login/LoginByGithub/styles.module.scss
@@ -0,0 +1,121 @@
+@use '~@cloudscape-design/design-tokens' as cs;
+
+body {
+ background: cs.$color-background-layout-main;
+ position: relative;
+}
+
+$viewport-breakpoint-s: 912px;
+
+body {
+ // Note: This token will be themed (see the product page index.tsx)
+ background: cs.$color-background-layout-main;
+}
+
+.productPageContentGrid {
+ display: grid;
+ grid-template-columns: 3fr 1fr;
+ grid-template-rows: 0 auto 0;
+ margin-block-start: cs.$space-static-xxl;
+}
+
+.onThisPageMobile {
+ grid-row: 1;
+ grid-column: 1 / 3;
+ display: none;
+ margin-block-end: cs.$space-static-xxl;
+}
+
+.productPageAside {
+ grid-row: 2;
+ grid-column: 2 / 3;
+ padding-inline-start: calc(#{cs.$space-scaled-xxxl} /2);
+}
+
+.productPageContent {
+ grid-row: 2;
+ grid-column: 1 / 2;
+ padding-inline-end: calc(#{cs.$space-scaled-xxxl} /2);
+ margin-bottom: 20px;
+}
+
+
+.productPageAsideSticky {
+ position: sticky;
+ inset-block-start: 40px;
+}
+
+@media only screen and (max-width: $viewport-breakpoint-s) {
+ .productPageContentGrid {
+ grid-template-columns: 100%;
+ grid-template-rows: auto auto auto;
+ }
+
+ .onThisPageMobile {
+ display: block;
+ }
+
+ .productPageMobile {
+ display: block;
+ }
+
+ .productPageAside {
+ display: none;
+ }
+}
+
+
+/* High-level sections of the main content area */
+.pageSection {
+ padding-block-end: cs.$space-static-xxxl;
+ margin-block-end: cs.$space-static-xxl;
+ border-bottom: 1px solid cs.$color-border-divider-default;
+
+ &:last-child {
+ border: none;
+ margin-block-end: 0;
+ }
+}
+
+/* Product details list containing keys and values */
+.productDetails {
+ display: grid;
+ grid-template-columns: 30% 35% 35%;
+ margin: 0;
+ padding: 0;
+
+ dt {
+ color: cs.$color-text-body-default;
+ font-weight: bold;
+ }
+
+ dt,
+ dd {
+ margin: 0;
+ padding: 0;
+ padding-block: cs.$space-scaled-xs;
+ border-block-end: 1px solid cs.$color-border-divider-default;
+ }
+}
+
+/* List of product cards */
+.productCardsList {
+ display: flex;
+ flex-wrap: wrap;
+ column-gap: cs.$space-scaled-l;
+ row-gap: cs.$space-scaled-l;
+
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
+
+.productCardsListItem {
+ flex: 1;
+ flex-basis: 250px;
+ max-inline-size: 312px;
+
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
diff --git a/frontend/src/App/Login/LoginByGithubCallback/index.tsx b/frontend/src/App/Login/LoginByGithubCallback/index.tsx
new file mode 100644
index 0000000000..45be311b6b
--- /dev/null
+++ b/frontend/src/App/Login/LoginByGithubCallback/index.tsx
@@ -0,0 +1,84 @@
+import React, { useEffect, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useNavigate, useSearchParams } from 'react-router-dom';
+
+import { NavigateLink } from 'components';
+import { UnauthorizedLayout } from 'layouts/UnauthorizedLayout';
+
+import { useAppDispatch } from 'hooks';
+import { ROUTES } from 'routes';
+import { useGetNextRedirectMutation, useGithubCallbackMutation } from 'services/auth';
+import { useLazyGetProjectsQuery } from 'services/project';
+
+import { AuthErrorMessage } from 'App/AuthErrorMessage';
+import { Loading } from 'App/Loading';
+import { setAuthData } from 'App/slice';
+
+export const LoginByGithubCallback: React.FC = () => {
+ const { t } = useTranslation();
+ const [searchParams] = useSearchParams();
+ const navigate = useNavigate();
+ const code = searchParams.get('code');
+ const state = searchParams.get('state');
+ const [isInvalidCode, setIsInvalidCode] = useState(false);
+ const dispatch = useAppDispatch();
+
+ const [getNextRedirect] = useGetNextRedirectMutation();
+ const [githubCallback] = useGithubCallbackMutation();
+ const [getProjects] = useLazyGetProjectsQuery();
+
+ const checkCode = () => {
+ if (code && state) {
+ getNextRedirect({ code: code, state: state })
+ .unwrap()
+ .then(async ({ redirect_url }) => {
+ if (redirect_url) {
+ window.location.href = redirect_url;
+ return;
+ }
+ githubCallback({ code, state })
+ .unwrap()
+ .then(async ({ creds: { token } }) => {
+ dispatch(setAuthData({ token }));
+ if (process.env.UI_VERSION === 'sky') {
+ const result = await getProjects({}).unwrap();
+ if (result?.length === 0) {
+ navigate(ROUTES.PROJECT.ADD);
+ return;
+ }
+ }
+ navigate('/');
+ })
+ .catch(() => {
+ setIsInvalidCode(true);
+ });
+ })
+ .catch(() => {
+ setIsInvalidCode(true);
+ });
+ }
+ };
+
+ useEffect(() => {
+ if (code) {
+ checkCode();
+ } else {
+ setIsInvalidCode(true);
+ }
+ }, []);
+
+ if (isInvalidCode)
+ return (
+
+
+ {t('auth.try_again')}
+
+
+ );
+
+ return (
+
+ ;
+
+ );
+};
diff --git a/frontend/src/App/Login/LoginByGoogle/index.tsx b/frontend/src/App/Login/LoginByGoogle/index.tsx
new file mode 100644
index 0000000000..b83a93f187
--- /dev/null
+++ b/frontend/src/App/Login/LoginByGoogle/index.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import cn from 'classnames';
+
+import { Button } from 'components';
+
+import { goToUrl } from 'libs';
+import { useGoogleAuthorizeMutation } from 'services/auth';
+
+import { ReactComponent as GoogleIcon } from 'assets/icons/google.svg';
+import styles from './styles.module.scss';
+
+export const LoginByGoogle: React.FC<{ className?: string }> = ({ className }) => {
+ const { t } = useTranslation();
+
+ const [googleAuthorize, { isLoading }] = useGoogleAuthorizeMutation();
+
+ const signInClick = () => {
+ googleAuthorize()
+ .unwrap()
+ .then((data) => {
+ goToUrl(data.authorization_url);
+ })
+ .catch(console.log);
+ };
+
+ return (
+
+
+
+
+ {t('common.login_google')}
+
+
+
+ );
+};
diff --git a/frontend/src/App/Login/LoginByGoogle/styles.module.scss b/frontend/src/App/Login/LoginByGoogle/styles.module.scss
new file mode 100644
index 0000000000..93407bda8d
--- /dev/null
+++ b/frontend/src/App/Login/LoginByGoogle/styles.module.scss
@@ -0,0 +1,20 @@
+@use '@cloudscape-design/design-tokens/index' as awsui;
+
+.signIn {
+ display: flex;
+ justify-content: center;
+
+ button {
+ .loginButtonInner {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ }
+
+ .loginButtonLabel {
+ height: 20px;
+ line-height: 21px;
+ }
+ }
+}
diff --git a/frontend/src/App/Login/LoginByGoogleCallback/index.tsx b/frontend/src/App/Login/LoginByGoogleCallback/index.tsx
new file mode 100644
index 0000000000..4f95f94e27
--- /dev/null
+++ b/frontend/src/App/Login/LoginByGoogleCallback/index.tsx
@@ -0,0 +1,75 @@
+import React, { useEffect, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useNavigate, useSearchParams } from 'react-router-dom';
+
+import { NavigateLink } from 'components';
+import { UnauthorizedLayout } from 'layouts/UnauthorizedLayout';
+
+import { useAppDispatch } from 'hooks';
+import { ROUTES } from 'routes';
+import { useGetNextRedirectMutation, useGoogleCallbackMutation } from 'services/auth';
+
+import { AuthErrorMessage } from 'App/AuthErrorMessage';
+import { Loading } from 'App/Loading';
+import { setAuthData } from 'App/slice';
+
+export const LoginByGoogleCallback: React.FC = () => {
+ const { t } = useTranslation();
+ const [searchParams] = useSearchParams();
+ const navigate = useNavigate();
+ const code = searchParams.get('code');
+ const state = searchParams.get('state');
+ const [isInvalidCode, setIsInvalidCode] = useState(false);
+ const dispatch = useAppDispatch();
+
+ const [getNextRedirect] = useGetNextRedirectMutation();
+ const [googleCallback] = useGoogleCallbackMutation();
+
+ const checkCode = () => {
+ if (code && state) {
+ getNextRedirect({ code, state })
+ .unwrap()
+ .then(({ redirect_url }) => {
+ if (redirect_url) {
+ window.location.href = redirect_url;
+ return;
+ }
+ googleCallback({ code, state })
+ .unwrap()
+ .then(({ creds: { token } }) => {
+ dispatch(setAuthData({ token }));
+ navigate('/');
+ })
+ .catch(() => {
+ setIsInvalidCode(true);
+ });
+ })
+ .catch(() => {
+ setIsInvalidCode(true);
+ });
+ }
+ };
+
+ useEffect(() => {
+ if (code && state) {
+ checkCode();
+ } else {
+ setIsInvalidCode(true);
+ }
+ }, []);
+
+ if (isInvalidCode)
+ return (
+
+
+ {t('auth.try_again')}
+
+
+ );
+
+ return (
+
+ ;
+
+ );
+};
diff --git a/frontend/src/App/Login/LoginByOkta/index.tsx b/frontend/src/App/Login/LoginByOkta/index.tsx
new file mode 100644
index 0000000000..5b01b6dd53
--- /dev/null
+++ b/frontend/src/App/Login/LoginByOkta/index.tsx
@@ -0,0 +1,37 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import cn from 'classnames';
+
+import { Button } from 'components';
+
+import { goToUrl } from 'libs';
+import { useOktaAuthorizeMutation } from 'services/auth';
+
+import { ReactComponent as OktaIcon } from 'assets/icons/okta.svg';
+import styles from './styles.module.scss';
+
+export const LoginByOkta: React.FC<{ className?: string }> = ({ className }) => {
+ const { t } = useTranslation();
+
+ const [oktaAuthorize, { isLoading }] = useOktaAuthorizeMutation();
+
+ const signInClick = () => {
+ oktaAuthorize()
+ .unwrap()
+ .then((data) => {
+ goToUrl(data.authorization_url);
+ })
+ .catch(console.log);
+ };
+
+ return (
+
+
+
+
+ {t('common.login_okta')}
+
+
+
+ );
+};
diff --git a/frontend/src/App/Login/LoginByOkta/styles.module.scss b/frontend/src/App/Login/LoginByOkta/styles.module.scss
new file mode 100644
index 0000000000..93407bda8d
--- /dev/null
+++ b/frontend/src/App/Login/LoginByOkta/styles.module.scss
@@ -0,0 +1,20 @@
+@use '@cloudscape-design/design-tokens/index' as awsui;
+
+.signIn {
+ display: flex;
+ justify-content: center;
+
+ button {
+ .loginButtonInner {
+ display: inline-flex;
+ align-items: center;
+ justify-content: center;
+ gap: 8px;
+ }
+
+ .loginButtonLabel {
+ height: 20px;
+ line-height: 21px;
+ }
+ }
+}
diff --git a/frontend/src/App/Login/LoginByOktaCallback/index.tsx b/frontend/src/App/Login/LoginByOktaCallback/index.tsx
new file mode 100644
index 0000000000..72cdc96185
--- /dev/null
+++ b/frontend/src/App/Login/LoginByOktaCallback/index.tsx
@@ -0,0 +1,75 @@
+import React, { useEffect, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useNavigate, useSearchParams } from 'react-router-dom';
+
+import { NavigateLink } from 'components';
+import { UnauthorizedLayout } from 'layouts/UnauthorizedLayout';
+
+import { useAppDispatch } from 'hooks';
+import { ROUTES } from 'routes';
+import { useGetNextRedirectMutation, useOktaCallbackMutation } from 'services/auth';
+
+import { AuthErrorMessage } from 'App/AuthErrorMessage';
+import { Loading } from 'App/Loading';
+import { setAuthData } from 'App/slice';
+
+export const LoginByOktaCallback: React.FC = () => {
+ const { t } = useTranslation();
+ const [searchParams] = useSearchParams();
+ const navigate = useNavigate();
+ const code = searchParams.get('code');
+ const state = searchParams.get('state');
+ const [isInvalidCode, setIsInvalidCode] = useState(false);
+ const dispatch = useAppDispatch();
+
+ const [getNextRedirect] = useGetNextRedirectMutation();
+ const [oktaCallback] = useOktaCallbackMutation();
+
+ const checkCode = () => {
+ if (code && state) {
+ getNextRedirect({ code, state })
+ .unwrap()
+ .then(({ redirect_url }) => {
+ if (redirect_url) {
+ window.location.href = redirect_url;
+ return;
+ }
+ oktaCallback({ code, state })
+ .unwrap()
+ .then(({ creds: { token } }) => {
+ dispatch(setAuthData({ token }));
+ navigate('/');
+ })
+ .catch(() => {
+ setIsInvalidCode(true);
+ });
+ })
+ .catch(() => {
+ setIsInvalidCode(true);
+ });
+ }
+ };
+
+ useEffect(() => {
+ if (code && state) {
+ checkCode();
+ } else {
+ setIsInvalidCode(true);
+ }
+ }, []);
+
+ if (isInvalidCode)
+ return (
+
+
+ {t('auth.try_again')}
+
+
+ );
+
+ return (
+
+ ;
+
+ );
+};
diff --git a/frontend/src/App/Login/LoginByTokenForm/index.tsx b/frontend/src/App/Login/LoginByTokenForm/index.tsx
new file mode 100644
index 0000000000..d5b7a76111
--- /dev/null
+++ b/frontend/src/App/Login/LoginByTokenForm/index.tsx
@@ -0,0 +1,71 @@
+import React from 'react';
+import { useForm } from 'react-hook-form';
+import { useTranslation } from 'react-i18next';
+import { useNavigate } from 'react-router-dom';
+import cn from 'classnames';
+
+import { Button, FormInput } from 'components';
+
+import { useAppDispatch } from 'hooks';
+import { useCheckAuthTokenMutation } from 'services/user';
+
+import { setAuthData } from 'App/slice';
+
+import styles from './styles.module.scss';
+
+type FormValues = Pick;
+
+export interface Props {
+ className?: string;
+}
+
+export const LoginByTokenForm: React.FC = ({ className }) => {
+ const { t } = useTranslation();
+ const { handleSubmit, control, setError } = useForm();
+ const dispatch = useAppDispatch();
+ const navigate = useNavigate();
+
+ const [checkToken, { isLoading }] = useCheckAuthTokenMutation();
+ const onSubmit = (data: FormValues) => {
+ checkToken(data)
+ .unwrap()
+ .then(() => {
+ dispatch(setAuthData(data));
+ navigate('/');
+ })
+ .catch((error) => {
+ if (error?.status === 401) {
+ setError('token', { type: 'custom', message: t('auth.invalid_token') });
+ return;
+ }
+
+ setError('token', { type: 'custom', message: t('common.server_error', { error: error?.msg }) });
+ });
+ };
+
+ return (
+
+ );
+};
diff --git a/frontend/src/App/Login/LoginByTokenForm/styles.module.scss b/frontend/src/App/Login/LoginByTokenForm/styles.module.scss
new file mode 100644
index 0000000000..859b39ebcc
--- /dev/null
+++ b/frontend/src/App/Login/LoginByTokenForm/styles.module.scss
@@ -0,0 +1,24 @@
+.form {
+ max-width: 440px;
+ margin-left: auto;
+ margin-right: auto;
+}
+.token {
+ display: flex;
+ align-items: flex-start;
+ gap: 12px;
+}
+.fieldWrap {
+ flex-grow: 1;
+ min-width: 0;
+}
+.buttonWrap {
+ display: flex;
+ flex-shrink: 0;
+ width: 104px;
+ margin-right: -20px;
+
+ button {
+ white-space: nowrap !important;
+ }
+}
diff --git a/frontend/src/App/Login/TokenLogin/index.tsx b/frontend/src/App/Login/TokenLogin/index.tsx
new file mode 100644
index 0000000000..b41393ba39
--- /dev/null
+++ b/frontend/src/App/Login/TokenLogin/index.tsx
@@ -0,0 +1,34 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import cn from 'classnames';
+
+import { Box, NavigateLink, SpaceBetween } from 'components';
+import { UnauthorizedLayout } from 'layouts/UnauthorizedLayout';
+
+import { ROUTES } from 'routes';
+
+import { LoginByTokenForm } from '../LoginByTokenForm';
+
+import styles from './styles.module.scss';
+
+export const TokenLogin: React.FC = () => {
+ const { t } = useTranslation();
+
+ return (
+
+
+
+
+ {t('auth.sign_in_to_dstack_enterprise')}
+
+
+
+
+
+ {t('auth.another_login_methods')}
+
+
+
+
+ );
+};
diff --git a/frontend/src/App/Login/TokenLogin/styles.module.scss b/frontend/src/App/Login/TokenLogin/styles.module.scss
new file mode 100644
index 0000000000..b648c81066
--- /dev/null
+++ b/frontend/src/App/Login/TokenLogin/styles.module.scss
@@ -0,0 +1,7 @@
+.form {
+ max-width: 440px;
+ width: 100%;
+ margin-left: auto;
+ margin-right: auto;
+ padding-top: 120px;
+}
diff --git a/frontend/src/App/Logout/index.tsx b/frontend/src/App/Logout/index.tsx
new file mode 100644
index 0000000000..0526c92cca
--- /dev/null
+++ b/frontend/src/App/Logout/index.tsx
@@ -0,0 +1,22 @@
+import React, { useEffect } from 'react';
+import { Navigate } from 'react-router-dom';
+
+import { useAppDispatch } from 'hooks';
+import { ROUTES } from 'routes';
+import { projectApi } from 'services/project';
+import { userApi } from 'services/user';
+
+import { removeAuthData } from '../slice';
+
+export const Logout: React.FC = () => {
+ const dispatch = useAppDispatch();
+
+ useEffect(() => {
+ dispatch(removeAuthData());
+
+ dispatch(userApi.util.resetApiState());
+ dispatch(projectApi.util.resetApiState());
+ }, []);
+
+ return ;
+};
diff --git a/frontend/src/App/constants.ts b/frontend/src/App/constants.ts
new file mode 100644
index 0000000000..d861606c36
--- /dev/null
+++ b/frontend/src/App/constants.ts
@@ -0,0 +1,3 @@
+export const AUTH_DATA_STORAGE_KEY = 'authData';
+export const MODE_STORAGE_KEY = 'mode';
+export const TUTORIAL_SHOW_STARTUP_STORAGE_KEY = 'tutorial-show-startup';
diff --git a/frontend/src/App/helpers.ts b/frontend/src/App/helpers.ts
new file mode 100644
index 0000000000..d02a016e1e
--- /dev/null
+++ b/frontend/src/App/helpers.ts
@@ -0,0 +1,8 @@
+import { Mode } from '@cloudscape-design/global-styles';
+
+export const getThemeMode = (): Mode => (window?.matchMedia('(prefers-color-scheme: dark)').matches ? Mode.Dark : Mode.Light);
+
+export function getBaseUrl(): string {
+ const { protocol, hostname, port } = window.location;
+ return `${protocol}//${hostname}${port ? `:${port}` : ''}`;
+}
diff --git a/frontend/src/App/index.tsx b/frontend/src/App/index.tsx
new file mode 100644
index 0000000000..de0f919079
--- /dev/null
+++ b/frontend/src/App/index.tsx
@@ -0,0 +1,86 @@
+import React, { useEffect } from 'react';
+import { useTranslation } from 'react-i18next';
+import { Outlet, useLocation } from 'react-router-dom';
+
+import AppLayout from 'layouts/AppLayout';
+
+import { useAppDispatch, useAppSelector } from 'hooks';
+import { useGetUserDataQuery } from 'services/user';
+
+import { EnterpriseLogin } from './Login/EnterpriseLogin';
+import { LoginByGithub } from './Login/LoginByGithub';
+import { ROUTES } from '../routes';
+import { AuthErrorMessage } from './AuthErrorMessage';
+import { selectAuthToken, setUserData } from './slice';
+
+const localStorageIsAvailable = 'localStorage' in window;
+
+const IGNORED_AUTH_PATHS = [
+ ROUTES.AUTH.GITHUB_CALLBACK,
+ ROUTES.AUTH.OKTA_CALLBACK,
+ ROUTES.AUTH.ENTRA_CALLBACK,
+ ROUTES.AUTH.GOOGLE_CALLBACK,
+ ROUTES.AUTH.TOKEN,
+];
+
+const LoginFormComponent = process.env.UI_VERSION === 'enterprise' ? EnterpriseLogin : LoginByGithub;
+
+const App: React.FC = () => {
+ const { t } = useTranslation();
+ const token = useAppSelector(selectAuthToken);
+ const isAuthenticated = Boolean(token);
+ const dispatch = useAppDispatch();
+ const { pathname } = useLocation();
+
+ const {
+ isLoading,
+ data: userData,
+ error: getUserError,
+ } = useGetUserDataQuery(
+ { token },
+ {
+ skip: !isAuthenticated || !localStorageIsAvailable,
+ },
+ );
+
+ useEffect(() => {
+ if (userData?.username || getUserError) {
+ if (userData?.username) {
+ dispatch(setUserData(userData));
+ }
+ }
+ }, [userData, getUserError, isLoading]);
+
+ const renderLocalstorageError = () => {
+ return (
+
+ );
+ };
+
+ const renderTokenError = () => {
+ return ;
+ };
+
+ const renderNotAuthorizedError = () => {
+ return ;
+ };
+
+ if (IGNORED_AUTH_PATHS.includes(pathname)) {
+ return ;
+ }
+
+ if (!localStorageIsAvailable) return renderLocalstorageError();
+ if (getUserError) return renderTokenError();
+ if (!isAuthenticated) return renderNotAuthorizedError();
+
+ return (
+
+
+
+ );
+};
+
+export default App;
diff --git a/frontend/src/App/slice.ts b/frontend/src/App/slice.ts
new file mode 100644
index 0000000000..9d684d5850
--- /dev/null
+++ b/frontend/src/App/slice.ts
@@ -0,0 +1,193 @@
+import type { RootState } from 'store';
+import { applyMode, Mode } from '@cloudscape-design/global-styles';
+import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+
+import { AUTH_DATA_STORAGE_KEY, MODE_STORAGE_KEY, TUTORIAL_SHOW_STARTUP_STORAGE_KEY } from './constants';
+import { getThemeMode } from './helpers';
+
+import { IAppState, ToolsTabs } from './types';
+
+const getInitialState = (): IAppState => {
+ let authData = null;
+ let storageData = null;
+ let hideStartUp: null | boolean = null;
+ let activeMode = getThemeMode();
+
+ try {
+ storageData = localStorage.getItem(AUTH_DATA_STORAGE_KEY);
+ } catch (e) {
+ console.log(e);
+ }
+
+ try {
+ hideStartUp = (() => {
+ if (!localStorage.getItem(TUTORIAL_SHOW_STARTUP_STORAGE_KEY)) {
+ return null;
+ }
+
+ return localStorage.getItem(TUTORIAL_SHOW_STARTUP_STORAGE_KEY) === 'true';
+ })();
+ } catch (e) {
+ console.log(e);
+ }
+
+ try {
+ const modeStorageData = localStorage.getItem(MODE_STORAGE_KEY);
+
+ if (modeStorageData) {
+ activeMode = modeStorageData as Mode;
+ }
+ } catch (e) {
+ console.log(e);
+ }
+
+ applyMode(activeMode);
+
+ if (storageData) authData = JSON.parse(storageData) as IUserAuthData;
+
+ return {
+ authData,
+ userData: null,
+ breadcrumbs: null,
+ systemMode: activeMode,
+
+ toolsPanelState: {
+ isOpen: false,
+ tab: ToolsTabs.TUTORIAL,
+ },
+
+ helpPanel: {
+ content: {},
+ },
+
+ tutorialPanel: {
+ createProjectCompleted: false,
+ billingCompleted: false,
+ configureCLICompleted: false,
+ discordCompleted: false,
+ tallyCompleted: false,
+ quickStartCompleted: false,
+ hideStartUp,
+ },
+ };
+};
+
+const initialState: IAppState = getInitialState();
+
+export const appSlice = createSlice({
+ name: 'app',
+ initialState,
+
+ reducers: {
+ setAuthData: (state, action: PayloadAction) => {
+ state.authData = action.payload;
+
+ try {
+ localStorage.setItem(AUTH_DATA_STORAGE_KEY, JSON.stringify(action.payload));
+ } catch (e) {
+ console.log(e);
+ }
+ },
+
+ setSystemMode: (state, action: PayloadAction) => {
+ state.systemMode = action.payload;
+ applyMode(action.payload);
+ try {
+ localStorage.setItem(MODE_STORAGE_KEY, action.payload);
+ } catch (e) {
+ console.log(e);
+ }
+ },
+
+ removeAuthData: (state) => {
+ state.authData = null;
+
+ try {
+ localStorage.removeItem(AUTH_DATA_STORAGE_KEY);
+ } catch (e) {
+ console.log(e);
+ }
+ },
+
+ setUserData: (state, action: PayloadAction) => {
+ state.userData = action.payload;
+ },
+
+ setBreadcrumb: (state, action: PayloadAction) => {
+ state.breadcrumbs = action.payload;
+ },
+
+ openHelpPanel: (state, action: PayloadAction) => {
+ state.toolsPanelState = {
+ isOpen: true,
+ tab: ToolsTabs.INFO,
+ };
+
+ state.helpPanel = { content: action.payload };
+ },
+
+ openTutorialPanel: (state) => {
+ state.toolsPanelState = {
+ isOpen: true,
+ tab: ToolsTabs.TUTORIAL,
+ };
+ },
+
+ closeToolsPanel: (state) => {
+ state.toolsPanelState = {
+ ...state.toolsPanelState,
+ isOpen: false,
+ };
+ },
+
+ setToolsTab: (state, action: PayloadAction) => {
+ state.toolsPanelState = {
+ ...state.toolsPanelState,
+ tab: action.payload,
+ };
+ },
+
+ updateTutorialPanelState: (state, action: PayloadAction>) => {
+ state.tutorialPanel = {
+ ...state.tutorialPanel,
+ ...action.payload,
+ };
+ },
+
+ setHideAtStartup: (state, action: PayloadAction) => {
+ state.tutorialPanel = {
+ ...state.tutorialPanel,
+ hideStartUp: action.payload,
+ };
+
+ try {
+ localStorage.setItem(TUTORIAL_SHOW_STARTUP_STORAGE_KEY, JSON.stringify(action.payload));
+ } catch (e) {
+ console.log(e);
+ }
+ },
+ },
+});
+
+export const {
+ setAuthData,
+ setSystemMode,
+ removeAuthData,
+ setUserData,
+ setBreadcrumb,
+ openHelpPanel,
+ closeToolsPanel,
+ setToolsTab,
+ openTutorialPanel,
+ updateTutorialPanelState,
+ setHideAtStartup,
+} = appSlice.actions;
+export const selectUserData = (state: RootState) => state.app.userData;
+export const selectAuthToken = (state: RootState) => state.app.authData?.token;
+export const selectUserName = (state: RootState) => state.app.userData?.username;
+export const selectBreadcrumbs = (state: RootState) => state.app.breadcrumbs;
+export const selectToolsPanelState = (state: RootState) => state.app.toolsPanelState;
+export const selectHelpPanelContent = (state: RootState) => state.app.helpPanel.content;
+export const selectTutorialPanel = (state: RootState) => state.app.tutorialPanel;
+export const selectSystemMode = (state: RootState) => state.app.systemMode;
+export default appSlice.reducer;
diff --git a/frontend/src/App/types.ts b/frontend/src/App/types.ts
new file mode 100644
index 0000000000..262c1b156c
--- /dev/null
+++ b/frontend/src/App/types.ts
@@ -0,0 +1,43 @@
+import { TutorialPanelProps } from '@cloudscape-design/components';
+import { Mode } from '@cloudscape-design/global-styles';
+
+import { HelpPanelProps } from 'components';
+
+export type THelpPanelContent = Pick & { body?: HelpPanelProps['children'] };
+
+export enum ToolsTabs {
+ INFO = 'info',
+ TUTORIAL = 'tutorial',
+}
+
+export interface ITutorialItem extends TutorialPanelProps.Tutorial {
+ id: number;
+ startCallback?: (tutorial: ITutorialItem) => void;
+ startWithoutActivation?: boolean;
+ finishCallback?: (tutorial: ITutorialItem) => void;
+}
+
+export interface IAppState {
+ userData: IUser | null;
+ authData: IUserAuthData | null;
+ breadcrumbs: TBreadcrumb[] | null;
+ systemMode: Mode;
+ toolsPanelState: {
+ isOpen: boolean;
+ tab: ToolsTabs;
+ };
+
+ helpPanel: {
+ content: THelpPanelContent;
+ };
+
+ tutorialPanel: {
+ createProjectCompleted: boolean;
+ billingCompleted: boolean;
+ configureCLICompleted: boolean;
+ discordCompleted: boolean;
+ tallyCompleted: boolean;
+ quickStartCompleted: boolean;
+ hideStartUp: boolean | null;
+ };
+}
diff --git a/frontend/src/api.ts b/frontend/src/api.ts
new file mode 100644
index 0000000000..78fcd72c33
--- /dev/null
+++ b/frontend/src/api.ts
@@ -0,0 +1,193 @@
+const BASE_URL = process.env.API_URL;
+
+export const API = {
+ BASE: () => `${BASE_URL}`,
+
+ AUTH: {
+ BASE: () => `${API.BASE()}/auth`,
+ NEXT_REDIRECT: () => `${API.AUTH.BASE()}/get_next_redirect`,
+ GITHUB: {
+ BASE: () => `${API.AUTH.BASE()}/github`,
+ AUTHORIZE: () => `${API.AUTH.GITHUB.BASE()}/authorize`,
+ CALLBACK: () => `${API.AUTH.GITHUB.BASE()}/callback`,
+ },
+ OKTA: {
+ BASE: () => `${API.AUTH.BASE()}/okta`,
+ INFO: () => `${API.AUTH.OKTA.BASE()}/info`,
+ AUTHORIZE: () => `${API.AUTH.OKTA.BASE()}/authorize`,
+ CALLBACK: () => `${API.AUTH.OKTA.BASE()}/callback`,
+ },
+ ENTRA: {
+ BASE: () => `${API.AUTH.BASE()}/entra`,
+ INFO: () => `${API.AUTH.ENTRA.BASE()}/info`,
+ AUTHORIZE: () => `${API.AUTH.ENTRA.BASE()}/authorize`,
+ CALLBACK: () => `${API.AUTH.ENTRA.BASE()}/callback`,
+ },
+ GOOGLE: {
+ BASE: () => `${API.AUTH.BASE()}/google`,
+ INFO: () => `${API.AUTH.GOOGLE.BASE()}/info`,
+ AUTHORIZE: () => `${API.AUTH.GOOGLE.BASE()}/authorize`,
+ CALLBACK: () => `${API.AUTH.GOOGLE.BASE()}/callback`,
+ },
+ },
+
+ USERS: {
+ BASE: () => `${API.BASE()}/users`,
+ LIST: () => `${API.USERS.BASE()}/list`,
+ CREATE: () => `${API.USERS.BASE()}/create`,
+ UPDATE: () => `${API.USERS.BASE()}/update`,
+ DETAILS: () => `${API.USERS.BASE()}/get_user`,
+ CURRENT_USER: () => `${API.USERS.BASE()}/get_my_user`,
+ REFRESH_TOKEN: () => `${API.USERS.BASE()}/refresh_token`,
+ DELETE: () => `${API.USERS.BASE()}/delete`,
+ },
+
+ USER_PAYMENTS: {
+ BASE: (username: string) => `${API.BASE()}/user/${username}/payments`,
+ LIST: (username: string) => `${API.USER_PAYMENTS.BASE(username)}/list`,
+ ADD: (username: string) => `${API.USER_PAYMENTS.BASE(username)}/add`,
+ },
+
+ USER_BILLING: {
+ BASE: (username: string) => `${API.BASE()}/user/${username}/billing`,
+ INFO: (username: string) => `${API.USER_BILLING.BASE(username)}/info`,
+ CHECKOUT_SESSION: (username: string) => `${API.USER_BILLING.BASE(username)}/checkout_session`,
+ PORTAL_SESSION: (username: string) => `${API.USER_BILLING.BASE(username)}/portal_session`,
+ },
+
+ EVENTS: {
+ BASE: () => `${API.BASE()}/events`,
+ LIST: () => `${API.EVENTS.BASE()}/list`,
+ },
+
+ PROJECTS: {
+ BASE: () => `${API.BASE()}/projects`,
+ LIST: () => `${API.PROJECTS.BASE()}/list`,
+ LIST_ONLY_NO_FLEETS: () => `${API.PROJECTS.BASE()}/list_only_no_fleets`,
+ CREATE: () => `${API.PROJECTS.BASE()}/create`,
+ CREATE_WIZARD: () => `${API.PROJECTS.BASE()}/create_wizard`,
+ DELETE: () => `${API.PROJECTS.BASE()}/delete`,
+ DETAILS: (name: IProject['project_name']) => `${API.PROJECTS.BASE()}/${name}`,
+ DETAILS_INFO: (name: IProject['project_name']) => `${API.PROJECTS.DETAILS(name)}/get`,
+ SET_MEMBERS: (name: IProject['project_name']) => `${API.PROJECTS.DETAILS(name)}/set_members`,
+ ADD_MEMBERS: (name: IProject['project_name']) => `${API.PROJECTS.DETAILS(name)}/add_members`,
+ REMOVE_MEMBERS: (name: IProject['project_name']) => `${API.PROJECTS.DETAILS(name)}/remove_members`,
+ UPDATE: (name: IProject['project_name']) => `${API.PROJECTS.DETAILS(name)}/update`,
+
+ // Repos
+ REPOS: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/repos`,
+ REPOS_LIST: (projectName: IProject['project_name']) => `${API.PROJECTS.REPOS(projectName)}/list`,
+ GET_REPO: (projectName: IProject['project_name']) => `${API.PROJECTS.REPOS(projectName)}/get`,
+ INIT_REPO: (projectName: IProject['project_name']) => `${API.PROJECTS.REPOS(projectName)}/init`,
+
+ // Runs
+ RUNS: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/runs`,
+ RUNS_LIST: (projectName: IProject['project_name']) => `${API.PROJECTS.RUNS(projectName)}/list`,
+ RUN_DETAILS: (projectName: IProject['project_name']) => `${API.PROJECTS.RUNS(projectName)}/get`,
+ RUN_GET_PLAN: (projectName: IProject['project_name']) => `${API.PROJECTS.RUNS(projectName)}/get_plan`,
+ RUNS_DELETE: (projectName: IProject['project_name']) => `${API.PROJECTS.RUNS(projectName)}/delete`,
+ RUNS_STOP: (projectName: IProject['project_name']) => `${API.PROJECTS.RUNS(projectName)}/stop`,
+ RUNS_SUBMIT: (projectName: IProject['project_name']) => `${API.PROJECTS.RUNS(projectName)}/submit`,
+ RUNS_APPLY: (projectName: IProject['project_name']) => `${API.PROJECTS.RUNS(projectName)}/apply`,
+
+ // Logs
+ LOGS: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/logs/poll`,
+
+ // Logs
+ ARTIFACTS: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/artifacts/list`,
+
+ // Fleets
+ FLEETS: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/fleets/list`,
+ FLEETS_DETAILS: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/fleets/get`,
+ FLEETS_APPLY: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/fleets/apply`,
+ FLEETS_DELETE: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/fleets/delete`,
+ FLEET_INSTANCES_DELETE: (projectName: IProject['project_name']) =>
+ `${API.BASE()}/project/${projectName}/fleets/delete_instances`,
+
+ // Fleets
+ VOLUMES_DELETE: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/volumes/delete`,
+
+ // METRICS
+ JOB_METRICS: (projectName: IProject['project_name'], runName: IRun['run_spec']['run_name']) =>
+ `${API.BASE()}/project/${projectName}/metrics/job/${runName}`,
+
+ // SECRETS
+ SECRETS_LIST: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/secrets/list`,
+ SECRET_GET: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/secrets/get`,
+ SECRETS_UPDATE: (projectName: IProject['project_name']) =>
+ `${API.BASE()}/project/${projectName}/secrets/create_or_update`,
+ SECRETS_DELETE: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/secrets/delete`,
+ // GPUS
+ GPUS_LIST: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/gpus/list`,
+ // GPUS
+ TEMPLATES_LIST: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/templates/list`,
+ },
+
+ BACKENDS: {
+ BASE: () => `${API.BASE()}/backends`,
+ LIST_TYPES: () => `${API.BACKENDS.BASE()}/list_types`,
+ LIST_BASE_TYPES: () => `${API.BACKENDS.BASE()}/list_base_types`,
+ CONFIG_VALUES: () => `${API.BACKENDS.BASE()}/config_values`,
+ },
+
+ PROJECT_BACKENDS: {
+ BASE: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/backends`,
+ LIST: (projectName: IProject['project_name']) => `${API.PROJECT_BACKENDS.BASE(projectName)}/list`,
+ CREATE: (projectName: IProject['project_name']) => `${API.PROJECT_BACKENDS.BASE(projectName)}/create`,
+ UPDATE: (projectName: IProject['project_name']) => `${API.PROJECT_BACKENDS.BASE(projectName)}/update`,
+ DELETE: (projectName: IProject['project_name']) => `${API.PROJECT_BACKENDS.BASE(projectName)}/delete`,
+ BACKEND_CONFIG_INFO: (projectName: IProject['project_name'], backendName: string) =>
+ `${API.PROJECT_BACKENDS.BASE(projectName)}/${backendName}/config_info`,
+ CREATE_YAML: (projectName: IProject['project_name']) => `${API.PROJECT_BACKENDS.BASE(projectName)}/create_yaml`,
+ UPDATE_YAML: (projectName: IProject['project_name']) => `${API.PROJECT_BACKENDS.BASE(projectName)}/update_yaml`,
+ GET_YAML: (projectName: IProject['project_name'], backendName: string) =>
+ `${API.PROJECT_BACKENDS.BASE(projectName)}/${backendName}/get_yaml`,
+ },
+
+ PROJECT_GATEWAYS: {
+ BASE: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/gateways`,
+ LIST: (projectName: IProject['project_name']) => `${API.PROJECT_GATEWAYS.BASE(projectName)}/list`,
+ CREATE: (projectName: IProject['project_name']) => `${API.PROJECT_GATEWAYS.BASE(projectName)}/create`,
+ DELETE: (projectName: IProject['project_name']) => `${API.PROJECT_GATEWAYS.BASE(projectName)}/delete`,
+ DETAILS: (projectName: IProject['project_name']) => `${API.PROJECT_GATEWAYS.BASE(projectName)}/get`,
+ SET_DEFAULT: (projectName: IProject['project_name']) => `${API.PROJECT_GATEWAYS.BASE(projectName)}/set_default`,
+ SET_WILDCARD_DOMAIN: (projectName: IProject['project_name']) =>
+ `${API.PROJECT_GATEWAYS.BASE(projectName)}/set_wildcard_domain`,
+
+ // TEST_DOMAIN: (projectName: IProject['project_name'], instanceName: string) =>
+ // `${API.PROJECT_GATEWAYS.DETAILS(projectName, instanceName)}/test_domain`,
+ },
+
+ RUNS: {
+ BASE: () => `${API.BASE()}/runs`,
+ LIST: () => `${API.RUNS.BASE()}/list`,
+ },
+
+ FLEETS: {
+ BASE: () => `${API.BASE()}/fleets`,
+ LIST: () => `${API.FLEETS.BASE()}/list`,
+ },
+
+ INSTANCES: {
+ BASE: () => `${API.BASE()}/instances`,
+ LIST: () => `${API.INSTANCES.BASE()}/list`,
+ DETAILS: (projectName: IProject['project_name']) => `${API.BASE()}/project/${projectName}/instances/get`,
+ },
+
+ SERVER: {
+ BASE: () => `${API.BASE()}/server`,
+ INFO: () => `${API.SERVER.BASE()}/get_info`,
+ },
+
+ VOLUME: {
+ BASE: () => `${API.BASE()}/volumes`,
+ LIST: () => `${API.VOLUME.BASE()}/list`,
+ },
+
+ USER_PUBLIC_KEYS: {
+ BASE: () => `${API.BASE()}/users/public_keys`,
+ LIST: () => `${API.USER_PUBLIC_KEYS.BASE()}/list`,
+ ADD: () => `${API.USER_PUBLIC_KEYS.BASE()}/add`,
+ DELETE: () => `${API.USER_PUBLIC_KEYS.BASE()}/delete`,
+ },
+};
diff --git a/frontend/src/assets/css/index.css b/frontend/src/assets/css/index.css
new file mode 100644
index 0000000000..d309dec325
--- /dev/null
+++ b/frontend/src/assets/css/index.css
@@ -0,0 +1,4 @@
+.b-page-header {
+ position: relative;
+ z-index: 1002;
+}
diff --git a/gateway/src/tests/core/__init__.py b/frontend/src/assets/css/mixins.css
similarity index 100%
rename from gateway/src/tests/core/__init__.py
rename to frontend/src/assets/css/mixins.css
diff --git a/frontend/src/assets/css/variables.css b/frontend/src/assets/css/variables.css
new file mode 100644
index 0000000000..76e0780a3a
--- /dev/null
+++ b/frontend/src/assets/css/variables.css
@@ -0,0 +1,8 @@
+@custom-media --mobile (width <= 640px);
+@custom-media --no-mobile (width > 640px);
+@custom-media --no-desktop (width < 980px);
+@custom-media --desktop (width >= 980px);
+
+:root {
+
+}
diff --git a/src/dstack/_internal/core/backends/remote/__init__.py b/frontend/src/assets/icons/.gitkeep
similarity index 100%
rename from src/dstack/_internal/core/backends/remote/__init__.py
rename to frontend/src/assets/icons/.gitkeep
diff --git a/frontend/src/assets/icons/entraID.svg b/frontend/src/assets/icons/entraID.svg
new file mode 100644
index 0000000000..0b8d726be7
--- /dev/null
+++ b/frontend/src/assets/icons/entraID.svg
@@ -0,0 +1,9 @@
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/assets/icons/github.svg b/frontend/src/assets/icons/github.svg
new file mode 100644
index 0000000000..31b3210206
--- /dev/null
+++ b/frontend/src/assets/icons/github.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/frontend/src/assets/icons/google.svg b/frontend/src/assets/icons/google.svg
new file mode 100644
index 0000000000..b352dde5d2
--- /dev/null
+++ b/frontend/src/assets/icons/google.svg
@@ -0,0 +1 @@
+
diff --git a/frontend/src/assets/icons/okta.svg b/frontend/src/assets/icons/okta.svg
new file mode 100644
index 0000000000..b36435a638
--- /dev/null
+++ b/frontend/src/assets/icons/okta.svg
@@ -0,0 +1,2 @@
+
+
diff --git a/frontend/src/assets/icons/theme.svg b/frontend/src/assets/icons/theme.svg
new file mode 100644
index 0000000000..b3c4d3b3bc
--- /dev/null
+++ b/frontend/src/assets/icons/theme.svg
@@ -0,0 +1,3 @@
+
+
+
diff --git a/src/dstack/_internal/server/background/tasks/__init__.py b/frontend/src/assets/images/.gitkeep
similarity index 100%
rename from src/dstack/_internal/server/background/tasks/__init__.py
rename to frontend/src/assets/images/.gitkeep
diff --git a/docs/assets/images/dstack-logo-notext.png b/frontend/src/assets/images/favicon.png
similarity index 100%
rename from docs/assets/images/dstack-logo-notext.png
rename to frontend/src/assets/images/favicon.png
diff --git a/frontend/src/assets/images/logo.svg b/frontend/src/assets/images/logo.svg
new file mode 100644
index 0000000000..f02e82d421
--- /dev/null
+++ b/frontend/src/assets/images/logo.svg
@@ -0,0 +1,124 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/frontend/src/components/Button/index.tsx b/frontend/src/components/Button/index.tsx
new file mode 100644
index 0000000000..770fc6bf7d
--- /dev/null
+++ b/frontend/src/components/Button/index.tsx
@@ -0,0 +1,22 @@
+import React from 'react';
+import classNames from 'classnames';
+import ButtonGeneral, { ButtonProps } from '@cloudscape-design/components/button';
+
+import styles from './styles.module.scss';
+
+type Variant = ButtonProps.Variant | 'danger-normal';
+
+export interface IProps extends Omit {
+ variant?: Variant;
+}
+
+export const Button: React.FC = ({ children, variant, ...props }) => {
+ const componentVariant: ButtonProps.Variant | undefined = variant === 'danger-normal' ? 'normal' : variant;
+ return (
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+
+ {children}
+
+ );
+};
diff --git a/frontend/src/components/Button/styles.module.scss b/frontend/src/components/Button/styles.module.scss
new file mode 100644
index 0000000000..02157f7200
--- /dev/null
+++ b/frontend/src/components/Button/styles.module.scss
@@ -0,0 +1,15 @@
+@use '@cloudscape-design/design-tokens/index' as awsui;
+
+.button {
+ &.danger-normal {
+ &:not([disabled]) {
+ color: awsui.$color-charts-red-600 !important;
+ border-color: awsui.$color-charts-red-600 !important;
+
+ &:hover {
+ color: awsui.$color-charts-red-500 !important;
+ border-color: awsui.$color-charts-red-500 !important;
+ }
+ }
+ }
+}
diff --git a/frontend/src/components/ButtonWithConfirmation/index.tsx b/frontend/src/components/ButtonWithConfirmation/index.tsx
new file mode 100644
index 0000000000..56ae78ad59
--- /dev/null
+++ b/frontend/src/components/ButtonWithConfirmation/index.tsx
@@ -0,0 +1,56 @@
+import React, { useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import Box from '@cloudscape-design/components/box';
+
+import { Button } from '../Button';
+import { ConfirmationDialog } from '../ConfirmationDialog';
+
+import { IProps } from './types';
+
+export const ButtonWithConfirmation: React.FC = ({
+ confirmTitle,
+ confirmContent,
+ onClick,
+ confirmButtonLabel,
+ ...props
+}) => {
+ const { t } = useTranslation();
+ const [showDeleteConfirm, setShowConfirmDelete] = useState(false);
+
+ const toggleDeleteConfirm = () => {
+ setShowConfirmDelete((val) => !val);
+ };
+
+ const onConfirm = () => {
+ if (onClick) onClick();
+
+ setShowConfirmDelete(false);
+ };
+
+ const getContent = () => {
+ if (!confirmContent) {
+ return {t('confirm_dialog.message')} ;
+ }
+
+ if (typeof confirmContent === 'string') {
+ return {confirmContent} ;
+ }
+
+ return confirmContent;
+ };
+
+ return (
+ <>
+
+
+
+ >
+ );
+};
diff --git a/frontend/src/components/ButtonWithConfirmation/types.ts b/frontend/src/components/ButtonWithConfirmation/types.ts
new file mode 100644
index 0000000000..b796b4dfbb
--- /dev/null
+++ b/frontend/src/components/ButtonWithConfirmation/types.ts
@@ -0,0 +1,10 @@
+import { ReactNode } from 'react';
+
+import type { IProps as ButtonProps } from '../Button';
+
+export interface IProps extends Omit {
+ confirmTitle?: string;
+ confirmContent?: ReactNode;
+ confirmButtonLabel?: string;
+ onClick?: () => void;
+}
diff --git a/frontend/src/components/Code/index.tsx b/frontend/src/components/Code/index.tsx
new file mode 100644
index 0000000000..db16c4fcb1
--- /dev/null
+++ b/frontend/src/components/Code/index.tsx
@@ -0,0 +1,21 @@
+import React, { forwardRef } from 'react';
+import classNames from 'classnames';
+import Box from '@cloudscape-design/components/box';
+
+import styles from './styles.module.scss';
+
+export interface Props extends React.PropsWithChildren {
+ className?: string;
+}
+
+export const Code = forwardRef(({ children, className }, ref) => {
+ return (
+
+
+ {children}
+
+
+ );
+});
+
+Code.displayName = 'Code';
diff --git a/frontend/src/components/Code/styles.module.scss b/frontend/src/components/Code/styles.module.scss
new file mode 100644
index 0000000000..d6c0b7d638
--- /dev/null
+++ b/frontend/src/components/Code/styles.module.scss
@@ -0,0 +1,8 @@
+@use '@cloudscape-design/design-tokens/index' as awsui;
+
+.code {
+ padding: 8px;
+ background-color: awsui.$color-background-input-disabled;
+ border-radius: 8px;
+ white-space: pre-wrap;
+}
diff --git a/frontend/src/components/CodeEditor/constants.ts b/frontend/src/components/CodeEditor/constants.ts
new file mode 100644
index 0000000000..86d70816e6
--- /dev/null
+++ b/frontend/src/components/CodeEditor/constants.ts
@@ -0,0 +1,25 @@
+import type { CodeEditorProps } from '@cloudscape-design/components/code-editor';
+
+export const CODE_EDITOR_I18N_STRINGS: CodeEditorProps['i18nStrings'] = {
+ loadingState: 'Loading code editor',
+ errorState: 'There was an error loading the code editor.',
+ errorStateRecovery: 'Retry',
+
+ editorGroupAriaLabel: 'Code editor',
+ statusBarGroupAriaLabel: 'Status bar',
+
+ cursorPosition: (row, column) => `Ln ${row}, Col ${column}`,
+ errorsTab: 'Errors',
+ warningsTab: 'Warnings',
+ preferencesButtonAriaLabel: 'Preferences',
+
+ paneCloseButtonAriaLabel: 'Close',
+
+ preferencesModalHeader: 'Preferences',
+ preferencesModalCancel: 'Cancel',
+ preferencesModalConfirm: 'Confirm',
+ preferencesModalWrapLines: 'Wrap lines',
+ preferencesModalTheme: 'Theme',
+ preferencesModalLightThemes: 'Light themes',
+ preferencesModalDarkThemes: 'Dark themes',
+};
diff --git a/frontend/src/components/CodeEditor/index.tsx b/frontend/src/components/CodeEditor/index.tsx
new file mode 100644
index 0000000000..f8d9daf385
--- /dev/null
+++ b/frontend/src/components/CodeEditor/index.tsx
@@ -0,0 +1,55 @@
+import React, { useEffect, useState } from 'react';
+import ace from 'ace-builds';
+import GeneralCodeEditor, { CodeEditorProps as GeneralCodeEditorProps } from '@cloudscape-design/components/code-editor';
+
+ace.config.set('useWorker', false);
+
+import { Mode } from '@cloudscape-design/global-styles';
+
+import { useAppSelector } from 'hooks';
+
+import { selectSystemMode } from 'App/slice';
+
+import { CODE_EDITOR_I18N_STRINGS } from './constants';
+
+import 'ace-builds/src-noconflict/theme-cloud_editor';
+import 'ace-builds/src-noconflict/theme-cloud_editor_dark';
+import 'ace-builds/src-noconflict/mode-yaml';
+import 'ace-builds/src-noconflict/mode-json';
+import 'ace-builds/src-noconflict/ext-language_tools';
+
+export type CodeEditorProps = Omit;
+
+export const CodeEditor: React.FC = (props) => {
+ const systemMode = useAppSelector(selectSystemMode) ?? '';
+
+ const [codeEditorPreferences, setCodeEditorPreferences] = useState(() => ({
+ theme: systemMode === Mode.Dark ? 'cloud_editor_dark' : 'cloud_editor',
+ }));
+
+ useEffect(() => {
+ if (systemMode === Mode.Dark)
+ setCodeEditorPreferences({
+ theme: 'cloud_editor_dark',
+ });
+ else
+ setCodeEditorPreferences({
+ theme: 'cloud_editor',
+ });
+ }, [systemMode]);
+
+ const onCodeEditorPreferencesChange: GeneralCodeEditorProps['onPreferencesChange'] = (e) => {
+ setCodeEditorPreferences(e.detail);
+ };
+
+ return (
+
+ );
+};
diff --git a/frontend/src/components/ConfirmationDialog/index.tsx b/frontend/src/components/ConfirmationDialog/index.tsx
new file mode 100644
index 0000000000..082d15f8d8
--- /dev/null
+++ b/frontend/src/components/ConfirmationDialog/index.tsx
@@ -0,0 +1,46 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import Box from '@cloudscape-design/components/box';
+import Button from '@cloudscape-design/components/button';
+import Modal from '@cloudscape-design/components/modal';
+import SpaceBetween from '@cloudscape-design/components/space-between';
+
+import { IProps } from './types';
+
+export const ConfirmationDialog: React.FC = ({
+ title: titleProp,
+ content,
+ visible = false,
+ onDiscard,
+ onConfirm,
+ cancelButtonLabel: cancelButtonLabelProp,
+ confirmButtonLabel: confirmButtonLabelProp,
+}) => {
+ const { t } = useTranslation();
+ const title = titleProp ?? t('confirm_dialog.title');
+ const cancelButtonLabel = cancelButtonLabelProp ?? t('common.cancel');
+ const confirmButtonLabel = confirmButtonLabelProp ?? t('common.ok');
+
+ return (
+
+
+
+ {cancelButtonLabel}
+
+
+
+ {confirmButtonLabel}
+
+
+
+ }
+ >
+ {content}
+
+ );
+};
diff --git a/frontend/src/components/ConfirmationDialog/slice.ts b/frontend/src/components/ConfirmationDialog/slice.ts
new file mode 100644
index 0000000000..d662c6b5fa
--- /dev/null
+++ b/frontend/src/components/ConfirmationDialog/slice.ts
@@ -0,0 +1,34 @@
+import type { RootState } from 'store';
+import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+
+import { IProps as ConfirmationDialogProps } from './types';
+
+type ConfirmationDialogPropsWithUuid = ConfirmationDialogProps & { uuid: string };
+
+type ConfirmationDialogsStata = {
+ dialogs: Array;
+};
+
+const initialState: ConfirmationDialogsStata = {
+ dialogs: [],
+};
+
+export const confirmationSlice = createSlice({
+ name: 'confirmation',
+ initialState,
+
+ reducers: {
+ open: (state, action: PayloadAction) => {
+ state.dialogs = [...state.dialogs, action.payload];
+ },
+ close: (state, action: PayloadAction) => {
+ state.dialogs = state.dialogs.filter((i) => i.uuid !== action.payload);
+ },
+ },
+});
+
+export const { open, close } = confirmationSlice.actions;
+
+export const selectConfirmationDialogs = (state: RootState) => state.confirmation.dialogs;
+
+export default confirmationSlice.reducer;
diff --git a/src/dstack/_internal/server/services/backends/configurators/__init__.py b/frontend/src/components/ConfirmationDialog/styles.module.scss
similarity index 100%
rename from src/dstack/_internal/server/services/backends/configurators/__init__.py
rename to frontend/src/components/ConfirmationDialog/styles.module.scss
diff --git a/frontend/src/components/ConfirmationDialog/types.ts b/frontend/src/components/ConfirmationDialog/types.ts
new file mode 100644
index 0000000000..cdfb6bd070
--- /dev/null
+++ b/frontend/src/components/ConfirmationDialog/types.ts
@@ -0,0 +1,14 @@
+import { ReactNode } from 'react';
+
+import { ButtonProps } from 'components';
+
+export interface IProps {
+ title?: string;
+ content?: ReactNode;
+ visible?: boolean;
+ onDiscard: ButtonProps['onClick'];
+ onConfirm: ButtonProps['onClick'];
+
+ cancelButtonLabel?: string;
+ confirmButtonLabel?: string;
+}
diff --git a/frontend/src/components/DetailsHeader/index.tsx b/frontend/src/components/DetailsHeader/index.tsx
new file mode 100644
index 0000000000..b10df3ec5b
--- /dev/null
+++ b/frontend/src/components/DetailsHeader/index.tsx
@@ -0,0 +1,43 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import Button from '@cloudscape-design/components/button';
+import Header from '@cloudscape-design/components/header';
+import SpaceBetween from '@cloudscape-design/components/space-between';
+
+import { IProps } from './types';
+
+export const DetailsHeader: React.FC = ({
+ title,
+ actionButtons,
+ editAction,
+ deleteAction,
+ editDisabled,
+ deleteDisabled,
+}) => {
+ const { t } = useTranslation();
+
+ return (
+
+ {actionButtons}
+
+ {editAction && (
+
+ {t('common.edit')}
+
+ )}
+
+ {deleteAction && (
+
+ {t('common.delete')}
+
+ )}
+
+ }
+ >
+ {title}
+
+ );
+};
diff --git a/frontend/src/components/DetailsHeader/types.ts b/frontend/src/components/DetailsHeader/types.ts
new file mode 100644
index 0000000000..c917b58553
--- /dev/null
+++ b/frontend/src/components/DetailsHeader/types.ts
@@ -0,0 +1,10 @@
+import React from 'react';
+
+export interface IProps {
+ title: React.ReactNode;
+ editAction?: () => void;
+ deleteAction?: () => void;
+ editDisabled?: boolean;
+ deleteDisabled?: boolean;
+ actionButtons?: React.ReactNode;
+}
diff --git a/frontend/src/components/FileUploader/FileEntry/index.tsx b/frontend/src/components/FileUploader/FileEntry/index.tsx
new file mode 100644
index 0000000000..21ba14a2f7
--- /dev/null
+++ b/frontend/src/components/FileUploader/FileEntry/index.tsx
@@ -0,0 +1,62 @@
+import React, { useState } from 'react';
+import Box from '@cloudscape-design/components/box';
+import SpaceBetween from '@cloudscape-design/components/space-between';
+import StatusIndicator from '@cloudscape-design/components/status-indicator';
+
+export interface IProps {
+ file: File;
+ showImage?: boolean;
+ truncateLength?: number;
+ i18nStrings?: {
+ numberOfBytes: (n: number) => string;
+ lastModified: (d: Date) => string;
+ };
+}
+
+export const FileEntry: React.FC = ({ file, showImage = false, truncateLength = 20, i18nStrings }) => {
+ const [imageData, setImageData] = useState();
+
+ const reader = new FileReader();
+ reader.onload = (event) => {
+ setImageData(event.target.result as string);
+ };
+ reader.readAsDataURL(file);
+
+ const ext = file.name.split('.').pop()!;
+ const displayFileName =
+ file.name.length - ext.length - 1 > truncateLength ? `${file.name.slice(0, truncateLength)}... .${ext}` : file.name;
+ const lastModifiedDate = new Date(file.lastModified);
+ const fileSize = file.size;
+
+ return (
+
+
+ {showImage && (
+
+ )}
+
+ {displayFileName}
+
+ {/* eslint-disable-next-line no-constant-binary-expression */}
+ {false && (
+ <>
+ {i18nStrings ? i18nStrings.numberOfBytes(fileSize) : `${fileSize} bytes`}
+
+ {i18nStrings
+ ? i18nStrings.lastModified(lastModifiedDate)
+ : `Last modified: ${lastModifiedDate.toDateString()}`}
+
+ >
+ )}
+
+
+ );
+};
diff --git a/frontend/src/components/FileUploader/Token/index.tsx b/frontend/src/components/FileUploader/Token/index.tsx
new file mode 100644
index 0000000000..0f5bcf6ae5
--- /dev/null
+++ b/frontend/src/components/FileUploader/Token/index.tsx
@@ -0,0 +1,23 @@
+import React, { ReactNode } from 'react';
+import Button from '@cloudscape-design/components/button';
+import SpaceBetween from '@cloudscape-design/components/space-between';
+
+import styles from './styles.module.scss';
+
+export interface IProps {
+ children: ReactNode;
+ onClose?: () => void;
+}
+
+export const Token: React.FC = ({ children, onClose }) => {
+ return (
+
+
{children}
+ {!!onClose && (
+
+
+
+ )}
+
+ );
+};
diff --git a/frontend/src/components/FileUploader/Token/styles.module.scss b/frontend/src/components/FileUploader/Token/styles.module.scss
new file mode 100644
index 0000000000..09e14fa8d7
--- /dev/null
+++ b/frontend/src/components/FileUploader/Token/styles.module.scss
@@ -0,0 +1,8 @@
+.tokenPanel {
+ background-color: var(--color-background-item-selected-ebt4bi);
+ display: flex;
+ border: 0.2em solid var(--color-border-item-selected-ppkssz);
+ padding: 1em;
+ margin: 1em;
+ border-radius: var(--border-radius-token-wohc9e);
+}
diff --git a/frontend/src/components/FileUploader/index.tsx b/frontend/src/components/FileUploader/index.tsx
new file mode 100644
index 0000000000..c41f971a6e
--- /dev/null
+++ b/frontend/src/components/FileUploader/index.tsx
@@ -0,0 +1,99 @@
+import React from 'react';
+import Box from '@cloudscape-design/components/box';
+import Button from '@cloudscape-design/components/button';
+import FormField from '@cloudscape-design/components/form-field';
+
+import { FileEntry } from './FileEntry';
+import { Token } from './Token';
+
+export interface IProp {
+ fileInputId: string;
+ text: string;
+ label?: string;
+ description?: string;
+ info?: React.ReactNode;
+ constraintText?: string;
+ errorText?: string;
+ files: File[];
+ accept?: string;
+ onFilesUploaded: (uploadedFiles: File[]) => void;
+ onFileRemoved?: (fileIdx: number) => void;
+ multiple?: boolean;
+ i18nStrings?: {
+ numberOfBytes: (n: number) => string;
+ lastModified: (d: Date) => string;
+ };
+}
+
+export const FileUploader = ({
+ fileInputId,
+ text,
+ label,
+ description,
+ info,
+ constraintText,
+ errorText,
+ files,
+ onFilesUploaded,
+ onFileRemoved,
+ multiple = false,
+ i18nStrings,
+ accept,
+}: IProp) => {
+ return (
+ <>
+
+ {
+ document.getElementById(fileInputId)?.click();
+ }}
+ >
+ {
+ const fileInput = document.getElementById(fileInputId);
+
+ if (fileInput) onFilesUploaded(Array.from((fileInput as HTMLInputElement).files));
+ }}
+ />
+ {text}
+
+
+
+ {files &&
+ files.length > 0 &&
+ (multiple ? (
+ Array.from(files).map((file, fileIdx) => (
+
+ {
+ onFileRemoved(fileIdx);
+ }
+ : undefined
+ }
+ >
+
+
+
+ ))
+ ) : (
+
+ ))}
+
+ >
+ );
+};
diff --git a/frontend/src/components/Hotspot/index.tsx b/frontend/src/components/Hotspot/index.tsx
new file mode 100644
index 0000000000..12fa1ffffe
--- /dev/null
+++ b/frontend/src/components/Hotspot/index.tsx
@@ -0,0 +1,14 @@
+import React from 'react';
+import HotspotGeneral, { HotspotProps } from '@cloudscape-design/components/hotspot';
+
+export interface IProps extends HotspotProps {
+ renderHotspot?: boolean;
+}
+
+export const Hotspot: React.FC = ({ renderHotspot = true, children, ...props }) => {
+ if (!renderHotspot) {
+ return children;
+ }
+
+ return {children} ;
+};
diff --git a/frontend/src/components/InfoLink/index.tsx b/frontend/src/components/InfoLink/index.tsx
new file mode 100644
index 0000000000..e795c6c0fc
--- /dev/null
+++ b/frontend/src/components/InfoLink/index.tsx
@@ -0,0 +1,15 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import Link from '@cloudscape-design/components/link';
+
+import { IProps } from './types';
+
+export const InfoLink: React.FC = (props) => {
+ const { t } = useTranslation();
+
+ return (
+
+ {t('common.info')}
+
+ );
+};
diff --git a/frontend/src/components/InfoLink/types.ts b/frontend/src/components/InfoLink/types.ts
new file mode 100644
index 0000000000..07f19efe82
--- /dev/null
+++ b/frontend/src/components/InfoLink/types.ts
@@ -0,0 +1,7 @@
+import { LinkProps } from '@cloudscape-design/components/link';
+
+export interface IProps {
+ id?: string;
+ ariaLabel?: string;
+ onFollow: LinkProps['onFollow'];
+}
diff --git a/frontend/src/components/ListEmptyMessage/index.tsx b/frontend/src/components/ListEmptyMessage/index.tsx
new file mode 100644
index 0000000000..e62a643d29
--- /dev/null
+++ b/frontend/src/components/ListEmptyMessage/index.tsx
@@ -0,0 +1,16 @@
+import React from 'react';
+import Box from '@cloudscape-design/components/box';
+
+import { IProps } from './types';
+
+export const ListEmptyMessage: React.FC = ({ title, message, children }) => {
+ return (
+
+ {title && {title} }
+
+ {message}
+
+ {children}
+
+ );
+};
diff --git a/frontend/src/components/ListEmptyMessage/types.ts b/frontend/src/components/ListEmptyMessage/types.ts
new file mode 100644
index 0000000000..03c2d2ccb3
--- /dev/null
+++ b/frontend/src/components/ListEmptyMessage/types.ts
@@ -0,0 +1,7 @@
+import { ReactNode } from 'react';
+
+export interface IProps {
+ title?: string;
+ message?: string;
+ children?: ReactNode;
+}
diff --git a/frontend/src/components/Loader/index.tsx b/frontend/src/components/Loader/index.tsx
new file mode 100644
index 0000000000..9c6eddb92f
--- /dev/null
+++ b/frontend/src/components/Loader/index.tsx
@@ -0,0 +1,33 @@
+import React from 'react';
+import classNames from 'classnames';
+import Box, { BoxProps } from '@cloudscape-design/components/box';
+import SpaceBetween from '@cloudscape-design/components/space-between';
+import Spinner from '@cloudscape-design/components/spinner';
+
+import styles from './styles.module.scss';
+
+export interface Props {
+ show?: boolean;
+ className?: string;
+ padding?: BoxProps['padding'];
+ loadingText?: string;
+}
+
+export const Loader: React.FC = ({
+ className,
+ show = true,
+ loadingText = 'Loading',
+ padding = { vertical: 'xxxl' },
+}) => {
+ return (
+
+
+
+
+
+ {loadingText}
+
+
+
+ );
+};
diff --git a/frontend/src/components/Loader/styles.module.scss b/frontend/src/components/Loader/styles.module.scss
new file mode 100644
index 0000000000..9160174513
--- /dev/null
+++ b/frontend/src/components/Loader/styles.module.scss
@@ -0,0 +1,9 @@
+.loader {
+ display: flex;
+ justify-content: center;
+ transition: opacity .2s ease;
+
+ &:not(.show) {
+ opacity: 0;
+ }
+}
diff --git a/frontend/src/components/NavigateLink/index.tsx b/frontend/src/components/NavigateLink/index.tsx
new file mode 100644
index 0000000000..7bac639685
--- /dev/null
+++ b/frontend/src/components/NavigateLink/index.tsx
@@ -0,0 +1,21 @@
+import React from 'react';
+import { useNavigate } from 'react-router-dom';
+import Link, { LinkProps } from '@cloudscape-design/components/link';
+
+import styles from './style.module.scss';
+
+export const NavigateLink: React.FC = ({ onFollow, ...props }) => {
+ const navigate = useNavigate();
+ const onFollowHandler: LinkProps['onFollow'] = (event) => {
+ event.preventDefault();
+
+ if (onFollow) onFollow(event);
+ if (event.detail.href) navigate(event.detail.href);
+ };
+
+ return (
+
+
+
+ );
+};
diff --git a/frontend/src/components/NavigateLink/style.module.scss b/frontend/src/components/NavigateLink/style.module.scss
new file mode 100644
index 0000000000..27eca2e170
--- /dev/null
+++ b/frontend/src/components/NavigateLink/style.module.scss
@@ -0,0 +1,5 @@
+.link {
+ & > a {
+ text-decoration: underline !important;
+ }
+}
diff --git a/frontend/src/components/Notifications/index.tsx b/frontend/src/components/Notifications/index.tsx
new file mode 100644
index 0000000000..190788dda2
--- /dev/null
+++ b/frontend/src/components/Notifications/index.tsx
@@ -0,0 +1,12 @@
+import React from 'react';
+import Flashbar from '@cloudscape-design/components/flashbar';
+
+import { useAppSelector } from 'hooks';
+
+import { selectNotifications } from './slice';
+
+export const Notifications: React.FC = () => {
+ const notifications = useAppSelector(selectNotifications);
+
+ return ;
+};
diff --git a/frontend/src/components/Notifications/slice.ts b/frontend/src/components/Notifications/slice.ts
new file mode 100644
index 0000000000..bf51846193
--- /dev/null
+++ b/frontend/src/components/Notifications/slice.ts
@@ -0,0 +1,30 @@
+import type { RootState } from 'store';
+import { createSlice, PayloadAction } from '@reduxjs/toolkit';
+
+import { Notification } from './types';
+
+interface NotificationsState {
+ items: Notification[];
+}
+
+const initialState: NotificationsState = {
+ items: [],
+};
+
+export const notificationsSlice = createSlice({
+ name: 'notifications',
+ initialState,
+
+ reducers: {
+ push: (state, action: PayloadAction) => {
+ state.items = [...state.items, action.payload];
+ },
+ remove: (state, action: PayloadAction) => {
+ state.items = state.items.filter((i) => i.id !== action.payload);
+ },
+ },
+});
+
+export const { remove, push } = notificationsSlice.actions;
+export const selectNotifications = (state: RootState) => state.notifications.items;
+export default notificationsSlice.reducer;
diff --git a/frontend/src/components/Notifications/types.ts b/frontend/src/components/Notifications/types.ts
new file mode 100644
index 0000000000..b406b6e8dc
--- /dev/null
+++ b/frontend/src/components/Notifications/types.ts
@@ -0,0 +1,3 @@
+import { FlashbarProps } from '@cloudscape-design/components/flashbar';
+
+export type Notification = FlashbarProps.MessageDefinition;
diff --git a/frontend/src/components/PermissionGuard/index.tsx b/frontend/src/components/PermissionGuard/index.tsx
new file mode 100644
index 0000000000..4e73ca51eb
--- /dev/null
+++ b/frontend/src/components/PermissionGuard/index.tsx
@@ -0,0 +1,13 @@
+import React from 'react';
+
+import { usePermissionGuard } from 'hooks';
+
+import { IProps } from './types';
+
+export const PermissionGuard: React.FC = ({ children, ...props }) => {
+ const [isAvailable] = usePermissionGuard(props);
+
+ if (!isAvailable) return null;
+
+ return <>{children}>;
+};
diff --git a/frontend/src/components/PermissionGuard/types.ts b/frontend/src/components/PermissionGuard/types.ts
new file mode 100644
index 0000000000..bf85822f39
--- /dev/null
+++ b/frontend/src/components/PermissionGuard/types.ts
@@ -0,0 +1,10 @@
+import React from 'react';
+
+import { GlobalUserRole, ProjectUserRole } from 'types';
+
+export interface IProps {
+ allowedGlobalRoles?: GlobalUserRole[];
+ allowedProjectRoles?: ProjectUserRole[];
+ projectRole?: string;
+ children: React.ReactNode;
+}
diff --git a/frontend/src/components/Tabs/index.tsx b/frontend/src/components/Tabs/index.tsx
new file mode 100644
index 0000000000..e51196db9c
--- /dev/null
+++ b/frontend/src/components/Tabs/index.tsx
@@ -0,0 +1,46 @@
+import React, { useMemo } from 'react';
+import { useLocation, useNavigate } from 'react-router-dom';
+import classNames from 'classnames';
+import type { TabsProps } from '@cloudscape-design/components/tabs';
+import GeneralTabs from '@cloudscape-design/components/tabs';
+
+import styles from './styles.module.scss';
+
+export interface IProps extends TabsProps {
+ className?: string;
+ withNavigation?: boolean;
+}
+
+export const Tabs: React.FC = ({ className, withNavigation, onChange, activeTabId: activeTabIdProp, ...props }) => {
+ const navigate = useNavigate();
+ const { pathname } = useLocation();
+
+ const hasContent = useMemo(() => {
+ return props.tabs.some((tab) => !!tab.content);
+ }, [props.tabs]);
+
+ const activeTabId = useMemo(() => {
+ if (activeTabIdProp) return activeTabIdProp;
+
+ if (withNavigation) {
+ const tab = props.tabs.find((t) => pathname === t.href);
+ return tab?.id;
+ }
+ }, [pathname, activeTabIdProp]);
+
+ const onChangeTab: TabsProps['onChange'] = (event) => {
+ if (withNavigation) {
+ const { detail } = event;
+
+ navigate(detail.activeTabHref!);
+ }
+
+ if (onChange) onChange(event);
+ };
+
+ return (
+
+
+
+ );
+};
diff --git a/frontend/src/components/Tabs/styles.module.scss b/frontend/src/components/Tabs/styles.module.scss
new file mode 100644
index 0000000000..f527927646
--- /dev/null
+++ b/frontend/src/components/Tabs/styles.module.scss
@@ -0,0 +1,9 @@
+.tabs {
+ &:not(.hasContent) {
+ :global {
+ [class^="awsui_tabs-content-wrapper"] {
+ display: none;
+ }
+ }
+ }
+}
diff --git a/frontend/src/components/form/Cards/index.tsx b/frontend/src/components/form/Cards/index.tsx
new file mode 100644
index 0000000000..17b12f1934
--- /dev/null
+++ b/frontend/src/components/form/Cards/index.tsx
@@ -0,0 +1,38 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import Cards from '@cloudscape-design/components/cards';
+import { CardsProps } from '@cloudscape-design/components/cards';
+
+import { FormCardsProps } from './types';
+
+export const FormCards = ({
+ name,
+ control,
+ onSelectionChange: onSelectionChangeProp,
+ ...props
+}: FormCardsProps) => {
+ return (
+ {
+ const onSelectionChange: CardsProps['onSelectionChange'] = (event) => {
+ onChange(event.detail.selectedItems.map(({ value }) => value));
+ onSelectionChangeProp?.(event);
+ };
+
+ const selectedItems = props.items.filter((item) => fieldRest.value?.includes(item.value));
+
+ return (
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/Cards/types.ts b/frontend/src/components/form/Cards/types.ts
new file mode 100644
index 0000000000..857ac77a5b
--- /dev/null
+++ b/frontend/src/components/form/Cards/types.ts
@@ -0,0 +1,7 @@
+import { Control, FieldValues, Path } from 'react-hook-form';
+import { CardsProps } from '@cloudscape-design/components/cards';
+
+export type FormCardsProps = CardsProps & {
+ control: Control;
+ name: Path;
+};
diff --git a/frontend/src/components/form/Checkbox/index.tsx b/frontend/src/components/form/Checkbox/index.tsx
new file mode 100644
index 0000000000..ac64f8f54c
--- /dev/null
+++ b/frontend/src/components/form/Checkbox/index.tsx
@@ -0,0 +1,56 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import CheckboxCSD from '@cloudscape-design/components/checkbox';
+import FormField from '@cloudscape-design/components/form-field';
+
+import { FormCheckboxProps } from './types';
+
+export const FormCheckbox = ({
+ name,
+ control,
+ rules,
+ label,
+ info,
+ constraintText,
+ description,
+ secondaryControl,
+ stretch,
+ leftContent,
+ checkboxLabel,
+ onChange: onChangeProp,
+ ...props
+}: FormCheckboxProps) => {
+ return (
+ {
+ return (
+
+ {leftContent}
+ {
+ onChange(event.detail.checked);
+ onChangeProp?.(event);
+ }}
+ >
+ {checkboxLabel}
+
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/Checkbox/types.ts b/frontend/src/components/form/Checkbox/types.ts
new file mode 100644
index 0000000000..22b474bf71
--- /dev/null
+++ b/frontend/src/components/form/Checkbox/types.ts
@@ -0,0 +1,11 @@
+import { ReactNode } from 'react';
+import { ControllerProps, FieldValues } from 'react-hook-form';
+import { CheckboxProps } from '@cloudscape-design/components/checkbox';
+import { FormFieldProps } from '@cloudscape-design/components/form-field';
+
+export type FormCheckboxProps = Omit &
+ Omit &
+ Pick, 'control' | 'name' | 'rules'> & {
+ leftContent?: ReactNode;
+ checkboxLabel?: string;
+ };
diff --git a/frontend/src/components/form/CodeEditor/index.tsx b/frontend/src/components/form/CodeEditor/index.tsx
new file mode 100644
index 0000000000..254c960d00
--- /dev/null
+++ b/frontend/src/components/form/CodeEditor/index.tsx
@@ -0,0 +1,51 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import FormField from '@cloudscape-design/components/form-field';
+
+import { CodeEditor } from '../../CodeEditor';
+
+import { FormCodeEditorProps } from './types';
+
+export const FormCodeEditor = ({
+ name,
+ control,
+ rules,
+ label,
+ info,
+ constraintText,
+ description,
+ secondaryControl,
+ stretch,
+ onChange: onChangeProp,
+ ...props
+}: FormCodeEditorProps) => {
+ return (
+ {
+ return (
+
+ {
+ onChange(event.detail.value);
+ onChangeProp?.(event);
+ }}
+ />
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/CodeEditor/types.ts b/frontend/src/components/form/CodeEditor/types.ts
new file mode 100644
index 0000000000..baedd567b8
--- /dev/null
+++ b/frontend/src/components/form/CodeEditor/types.ts
@@ -0,0 +1,11 @@
+import { ControllerProps, FieldValues } from 'react-hook-form';
+import { FormFieldProps } from '@cloudscape-design/components/form-field';
+
+import { CodeEditorProps } from '../../CodeEditor';
+
+export type FormCodeEditorProps = Omit<
+ CodeEditorProps,
+ 'value' | 'name' | 'i18nStrings' | 'ace' | 'onPreferencesChange' | 'preferences'
+> &
+ Omit &
+ Pick, 'control' | 'name' | 'rules'>;
diff --git a/frontend/src/components/form/Input/index.tsx b/frontend/src/components/form/Input/index.tsx
new file mode 100644
index 0000000000..b0c745b105
--- /dev/null
+++ b/frontend/src/components/form/Input/index.tsx
@@ -0,0 +1,76 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import FormField from '@cloudscape-design/components/form-field';
+import Hotspot from '@cloudscape-design/components/hotspot';
+import InputCSD, { InputProps } from '@cloudscape-design/components/input';
+
+import { FormInputProps } from './types';
+
+export const FormInput = ({
+ name,
+ control,
+ rules,
+ defaultValue,
+ label,
+ info,
+ constraintText,
+ description,
+ secondaryControl,
+ stretch,
+ leftContent,
+ hotspotId,
+ onChange: onChangeProp,
+ ...props
+}: FormInputProps) => {
+ const renderInput = (renderProps: InputProps) => {
+ return ;
+ };
+
+ return (
+ {
+ return (
+
+ {leftContent}
+
+ {hotspotId ? (
+
+ {renderInput({
+ ...fieldRest,
+ ...props,
+ invalid: !!error,
+ onChange: (event) => {
+ onChange(event.detail.value);
+ onChangeProp?.(event);
+ },
+ })}
+
+ ) : (
+ renderInput({
+ ...fieldRest,
+ ...props,
+ invalid: !!error,
+ onChange: (event) => {
+ onChange(event.detail.value);
+ onChangeProp?.(event);
+ },
+ })
+ )}
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/Input/types.ts b/frontend/src/components/form/Input/types.ts
new file mode 100644
index 0000000000..74db1fd036
--- /dev/null
+++ b/frontend/src/components/form/Input/types.ts
@@ -0,0 +1,11 @@
+import { ReactNode } from 'react';
+import { ControllerProps, FieldValues } from 'react-hook-form';
+import { FormFieldProps } from '@cloudscape-design/components/form-field';
+import { InputProps } from '@cloudscape-design/components/input';
+
+export type FormInputProps = Omit &
+ Omit &
+ Pick, 'control' | 'name' | 'rules' | 'defaultValue'> & {
+ leftContent?: ReactNode;
+ hotspotId?: string;
+ };
diff --git a/frontend/src/components/form/Multiselect/index.tsx b/frontend/src/components/form/Multiselect/index.tsx
new file mode 100644
index 0000000000..93166c010b
--- /dev/null
+++ b/frontend/src/components/form/Multiselect/index.tsx
@@ -0,0 +1,58 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import FormField from '@cloudscape-design/components/form-field';
+import MultiselectCSD from '@cloudscape-design/components/multiselect';
+import { MultiselectProps } from '@cloudscape-design/components/multiselect/interfaces';
+
+import { FormMultiselectProps } from './types';
+
+export const FormMultiselect = ({
+ name,
+ rules,
+ control,
+ label,
+ info,
+ constraintText,
+ description,
+ secondaryControl,
+ stretch,
+ onChange: onChangeProp,
+ ...props
+}: FormMultiselectProps) => {
+ return (
+ {
+ const selectedOptions = props.options?.filter((i) => fieldRest.value?.includes(i.value)) ?? null;
+
+ const onChangeSelect: MultiselectProps['onChange'] = (event) => {
+ const value = event.detail.selectedOptions.map((item) => item.value);
+ onChange(value);
+ onChangeProp?.(event);
+ };
+
+ return (
+
+
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/Multiselect/types.ts b/frontend/src/components/form/Multiselect/types.ts
new file mode 100644
index 0000000000..310bc0bf4d
--- /dev/null
+++ b/frontend/src/components/form/Multiselect/types.ts
@@ -0,0 +1,15 @@
+import { ControllerProps, FieldValues } from 'react-hook-form';
+import { FormFieldProps } from '@cloudscape-design/components/form-field';
+import { MultiselectProps } from '@cloudscape-design/components/multiselect';
+
+export type FormMultiselectOption = MultiselectProps.Option;
+export type FormMultiselectOptions = ReadonlyArray;
+
+export type FormMultiselectProps = Omit<
+ MultiselectProps,
+ 'value' | 'name' | 'selectedOptions' | 'options'
+> &
+ Omit &
+ Pick, 'control' | 'name' | 'rules'> & {
+ options: ReadonlyArray;
+ };
diff --git a/frontend/src/components/form/RadioButtons/index.tsx b/frontend/src/components/form/RadioButtons/index.tsx
new file mode 100644
index 0000000000..aa56652d62
--- /dev/null
+++ b/frontend/src/components/form/RadioButtons/index.tsx
@@ -0,0 +1,48 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import FormField from '@cloudscape-design/components/form-field';
+import RadioGroup, { RadioGroupProps } from '@cloudscape-design/components/radio-group';
+
+import { FormRadioButtonsProps } from './types';
+
+export const FormRadioButtons = ({
+ name,
+ rules,
+ control,
+ label,
+ info,
+ constraintText,
+ description,
+ secondaryControl,
+ stretch,
+ onChange: onChangeProp,
+ ...props
+}: FormRadioButtonsProps) => {
+ return (
+ {
+ const onChangeSelect: RadioGroupProps['onChange'] = (event) => {
+ onChange(event.detail.value);
+ onChangeProp?.(event);
+ };
+
+ return (
+
+
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/RadioButtons/types.ts b/frontend/src/components/form/RadioButtons/types.ts
new file mode 100644
index 0000000000..9184b4841e
--- /dev/null
+++ b/frontend/src/components/form/RadioButtons/types.ts
@@ -0,0 +1,7 @@
+import { ControllerProps, FieldValues } from 'react-hook-form';
+import { FormFieldProps } from '@cloudscape-design/components/form-field';
+import { RadioGroupProps } from '@cloudscape-design/components/radio-group';
+
+export type FormRadioButtonsProps = Omit &
+ Omit &
+ Pick, 'control' | 'name' | 'rules'>;
diff --git a/frontend/src/components/form/S3BucketSelector/index.tsx b/frontend/src/components/form/S3BucketSelector/index.tsx
new file mode 100644
index 0000000000..90b930af6e
--- /dev/null
+++ b/frontend/src/components/form/S3BucketSelector/index.tsx
@@ -0,0 +1,94 @@
+import React, { useMemo, useRef } from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import cn from 'classnames';
+import FormField from '@cloudscape-design/components/form-field';
+import S3ResourceSelector from '@cloudscape-design/components/s3-resource-selector';
+import { S3ResourceSelectorProps } from '@cloudscape-design/components/s3-resource-selector';
+
+import { getResourceSelectorI18n } from './utils';
+
+import { FormS3BucketSelectorProps } from './types';
+
+import styles from './styles.module.scss';
+
+export const FormS3BucketSelector = ({
+ name,
+ rules,
+ control,
+ label,
+ buckets: bucketsProp,
+ info,
+ constraintText,
+ description,
+ secondaryControl,
+ stretch,
+ onChange: onChangeProp,
+ disabled,
+ prefix = 's3://',
+ i18nStrings,
+ ...props
+}: FormS3BucketSelectorProps) => {
+ const fetch = async () => Promise.resolve([]);
+ const lastValue = useRef(null);
+
+ const buckets = useMemo(() => {
+ return bucketsProp.map((i) => ({
+ Name: i.name,
+ CreationDate: i.created,
+ Region: i.region,
+ }));
+ }, [bucketsProp]);
+
+ const fetchBuckets = (): Promise => Promise.resolve(buckets);
+
+ const customProps = {
+ bucketsVisibleColumns: ['Name'],
+ fetchBuckets: fetchBuckets,
+ fetchObjects: fetch,
+ fetchVersions: fetch,
+ i18nStrings: getResourceSelectorI18n(prefix, i18nStrings),
+ };
+
+ return (
+ {
+ const resource = { uri: value };
+ const onChangeSelect: S3ResourceSelectorProps['onChange'] = (event) => {
+ const bucket = event.detail.resource.uri.replace(/^s3:\/\//, '');
+
+ if (lastValue.current === bucket) return;
+ lastValue.current = bucket;
+
+ onChange(bucket);
+ onChangeProp?.(event);
+ };
+
+ return (
+
+
+
+
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/S3BucketSelector/styles.module.scss b/frontend/src/components/form/S3BucketSelector/styles.module.scss
new file mode 100644
index 0000000000..f0fb84b7f6
--- /dev/null
+++ b/frontend/src/components/form/S3BucketSelector/styles.module.scss
@@ -0,0 +1,24 @@
+@use '@cloudscape-design/design-tokens/index' as awsui;
+
+.bucketSelector {
+ &:global(.disabled) {
+ & * {
+ pointer-events: none!important;
+ }
+ & input {
+ background-color: awsui.$color-background-input-disabled !important;
+ border: 2px solid awsui.$color-background-input-disabled !important;
+ color: awsui.$color-text-input-disabled !important;
+ cursor: default !important;
+ }
+
+ & button {
+ background-color: awsui.$color-background-input-disabled !important;
+ border-color: awsui.$color-border-button-normal-disabled !important;
+ color: awsui.$color-text-interactive-disabled;
+ text-decoration: none !important;
+ pointer-events: none !important;
+ cursor: auto !important;
+ }
+ }
+}
diff --git a/frontend/src/components/form/S3BucketSelector/types.ts b/frontend/src/components/form/S3BucketSelector/types.ts
new file mode 100644
index 0000000000..82d2c2c732
--- /dev/null
+++ b/frontend/src/components/form/S3BucketSelector/types.ts
@@ -0,0 +1,16 @@
+import { ControllerProps, FieldValues } from 'react-hook-form';
+import { FormFieldProps } from '@cloudscape-design/components/form-field';
+import { S3ResourceSelectorProps } from '@cloudscape-design/components/s3-resource-selector';
+
+export type FormS3BucketSelectorProps = Omit<
+ S3ResourceSelectorProps,
+ 'resource' | 'fetchBuckets' | 'fetchVersions' | 'fetchObjects' | 'name' | 'i18nStrings'
+> &
+ Omit &
+ Pick, 'control' | 'name' | 'rules'> & {
+ prefix?: string;
+ label: string;
+ buckets: TAwsBucket[];
+ disabled?: boolean;
+ i18nStrings?: Partial;
+ };
diff --git a/frontend/src/components/form/S3BucketSelector/utils.ts b/frontend/src/components/form/S3BucketSelector/utils.ts
new file mode 100644
index 0000000000..8e24fb9187
--- /dev/null
+++ b/frontend/src/components/form/S3BucketSelector/utils.ts
@@ -0,0 +1,81 @@
+import { S3ResourceSelectorProps } from '@cloudscape-design/components/s3-resource-selector';
+
+export const getResourceSelectorI18n = (
+ prefix: string,
+ params?: Partial,
+): S3ResourceSelectorProps['i18nStrings'] => ({
+ inContextInputPlaceholder: 'my-bucket-name',
+ inContextSelectPlaceholder: '',
+ inContextBrowseButton: 'Browse S3',
+ inContextViewButton: 'View',
+ inContextViewButtonAriaLabel: 'View (opens in a new tab)',
+ inContextLoadingText: '',
+ inContextUriLabel: '',
+ inContextVersionSelectLabel: '',
+ modalTitle: 'Choose an archive in S3',
+ modalCancelButton: 'Cancel',
+ modalSubmitButton: 'Choose',
+ modalBreadcrumbRootItem: 'S3 buckets',
+ selectionBuckets: 'Buckets',
+ selectionObjects: '',
+ selectionVersions: '',
+ selectionBucketsSearchPlaceholder: 'Find bucket',
+ selectionObjectsSearchPlaceholder: 'Find object by prefix',
+ selectionVersionsSearchPlaceholder: 'Find version',
+ selectionBucketsLoading: 'Loading buckets',
+ selectionBucketsNoItems: 'No buckets',
+ selectionObjectsLoading: '',
+ selectionObjectsNoItems: '',
+ selectionVersionsLoading: '',
+ selectionVersionsNoItems: '',
+ filteringCounterText: (count: number) => '' + count + (count === 1 ? ' match' : ' matches'),
+ filteringNoMatches: 'No matches',
+ filteringCantFindMatch: "We can't find a match.",
+ clearFilterButtonText: 'Clear filter',
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ columnBucketID: 'ID',
+ columnBucketName: 'Name',
+ columnBucketCreationDate: 'Creation date',
+ columnBucketRegion: 'Region',
+ columnBucketAccess: 'Access',
+ // columnObjectID: 'ID',
+ // columnObjectKey: 'Key',
+ // columnObjectLastModified: 'Last modified',
+ // columnObjectSize: 'Size',
+ // columnVersionID: 'Version ID',
+ // columnVersionLastModified: 'Last modified',
+ // columnVersionSize: 'Size',
+ validationPathMustBegin: `The path must begin with ${prefix}`,
+ validationBucketLowerCase: 'The bucket name must start with a lowercase character or number.',
+ validationBucketMustNotContain: 'The bucket name must not contain uppercase characters.',
+ validationBucketMustComplyDns: 'The bucket name must comply with DNS naming conventions',
+ validationBucketLength: 'The bucket name must be from 3 to 63 characters.',
+ labelSortedDescending: (columnName: string) => columnName + ', sorted descending',
+ labelSortedAscending: (columnName: string) => columnName + ', sorted ascending',
+ labelNotSorted: (columnName: string) => columnName + ', not sorted',
+ labelsPagination: {
+ nextPageLabel: 'Next page',
+ previousPageLabel: 'Previous page',
+ pageLabel: (pageNumber: number) => 'Page ' + pageNumber + ' of all pages',
+ },
+ labelsBucketsSelection: {
+ itemSelectionLabel: (_, item) => item?.Name ?? '',
+ selectionGroupLabel: 'Buckets',
+ },
+ labelsObjectsSelection: {
+ itemSelectionLabel: () => '',
+ selectionGroupLabel: 'Objects',
+ },
+ labelsVersionsSelection: {
+ itemSelectionLabel: () => '',
+ selectionGroupLabel: 'Versions',
+ },
+ labelFiltering: (itemsType: string) => 'Find ' + itemsType,
+ labelRefresh: 'Refresh the data',
+ labelAlertDismiss: 'Dismiss the alert',
+ labelModalDismiss: 'Dismiss the modal',
+ labelBreadcrumbs: 'S3 navigation',
+
+ ...params,
+});
diff --git a/frontend/src/components/form/Select/index.tsx b/frontend/src/components/form/Select/index.tsx
new file mode 100644
index 0000000000..77dee60e11
--- /dev/null
+++ b/frontend/src/components/form/Select/index.tsx
@@ -0,0 +1,59 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import FormField from '@cloudscape-design/components/form-field';
+import SelectCSD from '@cloudscape-design/components/select';
+import { SelectProps } from '@cloudscape-design/components/select/interfaces';
+
+import { FormSelectProps } from './types';
+
+export const FormSelect = ({
+ name,
+ rules,
+ defaultValue,
+ control,
+ label,
+ info,
+ constraintText,
+ description,
+ secondaryControl,
+ stretch,
+ onChange: onChangeProp,
+ ...props
+}: FormSelectProps) => {
+ return (
+ {
+ const selectedOption = props.options?.find((i) => i.value === fieldRest.value) ?? null;
+
+ const onChangeSelect: SelectProps['onChange'] = (event) => {
+ onChange(event.detail.selectedOption.value);
+ onChangeProp?.(event);
+ };
+
+ return (
+
+
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/Select/types.ts b/frontend/src/components/form/Select/types.ts
new file mode 100644
index 0000000000..91bfd32427
--- /dev/null
+++ b/frontend/src/components/form/Select/types.ts
@@ -0,0 +1,12 @@
+import { ControllerProps, FieldValues } from 'react-hook-form';
+import { FormFieldProps } from '@cloudscape-design/components/form-field';
+import { SelectProps } from '@cloudscape-design/components/select';
+
+export type FormSelectOption = SelectProps.Option;
+export type FormSelectOptions = ReadonlyArray;
+
+export type FormSelectProps = Omit &
+ Omit &
+ Pick, 'control' | 'name' | 'rules' | 'defaultValue'> & {
+ options: ReadonlyArray;
+ };
diff --git a/frontend/src/components/form/Textarea/index.tsx b/frontend/src/components/form/Textarea/index.tsx
new file mode 100644
index 0000000000..e34ba2e6b5
--- /dev/null
+++ b/frontend/src/components/form/Textarea/index.tsx
@@ -0,0 +1,53 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import FormField from '@cloudscape-design/components/form-field';
+import TextareaCSD from '@cloudscape-design/components/textarea';
+
+import { FormTextareaProps } from './types';
+
+export const FormTextarea = ({
+ name,
+ control,
+ rules,
+ label,
+ info,
+ constraintText,
+ description,
+ secondaryControl,
+ stretch,
+ leftContent,
+ onChange: onChangeProp,
+ ...props
+}: FormTextareaProps) => {
+ return (
+ {
+ return (
+
+ {leftContent}
+ {
+ onChange(event.detail.value);
+ onChangeProp?.(event);
+ }}
+ />
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/Textarea/types.ts b/frontend/src/components/form/Textarea/types.ts
new file mode 100644
index 0000000000..5614525cae
--- /dev/null
+++ b/frontend/src/components/form/Textarea/types.ts
@@ -0,0 +1,10 @@
+import { ReactNode } from 'react';
+import { ControllerProps, FieldValues } from 'react-hook-form';
+import { FormFieldProps } from '@cloudscape-design/components/form-field';
+import { TextareaProps } from '@cloudscape-design/components/textarea';
+
+export type FormTextareaProps = Omit &
+ Omit &
+ Pick, 'control' | 'name' | 'rules'> & {
+ leftContent?: ReactNode;
+ };
diff --git a/frontend/src/components/form/Tiles/index.tsx b/frontend/src/components/form/Tiles/index.tsx
new file mode 100644
index 0000000000..82515115fa
--- /dev/null
+++ b/frontend/src/components/form/Tiles/index.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import Tiles from '@cloudscape-design/components/tiles';
+import { TilesProps } from '@cloudscape-design/components/tiles';
+
+import { FormTilesProps } from './types';
+
+export const FormTiles = ({ name, control, onChange: onChangeProp, ...props }: FormTilesProps) => {
+ return (
+ {
+ const onChangeSelect: TilesProps['onChange'] = (event) => {
+ onChange(event.detail.value);
+ onChangeProp?.(event);
+ };
+
+ return ;
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/Tiles/types.ts b/frontend/src/components/form/Tiles/types.ts
new file mode 100644
index 0000000000..4e9a28daff
--- /dev/null
+++ b/frontend/src/components/form/Tiles/types.ts
@@ -0,0 +1,7 @@
+import { Control, FieldValues, Path } from 'react-hook-form';
+import { TilesProps } from '@cloudscape-design/components/tiles';
+
+export type FormTilesProps = Omit & {
+ control: Control;
+ name: Path;
+};
diff --git a/frontend/src/components/form/Toogle/index.module.scss b/frontend/src/components/form/Toogle/index.module.scss
new file mode 100644
index 0000000000..b57b20a850
--- /dev/null
+++ b/frontend/src/components/form/Toogle/index.module.scss
@@ -0,0 +1,17 @@
+@use '@cloudscape-design/design-tokens/index' as awsui;
+
+.labelWithInfo {
+ display: inline-flex;
+ align-items: center;
+}
+
+.divider {
+ display: inline-block;
+ height: 16px;
+ border-left: 1px solid awsui.$color-border-divider-default;
+ margin: 0 8px;
+}
+
+.info {
+ display: inline-flex;
+}
diff --git a/frontend/src/components/form/Toogle/index.tsx b/frontend/src/components/form/Toogle/index.tsx
new file mode 100644
index 0000000000..1cdb3c62ad
--- /dev/null
+++ b/frontend/src/components/form/Toogle/index.tsx
@@ -0,0 +1,81 @@
+import React from 'react';
+import { Controller, FieldValues } from 'react-hook-form';
+import FormField from '@cloudscape-design/components/form-field';
+import ToggleCSD from '@cloudscape-design/components/toggle';
+
+import { FormToggleProps } from './types';
+
+import styles from './index.module.scss';
+
+export const FormToggle = ({
+ name,
+ control,
+ rules,
+ defaultValue,
+ label,
+ info,
+ constraintText,
+ description,
+ secondaryControl,
+ stretch,
+ leftContent,
+ toggleLabel,
+ onChange: onChangeProp,
+ toggleDescription,
+ toggleInfo,
+ errorText: externalErrorText,
+ ...props
+}: FormToggleProps) => {
+ return (
+ {
+ return (
+
+ {leftContent}
+
+ {
+ onChange(event.detail.checked);
+ onChangeProp?.(event);
+ }}
+ description={toggleDescription}
+ >
+ {(toggleLabel || toggleInfo) && (
+
+ {toggleLabel}
+ {toggleLabel && toggleInfo && }
+ {toggleInfo && (
+ e.stopPropagation()}
+ onMouseDown={(e) => e.stopPropagation()}
+ onPointerDown={(e) => e.stopPropagation()}
+ onKeyDown={(e) => e.stopPropagation()}
+ >
+ {toggleInfo}
+
+ )}
+
+ )}
+
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/components/form/Toogle/types.ts b/frontend/src/components/form/Toogle/types.ts
new file mode 100644
index 0000000000..bc037c23f7
--- /dev/null
+++ b/frontend/src/components/form/Toogle/types.ts
@@ -0,0 +1,13 @@
+import { ReactNode } from 'react';
+import { ControllerProps, FieldValues } from 'react-hook-form';
+import { FormFieldProps } from '@cloudscape-design/components/form-field';
+import { ToggleProps } from '@cloudscape-design/components/toggle';
+
+export type FormToggleProps = Omit &
+ FormFieldProps &
+ Pick, 'control' | 'name' | 'rules' | 'defaultValue'> & {
+ toggleDescription?: ReactNode;
+ leftContent?: ReactNode;
+ toggleLabel?: ReactNode | string;
+ toggleInfo?: ReactNode;
+ };
diff --git a/frontend/src/components/index.ts b/frontend/src/components/index.ts
new file mode 100644
index 0000000000..6acd2a2b05
--- /dev/null
+++ b/frontend/src/components/index.ts
@@ -0,0 +1,104 @@
+export { default as Alert } from '@cloudscape-design/components/alert';
+export type { AlertProps } from '@cloudscape-design/components/alert';
+export { default as Icon } from '@cloudscape-design/components/icon';
+export { default as ButtonDropdown } from '@cloudscape-design/components/button-dropdown';
+export type { ButtonDropdownProps } from '@cloudscape-design/components/button-dropdown';
+export { default as AppLayout } from '@cloudscape-design/components/app-layout';
+export type { AppLayoutProps } from '@cloudscape-design/components/app-layout';
+export { default as SideNavigation } from '@cloudscape-design/components/side-navigation';
+export type { SideNavigationProps } from '@cloudscape-design/components/side-navigation';
+export { default as TopNavigation } from '@cloudscape-design/components/top-navigation';
+export type { TopNavigationProps } from '@cloudscape-design/components/top-navigation';
+export { default as Box } from '@cloudscape-design/components/box';
+export { default as SpaceBetween } from '@cloudscape-design/components/space-between';
+export { default as Container } from '@cloudscape-design/components/container';
+export { default as Spinner } from '@cloudscape-design/components/spinner';
+export { default as Cards } from '@cloudscape-design/components/cards';
+export type { CardsProps } from '@cloudscape-design/components/cards';
+export { default as Header } from '@cloudscape-design/components/header';
+export { default as Link } from '@cloudscape-design/components/link';
+export type { LinkProps } from '@cloudscape-design/components/link';
+export { default as TextFilter } from '@cloudscape-design/components/text-filter';
+export { default as Pagination } from '@cloudscape-design/components/pagination';
+export { default as Table } from '@cloudscape-design/components/table';
+export type { TableProps } from '@cloudscape-design/components/table';
+export { default as CollectionPreferences } from '@cloudscape-design/components/collection-preferences';
+export type { CollectionPreferencesProps } from '@cloudscape-design/components/collection-preferences';
+export { default as ContentLayout } from '@cloudscape-design/components/content-layout';
+export { default as ColumnLayout } from '@cloudscape-design/components/column-layout';
+export { default as BreadcrumbGroup } from '@cloudscape-design/components/breadcrumb-group';
+export type { BreadcrumbGroupProps } from '@cloudscape-design/components/breadcrumb-group';
+export { default as FormUI } from '@cloudscape-design/components/form';
+export { default as FormField } from '@cloudscape-design/components/form-field';
+export { default as CheckboxCSD } from '@cloudscape-design/components/checkbox';
+export { default as InputCSD } from '@cloudscape-design/components/input';
+export { default as SelectCSD } from '@cloudscape-design/components/select';
+export type { SelectProps as SelectCSDProps } from '@cloudscape-design/components/select';
+export { default as MultiselectCSD } from '@cloudscape-design/components/multiselect';
+export type { MultiselectProps } from '@cloudscape-design/components/multiselect';
+export { default as StatusIndicator } from '@cloudscape-design/components/status-indicator';
+export type { StatusIndicatorProps } from '@cloudscape-design/components/status-indicator';
+export { default as Popover } from '@cloudscape-design/components/popover';
+export { default as Autosuggest } from '@cloudscape-design/components/autosuggest';
+export type { AutosuggestProps } from '@cloudscape-design/components/autosuggest';
+export { default as Grid } from '@cloudscape-design/components/grid';
+export { default as HelpPanel } from '@cloudscape-design/components/help-panel';
+export type { HelpPanelProps } from '@cloudscape-design/components/help-panel';
+export { default as TextContent } from '@cloudscape-design/components/text-content';
+export { default as Toggle } from '@cloudscape-design/components/toggle';
+export type { ToggleProps } from '@cloudscape-design/components/toggle';
+export { default as Modal } from '@cloudscape-design/components/modal';
+export { default as TutorialPanel } from '@cloudscape-design/components/tutorial-panel';
+export type { TutorialPanelProps } from '@cloudscape-design/components/tutorial-panel';
+export { default as AnnotationContext } from '@cloudscape-design/components/annotation-context';
+export type { AnnotationContextProps } from '@cloudscape-design/components/annotation-context';
+export { default as ChatBubble } from '@cloudscape-design/chat-components/chat-bubble';
+export type { ChatBubbleProps } from '@cloudscape-design/chat-components/chat-bubble';
+export { default as Avatar } from '@cloudscape-design/chat-components/avatar';
+export type { AvatarProps } from '@cloudscape-design/chat-components/avatar';
+export { default as LineChart } from '@cloudscape-design/components/line-chart';
+export { default as PropertyFilter } from '@cloudscape-design/components/property-filter';
+export type { PropertyFilterProps } from '@cloudscape-design/components/property-filter';
+export type { LineChartProps } from '@cloudscape-design/components/line-chart/interfaces';
+export type { ModalProps } from '@cloudscape-design/components/modal';
+export { default as AnchorNavigation } from '@cloudscape-design/components/anchor-navigation';
+export { default as ExpandableSection } from '@cloudscape-design/components/expandable-section';
+export { default as KeyValuePairs } from '@cloudscape-design/components/key-value-pairs';
+export { I18nProvider } from '@cloudscape-design/components/i18n';
+export { default as Wizard } from '@cloudscape-design/components/wizard';
+export { default as SegmentedControl } from '@cloudscape-design/components/segmented-control';
+export type { SegmentedControlProps } from '@cloudscape-design/components/segmented-control';
+
+// custom components
+export { NavigateLink } from './NavigateLink';
+export { ListEmptyMessage } from './ListEmptyMessage';
+export { DetailsHeader } from './DetailsHeader';
+export { Loader } from './Loader';
+export { FormCheckbox } from './form/Checkbox';
+export { FormToggle } from './form/Toogle';
+export { FormInput } from './form/Input';
+export { FormMultiselect } from './form/Multiselect';
+export { FormSelect } from './form/Select';
+export { FormTextarea } from './form/Textarea';
+export { FormCodeEditor } from './form/CodeEditor';
+export { FormRadioButtons } from './form/RadioButtons';
+export type { FormSelectOptions, FormSelectProps } from './form/Select/types';
+export type { FormMultiselectOptions, FormMultiselectProps } from './form/Multiselect/types';
+export { FormS3BucketSelector } from './form/S3BucketSelector';
+export type { FormTilesProps } from './form/Tiles/types';
+export { FormTiles } from './form/Tiles';
+export type { FormCardsProps } from './form/Cards/types';
+export { FormCards } from './form/Cards';
+export { Notifications } from './Notifications';
+export { ConfirmationDialog } from './ConfirmationDialog';
+export { CodeEditor } from './CodeEditor';
+export type { CodeEditorProps } from './CodeEditor';
+export { FileUploader } from './FileUploader';
+export { InfoLink } from './InfoLink';
+export { ButtonWithConfirmation } from './ButtonWithConfirmation';
+export { Tabs } from './Tabs';
+export { Button } from './Button';
+export type { IProps as ButtonProps } from './Button';
+export { Code } from './Code';
+export { Hotspot } from './Hotspot';
+export type { IProps as TabsProps } from './Tabs';
diff --git a/frontend/src/consts.ts b/frontend/src/consts.ts
new file mode 100644
index 0000000000..06715082d1
--- /dev/null
+++ b/frontend/src/consts.ts
@@ -0,0 +1,6 @@
+export const DATE_TIME_FORMAT = 'MM/dd/yyyy HH:mm';
+export const DISCORD_URL = 'https://discord.gg/u8SmfwPpMd';
+export const QUICK_START_URL = 'https://dstack.ai/docs/quickstart/';
+export const TALLY_FORM_ID = '3xYlYG';
+export const DOCS_URL = 'https://dstack.ai/docs/';
+export const DEFAULT_TABLE_PAGE_SIZE = 20;
diff --git a/frontend/src/consts/index.ts b/frontend/src/consts/index.ts
new file mode 100644
index 0000000000..663e7dedc1
--- /dev/null
+++ b/frontend/src/consts/index.ts
@@ -0,0 +1 @@
+export const TEMP = 'temp';
diff --git a/frontend/src/hooks/index.ts b/frontend/src/hooks/index.ts
new file mode 100644
index 0000000000..19a109d52c
--- /dev/null
+++ b/frontend/src/hooks/index.ts
@@ -0,0 +1,12 @@
+export { default as useAppDispatch } from './useAppDispatch';
+export { default as useAppSelector } from './useAppSelector';
+export { useBreadcrumbs } from './useBreadcrumbs';
+export { useNotifications } from './useNotifications';
+export { useConfirmationDialog } from './useConfirmationDialog';
+export { useHelpPanel } from './useHelpPanel';
+export { usePermissionGuard } from './usePermissionGuard';
+export { useInfiniteScroll } from './useInfiniteScroll';
+export { useLocalStorageState } from './useLocalStorageState';
+
+// cloudscape
+export { useCollection } from '@cloudscape-design/collection-hooks';
diff --git a/frontend/src/hooks/useAppDispatch.ts b/frontend/src/hooks/useAppDispatch.ts
new file mode 100644
index 0000000000..5abcc639ac
--- /dev/null
+++ b/frontend/src/hooks/useAppDispatch.ts
@@ -0,0 +1,6 @@
+import { useDispatch } from 'react-redux';
+import { AppDispatch } from 'store';
+
+const useAppDispatch = () => useDispatch();
+
+export default useAppDispatch;
diff --git a/frontend/src/hooks/useAppSelector.ts b/frontend/src/hooks/useAppSelector.ts
new file mode 100644
index 0000000000..a125d0e9f2
--- /dev/null
+++ b/frontend/src/hooks/useAppSelector.ts
@@ -0,0 +1,6 @@
+import { TypedUseSelectorHook, useSelector } from 'react-redux';
+import { RootState } from 'store';
+
+const useAppSelector: TypedUseSelectorHook = useSelector;
+
+export default useAppSelector;
diff --git a/frontend/src/hooks/useBreadcrumbs.ts b/frontend/src/hooks/useBreadcrumbs.ts
new file mode 100644
index 0000000000..7d47520bca
--- /dev/null
+++ b/frontend/src/hooks/useBreadcrumbs.ts
@@ -0,0 +1,17 @@
+import { useEffect } from 'react';
+
+import { setBreadcrumb } from 'App/slice';
+
+import useAppDispatch from './useAppDispatch';
+
+export const useBreadcrumbs = (breadcrumbs: TBreadcrumb[]) => {
+ const dispatch = useAppDispatch();
+
+ useEffect(() => {
+ dispatch(setBreadcrumb(breadcrumbs));
+
+ return () => {
+ dispatch(setBreadcrumb(null));
+ };
+ }, [breadcrumbs]);
+};
diff --git a/frontend/src/hooks/useCheckingForFleetsInProjectsOfMember.ts b/frontend/src/hooks/useCheckingForFleetsInProjectsOfMember.ts
new file mode 100644
index 0000000000..b330358b46
--- /dev/null
+++ b/frontend/src/hooks/useCheckingForFleetsInProjectsOfMember.ts
@@ -0,0 +1,40 @@
+import { useMemo } from 'react';
+
+import { useGetOnlyNoFleetsProjectsQuery, useGetProjectsQuery } from 'services/project';
+
+type Args = { projectNames?: IProject['project_name'][] };
+
+export const useCheckingForFleetsInProjects = ({ projectNames }: Args) => {
+ const { data: projectsData } = useGetProjectsQuery(
+ {},
+ {
+ skip: !!projectNames?.length,
+ },
+ );
+
+ const { data: noFleetsProjectsData } = useGetOnlyNoFleetsProjectsQuery();
+
+ const projectNameForChecking = useMemo(() => {
+ if (projectNames) {
+ return projectNames;
+ }
+
+ if (projectsData?.data) {
+ return projectsData.data.map((project) => project.project_name);
+ }
+
+ return [];
+ }, [projectNames, projectsData]);
+
+ const projectHavingFleetMap = useMemo>(() => {
+ const map: Record = {};
+
+ projectNameForChecking.forEach((projectName) => {
+ map[projectName] = !noFleetsProjectsData?.some((i) => i.project_name === projectName);
+ });
+
+ return map;
+ }, [projectNameForChecking, noFleetsProjectsData]);
+
+ return projectHavingFleetMap;
+};
diff --git a/frontend/src/hooks/useConfirmationDialog.ts b/frontend/src/hooks/useConfirmationDialog.ts
new file mode 100644
index 0000000000..f6ba67cdc5
--- /dev/null
+++ b/frontend/src/hooks/useConfirmationDialog.ts
@@ -0,0 +1,27 @@
+import { close, open } from 'components/ConfirmationDialog/slice';
+import { IProps as ConfirmationDialogProps } from 'components/ConfirmationDialog/types';
+
+import { getUid } from '../libs';
+import useAppDispatch from './useAppDispatch';
+
+export const useConfirmationDialog = () => {
+ const dispatch = useAppDispatch();
+
+ const onDiscard = (uuid: string) => {
+ dispatch(close(uuid));
+ };
+
+ const openConfirmationDialog = (props: Omit) => {
+ const uuid = getUid();
+
+ dispatch(
+ open({
+ uuid,
+ ...props,
+ onDiscard: () => onDiscard(uuid),
+ }),
+ );
+ };
+
+ return [openConfirmationDialog];
+};
diff --git a/frontend/src/hooks/useHelpPanel.ts b/frontend/src/hooks/useHelpPanel.ts
new file mode 100644
index 0000000000..fb88916065
--- /dev/null
+++ b/frontend/src/hooks/useHelpPanel.ts
@@ -0,0 +1,15 @@
+import { openHelpPanel } from 'App/slice';
+
+import useAppDispatch from './useAppDispatch';
+
+import { THelpPanelContent } from 'App/types';
+
+export const useHelpPanel = () => {
+ const dispatch = useAppDispatch();
+
+ const openPanel = (content: THelpPanelContent) => {
+ dispatch(openHelpPanel(content));
+ };
+
+ return [openPanel];
+};
diff --git a/frontend/src/hooks/useInfiniteScroll.ts b/frontend/src/hooks/useInfiniteScroll.ts
new file mode 100644
index 0000000000..9064e6b346
--- /dev/null
+++ b/frontend/src/hooks/useInfiniteScroll.ts
@@ -0,0 +1,166 @@
+/* eslint-disable @typescript-eslint/no-explicit-any */
+import { useCallback, useEffect, useLayoutEffect, useRef, useState } from 'react';
+import { isEqual } from 'lodash';
+import { UseLazyQuery /*, UseQueryStateOptions*/ } from '@reduxjs/toolkit/dist/query/react/buildHooks';
+import { QueryDefinition } from '@reduxjs/toolkit/query';
+
+const SCROLL_POSITION_GAP = 400;
+
+type InfinityListArgs = Partial>;
+
+type ListResponse = DataItem[];
+type ResponseWithDataProp = { data: ListResponse; total_count: number };
+
+type LazyQueryResponse = ResponseWithDataProp | ListResponse;
+
+type UseInfinityParams = {
+ useLazyQuery: UseLazyQuery, any>>;
+ args: { limit?: number } & Args;
+ getResponseItems?: (listItem: DataItem) => Partial;
+ getPaginationParams: (listItem: DataItem) => Partial;
+ skip?: boolean;
+ // options?: UseQueryStateOptions, Record>;
+};
+
+export const useInfiniteScroll = ({
+ useLazyQuery,
+ getPaginationParams,
+ // options,
+ args,
+ skip,
+}: UseInfinityParams) => {
+ const [data, setData] = useState>([]);
+ const [totalCount, setTotalCount] = useState();
+ const scrollElement = useRef(document.documentElement);
+ const isLoadingRef = useRef(false);
+ const isDisabledMoreRef = useRef(false);
+ const lastRequestParams = useRef(undefined);
+ const { limit, ...argsProp } = args;
+ const lastArgsProps = useRef>(null);
+
+ const [getItems, { isLoading, isFetching }] = useLazyQuery({ ...args } as Args);
+
+ const getDataRequest = (params: Args) => {
+ const request = getItems({
+ limit,
+ ...params,
+ } as Args).unwrap();
+
+ request.then(() => {
+ lastRequestParams.current = { ...params };
+ });
+
+ return request;
+ };
+
+ const getEmptyList = () => {
+ isLoadingRef.current = true;
+
+ setData([]);
+
+ getDataRequest(argsProp as Args).then((result: LazyQueryResponse) => {
+ // setDisabledMore(false);
+ isDisabledMoreRef.current = false;
+
+ if ('data' in result) {
+ setData(result.data as ListResponse);
+ setTotalCount(result.total_count);
+ } else {
+ setData(result as ListResponse);
+ setTotalCount();
+ }
+
+ isLoadingRef.current = false;
+ });
+ };
+
+ useEffect(() => {
+ if (!isEqual(argsProp, lastArgsProps.current) && !skip) {
+ getEmptyList();
+ lastArgsProps.current = argsProp as Args;
+ }
+ }, [argsProp, lastArgsProps, skip]);
+
+ const getMore = async () => {
+ if (isLoadingRef.current || isDisabledMoreRef.current || skip) {
+ return;
+ }
+
+ const requestParams = {
+ ...argsProp,
+ ...getPaginationParams(data[data.length - 1]),
+ };
+
+ if (!isEqual(requestParams, lastRequestParams.current)) {
+ try {
+ isLoadingRef.current = true;
+
+ const result = await getDataRequest(requestParams as Args);
+
+ let listResponse: ListResponse;
+
+ if ('data' in result) {
+ listResponse = result.data;
+ setTotalCount(result.total_count);
+ } else {
+ listResponse = result;
+ setTotalCount();
+ }
+
+ if (listResponse.length > 0) {
+ setData((prev) => [...prev, ...listResponse]);
+ } else {
+ isDisabledMoreRef.current = true;
+ }
+ } catch (e) {
+ console.log(e);
+ }
+
+ setTimeout(() => {
+ isLoadingRef.current = false;
+ }, 50);
+ }
+ };
+
+ useLayoutEffect(() => {
+ const element = scrollElement.current;
+
+ if (isLoadingRef.current || !data.length) return;
+
+ if (element.scrollHeight - element.clientHeight <= 0) {
+ getMore().catch(console.log);
+ }
+ }, [data]);
+
+ const onScroll = useCallback(() => {
+ if (isDisabledMoreRef.current || isLoadingRef.current) {
+ return;
+ }
+
+ const element = scrollElement.current;
+
+ const scrollPositionFromBottom = element.scrollHeight - (element.clientHeight + element.scrollTop);
+
+ if (scrollPositionFromBottom < SCROLL_POSITION_GAP) {
+ getMore().catch(console.log);
+ }
+ }, [getMore]);
+
+ useEffect(() => {
+ document.addEventListener('scroll', onScroll);
+
+ return () => {
+ document.removeEventListener('scroll', onScroll);
+ };
+ }, [onScroll]);
+
+ const isLoadingMore = data.length > 0 && isFetching;
+
+ return {
+ data,
+ totalCount,
+ isLoading: isLoading || (data.length === 0 && isFetching),
+ isLoadingMore,
+ refreshList: getEmptyList,
+ } as const;
+};
diff --git a/frontend/src/hooks/useIsMounted.ts b/frontend/src/hooks/useIsMounted.ts
new file mode 100644
index 0000000000..8eb727af34
--- /dev/null
+++ b/frontend/src/hooks/useIsMounted.ts
@@ -0,0 +1,17 @@
+import { useCallback, useEffect, useRef } from 'react';
+
+function useIsMounted() {
+ const isMounted = useRef(false);
+
+ useEffect(() => {
+ isMounted.current = true;
+
+ return () => {
+ isMounted.current = false;
+ };
+ }, []);
+
+ return useCallback(() => isMounted.current, []);
+}
+
+export default useIsMounted;
diff --git a/frontend/src/hooks/useLocalStorageState.ts b/frontend/src/hooks/useLocalStorageState.ts
new file mode 100644
index 0000000000..c2decd3ddd
--- /dev/null
+++ b/frontend/src/hooks/useLocalStorageState.ts
@@ -0,0 +1,37 @@
+import { useCallback, useEffect, useState } from 'react';
+
+export const useLocalStorageState = (key: string, defaultState?: T): [T, (state: T) => void] => {
+ const storageItem = localStorage.getItem(key);
+ const [state, setState] = useState(storageItem ? JSON.parse(storageItem) : defaultState);
+
+ useEffect(() => {
+ const listener = (event: StorageEvent) => {
+ if (event.key === key) {
+ setState(event.newValue ? JSON.parse(event.newValue) : defaultState);
+ }
+ };
+
+ window.addEventListener('storage', listener);
+
+ return () => {
+ window.removeEventListener('storage', listener);
+ };
+ }, [key, defaultState]);
+
+ const setStorage = useCallback(
+ (newState: T) => {
+ const storageState = JSON.stringify(newState);
+
+ window.dispatchEvent(
+ new StorageEvent('storage', {
+ key,
+ newValue: storageState,
+ }),
+ );
+ localStorage.setItem(key, storageState);
+ },
+ [key],
+ );
+
+ return [state, setStorage];
+};
diff --git a/frontend/src/hooks/useNotifications.ts b/frontend/src/hooks/useNotifications.ts
new file mode 100644
index 0000000000..61189303eb
--- /dev/null
+++ b/frontend/src/hooks/useNotifications.ts
@@ -0,0 +1,65 @@
+import { useEffect, useRef } from 'react';
+
+import { push, remove } from 'components/Notifications/slice';
+import { Notification } from 'components/Notifications/types';
+
+import { getUid } from 'libs';
+
+import useAppDispatch from './useAppDispatch';
+
+const NOTIFICATION_LIFE_TIME = 6000;
+
+type TUseNotificationsArgs = { temporary?: boolean; liveTime?: number } | undefined;
+
+const defaultArgs: NonNullable> = { temporary: true, liveTime: NOTIFICATION_LIFE_TIME };
+
+export const useNotifications = (args: TUseNotificationsArgs = defaultArgs) => {
+ const dispatch = useAppDispatch();
+ const notificationIdsSet = useRef(new Set>());
+
+ const { temporary, liveTime } = {
+ ...defaultArgs,
+ ...args,
+ };
+
+ const removeNotification = (id: NonNullable) => {
+ dispatch(remove(id));
+
+ if (notificationIdsSet.current.has(id)) {
+ notificationIdsSet.current.delete(id);
+ }
+ };
+
+ const pushNotification = (notification: Omit) => {
+ const id = getUid();
+
+ dispatch(
+ push({
+ id,
+ ...notification,
+ dismissible: true,
+ onDismiss: () => {
+ removeNotification(id);
+ },
+ }),
+ );
+
+ if (temporary) {
+ setTimeout(() => {
+ removeNotification(id);
+ }, liveTime);
+ } else {
+ notificationIdsSet.current.add(id);
+ }
+ };
+
+ useEffect(() => {
+ return () => {
+ notificationIdsSet.current.forEach((notificationId) => {
+ removeNotification(notificationId);
+ });
+ };
+ }, []);
+
+ return [pushNotification];
+};
diff --git a/frontend/src/hooks/useOnClickOutside.ts b/frontend/src/hooks/useOnClickOutside.ts
new file mode 100644
index 0000000000..cd36d38b03
--- /dev/null
+++ b/frontend/src/hooks/useOnClickOutside.ts
@@ -0,0 +1,24 @@
+import React, { useEffect } from 'react';
+
+function useOnClickOutside(
+ ref: React.RefObject,
+ handler: (event: MouseEvent | TouchEvent) => void,
+) {
+ useEffect(() => {
+ const listener = (event: MouseEvent | TouchEvent) => {
+ if (!ref.current || ref.current.contains(event.target as Node)) return;
+
+ handler(event);
+ };
+
+ document.addEventListener('mousedown', listener);
+ document.addEventListener('touchstart', listener);
+
+ return () => {
+ document.removeEventListener('mousedown', listener);
+ document.removeEventListener('touchstart', listener);
+ };
+ }, [ref, handler]);
+}
+
+export default useOnClickOutside;
diff --git a/frontend/src/hooks/usePermissionGuard.ts b/frontend/src/hooks/usePermissionGuard.ts
new file mode 100644
index 0000000000..c794403a5a
--- /dev/null
+++ b/frontend/src/hooks/usePermissionGuard.ts
@@ -0,0 +1,41 @@
+import { useMemo } from 'react';
+
+import { selectUserData } from 'App/slice';
+
+import useAppSelector from './useAppSelector';
+
+import { GlobalUserRole, ProjectUserRole, UserPermission } from '../types';
+
+interface Args {
+ allowedGlobalRoles?: GlobalUserRole[];
+ allowedProjectRoles?: ProjectUserRole[];
+ allowedPermissions?: UserPermission[];
+ projectRole?: string;
+}
+export const usePermissionGuard = ({ allowedGlobalRoles, allowedProjectRoles, allowedPermissions, projectRole }: Args) => {
+ const userData = useAppSelector(selectUserData);
+ const userGlobalRole = userData?.global_role ?? '';
+ const userPermissions = userData?.permissions ?? [];
+
+ const isAvailableForGlobalUser = useMemo(() => {
+ if (!allowedGlobalRoles?.length) return false;
+
+ return allowedGlobalRoles.includes(userGlobalRole as GlobalUserRole);
+ }, [allowedGlobalRoles, userGlobalRole]);
+
+ const isAvailableForProjectUser = useMemo(() => {
+ if (!allowedProjectRoles?.length) return false;
+
+ return allowedProjectRoles.includes(projectRole as ProjectUserRole);
+ }, [allowedGlobalRoles, userGlobalRole]);
+
+ const hasPermission = useMemo(() => {
+ if (!allowedPermissions?.length) return false;
+
+ return userPermissions.some((userPermission) => allowedPermissions.includes(userPermission as UserPermission));
+ }, [allowedGlobalRoles, userGlobalRole]);
+
+ const isAvailableContent = isAvailableForGlobalUser || isAvailableForProjectUser || hasPermission;
+
+ return [isAvailableContent] as const;
+};
diff --git a/frontend/src/hooks/usePrevious.ts b/frontend/src/hooks/usePrevious.ts
new file mode 100644
index 0000000000..dadc595ee5
--- /dev/null
+++ b/frontend/src/hooks/usePrevious.ts
@@ -0,0 +1,13 @@
+import { useEffect, useRef } from 'react';
+
+function usePrevious(value: T): T {
+ const ref = useRef(value);
+
+ useEffect(() => {
+ ref.current = value;
+ }, [value]);
+
+ return ref.current;
+}
+
+export default usePrevious;
diff --git a/frontend/src/hooks/useProjectFilter.ts b/frontend/src/hooks/useProjectFilter.ts
new file mode 100644
index 0000000000..5c54fd28e0
--- /dev/null
+++ b/frontend/src/hooks/useProjectFilter.ts
@@ -0,0 +1,45 @@
+import { useEffect, useMemo } from 'react';
+
+import { SelectCSDProps } from 'components';
+
+import { useGetProjectsQuery } from 'services/project';
+
+import { useLocalStorageState } from './useLocalStorageState';
+
+type Args = {
+ localStorePrefix: string;
+};
+
+export const useProjectFilter = ({ localStorePrefix }: Args) => {
+ const [selectedProject, setSelectedProject] = useLocalStorageState(
+ `${localStorePrefix}-project_name`,
+ null,
+ );
+
+ const { data: projectsData, isLoading } = useGetProjectsQuery({});
+
+ const projectOptions = useMemo(() => {
+ if (!projectsData?.data?.length) return [];
+
+ return projectsData.data.map((project) => ({ label: project.project_name, value: project.project_name }));
+ }, [projectsData]);
+
+ useEffect(() => {
+ if (!projectsData?.data || !selectedProject) {
+ return;
+ }
+
+ const hasSelectedProject = projectsData.data.some(({ project_name }) => selectedProject?.value === project_name);
+
+ if (!hasSelectedProject) {
+ setSelectedProject(null);
+ }
+ }, [projectsData]);
+
+ return {
+ projectOptions,
+ selectedProject,
+ setSelectedProject,
+ isLoadingProjectOptions: isLoading,
+ } as const;
+};
diff --git a/frontend/src/index.tsx b/frontend/src/index.tsx
new file mode 100644
index 0000000000..c02da1084c
--- /dev/null
+++ b/frontend/src/index.tsx
@@ -0,0 +1,46 @@
+import React from 'react';
+import { Provider as BusProvider } from 'react-bus';
+import { createRoot } from 'react-dom/client';
+import { Provider } from 'react-redux';
+import { RouterProvider } from 'react-router-dom';
+import { applyTheme, Theme } from '@cloudscape-design/components/theming';
+
+import { router } from './router';
+import { store } from './store';
+
+import '@cloudscape-design/global-styles/index.css';
+import 'ace-builds/css/ace.css';
+import 'ace-builds/css/theme/cloud_editor.css';
+import 'ace-builds/css/theme/cloud_editor_dark.css';
+import 'assets/css/index.css';
+
+import 'locale';
+
+const container = document.getElementById('root');
+
+const theme: Theme = {
+ tokens: {
+ fontFamilyBase:
+ 'metro-web, Metro, -apple-system, "system-ui", "Segoe UI", Roboto, Oxygen-Sans, Ubuntu, Cantarell, "Helvetica Neue", sans-serif',
+ fontSizeHeadingS: '15px',
+ fontSizeHeadingL: '19px',
+ fontSizeHeadingXl: '22px',
+ fontSizeDisplayL: '40px',
+ },
+};
+
+applyTheme({ theme });
+
+if (container) {
+ const root = createRoot(container);
+
+ root.render(
+
+
+
+
+
+
+ ,
+ );
+}
diff --git a/frontend/src/layouts/AppLayout/AnnotationContext/index.tsx b/frontend/src/layouts/AppLayout/AnnotationContext/index.tsx
new file mode 100644
index 0000000000..4ecde1c8a7
--- /dev/null
+++ b/frontend/src/layouts/AppLayout/AnnotationContext/index.tsx
@@ -0,0 +1,61 @@
+import React, { PropsWithChildren, useMemo, useState } from 'react';
+
+import { AnnotationContext as AnnotationContextGeneric, AnnotationContextProps } from 'components';
+
+import { useAppDispatch, useAppSelector } from 'hooks';
+
+import { selectToolsPanelState, setToolsTab } from 'App/slice';
+
+import { overlayI18nStrings } from '../TutorialPanel/constants';
+import { useTutorials } from '../TutorialPanel/hooks';
+
+import { ITutorialItem, ToolsTabs } from 'App/types';
+
+export const AnnotationContext: React.FC = ({ children }) => {
+ const dispatch = useAppDispatch();
+ const [activeTutorialId, setActiveTutorialId] = useState();
+ const { tab } = useAppSelector(selectToolsPanelState);
+
+ const { tutorials } = useTutorials();
+
+ const currentTutorial = useMemo(() => {
+ if (!activeTutorialId) return null;
+
+ return tutorials.find((t) => t.id === activeTutorialId) ?? null;
+ }, [activeTutorialId, tutorials]);
+
+ const onStepChange: AnnotationContextProps['onStepChange'] = () => {
+ if (tab !== ToolsTabs.TUTORIAL) dispatch(setToolsTab(ToolsTabs.TUTORIAL));
+ };
+
+ return (
+ {
+ const tutorial = event.detail.tutorial as ITutorialItem;
+
+ if (tutorial.startCallback) {
+ tutorial.startCallback(tutorial);
+ }
+
+ if (!tutorial.startWithoutActivation) {
+ setActiveTutorialId(tutorial.id);
+ }
+ }}
+ onExitTutorial={() => {
+ setActiveTutorialId(undefined);
+ }}
+ onFinish={() => {
+ if (currentTutorial && currentTutorial.finishCallback) {
+ currentTutorial.finishCallback(currentTutorial);
+ }
+
+ setActiveTutorialId(undefined);
+ }}
+ i18nStrings={overlayI18nStrings}
+ >
+ {children}
+
+ );
+};
diff --git a/frontend/src/layouts/AppLayout/Tally/index.tsx b/frontend/src/layouts/AppLayout/Tally/index.tsx
new file mode 100644
index 0000000000..638b3259bb
--- /dev/null
+++ b/frontend/src/layouts/AppLayout/Tally/index.tsx
@@ -0,0 +1,16 @@
+import React, { useEffect } from 'react';
+
+export const TallyComponent: React.FC = () => {
+ useEffect(() => {
+ const widgetScriptSrc = 'https://tally.so/widgets/embed.js';
+
+ if (document.querySelector(`script[src="${widgetScriptSrc}"]`) === null) {
+ const script = document.createElement('script');
+ script.src = widgetScriptSrc;
+ document.body.appendChild(script);
+ return;
+ }
+ }, []);
+
+ return null;
+};
diff --git a/frontend/src/layouts/AppLayout/TutorialPanel/constants.tsx b/frontend/src/layouts/AppLayout/TutorialPanel/constants.tsx
new file mode 100644
index 0000000000..4ee909c0cf
--- /dev/null
+++ b/frontend/src/layouts/AppLayout/TutorialPanel/constants.tsx
@@ -0,0 +1,177 @@
+// Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
+// SPDX-License-Identifier: MIT-0
+import React from 'react';
+
+import { AnnotationContextProps, TutorialPanelProps } from 'components';
+import { Box } from 'components';
+
+export const tutorialPanelI18nStrings: TutorialPanelProps.I18nStrings = {
+ labelsTaskStatus: { pending: 'Pending', 'in-progress': 'In progress', success: 'Success' },
+ loadingText: 'Loading',
+ tutorialListTitle: '',
+ tutorialListDescription: 'Follow the tutorials below to get up to speed with dstack Sky.',
+ tutorialListDownloadLinkText: 'Download PDF version',
+ tutorialCompletedText: 'Completed',
+ labelExitTutorial: 'dismiss tutorial',
+ learnMoreLinkText: 'Learn more',
+ startTutorialButtonText: 'Start',
+ restartTutorialButtonText: 'Restart',
+ completionScreenTitle: 'Congratulations! You completed it.',
+ feedbackLinkText: 'Feedback',
+ dismissTutorialButtonText: 'Dismiss',
+ taskTitle: (taskIndex, taskTitle) => `Task ${taskIndex + 1}: ${taskTitle}`,
+ stepTitle: (stepIndex, stepTitle) => `Step ${stepIndex + 1}: ${stepTitle}`,
+ labelTotalSteps: (totalStepCount) => `Total steps: ${totalStepCount}`,
+ labelLearnMoreExternalIcon: 'Opens in a new tab',
+ labelTutorialListDownloadLink: 'Download PDF version of this tutorial',
+ labelLearnMoreLink: 'Learn more about transcribe audio (opens new tab)',
+};
+
+export const overlayI18nStrings: AnnotationContextProps.I18nStrings = {
+ stepCounterText: (stepIndex, totalStepCount) => `Step ${stepIndex + 1}/${totalStepCount}`,
+ taskTitle: (taskIndex, taskTitle) => `Task ${taskIndex + 1}: ${taskTitle}`,
+ labelHotspot: (openState, stepIndex, totalStepCount) =>
+ openState
+ ? `close annotation for step ${stepIndex + 1} of ${totalStepCount}`
+ : `open annotation for step ${stepIndex + 1} of ${totalStepCount}`,
+ nextButtonText: 'Next',
+ previousButtonText: 'Previous',
+ finishButtonText: 'Finish',
+ labelDismissAnnotation: 'hide annotation',
+};
+
+export enum HotspotIds {
+ ADD_TOP_UP_BALANCE = 'billing-top-up-balance',
+ PAYMENT_CONTINUE_BUTTON = 'billing-payment-continue-button',
+ INSTALL_CLI_COMMAND = 'install-cli-command',
+ CONFIGURE_CLI_COMMAND = 'configure-cli-command',
+ CREATE_FIRST_PROJECT = 'create-first-project',
+}
+
+export const BILLING_TUTORIAL: TutorialPanelProps.Tutorial = {
+ completed: false,
+ title: 'Billing',
+ description: (
+ <>
+
+ If you plan to use the GPU marketplace, top up your balance with a credit card.
+
+ >
+ ),
+ completedScreenDescription: 'TBA',
+ tasks: [
+ {
+ title: 'Add payment method',
+ steps: [
+ {
+ title: 'Click Top up balance button',
+ content: 'Click Top up balance button',
+ hotspotId: HotspotIds.ADD_TOP_UP_BALANCE,
+ },
+ {
+ title: 'Click continue',
+ content: 'Please, click continue',
+ hotspotId: HotspotIds.PAYMENT_CONTINUE_BUTTON,
+ },
+ ],
+ },
+ ],
+};
+
+export const CONFIGURE_CLI_TUTORIAL: TutorialPanelProps.Tutorial = {
+ completed: false,
+ title: 'CLI',
+ prerequisitesAlert: 'Please, create a project before set up the CLI',
+ description: (
+ <>
+
+ Configure the CLI on your local machine to submit workload to dstack Sky.
+
+ >
+ ),
+ completedScreenDescription: 'TBA',
+ tasks: [
+ {
+ title: 'Configure the CLI',
+ steps: [
+ {
+ title: 'Run the CLI install command',
+ content: 'Run this command on your local machine to install the CLI.',
+ hotspotId: HotspotIds.INSTALL_CLI_COMMAND,
+ },
+ {
+ title: 'Run the dstack project add command',
+ content: 'Run this command on your local machine to configure the dstack CLI.',
+ hotspotId: HotspotIds.CONFIGURE_CLI_COMMAND,
+ },
+ ],
+ },
+ ],
+};
+
+export const CREATE_FIRST_PROJECT: TutorialPanelProps.Tutorial = {
+ completed: false,
+ title: 'Project',
+ description: (
+ <>
+
+ Create your first project. Choose to use the GPU marketplace or configure your own cloud credentials.
+
+ >
+ ),
+ completedScreenDescription: 'TBA',
+ tasks: [
+ {
+ title: 'Create the first project',
+ steps: [
+ {
+ title: 'Create the first project',
+ content: 'Create the first project',
+ hotspotId: HotspotIds.CREATE_FIRST_PROJECT,
+ },
+ ],
+ },
+ ],
+};
+
+export const JOIN_DISCORD_TUTORIAL: TutorialPanelProps.Tutorial = {
+ completed: false,
+ title: 'Discord',
+ description: (
+ <>
+
+ Need help or want to chat with other users of dstack? Join our Discord server!
+
+ >
+ ),
+ completedScreenDescription: 'TBA',
+ tasks: [],
+};
+
+export const QUICKSTART_TUTORIAL: TutorialPanelProps.Tutorial = {
+ completed: false,
+ title: 'Quickstart',
+ description: (
+ <>
+
+ Check out the quickstart guide to get started with dstack
+
+ >
+ ),
+ completedScreenDescription: 'TBA',
+ tasks: [],
+};
+
+export const CREDITS_TUTORIAL: TutorialPanelProps.Tutorial = {
+ completed: false,
+ title: 'Get free credits',
+ description: (
+ <>
+
+ Tell us about your project and get some free credits to try dstack Sky!
+
+ >
+ ),
+ completedScreenDescription: 'TBA',
+ tasks: [],
+};
diff --git a/frontend/src/layouts/AppLayout/TutorialPanel/hooks.ts b/frontend/src/layouts/AppLayout/TutorialPanel/hooks.ts
new file mode 100644
index 0000000000..305a711a05
--- /dev/null
+++ b/frontend/src/layouts/AppLayout/TutorialPanel/hooks.ts
@@ -0,0 +1,208 @@
+import { useCallback, useEffect, useMemo, useRef } from 'react';
+import { useLocation, useNavigate } from 'react-router-dom';
+
+import {
+ DISCORD_URL,
+ QUICK_START_URL,
+ // TALLY_FORM_ID
+} from 'consts';
+import { useAppDispatch, useAppSelector } from 'hooks';
+import { goToUrl } from 'libs';
+import { ROUTES } from 'routes';
+import { useGetProjectsQuery } from 'services/project';
+import { useGetRunsQuery } from 'services/run';
+import { useGetUserBillingInfoQuery } from 'services/user';
+
+import { openTutorialPanel, selectTutorialPanel, selectUserName, updateTutorialPanelState } from 'App/slice';
+
+import { useSideNavigation } from '../hooks';
+import {
+ BILLING_TUTORIAL,
+ CONFIGURE_CLI_TUTORIAL,
+ CREATE_FIRST_PROJECT,
+ // CREDITS_TUTORIAL,
+ JOIN_DISCORD_TUTORIAL,
+ QUICKSTART_TUTORIAL,
+} from './constants';
+
+import { ITutorialItem } from 'App/types';
+
+export const useTutorials = () => {
+ const navigate = useNavigate();
+ const location = useLocation();
+ const dispatch = useAppDispatch();
+ const { billingUrl } = useSideNavigation();
+ const useName = useAppSelector(selectUserName);
+ const {
+ billingCompleted,
+ createProjectCompleted,
+ configureCLICompleted,
+ discordCompleted,
+ tallyCompleted,
+ quickStartCompleted,
+ hideStartUp,
+ } = useAppSelector(selectTutorialPanel);
+
+ const { data: userBillingData } = useGetUserBillingInfoQuery({ username: useName ?? '' }, { skip: !useName });
+ const { data: projectData } = useGetProjectsQuery({});
+ const { data: runsData } = useGetRunsQuery({
+ limit: 1,
+ });
+
+ const completeIsChecked = useRef(false);
+
+ useEffect(() => {
+ if (
+ userBillingData &&
+ projectData?.data &&
+ runsData &&
+ !completeIsChecked.current &&
+ location.pathname !== ROUTES.PROJECT.ADD
+ ) {
+ const billingCompleted = userBillingData.balance > 0;
+ const configureCLICompleted = runsData.length > 0;
+ const createProjectCompleted = projectData.data.length > 0;
+
+ let tempHideStartUp = hideStartUp;
+
+ if (hideStartUp === null) {
+ tempHideStartUp = billingCompleted && configureCLICompleted && createProjectCompleted;
+ }
+
+ // Set hideStartUp without updating localstorage
+ dispatch(
+ updateTutorialPanelState({
+ billingCompleted,
+ configureCLICompleted,
+ createProjectCompleted,
+ hideStartUp: tempHideStartUp,
+ }),
+ );
+
+ if (!tempHideStartUp && process.env.UI_VERSION === 'sky') {
+ dispatch(openTutorialPanel());
+ }
+
+ completeIsChecked.current = true;
+ }
+ }, [userBillingData, runsData, projectData, location.pathname]);
+
+ useEffect(() => {
+ if (projectData?.data && projectData.data.length > 0 && !createProjectCompleted) {
+ dispatch(
+ updateTutorialPanelState({
+ createProjectCompleted: true,
+ }),
+ );
+ }
+ }, [projectData]);
+
+ const startBillingTutorial = useCallback(() => {
+ navigate(billingUrl);
+ }, [billingUrl]);
+
+ const finishBillingTutorial = useCallback(() => {
+ dispatch(updateTutorialPanelState({ billingCompleted: true }));
+ }, []);
+
+ const startFirstProjectTutorial = useCallback(() => {
+ navigate(ROUTES.PROJECT.ADD);
+ }, []);
+
+ const finishFirstProjectTutorial = useCallback(() => {
+ dispatch(updateTutorialPanelState({ createProjectCompleted: true }));
+ }, []);
+
+ const startConfigCliTutorial = useCallback(() => {
+ if (projectData?.data?.length) {
+ navigate(ROUTES.PROJECT.DETAILS.SETTINGS.FORMAT(projectData.data[0].project_name));
+ }
+ }, [projectData]);
+
+ const finishConfigCliTutorial = useCallback(() => {
+ dispatch(updateTutorialPanelState({ configureCLICompleted: true }));
+ }, []);
+
+ const startDiscordTutorial = useCallback(() => {
+ goToUrl(DISCORD_URL, true);
+ dispatch(updateTutorialPanelState({ discordCompleted: true }));
+ }, []);
+
+ const startQuickStartTutorial = useCallback(() => {
+ goToUrl(QUICK_START_URL, true);
+ dispatch(updateTutorialPanelState({ quickStartCompleted: true }));
+ }, []);
+
+ // const startCreditsTutorial = useCallback(() => {
+ // if (typeof Tally !== 'undefined') {
+ // Tally.openPopup(TALLY_FORM_ID);
+ // dispatch(updateTutorialPanelState({ tallyCompleted: true }));
+ // }
+ // }, []);
+
+ const tutorials = useMemo(() => {
+ return [
+ // {
+ // ...CREDITS_TUTORIAL,
+ // id: 1,
+ // startWithoutActivation: true,
+ // completed: tallyCompleted,
+ // startCallback: startCreditsTutorial,
+ // },
+
+ {
+ ...CREATE_FIRST_PROJECT,
+ id: 2,
+ completed: createProjectCompleted,
+ startCallback: startFirstProjectTutorial,
+ finishCallback: finishFirstProjectTutorial,
+ },
+
+ {
+ ...CONFIGURE_CLI_TUTORIAL,
+ id: 3,
+ completed: configureCLICompleted,
+ startCallback: startConfigCliTutorial,
+ finishCallback: finishConfigCliTutorial,
+ prerequisitesNeeded: !createProjectCompleted,
+ },
+
+ {
+ ...QUICKSTART_TUTORIAL,
+ id: 5,
+ startWithoutActivation: true,
+ completed: quickStartCompleted,
+ startCallback: startQuickStartTutorial,
+ },
+
+ {
+ ...JOIN_DISCORD_TUTORIAL,
+ id: 6,
+ startWithoutActivation: true,
+ completed: discordCompleted,
+ startCallback: startDiscordTutorial,
+ },
+
+ {
+ ...BILLING_TUTORIAL,
+ id: 4,
+ completed: billingCompleted,
+ startCallback: startBillingTutorial,
+ finishCallback: finishBillingTutorial,
+ },
+ ];
+ }, [
+ billingUrl,
+ createProjectCompleted,
+ quickStartCompleted,
+ discordCompleted,
+ tallyCompleted,
+ billingCompleted,
+ configureCLICompleted,
+ finishFirstProjectTutorial,
+ finishBillingTutorial,
+ finishConfigCliTutorial,
+ ]);
+
+ return { tutorials } as const;
+};
diff --git a/frontend/src/layouts/AppLayout/TutorialPanel/index.tsx b/frontend/src/layouts/AppLayout/TutorialPanel/index.tsx
new file mode 100644
index 0000000000..9a614d14e4
--- /dev/null
+++ b/frontend/src/layouts/AppLayout/TutorialPanel/index.tsx
@@ -0,0 +1,54 @@
+import React, { useLayoutEffect, useRef } from 'react';
+import { createRoot, Root } from 'react-dom/client';
+
+import { Box, Toggle, TutorialPanel as TutorialPanelGeneric, TutorialPanelProps } from 'components';
+
+import { useAppDispatch, useAppSelector } from 'hooks';
+
+import { selectTutorialPanel, setHideAtStartup } from 'App/slice';
+
+import { tutorialPanelI18nStrings } from './constants';
+import { useTutorials } from './hooks';
+
+export interface Props extends Partial {
+ test?: string;
+}
+
+export const TutorialPanel: React.FC = () => {
+ const dispatch = useAppDispatch();
+ const { tutorials } = useTutorials();
+ const tutorialRootRef = useRef(null);
+ const { hideStartUp } = useAppSelector(selectTutorialPanel);
+
+ const onChangeShowStartUp = (value: boolean) => {
+ dispatch(setHideAtStartup(!value));
+ };
+
+ const renderShowAtStartup = () => {
+ return (
+
+ onChangeShowStartUp(detail.checked)} checked={!hideStartUp}>
+ Show at startup
+
+
+ );
+ };
+
+ useLayoutEffect(() => {
+ const tutorialPanelElement = document.querySelector('[class*="awsui_tutorial-panel"]');
+
+ if (tutorialPanelElement && !tutorialRootRef.current) {
+ const divElement = document.createElement('div');
+ tutorialPanelElement.appendChild(divElement);
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ tutorialRootRef.current = createRoot(divElement);
+ }
+
+ if (tutorialRootRef.current) {
+ tutorialRootRef.current.render(renderShowAtStartup());
+ }
+ }, [hideStartUp]);
+
+ return ;
+};
diff --git a/frontend/src/layouts/AppLayout/hooks.ts b/frontend/src/layouts/AppLayout/hooks.ts
new file mode 100644
index 0000000000..f46366fcd6
--- /dev/null
+++ b/frontend/src/layouts/AppLayout/hooks.ts
@@ -0,0 +1,101 @@
+import { useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useLocation, useMatch } from 'react-router-dom';
+
+import { SideNavigationProps } from 'components';
+
+import { useAppSelector, usePermissionGuard } from 'hooks';
+import { ROUTES } from 'routes';
+import { useGetServerInfoQuery } from 'services/server';
+import { GlobalUserRole } from 'types';
+
+import { selectUserName } from 'App/slice';
+
+export const useSideNavigation = () => {
+ const { t } = useTranslation();
+ const userName = useAppSelector(selectUserName) ?? '';
+ const { pathname } = useLocation();
+ const [isGlobalAdmin] = usePermissionGuard({ allowedGlobalRoles: [GlobalUserRole.ADMIN] });
+ const { data: serverInfoData } = useGetServerInfoQuery();
+
+ const isPoolDetails = Boolean(useMatch(ROUTES.FLEETS.DETAILS.TEMPLATE));
+ const billingUrl = ROUTES.USER.BILLING.LIST.FORMAT(userName);
+ const userProjectsUrl = ROUTES.USER.PROJECTS.FORMAT(userName);
+
+ const generalLinks = [
+ { type: 'link', text: t('navigation.runs'), href: ROUTES.RUNS.LIST },
+ { type: 'link', text: t('navigation.offers'), href: ROUTES.OFFERS.LIST },
+ { type: 'link', text: t('navigation.fleets'), href: ROUTES.FLEETS.LIST },
+ { type: 'link', text: t('navigation.instances'), href: ROUTES.INSTANCES.LIST },
+ { type: 'link', text: t('navigation.volumes'), href: ROUTES.VOLUMES.LIST },
+ { type: 'link', text: t('navigation.events'), href: ROUTES.EVENTS.LIST },
+ { type: 'link', text: t('navigation.models'), href: ROUTES.MODELS.LIST },
+ { type: 'link', text: t('navigation.project_other'), href: ROUTES.PROJECT.LIST },
+
+ isGlobalAdmin && {
+ type: 'link',
+ text: t('navigation.users'),
+ href: ROUTES.USER.LIST,
+ },
+ ].filter(Boolean);
+
+ const userSettingsLinks = [
+ {
+ type: 'link',
+ text: t('navigation.settings'),
+ href: ROUTES.USER.DETAILS.FORMAT(userName),
+ },
+ {
+ type: 'link',
+ text: t('users.projects'),
+ href: userProjectsUrl,
+ },
+ process.env.UI_VERSION === 'sky' && {
+ type: 'link',
+ text: t('navigation.billing'),
+ href: billingUrl,
+ },
+ ].filter(Boolean);
+
+ const navLinks: SideNavigationProps['items'] = [
+ {
+ type: 'section-group',
+ title: t('navigation.general'),
+ items: generalLinks,
+ },
+
+ { type: 'divider' },
+
+ {
+ type: 'section-group',
+ title: t('navigation.account'),
+ items: userSettingsLinks,
+ },
+
+ { type: 'divider' },
+
+ {
+ type: 'link',
+ href: '#version',
+ text: `dstack version: ${serverInfoData?.server_version ?? 'No version'}`,
+ },
+ ].filter(Boolean) as SideNavigationProps['items'];
+
+ const activeHref = useMemo(() => {
+ if (isPoolDetails) {
+ return ROUTES.FLEETS.LIST;
+ }
+
+ const generalActiveLink = generalLinks.find((linkItem) => pathname.indexOf(linkItem.href) === 0);
+
+ if (generalActiveLink) return pathname;
+
+ const settingsActiveLink = userSettingsLinks.find((linkItem) => linkItem.href === pathname);
+
+ if (settingsActiveLink) return pathname;
+
+ return '/' + pathname.split('/')[1];
+ }, [pathname, userName]);
+
+ return { navLinks, activeHref, billingUrl } as const;
+};
diff --git a/frontend/src/layouts/AppLayout/index.module.scss b/frontend/src/layouts/AppLayout/index.module.scss
new file mode 100644
index 0000000000..dcf3c8858f
--- /dev/null
+++ b/frontend/src/layouts/AppLayout/index.module.scss
@@ -0,0 +1,103 @@
+@use '@cloudscape-design/design-tokens/index' as awsui;
+
+:global {
+ .b-page-header {
+ .awsui-context-top-navigation {
+ border-bottom: 1px solid awsui.$color-border-divider-default;
+
+ [class*="awsui_utility-type-button"] {
+ [class*="awsui_link"][href="theme-button"] {
+ [class^="awsui_icon"] {
+ width: 48px !important;
+ }
+ }
+ }
+ }
+ }
+}
+
+[class^='awsui_navigation'] {
+ [class^='awsui_list-container'] {
+ a[href='#version'] {
+ pointer-events: none;
+ color: awsui.$color-text-status-inactive !important;
+ }
+ }
+}
+
+.appHeader {
+ height: 48px;
+ @media (screen and min-width: 913px) {
+ height: 56px;
+ }
+ .userAvatar {
+ width: 40px;
+ height: 40px;
+ border-radius: 50%;
+ overflow: hidden;
+ }
+ [data-class="user-menu"] {
+ [class^="awsui_dropdown-trigger"] {
+ [class^="awsui_text"] {
+ margin-right: 0!important;
+ }
+ [class*="awsui_icon"] {
+ display: none !important;
+ }
+ }
+ }
+ & > * {
+ position: fixed;
+ top: 0;
+ left: 0;
+ right: 0;
+ }
+}
+
+.themeIcon {
+ display: flex;
+ align-items: center;
+ width: 48px;
+ gap: 6px;
+
+ .switcher {
+ position: relative;
+ flex-shrink: 0;
+ width: 24px;
+ height: 16px;
+ border-radius: 8px;
+ background-color: awsui.$color-background-layout-toggle-default;
+ transition: background-color .2s ease;
+
+ &::before {
+ content: "";
+ position: absolute;
+ top: 2px;
+ left: 0;
+ transform: translateX(2px);
+ width: 12px;
+ height: 12px;
+ border-radius: 50%;
+ background-color: awsui.$color-foreground-control-default;
+ transition: transform .2s ease;
+ }
+
+ &.on {
+ background-color: awsui.$color-background-control-checked;
+ &::before {
+ transform: translateX(10px);
+ }
+ }
+ }
+
+ .icon {
+ flex-shrink: 0;
+ }
+}
+
+.dstackVersion {
+ z-index: 9999;
+ position: absolute;
+ bottom: 6px;
+ left: 28px;
+}
diff --git a/frontend/src/layouts/AppLayout/index.tsx b/frontend/src/layouts/AppLayout/index.tsx
new file mode 100644
index 0000000000..3dd4db470b
--- /dev/null
+++ b/frontend/src/layouts/AppLayout/index.tsx
@@ -0,0 +1,268 @@
+import React from 'react';
+import Avatar from 'react-avatar';
+import { createPortal } from 'react-dom';
+import { useTranslation } from 'react-i18next';
+import { useNavigate } from 'react-router-dom';
+import { SideNavigationProps } from '@cloudscape-design/components/side-navigation';
+import { Mode } from '@cloudscape-design/global-styles';
+
+import {
+ AppLayout as GenericAppLayout,
+ AppLayoutProps as GenericAppLayoutProps,
+ BreadcrumbGroup,
+ ConfirmationDialog,
+ HelpPanel,
+ Notifications,
+ SideNavigation,
+ Tabs,
+ TopNavigation,
+} from 'components';
+
+import { DISCORD_URL, DOCS_URL } from 'consts';
+import { useAppDispatch, useAppSelector } from 'hooks';
+import { goToUrl } from 'libs';
+import { ROUTES } from 'routes';
+import { useGetServerInfoQuery } from 'services/server';
+
+import {
+ closeToolsPanel,
+ openTutorialPanel,
+ selectBreadcrumbs,
+ selectHelpPanelContent,
+ selectSystemMode,
+ selectToolsPanelState,
+ selectUserName,
+ setSystemMode,
+ setToolsTab,
+} from 'App/slice';
+
+import { selectConfirmationDialogs } from '../../components/ConfirmationDialog/slice';
+import { AnnotationContext } from './AnnotationContext';
+import { useSideNavigation } from './hooks';
+import { TallyComponent } from './Tally';
+import { DarkThemeIcon, LightThemeIcon } from './themeIcons';
+import { TutorialPanel } from './TutorialPanel';
+
+import { ToolsTabs } from 'App/types';
+
+import logo from 'assets/images/logo.svg';
+import styles from './index.module.scss';
+
+type PortalProps = { children: React.ReactNode };
+
+const HeaderPortal = ({ children }: PortalProps) => {
+ const domNode = document.querySelector('#header');
+ if (domNode) return createPortal(children, domNode);
+ return null;
+};
+
+const THEME_ICON_MAP: Record = {
+ [Mode.Dark]: DarkThemeIcon,
+ [Mode.Light]: LightThemeIcon,
+};
+
+const AppLayout: React.FC<{ children: React.ReactNode }> = ({ children }) => {
+ const { t } = useTranslation();
+ const navigate = useNavigate();
+ useGetServerInfoQuery();
+
+ const userName = useAppSelector(selectUserName) ?? '';
+ const systemMode = useAppSelector(selectSystemMode) ?? '';
+ const breadcrumbs = useAppSelector(selectBreadcrumbs);
+ const { isOpen: toolsIsOpen, tab: toolsActiveTab } = useAppSelector(selectToolsPanelState);
+ const helpPanelContent = useAppSelector(selectHelpPanelContent);
+ const dispatch = useAppDispatch();
+ const { navLinks, activeHref } = useSideNavigation();
+ const confirmationDialogs = useAppSelector(selectConfirmationDialogs);
+
+ const onFollowHandler: SideNavigationProps['onFollow'] = (event) => {
+ event.preventDefault();
+
+ if (event.detail.external) {
+ goToUrl(event.detail.href, true);
+ } else {
+ navigate(event.detail.href);
+ }
+ };
+
+ const renderBreadcrumbs = () => {
+ if (breadcrumbs) return ;
+ };
+
+ const i18nStrings = {
+ overflowMenuTriggerText: '',
+ overflowMenuTitleText: '',
+ overflowMenuBackIconAriaLabel: '',
+ overflowMenuDismissIconAriaLabel: '',
+ };
+
+ const profileActions = [
+ { type: 'button', href: ROUTES.USER.DETAILS.FORMAT(userName), id: 'settings', text: t('common.settings') },
+ { type: 'button', href: ROUTES.LOGOUT, id: 'signout', text: t('common.sign_out') },
+ ];
+
+ const onChangeToolHandler: GenericAppLayoutProps['onToolsChange'] = ({ detail: { open } }) => {
+ if (!open) dispatch(closeToolsPanel());
+ };
+
+ const onChangeToolsTab = (tabName: ToolsTabs) => {
+ dispatch(setToolsTab(tabName));
+ };
+
+ const toggleTutorialPanel = () => {
+ if (process.env.UI_VERSION !== 'sky') {
+ return;
+ }
+
+ if (toolsIsOpen) {
+ dispatch(closeToolsPanel());
+ return;
+ }
+
+ dispatch(openTutorialPanel());
+ };
+
+ const isVisibleInfoTab = helpPanelContent.header || helpPanelContent.footer || helpPanelContent.body;
+
+ const avatarProps = process.env.UI_VERSION === 'enterprise' ? { name: userName } : { githubHandle: userName };
+
+ const onChangeSystemModeToggle: SideNavigationProps['onFollow'] = (event) => {
+ event.preventDefault();
+
+ switch (systemMode) {
+ case Mode.Light:
+ dispatch(setSystemMode(Mode.Dark));
+ return;
+ default:
+ dispatch(setSystemMode(Mode.Light));
+ }
+ };
+
+ const ThemeIcon = THEME_ICON_MAP[systemMode];
+
+ const askAi = () => {
+ window.document.body.focus();
+ window?.Kapa?.open();
+ };
+
+ return (
+
+
+
+
goToUrl(DOCS_URL, true),
+ },
+ {
+ type: 'button',
+ text: t('common.discord'),
+ external: true,
+ onClick: () => goToUrl(DISCORD_URL, true),
+ },
+ {
+ href: 'theme-button',
+ type: 'button',
+ iconSvg: ,
+ onClick: onChangeSystemModeToggle,
+ },
+ process.env.UI_VERSION === 'sky' && {
+ type: 'button',
+ iconName: 'gen-ai',
+ text: t('common.ask_ai'),
+ title: t('common.ask_ai'),
+ onClick: askAi,
+ },
+ process.env.UI_VERSION === 'sky' && {
+ type: 'button',
+ iconName: 'support',
+ title: t('common.tutorial_other'),
+ onClick: toggleTutorialPanel,
+ },
+ {
+ 'data-class': 'user-menu',
+ type: 'menu-dropdown',
+ text: (
+
+ ),
+ items: profileActions,
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ onItemFollow: onFollowHandler,
+ },
+ ].filter(Boolean)}
+ />
+
+
+
+ }
+ navigation={
+
+ }
+ tools={
+ <>
+ onChangeToolsTab(event.detail.activeTabId as ToolsTabs)}
+ tabs={[
+ isVisibleInfoTab && {
+ id: ToolsTabs.INFO,
+ label: t('common.info'),
+ content: (
+
+ {helpPanelContent.body}
+
+ ),
+ },
+ process.env.UI_VERSION === 'sky' && {
+ id: ToolsTabs.TUTORIAL,
+ label: t('common.tutorial_other'),
+ content: (
+
+ window.prompt('Please enter your feedback here (this will not be saved):')
+ }
+ />
+ ),
+ },
+ ].filter(Boolean)}
+ />
+ >
+ }
+ toolsHide={!toolsIsOpen}
+ toolsOpen={toolsIsOpen}
+ toolsWidth={330}
+ onToolsChange={onChangeToolHandler}
+ />
+
+
+
+ {confirmationDialogs.map(({ uuid, ...props }) => (
+
+ ))}
+
+ );
+};
+
+export default AppLayout;
diff --git a/frontend/src/layouts/AppLayout/themeIcons.tsx b/frontend/src/layouts/AppLayout/themeIcons.tsx
new file mode 100644
index 0000000000..214ef9b27c
--- /dev/null
+++ b/frontend/src/layouts/AppLayout/themeIcons.tsx
@@ -0,0 +1,23 @@
+import React from 'react';
+import cn from 'classnames';
+
+import { ReactComponent as ThemeIcon } from 'assets/icons/theme.svg';
+import styles from './index.module.scss';
+
+export const DarkThemeIcon: React.FC = () => {
+ return (
+
+ );
+};
+
+export const LightThemeIcon: React.FC = () => {
+ return (
+
+ );
+};
diff --git a/frontend/src/layouts/UnauthorizedLayout/index.tsx b/frontend/src/layouts/UnauthorizedLayout/index.tsx
new file mode 100644
index 0000000000..7286699082
--- /dev/null
+++ b/frontend/src/layouts/UnauthorizedLayout/index.tsx
@@ -0,0 +1,11 @@
+import React from 'react';
+
+import styles from './styles.module.scss';
+
+export interface UnauthorizedLayoutProps {
+ children?: React.ReactNode;
+}
+
+export const UnauthorizedLayout: React.FC = ({ children }) => {
+ return {children}
;
+};
diff --git a/frontend/src/layouts/UnauthorizedLayout/styles.module.scss b/frontend/src/layouts/UnauthorizedLayout/styles.module.scss
new file mode 100644
index 0000000000..78d14c2f10
--- /dev/null
+++ b/frontend/src/layouts/UnauthorizedLayout/styles.module.scss
@@ -0,0 +1,9 @@
+@use '@cloudscape-design/design-tokens/index' as awsui;
+
+.layout {
+ background: awsui.$color-background-layout-main;
+ padding-top: 40px;
+ padding-bottom: 40px;
+ min-height: 100vh;
+ box-sizing: border-box;
+}
diff --git a/frontend/src/libs/fetchBaseQueryHeaders.ts b/frontend/src/libs/fetchBaseQueryHeaders.ts
new file mode 100644
index 0000000000..d517358204
--- /dev/null
+++ b/frontend/src/libs/fetchBaseQueryHeaders.ts
@@ -0,0 +1,18 @@
+import type { BaseQueryApi } from '@reduxjs/toolkit/query';
+
+import { RootState } from '../store';
+
+function baseQueryHeaders(headers: Headers, { getState }: Pick): Headers {
+ const token = (getState() as RootState).app.authData?.token;
+ const authorizationHeader = headers.get('Authorization');
+
+ if (token && !authorizationHeader) {
+ headers.set('Authorization', `Bearer ${token}`);
+ }
+
+ headers.set('X-API-VERSION', 'latest');
+
+ return headers;
+}
+
+export default baseQueryHeaders;
diff --git a/frontend/src/libs/filters.test.ts b/frontend/src/libs/filters.test.ts
new file mode 100644
index 0000000000..1efeee9890
--- /dev/null
+++ b/frontend/src/libs/filters.test.ts
@@ -0,0 +1,36 @@
+import { getTokenAwareNamePatternFilterRequestParams } from './filters';
+
+describe('filters helpers', () => {
+ test('loads the full list when reopening an existing token value', () => {
+ expect(
+ getTokenAwareNamePatternFilterRequestParams({
+ filteringText: 'main',
+ limit: 100,
+ propertyKey: 'project_name',
+ tokens: [{ propertyKey: 'project_name', operator: '=', value: 'main' }],
+ }),
+ ).toEqual({ limit: 100 });
+ });
+
+ test('keeps the typed text when the value is being edited', () => {
+ expect(
+ getTokenAwareNamePatternFilterRequestParams({
+ filteringText: 'mai',
+ limit: 100,
+ propertyKey: 'project_name',
+ tokens: [{ propertyKey: 'project_name', operator: '=', value: 'main' }],
+ }),
+ ).toEqual({ limit: 100, name_pattern: 'mai' });
+ });
+
+ test('ignores matching values from other properties', () => {
+ expect(
+ getTokenAwareNamePatternFilterRequestParams({
+ filteringText: 'main',
+ limit: 100,
+ propertyKey: 'project_name',
+ tokens: [{ propertyKey: 'username', operator: '=', value: 'main' }],
+ }),
+ ).toEqual({ limit: 100, name_pattern: 'main' });
+ });
+});
diff --git a/frontend/src/libs/filters.ts b/frontend/src/libs/filters.ts
new file mode 100644
index 0000000000..13b3605372
--- /dev/null
+++ b/frontend/src/libs/filters.ts
@@ -0,0 +1,169 @@
+import type { PropertyFilterProps } from 'components';
+
+export const tokensToSearchParams = (
+ tokens: PropertyFilterProps.Query['tokens'],
+ onlyActive?: boolean,
+) => {
+ const params = new URLSearchParams();
+
+ tokens.forEach((token) => {
+ if (token.propertyKey) {
+ params.append(token.propertyKey as RequestParamsKeys, token.value);
+ }
+ });
+
+ if (onlyActive) {
+ params.append('only_active', 'true');
+ }
+
+ return params;
+};
+
+export type RequestParam = string | { min: number } | { max: number };
+
+export const getNamePatternFilterRequestParams = (filteringText: string, limit: number) => {
+ return {
+ ...(filteringText ? { name_pattern: filteringText } : {}),
+ limit,
+ };
+};
+
+export const getTokenAwareNamePatternFilterRequestParams = ({
+ filteringText,
+ limit,
+ propertyKey,
+ tokens,
+}: {
+ filteringText: string;
+ limit: number;
+ propertyKey: PropertyKey;
+ tokens: PropertyFilterProps.Query['tokens'];
+}) => {
+ const matchingExistingToken = tokens.some((token) => {
+ return token.propertyKey === propertyKey && typeof token.value === 'string' && token.value === filteringText;
+ });
+
+ return getNamePatternFilterRequestParams(matchingExistingToken ? '' : filteringText, limit);
+};
+
+const convertTokenValueToRequestParam = (token: PropertyFilterProps.Query['tokens'][number]): RequestParam => {
+ const { value, operator } = token;
+
+ if (operator === '>=') {
+ return { min: Number(value) };
+ }
+
+ if (operator === '<=') {
+ return { max: Number(value) };
+ }
+
+ return value;
+};
+
+export const tokensToRequestParams = ({
+ tokens,
+ arrayFieldKeys,
+}: {
+ tokens: PropertyFilterProps.Query['tokens'];
+ arrayFieldKeys?: RequestParamsKeys[];
+}) => {
+ return tokens.reduce>(
+ (acc, token) => {
+ const propertyKey = token.propertyKey as RequestParamsKeys;
+
+ if (!propertyKey) {
+ return acc;
+ }
+
+ const convertedValue = convertTokenValueToRequestParam(token);
+
+ if (arrayFieldKeys?.includes(propertyKey)) {
+ if (Array.isArray(acc[propertyKey])) {
+ acc[propertyKey].push(convertedValue as string);
+ } else {
+ acc[propertyKey] = [convertedValue as string];
+ }
+
+ return acc;
+ }
+
+ acc[propertyKey] = convertedValue;
+
+ return acc;
+ },
+ {} as Record,
+ );
+};
+
+export const EMPTY_QUERY: PropertyFilterProps.Query = {
+ tokens: [],
+ operation: 'and',
+};
+
+export const requestParamsToTokens = ({
+ searchParams,
+ filterKeys,
+ defaultFilterValues,
+}: {
+ searchParams: URLSearchParams;
+ filterKeys: Record;
+ defaultFilterValues?: Partial>;
+}): PropertyFilterProps.Query => {
+ const tokens = [];
+ const filterKeysValues = Object.values(filterKeys);
+
+ if (defaultFilterValues) {
+ Object.keys(defaultFilterValues).forEach((defaultFilterKey) => {
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ const defaultFilterValue: string[] = Array.isArray(defaultFilterValues[defaultFilterKey])
+ ? // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ defaultFilterValues[defaultFilterKey]
+ : // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ [defaultFilterValues[defaultFilterKey]];
+
+ defaultFilterValue.forEach((value) => {
+ tokens.push({ propertyKey: defaultFilterKey, operator: '=', value: value });
+ });
+ });
+ }
+
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+ for (const [paramKey, paramValue] of searchParams.entries()) {
+ if (filterKeysValues.includes(paramKey)) {
+ tokens.push({ propertyKey: paramKey, operator: '=', value: paramValue });
+ }
+ }
+
+ if (!tokens.length) {
+ return EMPTY_QUERY;
+ }
+
+ return {
+ ...EMPTY_QUERY,
+ tokens,
+ };
+};
+
+export const requestParamsToArray = ({
+ searchParams,
+ paramName,
+}: {
+ searchParams: URLSearchParams;
+ paramName: Key;
+}) => {
+ const paramValues: string[] = [];
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-ignore
+
+ for (const [paramKey, paramValue] of searchParams.entries()) {
+ if (paramKey === paramName) {
+ paramValues.push(paramValue);
+ }
+ }
+
+ return paramValues;
+};
diff --git a/frontend/src/libs/fleet.ts b/frontend/src/libs/fleet.ts
new file mode 100644
index 0000000000..3a56e23b96
--- /dev/null
+++ b/frontend/src/libs/fleet.ts
@@ -0,0 +1,176 @@
+import { isEqual } from 'lodash';
+import { StatusIndicatorProps } from '@cloudscape-design/components';
+
+export const formatBackend = (backend: TBackendType | string | null | undefined): string => {
+ if (!backend) return '-';
+ if (backend === 'remote') return 'ssh';
+ return backend;
+};
+
+export const getStatusIconType = (status: IInstance['status']): StatusIndicatorProps['type'] => {
+ switch (status) {
+ case 'pending':
+ case 'creating':
+ return 'pending';
+ case 'terminated':
+ return 'stopped';
+ case 'terminating':
+ case 'provisioning':
+ case 'starting':
+ case 'busy':
+ return 'in-progress';
+ case 'idle':
+ return 'success';
+ default:
+ console.error(new Error('Undefined fleet status'));
+ }
+};
+
+export const getStatusIconColor = (status: IInstance['status']): StatusIndicatorProps.Color | undefined => {
+ switch (status) {
+ case 'busy':
+ case 'provisioning':
+ case 'starting':
+ case 'terminating':
+ return 'blue';
+ default:
+ return undefined;
+ }
+};
+
+export const getFleetStatusIconType = (status: IFleet['status']): StatusIndicatorProps['type'] => {
+ switch (status) {
+ case 'submitted':
+ return 'pending';
+ case 'failed':
+ case 'terminated':
+ return 'stopped';
+ case 'terminating':
+ return 'in-progress';
+ case 'active':
+ return 'success';
+ default:
+ console.error(new Error('Undefined fleet status'));
+ }
+};
+
+export const getFleetPrice = (fleet: IFleet): number | null => {
+ return fleet.instances.reduce((acc, instance) => {
+ if (typeof instance.price === 'number' && instance.status !== 'terminated') {
+ if (acc === null) return instance.price;
+
+ acc += instance.price;
+ }
+
+ return acc;
+ }, null);
+};
+
+const getInstanceFields = (instance: IInstance) => ({
+ backend: instance.backend,
+ region: instance.region,
+ type: instance.instance_type?.name,
+ spot: instance.instance_type?.resources.spot,
+});
+
+const formatRange = (min: unknown, max: unknown, suffix = ''): string => {
+ if (min == null && max == null) return '';
+ if (min === max) return `${min}${suffix}`;
+ if (max == null) return `${min}${suffix}..`;
+ if (min == null) return `..${max}${suffix}`;
+ return `${min}${suffix}..${max}${suffix}`;
+};
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const formatCpu = (cpu: any): string | null => {
+ if (!cpu) return null;
+ if (typeof cpu === 'number') return `cpu=${cpu}`;
+ if (cpu.min != null || cpu.max != null) return `cpu=${formatRange(cpu.min, cpu.max)}`;
+ const arch = cpu.arch;
+ const count = cpu.count;
+ if (!count) return null;
+ const prefix = arch === 'arm' ? 'arm:' : '';
+ return `cpu=${prefix}${formatRange(count.min, count.max)}`;
+};
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+const formatGpu = (gpu: any): string | null => {
+ if (!gpu) return null;
+ const count = gpu.count;
+ if (!count || (count.min === 0 && (count.max == null || count.max === 0))) return null;
+
+ const gpuParts: string[] = [];
+
+ if (gpu.memory) {
+ const memStr = formatRange(gpu.memory.min, gpu.memory.max, 'GB');
+ if (memStr) gpuParts.push(memStr);
+ }
+
+ const countStr = formatRange(count.min, count.max);
+ if (countStr) gpuParts.push(countStr);
+
+ if (gpu.total_memory) {
+ const tmStr = formatRange(gpu.total_memory.min, gpu.total_memory.max, 'GB');
+ if (tmStr) gpuParts.push(tmStr);
+ }
+
+ let label: string;
+ if (gpu.name && gpu.name.length > 0) {
+ label = gpu.name.join(',');
+ } else if (gpu.vendor) {
+ label = gpu.vendor;
+ } else {
+ label = '';
+ }
+
+ return 'gpu=' + [label, ...gpuParts].filter(Boolean).join(':');
+};
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export const formatFleetResources = (resources: any): string => {
+ if (!resources) return '-';
+
+ const parts: string[] = [];
+
+ const cpuStr = formatCpu(resources.cpu);
+ if (cpuStr) parts.push(cpuStr);
+
+ if (resources.memory) {
+ const memStr = formatRange(resources.memory.min, resources.memory.max, 'GB');
+ if (memStr) parts.push(`mem=${memStr}`);
+ }
+
+ if (resources.disk?.size) {
+ const diskStr = formatRange(resources.disk.size.min, resources.disk.size.max, 'GB');
+ if (diskStr) parts.push(`disk=${diskStr}`);
+ }
+
+ const gpuStr = formatGpu(resources.gpu);
+ if (gpuStr) parts.push(gpuStr);
+
+ return parts.length > 0 ? parts.join(' ') : '-';
+};
+
+export const formatFleetBackend = (config: IFleetConfigurationRequest): string => {
+ if (config.ssh_config) return 'ssh';
+ if (!config.backends || config.backends.length === 0) return '-';
+ return config.backends.map((b) => formatBackend(b)).join(', ');
+};
+
+export const getFleetInstancesLinkText = (fleet: IFleet): string => {
+ const instances = fleet.instances.filter((i) => i.status !== 'terminated');
+ const hasPending = instances.some((i) => i.status === 'pending');
+
+ if (!instances.length) return '0 instances';
+
+ if (hasPending) return `${instances.length} instances`;
+
+ const isSameInstances = instances.every((i) => isEqual(getInstanceFields(instances[0]), getInstanceFields(i)));
+
+ if (isSameInstances)
+ return `${instances.length}x ${instances[0].instance_type?.name}${
+ instances[0].instance_type?.resources.spot ? ' (spot)' : ''
+ } @ ${formatBackend(instances[0].backend)} (${instances[0].region})`;
+
+ return `${instances.length} instances`;
+};
diff --git a/frontend/src/libs/form.ts b/frontend/src/libs/form.ts
new file mode 100644
index 0000000000..86b34a1c5c
--- /dev/null
+++ b/frontend/src/libs/form.ts
@@ -0,0 +1,8 @@
+import { FormFieldError } from './types';
+
+export const getFieldErrorFromServerResponse = (error: FormFieldError): { fieldNamePath: string; message: string } => {
+ const fieldNamePath = error.loc.filter((key) => key !== 'body').join('.');
+ const message = error.msg;
+
+ return { fieldNamePath, message };
+};
diff --git a/frontend/src/libs/index.test.ts b/frontend/src/libs/index.test.ts
new file mode 100644
index 0000000000..9eaf7b3b56
--- /dev/null
+++ b/frontend/src/libs/index.test.ts
@@ -0,0 +1,53 @@
+import { arrayToRecordByKeyName, getDateAgoSting, getUid, isErrorWithMessage, MINUTE } from './index';
+
+describe('test libs', () => {
+ test('Check is error with message', () => {
+ expect(isErrorWithMessage({})).toBeFalsy();
+ expect(isErrorWithMessage(null)).toBeFalsy();
+ expect(isErrorWithMessage({ data: { test: 'test' } })).toBeFalsy();
+ expect(isErrorWithMessage({ data: { message: 'error message' } })).toBeTruthy();
+ });
+
+ test('array to record by name', () => {
+ const mockData = [
+ { name: 'test', lastname: 'test_lastname' },
+ { name: 'test2', lastname: 'test_lastname2' },
+ ];
+
+ expect(arrayToRecordByKeyName(mockData, 'name')).toEqual({
+ test: mockData[0],
+ test2: mockData[1],
+ });
+
+ expect(arrayToRecordByKeyName(mockData, 'lastname')).toEqual({
+ test_lastname: mockData[0],
+ test_lastname2: mockData[1],
+ });
+ });
+
+ test('getDateAgoSting', () => {
+ const date = new Date();
+ const timestamp = date.getTime();
+ date.setDate(date.getDate() - 1);
+ const day: string = date.getDate() < 10 ? `0${date.getDate()}` : `${date.getDate()}`;
+ const month: string = date.getMonth() < 9 ? `0${date.getMonth() + 1}` : `${date.getMonth() + 1}`;
+ const year: string = date.getFullYear().toString();
+
+ expect(getDateAgoSting(timestamp)).toEqual('Just now');
+ expect(getDateAgoSting(timestamp - MINUTE + 100)).toEqual('Just now');
+ expect(getDateAgoSting(timestamp - MINUTE)).toEqual('1 minute ago');
+ expect(getDateAgoSting(timestamp - MINUTE * 2)).toEqual('2 minutes ago');
+ expect(getDateAgoSting(timestamp - MINUTE * 60)).toEqual('1 hour ago');
+ expect(getDateAgoSting(timestamp - MINUTE * 60 * 2)).toEqual('2 hours ago');
+ expect(getDateAgoSting(timestamp - MINUTE * 60 * 24)).toEqual(`${day}/${month}/${year}`);
+ });
+
+ test('get unique id', () => {
+ const set = new Set();
+ const iterationCount = 20;
+
+ for (let i = 0; i < iterationCount; i++) set.add(getUid());
+
+ expect(set.size).toBe(iterationCount);
+ });
+});
diff --git a/frontend/src/libs/index.ts b/frontend/src/libs/index.ts
new file mode 100644
index 0000000000..4d5123787c
--- /dev/null
+++ b/frontend/src/libs/index.ts
@@ -0,0 +1,117 @@
+export {
+ default as isErrorWithMessage,
+ isResponseServerFormFieldError,
+ isResponseServerError,
+ getServerError,
+} from './serverErrors';
+import { format, formatDistanceToNowStrict } from 'date-fns';
+export { generateSecurePassword, generatePassword, generateSimplePassword } from './password';
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export function arrayToRecordByKeyName(array: T[], selector: K) {
+ return array.reduce(
+ (acc, item) => {
+ acc[item[selector]] = item;
+ return acc;
+ },
+ {} as Record,
+ );
+}
+
+export function wait(delayInMS: number): Promise {
+ return new Promise((resolve) => setTimeout(resolve, delayInMS));
+}
+
+export function goToUrl(url: string, blank?: boolean): void {
+ const link = document.createElement('a');
+ link.style.opacity = '0';
+ link.style.position = 'absolute';
+ link.style.top = '-2000px';
+
+ if (blank) link.target = '_blank';
+
+ link.href = url;
+
+ document.body.append(link);
+ link.click();
+ link.remove();
+}
+
+export const copyToClipboard = (copyText: string, success?: () => void, failed?: () => void) => {
+ navigator.clipboard.writeText(copyText).then(success, failed);
+};
+
+export const MINUTE = 60000;
+
+export const getDateAgoSting = (time: number): string => {
+ try {
+ if (Date.now() - time < MINUTE) return 'Just now';
+
+ if (Date.now() - time < MINUTE * 60 * 24) return formatDistanceToNowStrict(new Date(time), { addSuffix: true });
+
+ return format(new Date(time), 'dd/MM/yyyy');
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ } catch (err) {
+ return '';
+ }
+};
+
+export const getUid = (a?: string): string => {
+ return a ? (0 | (Math.random() * 16)).toString(16) : ('' + 1e11 + 1e11).replace(/1|0/g, getUid);
+};
+
+export const buildRoute = (route: string, params: HashMap): string => {
+ return Object.keys(params).reduce((acc, key) => {
+ const regExp = new RegExp(`:${key}`);
+
+ return acc.replace(regExp, params[key] as string);
+ }, route);
+};
+
+export const formatBytes = (bytes: number, decimals = 2): string => {
+ if (bytes === 0) return '0Bytes';
+
+ const k = 1024;
+
+ const dm = decimals <= 0 ? 0 : decimals;
+
+ const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
+
+ const i = Math.floor(Math.log(bytes) / Math.log(k));
+
+ return parseFloat((bytes / Math.pow(k, i)).toFixed(dm)) + sizes[i];
+};
+
+export const centsToFormattedString = (cents: number, currency?: string): string => {
+ const floatValue = cents / 100;
+
+ return `${floatValue < 0 ? '-' : ''}${currency}${Math.abs(floatValue).toFixed(2)}`;
+};
+
+export const riseRouterException = (status = 404, json = 'Not Found'): never => {
+ throw new Response(json, { status });
+};
+
+export const base64ToArrayBuffer = (base64: string) => {
+ const binaryString = atob(base64);
+ const bytes = new Uint8Array(binaryString.length);
+ for (let i = 0; i < binaryString.length; i++) {
+ bytes[i] = binaryString.charCodeAt(i);
+ }
+ return bytes;
+};
+
+export const isValidUrl = (urlString: string) => {
+ try {
+ return Boolean(new URL(urlString));
+ // eslint-disable-next-line @typescript-eslint/no-unused-vars
+ } catch (e) {
+ return false;
+ }
+};
+
+export const includeSubString = (value: string, query: string) => {
+ return value.toLowerCase().includes(query.trim().toLowerCase());
+};
+
+export const capitalize = (str: string): string => str.charAt(0).toUpperCase() + str.slice(1);
diff --git a/frontend/src/libs/instance.ts b/frontend/src/libs/instance.ts
new file mode 100644
index 0000000000..614081569d
--- /dev/null
+++ b/frontend/src/libs/instance.ts
@@ -0,0 +1,28 @@
+import { StatusIndicatorProps } from '@cloudscape-design/components';
+
+export const prettyEnumValue = (value: string): string => {
+ return value.replace(/_/g, ' ').replace(/^\w/, (c) => c.toUpperCase());
+};
+
+export const getHealthStatusIconType = (healthStatus: THealthStatus): StatusIndicatorProps['type'] => {
+ switch (healthStatus) {
+ case 'healthy':
+ return 'success';
+ case 'warning':
+ return 'warning';
+ case 'failure':
+ return 'error';
+ default:
+ return 'info';
+ }
+};
+
+export const formatInstanceStatusText = (instance: IInstance): string => {
+ const status = instance.status;
+
+ if ((status === 'idle' || status === 'busy') && instance.total_blocks !== null && instance.total_blocks > 1) {
+ return `${instance.busy_blocks}/${instance.total_blocks} Busy`;
+ }
+
+ return prettyEnumValue(status);
+};
diff --git a/frontend/src/libs/password.ts b/frontend/src/libs/password.ts
new file mode 100644
index 0000000000..e430cdcf15
--- /dev/null
+++ b/frontend/src/libs/password.ts
@@ -0,0 +1,106 @@
+const UPPERCASE_LETTERS = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ';
+const LOWERCASE_LETTERS = 'abcdefghijklmnopqrstuvwxyz';
+const NUMBERS = '0123456789';
+const SPECIAL_CHARACTERS = '@#$^_+-';
+
+interface PasswordOptions {
+ length: number;
+ includeUppercase?: boolean;
+ includeLowercase?: boolean;
+ includeNumbers?: boolean;
+ includeSpecial?: boolean;
+}
+function generatePassword(options: PasswordOptions): string {
+ const { length, includeUppercase = true, includeLowercase = true, includeNumbers = true, includeSpecial = true } = options;
+
+ let allowedChars = '';
+
+ if (includeUppercase) allowedChars += UPPERCASE_LETTERS;
+ if (includeLowercase) allowedChars += LOWERCASE_LETTERS;
+ if (includeNumbers) allowedChars += NUMBERS;
+ if (includeSpecial) allowedChars += SPECIAL_CHARACTERS;
+
+ if (allowedChars.length === 0) {
+ throw new Error('No character type is selected for the password');
+ }
+
+ if (length < 4) {
+ throw new Error('The password must be at least 4 characters long');
+ }
+
+ let password = '';
+ const randomValues = new Uint32Array(length);
+
+ crypto.getRandomValues(randomValues);
+
+ for (let i = 0; i < length; i++) {
+ const randomIndex = randomValues[i] % allowedChars.length;
+ password += allowedChars[randomIndex];
+ }
+
+ return password;
+}
+
+function generateSimplePassword(length: number): string {
+ const ALL_CHARS = UPPERCASE_LETTERS + LOWERCASE_LETTERS + NUMBERS + SPECIAL_CHARACTERS;
+
+ if (length < 1) {
+ throw new Error('The password length must be a positive number');
+ }
+
+ let password = '';
+ const randomValues = new Uint32Array(length);
+
+ crypto.getRandomValues(randomValues);
+
+ for (let i = 0; i < length; i++) {
+ const randomIndex = randomValues[i] % ALL_CHARS.length;
+ password += ALL_CHARS[randomIndex];
+ }
+
+ return password;
+}
+
+function generateSecurePassword(length: number): string {
+ if (length < 4) {
+ throw new Error('The minimum length for a secure password is 4 characters');
+ }
+
+ const charSets = [UPPERCASE_LETTERS, LOWERCASE_LETTERS, NUMBERS, SPECIAL_CHARACTERS];
+
+ let password = '';
+ password += UPPERCASE_LETTERS[Math.floor(Math.random() * UPPERCASE_LETTERS.length)];
+ password += LOWERCASE_LETTERS[Math.floor(Math.random() * LOWERCASE_LETTERS.length)];
+ password += NUMBERS[Math.floor(Math.random() * NUMBERS.length)];
+ password += SPECIAL_CHARACTERS[Math.floor(Math.random() * SPECIAL_CHARACTERS.length)];
+
+ const ALL_CHARS = charSets.join('');
+ const remainingLength = length - 4;
+
+ if (remainingLength > 0) {
+ const randomValues = new Uint32Array(remainingLength);
+ crypto.getRandomValues(randomValues);
+
+ for (let i = 0; i < remainingLength; i++) {
+ const randomIndex = randomValues[i] % ALL_CHARS.length;
+ password += ALL_CHARS[randomIndex];
+ }
+ }
+
+ return password
+ .split('')
+ .sort(() => Math.random() - 0.5)
+ .join('');
+}
+
+export {
+ generatePassword,
+ generateSimplePassword,
+ generateSecurePassword,
+ UPPERCASE_LETTERS,
+ LOWERCASE_LETTERS,
+ NUMBERS,
+ SPECIAL_CHARACTERS,
+};
+
+export type { PasswordOptions };
diff --git a/frontend/src/libs/repo.ts b/frontend/src/libs/repo.ts
new file mode 100644
index 0000000000..8f82f6f371
--- /dev/null
+++ b/frontend/src/libs/repo.ts
@@ -0,0 +1,39 @@
+function bufferToHex(buffer: ArrayBuffer): string {
+ return Array.from(new Uint8Array(buffer))
+ .map((b) => b.toString(16).padStart(2, '0'))
+ .join('');
+}
+
+export async function slugify(prefix: string, unique_key: string, hash_size: number = 8): Promise {
+ const encoder = new TextEncoder();
+ const data = encoder.encode(unique_key);
+ const hashBuffer = await crypto.subtle.digest('SHA-256', data);
+ const fullHash = bufferToHex(hashBuffer);
+ return `${prefix}-${fullHash.substring(0, hash_size)}`;
+}
+
+export function getRepoName(url: string): string {
+ const cleaned = url
+ .replace(/^https?:\/\//i, '')
+ .replace(/:\/(\S*)/, '')
+ .replace(/\/+$/, '')
+ .replace(/\.git$/, '');
+ const parts = cleaned.split('/').filter(Boolean);
+ return parts.length ? parts[parts.length - 1] : '';
+}
+
+export function getPathWithoutProtocol(url: string): string {
+ return url.replace(/^https?:\/\//i, '');
+}
+
+export function getRepoUrlWithOutDir(url: string): string {
+ const parsedUrl = url.match(/^([^:]+(?::[^:]+)?)/)?.[1];
+
+ return parsedUrl ?? url;
+}
+
+export function getRepoDirFromUrl(url: string): string | undefined {
+ const dirName = url.replace(/^https?:\/\//i, '').match(/:\/(\S*)/)?.[1];
+
+ return dirName ? `/${dirName}` : undefined;
+}
diff --git a/frontend/src/libs/resources.ts b/frontend/src/libs/resources.ts
new file mode 100644
index 0000000000..17ec638740
--- /dev/null
+++ b/frontend/src/libs/resources.ts
@@ -0,0 +1,39 @@
+const mibToGB = (mib: number): string => `${Math.round(mib / 1024)}GB`;
+
+export const formatResources = (resources: IResources, includeSpot = true): string => {
+ const parts: string[] = [];
+
+ if (resources.cpus > 0) {
+ const archPrefix = resources.cpu_arch === 'arm' ? 'arm:' : '';
+ parts.push(`cpu=${archPrefix}${resources.cpus}`);
+ }
+
+ if (resources.memory_mib > 0) {
+ parts.push(`mem=${mibToGB(resources.memory_mib)}`);
+ }
+
+ if (resources.disk && resources.disk.size_mib > 0) {
+ parts.push(`disk=${mibToGB(resources.disk.size_mib)}`);
+ }
+
+ if (resources.gpus.length > 0) {
+ const gpu = resources.gpus[0];
+ const gpuParts: string[] = [];
+
+ if (gpu.memory_mib > 0) {
+ gpuParts.push(mibToGB(gpu.memory_mib));
+ }
+
+ gpuParts.push(String(resources.gpus.length));
+
+ parts.push('gpu=' + [gpu.name, ...gpuParts].filter(Boolean).join(':'));
+ }
+
+ let output = parts.join(' ');
+
+ if (includeSpot && resources.spot) {
+ output += ' (spot)';
+ }
+
+ return output || '-';
+};
diff --git a/frontend/src/libs/run.ts b/frontend/src/libs/run.ts
new file mode 100644
index 0000000000..d0773e15b3
--- /dev/null
+++ b/frontend/src/libs/run.ts
@@ -0,0 +1,117 @@
+import { get as _get } from 'lodash';
+import { StatusIndicatorProps } from '@cloudscape-design/components';
+
+import { capitalize } from 'libs';
+import { formatResources } from 'libs/resources';
+
+import { finishedRunStatuses } from '../pages/Runs/constants';
+import { getJobProbesStatuses } from '../pages/Runs/Details/Jobs/List/helpers';
+
+import { IModelExtended } from '../pages/Models/List/types';
+
+export const getStatusIconType = (
+ status: IRun['status'] | TJobStatus,
+ terminationReason: string | null | undefined,
+): StatusIndicatorProps['type'] => {
+ if (finishedRunStatuses.includes(status) && terminationReason === 'interrupted_by_no_capacity') {
+ return 'stopped';
+ }
+ switch (status) {
+ case 'failed':
+ return 'error';
+ case 'done':
+ return 'success';
+ case 'aborted':
+ case 'terminated':
+ return 'stopped';
+ case 'running':
+ return 'success';
+ case 'terminating':
+ case 'pulling':
+ case 'provisioning':
+ return 'in-progress';
+ case 'submitted':
+ case 'pending':
+ return 'pending';
+ default:
+ console.error(new Error('Undefined run status'));
+ }
+};
+
+export const getStatusIconColor = (
+ status: IRun['status'] | TJobStatus,
+ terminationReason: string | null | undefined,
+ statusMessage: string,
+): StatusIndicatorProps.Color | undefined => {
+ if (statusMessage === 'No fleets') {
+ return 'red';
+ }
+ if (terminationReason === 'failed_to_start_due_to_no_capacity' || terminationReason === 'interrupted_by_no_capacity') {
+ return 'yellow';
+ }
+ switch (status) {
+ case 'submitted':
+ case 'pending':
+ case 'provisioning':
+ case 'pulling':
+ case 'terminating':
+ return 'blue';
+ case 'aborted':
+ return 'yellow';
+ case 'done':
+ return 'grey';
+ default:
+ return undefined;
+ }
+};
+
+export const getRunStatusMessage = (run: IRun): string => {
+ if (finishedRunStatuses.includes(run.status) && run.latest_job_submission?.status_message) {
+ return capitalize(run.latest_job_submission.status_message);
+ } else {
+ return capitalize(run.status_message || run.status);
+ }
+};
+
+export const getRunError = (run: IRun): string | null => {
+ const error = run.error ?? run.latest_job_submission?.error ?? null;
+ return error ? capitalize(error) : null;
+};
+
+export const getRunProbeStatuses = (run: IRun): StatusIndicatorProps.Type[] => {
+ const job = run.jobs[0];
+
+ if (!job) {
+ return [];
+ }
+
+ return getJobProbesStatuses(run.jobs[0]);
+};
+
+export const getRunPriority = (run: IRun): number | null => {
+ return run.run_spec.configuration?.priority ?? null;
+};
+
+export const getExtendedModelFromRun = (run: IRun): IModelExtended | null => {
+ if (!run?.service?.model) return null;
+
+ return {
+ ...(run.service?.model ?? {}),
+ id: run.id,
+ project_name: run.project_name,
+ run_name: run?.run_spec.run_name ?? 'No run name',
+ user: run.user,
+ resources: run.latest_job_submission?.job_provisioning_data?.instance_type?.resources
+ ? formatResources(run.latest_job_submission.job_provisioning_data.instance_type.resources)
+ : null,
+ price: run.latest_job_submission?.job_provisioning_data?.price ?? null,
+ submitted_at: run.submitted_at,
+ repository: getRepoNameFromRun(run),
+ backend: run.latest_job_submission?.job_provisioning_data?.backend ?? null,
+ region: run.latest_job_submission?.job_provisioning_data?.region ?? null,
+ };
+};
+
+export const getRepoNameFromRun = (run: IRun): string => {
+ return _get(run.run_spec.repo_data, 'repo_name', _get(run.run_spec.repo_data, 'repo_dir', '-'));
+};
diff --git a/frontend/src/libs/serverErrors.ts b/frontend/src/libs/serverErrors.ts
new file mode 100644
index 0000000000..ce2f6f0d68
--- /dev/null
+++ b/frontend/src/libs/serverErrors.ts
@@ -0,0 +1,52 @@
+import { isArray } from 'lodash';
+
+import { FormFieldError, ResponseServerError } from './types';
+
+export default function serverErrors(error: unknown): error is { data: { message: string } } {
+ return (
+ typeof error === 'object' &&
+ error !== null &&
+ 'data' in error &&
+ // eslint-disable-next-line @typescript-eslint/no-explicit-any
+ typeof ((error as any).data as any)?.message === 'string'
+ );
+}
+
+export function isResponseServerFormFieldError(fieldError: unknown): fieldError is FormFieldError {
+ return (
+ typeof fieldError === 'object' &&
+ fieldError !== null &&
+ fieldError !== undefined &&
+ 'loc' in fieldError &&
+ 'msg' in fieldError &&
+ isArray(fieldError?.loc) &&
+ typeof fieldError?.msg === 'string'
+ );
+}
+
+export function isResponseServerError(formErrors: unknown): formErrors is ResponseServerError {
+ return (
+ typeof formErrors === 'object' &&
+ formErrors !== null &&
+ formErrors !== undefined &&
+ 'detail' in formErrors &&
+ isArray(formErrors?.detail) &&
+ !!formErrors.detail.length &&
+ 'msg' in formErrors.detail[0]
+ );
+}
+
+// eslint-disable-next-line @typescript-eslint/no-explicit-any
+export function getServerError(error: any): string {
+ let errorText = error?.error;
+
+ const errorData = error.data;
+
+ if (isResponseServerError(errorData)) {
+ const errorDetail = errorData.detail;
+
+ errorText = errorDetail.flatMap(({ msg }) => msg).join(', ');
+ }
+
+ return errorText;
+}
diff --git a/frontend/src/libs/types.ts b/frontend/src/libs/types.ts
new file mode 100644
index 0000000000..22b1d14c27
--- /dev/null
+++ b/frontend/src/libs/types.ts
@@ -0,0 +1,15 @@
+export type FormFieldError = {
+ loc: string[];
+ msg: string;
+ type?: string;
+ code: string;
+};
+
+export type ResponseServerErrorItem = {
+ msg: string;
+ code: string;
+};
+
+export type ResponseServerError = {
+ detail: (FormFieldError | ResponseServerErrorItem)[];
+};
diff --git a/frontend/src/libs/volumes.ts b/frontend/src/libs/volumes.ts
new file mode 100644
index 0000000000..f5db13a3ef
--- /dev/null
+++ b/frontend/src/libs/volumes.ts
@@ -0,0 +1,15 @@
+import { StatusIndicatorProps } from '@cloudscape-design/components';
+
+export const getStatusIconType = (status: IVolume['status']): StatusIndicatorProps['type'] => {
+ switch (status) {
+ case 'failed':
+ return 'error';
+ case 'active':
+ return 'success';
+ case 'provisioning':
+ return 'in-progress';
+ case 'submitted':
+ default:
+ console.error(new Error('Undefined volume status'));
+ }
+};
diff --git a/frontend/src/locale/en.json b/frontend/src/locale/en.json
new file mode 100644
index 0000000000..804134f3d1
--- /dev/null
+++ b/frontend/src/locale/en.json
@@ -0,0 +1,838 @@
+{
+ "dstack": "Dstack",
+ "common": {
+ "ok": "OK",
+ "loading": "Loading",
+ "add": "Add",
+ "yes": "Yes",
+ "no": "No",
+ "create": "Create",
+ "create_wit_text": "Create {{text}}",
+ "edit": "Edit",
+ "delete": "Delete",
+ "remove": "Remove",
+ "apply": "Apply",
+ "next": "Next",
+ "previous": "Back",
+ "settings": "Settings",
+ "match_count_with_value_one": "{{count}} match",
+ "match_count_with_value_other": "{{count}} matches",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match.",
+ "sign_out": "Sign out",
+ "cancel": "Cancel",
+ "save": "Save",
+ "send": "Send",
+ "profile": "Profile",
+ "copied": "Copied",
+ "copy": "Copy",
+ "info": "Info",
+ "stop": "Stop",
+ "abort": "Abort",
+ "close": "Close",
+ "clearFilter": "Clear filter",
+ "server_error": "Server error: {{error}}",
+ "login": "Sign in",
+ "login_github": "Sign in with GitHub",
+ "login_okta": "Sign in with Okta",
+ "login_entra": "Sign in with EntraID",
+ "login_google": "Sign in with Google",
+ "general": "General",
+ "test": "Test",
+ "local_storage_unavailable": "Local Storage is unavailable",
+ "local_storage_unavailable_message": "Your browser doesn't support local storage",
+ "object": "Object",
+ "objects_other": "Objects",
+ "continue": "Continue",
+ "select_visible_columns": "Select visible columns",
+ "tutorial": "Tutorials",
+ "tutorial_other": "Take a tour",
+ "docs": "Docs",
+ "discord": "Discord",
+ "danger_zone": "Danger zone",
+ "control_plane": "Control plane",
+ "refresh": "Refresh",
+ "quickstart": "Quickstart",
+ "ask_ai": "Ask AI",
+ "new": "New",
+ "full_view": "Full view"
+ },
+
+ "auth": {
+ "invalid_token": "Invalid token",
+ "you_are_not_logged_in": "You are not logged in",
+ "contact_to_administrator": "For getting the authorization token, contact to the administrator",
+ "sign_in_to_dstack": "Welcome to dstack Sky",
+ "sign_in_to_dstack_enterprise": "Welcome to dstack",
+ "authorization_failed": "Authorization is failed",
+ "try_again": "Please try again",
+ "login_by_token": "Sign in via a token",
+ "another_login_methods": "Other sign in options"
+ },
+
+ "navigation": {
+ "settings": "Settings",
+ "runs": "Runs",
+ "models": "Models",
+ "fleets": "Fleets",
+ "fleet": "Fleet",
+ "project": "project",
+ "project_other": "Projects",
+ "general": "General",
+ "users": "Users",
+ "user_settings": "User settings",
+ "account": "User",
+ "billing": "Billing",
+ "resources": "Resources",
+ "volumes": "Volumes",
+ "instances": "Instances",
+ "offers": "Offers",
+ "events": "Events"
+ },
+
+ "backend": {
+ "page_title_one": "Backend",
+ "page_title_other": "Backends",
+ "add_backend": "Add backend",
+ "edit_backend": "Edit backend",
+ "empty_message_title": "No backends",
+ "empty_message_text": "No backends to display.",
+ "type": {
+ "aws": "AWS",
+ "aws_description": "Run workflows and store data in Amazon Web Services ",
+ "gcp": "GCP",
+ "gcp_description": "Run workflows and store data in Google Cloud Platform",
+ "azure": "Azure",
+ "azure_description": "Run workflows and store data in Microsoft Azure",
+ "lambda": "Lambda",
+ "lambda_description": "Run workflows and store data in Lambda",
+ "local": "Local",
+ "local_description": "Run workflows and store data locally via Docker"
+ },
+
+ "table": {
+ "region": "Region",
+ "bucket": "Storage"
+ },
+
+ "edit": {
+ "success_notification": "Project updating is successful",
+ "delete_backend_confirm_title": "Delete backend",
+ "delete_backend_confirm_message": "Are you sure you want to delete this backend?",
+ "delete_backends_confirm_title": "Delete backends",
+ "delete_backends_confirm_message": "Are you sure you want to delete these backends?"
+ },
+
+ "create": {
+ "success_notification": "Backend is created"
+ }
+ },
+
+ "gateway": {
+ "page_title_one": "Gateway",
+ "page_title_other": "Gateways",
+ "add_gateway": "Add gateway",
+ "edit_gateway": "Edit gateway",
+ "empty_message_title": "No gateways",
+ "empty_message_text": "No gateways to display.",
+
+ "edit": {
+ "name": "Name",
+ "backend": "Backend",
+ "backend_description": "Select a backend",
+ "region": "Region",
+ "region_description": "Select a region",
+ "default": "Default",
+ "default_checkbox": "Turn on default",
+ "hostname": "Hostname",
+ "external_ip": "External IP",
+ "wildcard_domain": "Wildcard domain",
+ "wildcard_domain_description": "Specify the wildcard domain mapped to the external IP.",
+ "wildcard_domain_placeholder": "*.mydomain.com",
+ "delete_gateway_confirm_title": "Delete gateway",
+ "delete_gateway_confirm_message": "Are you sure you want to delete this gateway?",
+ "delete_gateways_confirm_title": "Delete gateways",
+ "delete_gateways_confirm_message": "Are you sure you want to delete these gateways?",
+
+ "validation": {
+ "wildcard_domain_format": "Should use next format: {{pattern}}"
+ }
+ },
+
+ "create": {
+ "success_notification": "Gateway is created",
+ "creating_notification": "The gateway is creating. It may take some time"
+ },
+
+ "update": {
+ "success_notification": "Gateway is updated"
+ },
+
+ "test_domain": {
+ "success_notification": "Domain is valid"
+ }
+ },
+
+ "projects": {
+ "page_title": "Projects",
+ "search_placeholder": "Find projects",
+ "empty_message_title": "No projects",
+ "empty_message_text": "No projects to display.",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match.",
+ "nomatch_message_button_label": "Clear filter",
+ "repositories": "Repositories",
+ "runs": "Runs",
+ "tags": "Tags",
+ "events": "Events",
+ "settings": "Settings",
+ "join": "Join",
+ "leave_confirm_title": "Leave project",
+ "leave_confirm_message": "Are you sure you want to leave this project?",
+ "leave": "Leave",
+ "join_success": "Successfully joined the project",
+ "leave_success": "Successfully left the project",
+ "join_error": "Failed to join project",
+ "leave_error": "Failed to leave project",
+ "card": {
+ "backend": "Backend",
+ "settings": "Settings"
+ },
+ "wizard": {
+ "submit": "Create"
+ },
+ "edit": {
+ "general": "General",
+ "project_name": "Name",
+ "owner": "Owner",
+ "project_name_description": "Only latin characters, dashes, underscores, and digits",
+ "project_type": "Project type",
+ "project_type_description": "Choose which project type you want to create",
+ "backends": "Backends",
+ "base_backends_description": "dstack will automatically collect offers from the following providers. Deselect providers you don’t want to use.",
+ "backends_description": "The following backends can be configured with your own cloud credentials in the project settings after the project is created.",
+ "create_default_fleet": "Create a default fleet",
+ "default_fleet": "Default fleet",
+ "default_fleet_description": "At least one fleet is required to run dev environments, tasks, or services.",
+ "is_public": "Public",
+ "is_public_description": "Allow any user join the project as a member",
+ "backend": "Backend",
+ "backend_config": "Backend config",
+ "backend_config_description": "Specify the backend config in the YAML format. Click Info for examples.",
+ "backend_type": "Type",
+ "backend_type_description": "Select a backend type",
+ "members_empty_message_title": "No members",
+ "members_empty_message_text": "Select project's members",
+ "update_members_success": "Members are updated",
+ "update_visibility_success": "Project visibility updated successfully",
+ "update_templates_repo_success": "Templates updated successfully",
+ "update_visibility_confirm_title": "Change visibility",
+ "update_visibility_confirm_message": "Are you sure you want to change the project visibility? This will affect who can access this project.",
+ "change_visibility": "Change",
+ "project_visibility": "Visibility",
+ "project_visibility_settings": "Visibility",
+ "templates_repo": "Templates",
+ "override_project_templates": "Templates",
+ "transfer_ownership": "Ownership",
+ "templates_repo_description": "Set a project-level templates repository URL",
+ "templates_repo_placeholder": "https://github.com/org/templates.git",
+ "templates_repo_not_set": "not set",
+ "templates_repo_required": "Templates repo URL cannot be empty",
+ "save_templates_repo": "Save",
+ "configure_templates_repo": "Configure",
+ "change_templates_repo_title": "Override project templates",
+ "change_templates_repo_message": "Specify a new templates Git repo URL:",
+ "reset_templates_repo": "Reset",
+ "reset_templates_repo_title": "Reset templates",
+ "reset_templates_repo_message": "Are you sure you want to reset templates for this project?",
+ "project_visibility_description": "Control who can access this project",
+ "make_project_public": "Make project public",
+ "delete_project_confirm_title": "Delete project",
+ "delete_project_confirm_message": "Are you sure you want to delete this project?",
+ "delete_projects_confirm_title": "Delete projects",
+ "delete_projects_confirm_message": "Are you sure you want to delete these projects?",
+ "delete_this_project": "Delete this project",
+ "cli": "CLI",
+ "aws": {
+ "authorization": "Authorization",
+ "authorization_default": "Default credentials",
+ "authorization_access_key": "Access key",
+ "access_key": "Access key",
+ "access_key_id": "Access key ID",
+ "access_key_id_description": "Specify the AWS access key ID",
+ "secret_key": "Secret key",
+ "secret_key_id": "Secret access key",
+ "secret_key_id_description": "Specify the AWS secret access key",
+ "regions": "Regions",
+ "regions_description": "Select regions to run workflows and store artifacts",
+ "regions_placeholder": "Select regions",
+ "s3_bucket_name": "Bucket",
+ "s3_bucket_name_description": "Select an S3 bucket to store artifacts",
+ "ec2_subnet_id": "Subnet",
+ "ec2_subnet_id_description": "Select a subnet to run workflows in",
+ "ec2_subnet_id_placeholder": "Not selected",
+ "vpc_name": "VPC",
+ "vpc_name_description": "Enter a vpc"
+ },
+ "azure": {
+ "authorization": "Authorization",
+ "authorization_default": "Default credentials",
+ "authorization_client": "Client secret",
+ "tenant_id": "Tenant ID",
+ "tenant_id_description": "Specify an Azure tenant ID",
+ "tenant_id_placeholder": "Not selected",
+ "client_id": "Client ID",
+ "client_id_description": "Specify an Azure client (application) ID",
+ "client_secret": "Client secret",
+ "client_secret_description": "Specify an Azure client (application) secret",
+ "subscription_id": "Subscription ID",
+ "subscription_id_description": "Select an Azure subscription ID",
+ "subscription_id_placeholder": "Not selected",
+ "locations": "Locations",
+ "locations_description": "Select locations to run workflows",
+ "locations_placeholder": "Select locations",
+ "storage_account": "Storage account",
+ "storage_account_description": "Select an Azure storage account to store artifacts",
+ "storage_account_placeholder": "Not selected"
+ },
+ "gcp": {
+ "authorization": "Authorization",
+ "authorization_default": "Default credentials",
+ "service_account": "Service account key",
+ "credentials_description": "Credentials description",
+ "credentials_placeholder": "Credentials placeholder",
+ "regions": "Regions",
+ "regions_description": "Select regions to run workflows and store artifacts",
+ "regions_placeholder": "Select regions",
+ "project_id": "Project Id",
+ "project_id_description": "Select a project id",
+ "project_id_placeholder": "Select a project Id"
+ },
+ "lambda": {
+ "api_key": "API key",
+ "api_key_description": "Specify the Lambda API key",
+ "regions": "Regions",
+ "regions_description": "Select regions to run workflows",
+ "regions_placeholder": "Select regions",
+ "storage_backend": {
+ "type": "Storage",
+ "type_description": "Select backend storage",
+ "type_placeholder": "Select type",
+ "credentials": {
+ "access_key_id": "Access key ID",
+ "access_key_id_description": "Specify the AWS access key ID",
+ "secret_key_id": "Secret access key",
+ "secret_key_id_description": "Specify the AWS secret access key"
+ },
+ "s3_bucket_name": "Bucket",
+ "s3_bucket_name_description": "Select an S3 bucket to store artifacts"
+ }
+ },
+ "local": {
+ "path": "Files path"
+ },
+ "members": {
+ "section_title": "Members",
+ "name": "User name",
+ "role": "Project role"
+ },
+ "secrets": {
+ "section_title": "Secrets",
+ "empty_message_title": "No secrets",
+ "empty_message_text": "No secrets to display.",
+ "name": "Secret name",
+ "value": "Secret value",
+ "create_secret": "Create secret",
+ "update_secret": "Update secret",
+ "delete_confirm_title": "Delete secret",
+ "delete_confirm_message": "Are you sure you want to delete the {{name}} secret?",
+ "multiple_delete_confirm_title": "Delete secrets",
+ "multiple_delete_confirm_message": "Are you sure you want to delete {{count}} secrets?",
+ "not_permissions_title": "No permissions",
+ "not_permissions_description": "You don't have permissions for managing secrets",
+ "validation": {
+ "secret_name_format": "Invalid secret name"
+ }
+ },
+ "error_notification": "Update project error",
+ "validation": {
+ "user_name_format": "Only letters, numbers, - or _"
+ },
+ "visibility": {
+ "private": "Private",
+ "public": "Public"
+ }
+ },
+ "create": {
+ "page_title": "Create project",
+ "error_notification": "Create project error",
+ "success_notification": "Project is created"
+ },
+ "repo": {
+ "search_placeholder": "Find repositories",
+ "empty_message_title": "No repositories",
+ "empty_message_text": "No repositories to display.",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match.",
+ "card": {
+ "owner": "Owner",
+ "last_run": "Last run",
+ "tags_count": "Tags count",
+ "directory": "Directory"
+ },
+ "secrets": {
+ "table_title": "Secrets",
+ "add_modal_title": "Add secret",
+ "update_modal_title": "Update secret",
+ "name": "Secret name",
+ "name_description": "Secret name",
+ "value": "Secret value",
+ "value_description": "Secret value",
+ "search_placeholder": "Find secrets",
+ "empty_message_title": "No secrets",
+ "empty_message_text": "No secrets to display."
+ }
+ },
+ "run": {
+ "list_page_title": "Runs",
+ "search_placeholder": "Find runs",
+ "empty_message_title": "No runs",
+ "empty_message_text": "No runs to display.",
+ "quickstart_message_text": "Check out the quickstart guide to get started with dstack",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match. Try to change project or clear filter",
+ "filter_property_placeholder": "Filter by properties",
+ "project": "Project",
+ "project_placeholder": "Filtering by project",
+ "repo": "Repository",
+ "repo_placeholder": "Filtering by repository",
+ "user": "User",
+ "user_placeholder": "Filtering by user",
+ "active_only": "Active runs",
+ "log": "Logs",
+ "log_empty_message_title": "No logs",
+ "log_empty_message_text": "No logs to display.",
+ "inspect": "Inspect",
+ "run_name": "Name",
+ "workflow_name": "Workflow",
+ "configuration": "Configuration",
+ "instance": "Instance",
+ "priority": "Priority",
+ "provider_name": "Provider",
+ "status": "Status",
+ "probe": "Probes",
+ "submitted_at": "Submitted",
+ "finished_at": "Finished",
+ "metrics": {
+ "title": "Metrics",
+ "show_metrics": "Show metrics",
+ "cpu_utilization": "CPU utilization %",
+ "memory_used": "System memory used",
+ "per_each_cpu_utilization": "GPU utilization %",
+ "per_each_memory_used": "GPU memory used"
+ },
+ "jobs": "Jobs",
+ "job_name": "Job Name",
+ "cost": "Cost",
+ "backend": "Backend",
+ "region": "Region",
+ "instance_id": "Instance ID",
+ "schedule": "Schedule",
+ "next_run": "Next run",
+ "resources": "Resources",
+ "spot": "Spot",
+ "termination_reason": "Termination reason",
+ "price": "Price",
+ "error": "Error",
+ "artifacts": "Artifacts",
+ "artifacts_count": "Artifacts",
+ "hub_user_name": "User",
+ "service_url": "Service URL",
+ "statuses": {
+ "pending": "Pending",
+ "submitted": "Submitted",
+ "provisioning": "Provisioning",
+ "pulling": "Pulling",
+ "downloading": "Downloading",
+ "running": "Running",
+ "uploading": "Uploading",
+ "stopping": "Stopping",
+ "stopped": "Stopped",
+ "terminating": "Terminating",
+ "terminated": "Terminated",
+ "aborting": "Aborting",
+ "aborted": "Aborted",
+ "failed": "Failed",
+ "done": "Done",
+ "building": "Building"
+ }
+ },
+ "tag": {
+ "list_page_title": "Artifacts",
+ "search_placeholder": "Find tags",
+ "empty_message_title": "No tags",
+ "empty_message_text": "No tags to display.",
+ "tag_name": "Tag",
+ "run_name": "Run",
+ "artifacts": "Files"
+ },
+ "artifact": {
+ "list_page_title": "Artifacts",
+ "search_placeholder": "Find objects",
+ "empty_message_title": "No objects",
+ "empty_message_text": "No objects to display.",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match.",
+ "name": "Name",
+ "type": "Type",
+ "size": "Size"
+ }
+ },
+ "runs": {
+ "launch_button": "Launch",
+ "no_templates_alert": {
+ "title": "No templates configured",
+ "description": "The selected project has no templates available for Launch.",
+ "action": "Settings"
+ },
+ "launch": {
+ "wizard": {
+ "title": "Launch",
+ "submit": "Apply",
+ "project": "Project",
+ "project_description": "Select a project",
+ "project_empty": "No options",
+ "project_loading": "Loading options",
+ "template": "Template",
+ "template_description": "Select a template",
+ "template_empty": "No options",
+ "template_loading": "Loading options",
+ "template_placeholder": "Select a project to select a template",
+ "template_card_type": "Type",
+ "gpu": "GPU",
+ "gpu_description_enabled": "Choose a specific offer, or let dstack select it automatically.",
+ "gpu_description_disabled": "Enable GPU for this run.",
+ "offer": "Offer",
+ "offer_description": "Select an offer for the run.",
+ "name": "Name",
+ "name_description": "The name of the run, e.g. 'my-dev-env'",
+ "name_constraint": "Example: 'my-fleet' or 'default'. If not specified, generated automatically.",
+ "name_placeholder": "Optional",
+ "ide": "IDE",
+ "ide_description": "Optionally select an IDE to pre-install in the dev environment.",
+ "docker": "Docker",
+ "docker_image": "Image",
+ "docker_image_description": "A Docker image name, e.g. 'lmsysorg/sglang:latest'",
+ "docker_image_constraint": "The image must be public",
+ "docker_image_placeholder": "Required",
+ "python": "Python",
+ "python_description": "The version of Python, e.g. '3.12'",
+ "python_placeholder": "Optional",
+ "repo": "Repo",
+ "working_dir": "Working dir",
+ "working_dir_description": "The absolute path to the working directory inside the container, e.g. '/home/user/project'",
+ "working_dir_placeholder": "Optional",
+ "working_dir_constraint": "By default, set to '/workflow'",
+ "repo_url": "URL",
+ "repo_url_description": "A URL of a Git repository, e.g. 'https://github.com/user/repo'",
+ "repo_url_constraint": "The repo must be public",
+ "repo_url_placeholder": "Required",
+ "repo_path": "Path",
+ "repo_path_description": "The path inside the container to clone the repository, e.g. '/home/user/project'",
+ "repo_path_placeholder": "Optional",
+ "repo_path_constraint": "By default, set to '/workflow'",
+ "config": "Configuration file",
+ "configuration_label": "Configuration",
+ "configuration_description": "Review and adjust the configuration if needed.",
+ "success_notification": "The run is submitted!"
+ }
+ }
+ },
+ "offer": {
+ "title": "Offers",
+ "filter_property_placeholder": "Filter by properties",
+ "backend": "Backend",
+ "backend_plural": "Backends",
+ "availability_not_available": "Not available",
+ "availability_no_quota": "No quota",
+ "availability_no_balance": "No balance",
+ "groupBy": "Group by properties",
+ "region": "Region",
+ "count": "Count",
+ "price": "$/GPU",
+ "memory_mib": "Memory",
+ "spot": "Spot policy",
+ "empty_message_title_select_project": "Select a project",
+ "empty_message_text_select_project": "Use the filter above to select a project",
+ "empty_message_title_select_groupBy": "Select a group by",
+ "empty_message_text_select_groupBy": "Use the field above to select a group by",
+ "empty_message_title": "No offers",
+ "empty_message_text": "No offers to display.",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match."
+ },
+
+ "models": {
+ "model_name": "Name",
+ "url": "URL",
+ "gateway": "Gateway",
+ "type": "Type",
+ "run": "Run",
+ "resources": "Resources",
+ "price": "Price",
+ "submitted_at": "Submitted",
+ "user": "User",
+ "repository": "Repository",
+ "backend": "Backend",
+ "code": "Code",
+ "empty_message_title": "No models",
+ "empty_message_text": "No models to display.",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match.",
+ "nomatch_message_button_label": "Clear filter",
+
+ "details": {
+ "instructions": "System",
+ "instructions_description": "Specify system",
+ "message_placeholder": "Enter your question",
+ "chat_empty_title": "No messages yet",
+ "chat_empty_message": "Please start a chat",
+ "run_name": "Run name",
+ "view_code": "View code",
+ "view_code_description": "You can use the following code to start integrating your current prompt and settings into your application."
+ }
+ },
+
+ "fleets": {
+ "no_alert": {
+ "title": "No fleets",
+ "description": "The project has no fleets. Create one before submitting a run.",
+ "button_title": "Create a fleet"
+ },
+ "fleet": "Fleet",
+ "fleet_column_name": "Name",
+ "fleet_placeholder": "Filtering by fleet",
+ "fleet_name": "Fleet name",
+ "total_instances": "Number of instances",
+ "inspect": "Inspect",
+ "empty_message_title": "No fleets",
+ "empty_message_text": "No fleets to display.",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match.",
+ "nomatch_message_button_label": "Clear filter",
+ "active_only": "Active fleets",
+ "filter_property_placeholder": "Filter by properties",
+ "statuses": {
+ "active": "Active",
+ "submitted": "Submitted",
+ "failed": "Failed",
+ "terminating": "Terminating",
+ "terminated": "Terminated"
+ },
+ "create": {
+ "success_notification": "The fleet is created!"
+ },
+ "instances": {
+ "active_only": "Active instances",
+ "filter_property_placeholder": "Filter by properties",
+ "title": "Instances",
+ "empty_message_title": "No instances",
+ "empty_message_text": "No instances to display.",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match.",
+ "instance_name": "Name",
+ "instance_num": "Num",
+ "created": "Created",
+ "status": "Status",
+ "project": "Project",
+ "hostname": "Hostname",
+ "instance_type": "Type",
+ "statuses": {
+ "pending": "Pending",
+ "provisioning": "Provisioning",
+ "idle": "Idle",
+ "busy": "Busy",
+ "terminating": "Terminating",
+ "terminated": "Terminated"
+ },
+ "resources": "Resources",
+ "backend": "Backend",
+ "region": "Region",
+ "spot": "Spot",
+ "started": "Started",
+ "finished_at": "Finished",
+ "price": "Price",
+ "termination_reason": "Termination reason",
+ "health": "Health",
+ "blocks": "Blocks",
+ "inspect": "Inspect"
+ },
+ "edit": {
+ "name": "Name",
+ "name_description": "The name of the fleet, e.g. 'my-fleet'",
+ "name_placeholder": "Optional",
+ "name_constraint": "Example: 'my-fleet' or 'default'. If not specified, generated automatically.",
+ "min_instances": "Min number of instances",
+ "min_instances_description": "Set it '0' to provision instances only when required",
+ "max_instances": "Max number of instances",
+ "max_instances_description": "Required only if you want to set an upper limit",
+ "max_instances_placeholder": "Optional",
+ "idle_duration": "Idle duration",
+ "idle_duration_description": "Example: '0s', '1m', '1h'",
+ "spot_policy": "Spot policy",
+ "spot_policy_description": "Set it to 'auto' to allow the use of both on-demand and spot instances"
+ }
+ },
+ "volume": {
+ "volumes": "Volumes",
+ "empty_message_title": "No volumes",
+ "empty_message_text": "No volumes to display.",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match.",
+ "delete_volumes_confirm_title": "Delete volumes",
+ "delete_volumes_confirm_message": "Are you sure you want to delete these volumes?",
+ "active_only": "Active volumes",
+ "filter_property_placeholder": "Filter by properties",
+
+ "name": "Name",
+ "project": "Project name",
+ "region": "Region",
+ "backend": "Backend",
+ "status": "Status",
+ "created": "Created",
+ "finished": "Finished",
+ "price": "Price (per month)",
+ "cost": "Cost",
+ "statuses": {
+ "failed": "Failed",
+ "submitted": "Submitted",
+ "provisioning": "Provisioning",
+ "active": "Active",
+ "deleted": "Deleted"
+ }
+ },
+
+ "events": {
+ "recorded_at": "Recorded At",
+ "actor": "Actor",
+ "targets": "Targets",
+ "message": "Message"
+ },
+
+ "users": {
+ "page_title": "Users",
+ "search_placeholder": "Find members",
+ "empty_message_title": "No members",
+ "empty_message_text": "No members to display.",
+ "nomatch_message_title": "No matches",
+ "nomatch_message_text": "We can't find a match.",
+ "user_name": "User name",
+ "user_name_description": "Only latin characters, dashes, underscores, and digits",
+ "global_role_description": "Whether the user is an administrator or not",
+ "email_description": "Enter user email",
+ "token": "Token",
+ "token_description": "Specify use your personal access token",
+ "global_role": "Global role",
+ "active": "Active",
+ "active_description": "Specify user activation",
+ "activated": "Activated",
+ "deactivated": "Deactivated",
+ "email": "Email",
+ "created_at": "Created at",
+ "account": "User",
+ "account_settings": "User settings",
+ "settings": "Settings",
+ "projects": "Projects",
+ "events": "Events",
+ "public_keys": {
+ "title": "SSH keys",
+ "add_key": "Add SSH key",
+ "name": "Title",
+ "fingerprint": "Fingerprint",
+ "key_type": "Key type",
+ "added": "Added",
+ "empty_title": "No SSH keys",
+ "empty_message": "You haven't added any SSH keys yet.",
+ "key_name_label": "Title",
+ "key_name_description": "A label to identify this key",
+ "key_name_placeholder": "My SSH key",
+ "key_label": "Key",
+ "key_description": "Paste your public key content (e.g. the contents of ~/.ssh/id_ed25519.pub)",
+ "key_required": "Key content is required",
+ "key_already_exists": "This public key is already added to your account",
+ "delete_confirm_title": "Delete SSH key",
+ "delete_confirm_message": "Are you sure you want to delete the selected SSH key(s)?"
+ },
+ "create": {
+ "page_title": "Create user",
+ "error_notification": "Create user error",
+ "success_notification": "User is created"
+ },
+ "edit": {
+ "error_notification": "Update user error",
+ "success_notification": "User updating is successful",
+ "refresh_token_success_notification": "Token rotating is successful",
+ "refresh_token_error_notification": "Token rotating error",
+ "refresh_token_confirm_title": "Rotate token",
+ "refresh_token_confirm_message": "Are you sure you want to rotate token?",
+ "refresh_token_button_label": "Rotate",
+ "validation": {
+ "user_name_format": "Only letters, numbers, - or _",
+ "email_format": "Incorrect email"
+ }
+ },
+
+ "manual_payments": {
+ "title": "Credits history",
+ "add_payment": "Add payment",
+ "empty_message_title": "No payments",
+ "empty_message_text": "No payments to display.",
+
+ "create": {
+ "success_notification": "Payment creating is successful"
+ },
+
+ "edit": {
+ "value": "Amount",
+ "value_description": "Enter amount here",
+ "description": "Description",
+ "description_description": "Describe payment here",
+ "created_at": "Created at"
+ }
+ },
+
+ "token_copied": "Token copied"
+ },
+ "billing": {
+ "title": "Billing",
+ "balance": "Balance",
+ "billing_history": "Billing history",
+ "payment_method": "Payment method",
+ "no_payment_method": "No payment method attached",
+ "top_up_balance": "Top up balance",
+ "edit_payment_method": "Edit payment method",
+ "payment_amount": "Payment amount",
+ "amount_description": "Minimum: ${{value}}",
+ "make_payment": "Make a payment",
+ "min_amount_error_message": "The amount is allowed to be more than {{value}}",
+ "payment_success_message": "Payment succeeded. There can be a short delay before the balance is updated."
+ },
+ "validation": {
+ "required": "This is required field"
+ },
+ "users_autosuggest": {
+ "placeholder": "Enter username or email to add member",
+ "entered_text": "Add member",
+ "loading": "Loading users",
+ "no_match": "No matches found"
+ },
+ "roles": {
+ "admin": "Admin",
+ "manager": "Manager",
+ "user": "User"
+ },
+ "confirm_dialog": {
+ "title": "Confirm delete",
+ "message": "Are you sure you want to delete?"
+ }
+}
diff --git a/frontend/src/locale/index.ts b/frontend/src/locale/index.ts
new file mode 100644
index 0000000000..7b2f70ba0f
--- /dev/null
+++ b/frontend/src/locale/index.ts
@@ -0,0 +1,18 @@
+import i18n from 'i18next';
+import { initReactI18next } from 'react-i18next';
+
+import en from './en.json';
+
+i18n.use(initReactI18next).init({
+ returnNull: false,
+ resources: {
+ en: {
+ translation: en,
+ },
+ },
+ fallbackLng: 'en',
+
+ interpolation: {
+ escapeValue: false,
+ },
+});
diff --git a/frontend/src/pages/Events/List/ListPage.tsx b/frontend/src/pages/Events/List/ListPage.tsx
new file mode 100644
index 0000000000..9117b37bf0
--- /dev/null
+++ b/frontend/src/pages/Events/List/ListPage.tsx
@@ -0,0 +1,46 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Button, Header, SpaceBetween } from 'components';
+
+import { useBreadcrumbs } from 'hooks';
+import { ROUTES } from 'routes';
+
+import { EventList } from './index';
+
+export const ListPage: React.FC = () => {
+ const { t } = useTranslation();
+
+ useBreadcrumbs([
+ {
+ text: t('navigation.events'),
+ href: ROUTES.EVENTS.LIST,
+ },
+ ]);
+
+ return (
+ {
+ return (
+
+
+
+ }
+ >
+ {t('navigation.events')}
+
+ );
+ }}
+ />
+ );
+};
diff --git a/frontend/src/pages/Events/List/helpers.ts b/frontend/src/pages/Events/List/helpers.ts
new file mode 100644
index 0000000000..702c8a5617
--- /dev/null
+++ b/frontend/src/pages/Events/List/helpers.ts
@@ -0,0 +1,23 @@
+import type { PropertyFilterProps } from 'components';
+
+export function filterLastElementByPrefix(
+ arr: PropertyFilterProps.Query['tokens'],
+ prefix: string,
+): PropertyFilterProps.Query['tokens'] {
+ // Ищем индекс последнего элемента с префиксом "test_"
+ let lastTestIndex = -1;
+ for (let i = arr.length - 1; i >= 0; i--) {
+ if (arr[i].propertyKey?.startsWith(prefix)) {
+ lastTestIndex = i;
+ break;
+ }
+ }
+
+ // Фильтруем массив
+ return arr.filter((item, index) => {
+ // Оставляем элемент, если:
+ // 1. Это не строка с префиксом "test_"?
+ // 2. ИЛИ это строка с префиксом "test_" И она последняя в массиве
+ return !item.propertyKey?.startsWith(prefix) || index === lastTestIndex;
+ });
+}
diff --git a/frontend/src/pages/Events/List/hooks/useColumnDefinitions.tsx b/frontend/src/pages/Events/List/hooks/useColumnDefinitions.tsx
new file mode 100644
index 0000000000..be4ec19a5e
--- /dev/null
+++ b/frontend/src/pages/Events/List/hooks/useColumnDefinitions.tsx
@@ -0,0 +1,171 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { format } from 'date-fns';
+
+import { NavigateLink, TableProps } from 'components';
+
+import { DATE_TIME_FORMAT } from 'consts';
+import { ROUTES } from 'routes';
+
+export const useColumnsDefinitions = () => {
+ const { t } = useTranslation();
+
+ const columns: TableProps.ColumnDefinition[] = [
+ {
+ id: 'recorded_at',
+ header: t('events.recorded_at'),
+ cell: (item) => format(new Date(item.recorded_at), DATE_TIME_FORMAT),
+ },
+ {
+ id: 'actor',
+ header: t('events.actor'),
+ cell: (item) =>
+ item.actor_user ? (
+ {item.actor_user}
+ ) : (
+ '-'
+ ),
+ },
+ {
+ id: 'target',
+ header: t('events.targets'),
+ cell: (item) => {
+ return item.targets.map((target) => {
+ switch (target.type) {
+ case 'project':
+ return (
+
+ Project{' '}
+ {target.project_name && (
+
+ {target.project_name}
+
+ )}
+
+ );
+
+ case 'fleet':
+ return (
+
+ Fleet{' '}
+ {target.project_name && (
+
+ {target.project_name}
+
+ )}
+ /
+
+ {target.name}
+
+
+ );
+
+ case 'user':
+ return (
+
+ User{' '}
+ {target.name}
+
+ );
+
+ case 'instance':
+ return (
+
+ Instance{' '}
+ {target.project_name && (
+
+ {target.project_name}
+
+ )}
+ /
+
+ {target.name}
+
+
+ );
+
+ case 'run':
+ return (
+
+ Run{' '}
+ {target.project_name && (
+
+ {target.project_name}
+
+ )}
+ /
+
+ {target.name}
+
+
+ );
+
+ case 'job':
+ return (
+
+ Job{' '}
+ {target.project_name && (
+
+ {target.project_name}
+
+ )}
+ /{target.name}
+
+ );
+
+ case 'volume':
+ return (
+
+ Volume{' '}
+ {target.project_name && (
+
+ {target.project_name}
+
+ )}
+ /{target.name}
+
+ );
+
+ case 'gateway':
+ return (
+
+ Gateway{' '}
+ {target.project_name && (
+
+ {target.project_name}
+
+ )}
+ /{target.name}
+
+ );
+
+ case 'secret':
+ return (
+
+ Secret{' '}
+ {target.project_name && (
+
+ {target.project_name}
+
+ )}
+ /{target.name}
+
+ );
+
+ default:
+ return '---';
+ }
+ });
+ },
+ },
+ {
+ id: 'message',
+ header: t('events.message'),
+ cell: ({ message }) => message,
+ },
+ ];
+
+ return { columns } as const;
+};
diff --git a/frontend/src/pages/Events/List/hooks/useFilters.ts b/frontend/src/pages/Events/List/hooks/useFilters.ts
new file mode 100644
index 0000000000..d160caa17f
--- /dev/null
+++ b/frontend/src/pages/Events/List/hooks/useFilters.ts
@@ -0,0 +1,392 @@
+import { useMemo, useState } from 'react';
+import { useSearchParams } from 'react-router-dom';
+import { omit } from 'lodash';
+
+import type { PropertyFilterProps } from 'components';
+
+import {
+ EMPTY_QUERY,
+ getNamePatternFilterRequestParams,
+ requestParamsToTokens,
+ tokensToRequestParams,
+ tokensToSearchParams,
+} from 'libs/filters';
+import { useLazyGetProjectsQuery } from 'services/project';
+import { useLazyGetUserListQuery } from 'services/user';
+
+import { filterLastElementByPrefix } from '../helpers';
+
+type RequestParamsKeys = keyof TEventListFilters;
+
+const filterKeys: Record = {
+ TARGET_PROJECTS: 'target_projects',
+ TARGET_USERS: 'target_users',
+ TARGET_FLEETS: 'target_fleets',
+ TARGET_INSTANCES: 'target_instances',
+ TARGET_RUNS: 'target_runs',
+ TARGET_JOBS: 'target_jobs',
+ TARGET_VOLUMES: 'target_volumes',
+ TARGET_GATEWAYS: 'target_gateways',
+ TARGET_SECRETS: 'target_secrets',
+ WITHIN_PROJECTS: 'within_projects',
+ WITHIN_FLEETS: 'within_fleets',
+ WITHIN_RUNS: 'within_runs',
+ INCLUDE_TARGET_TYPES: 'include_target_types',
+ ACTORS: 'actors',
+};
+
+const onlyOneFilterGroupPrefixes = ['target_', 'within_'];
+
+const multipleChoiseKeys: RequestParamsKeys[] = [
+ 'target_projects',
+ 'target_users',
+ 'target_fleets',
+ 'target_instances',
+ 'target_runs',
+ 'target_jobs',
+ 'target_volumes',
+ 'target_gateways',
+ 'target_secrets',
+ 'within_projects',
+ 'within_fleets',
+ 'within_runs',
+ 'include_target_types',
+ 'actors',
+];
+
+const targetTypes = [
+ { label: 'Project', value: 'project' },
+ { label: 'User', value: 'user' },
+ { label: 'Fleet', value: 'fleet' },
+ { label: 'Instance', value: 'instance' },
+ { label: 'Run', value: 'run' },
+ { label: 'Job', value: 'job' },
+ { label: 'Volume', value: 'volume' },
+ { label: 'Gateway', value: 'gateway' },
+ { label: 'Secret', value: 'secret' },
+];
+
+const baseFilteringProperties = [
+ {
+ key: filterKeys.TARGET_PROJECTS,
+ operators: ['='],
+ propertyLabel: 'Target projects',
+ groupValuesLabel: 'Project ids',
+ },
+ {
+ key: filterKeys.TARGET_USERS,
+ operators: ['='],
+ propertyLabel: 'Target users',
+ groupValuesLabel: 'User ids',
+ },
+ {
+ key: filterKeys.TARGET_FLEETS,
+ operators: ['='],
+ propertyLabel: 'Target fleet IDs',
+ groupValuesLabel: 'Fleet ids',
+ },
+ {
+ key: filterKeys.TARGET_INSTANCES,
+ operators: ['='],
+ propertyLabel: 'Target instance IDs',
+ groupValuesLabel: 'Instance ids',
+ },
+ {
+ key: filterKeys.TARGET_RUNS,
+ operators: ['='],
+ propertyLabel: 'Target run IDs',
+ groupValuesLabel: 'Run ids',
+ },
+ {
+ key: filterKeys.TARGET_JOBS,
+ operators: ['='],
+ propertyLabel: 'Target job IDs',
+ groupValuesLabel: 'Job ids',
+ },
+ {
+ key: filterKeys.TARGET_VOLUMES,
+ operators: ['='],
+ propertyLabel: 'Target volume IDs',
+ groupValuesLabel: 'Volume ids',
+ },
+ {
+ key: filterKeys.TARGET_GATEWAYS,
+ operators: ['='],
+ propertyLabel: 'Target gateway IDs',
+ groupValuesLabel: 'Gateway ids',
+ },
+ {
+ key: filterKeys.TARGET_SECRETS,
+ operators: ['='],
+ propertyLabel: 'Target secret IDs',
+ groupValuesLabel: 'Secret ids',
+ },
+
+ {
+ key: filterKeys.WITHIN_PROJECTS,
+ operators: ['='],
+ propertyLabel: 'Within projects',
+ groupValuesLabel: 'Project ids',
+ },
+
+ {
+ key: filterKeys.WITHIN_FLEETS,
+ operators: ['='],
+ propertyLabel: 'Within fleet IDs',
+ groupValuesLabel: 'Fleet ids',
+ },
+
+ {
+ key: filterKeys.WITHIN_RUNS,
+ operators: ['='],
+ propertyLabel: 'Within run IDs',
+ groupValuesLabel: 'Run ids',
+ },
+
+ {
+ key: filterKeys.INCLUDE_TARGET_TYPES,
+ operators: ['='],
+ propertyLabel: 'Target types',
+ groupValuesLabel: 'Target type values',
+ },
+
+ {
+ key: filterKeys.ACTORS,
+ operators: ['='],
+ propertyLabel: 'Actors',
+ groupValuesLabel: 'User names',
+ },
+];
+
+const limit = 100;
+
+export const useFilters = ({
+ permanentFilters,
+ withSearchParams,
+}: {
+ permanentFilters?: Partial;
+ withSearchParams?: boolean;
+}) => {
+ const [searchParams, setSearchParams] = useSearchParams();
+ const [dynamicFilteringOptions, setDynamicFilteringOptions] = useState([]);
+ const [filteringStatusType, setFilteringStatusType] = useState();
+ const [getProjects] = useLazyGetProjectsQuery();
+ const [getUsers] = useLazyGetUserListQuery();
+
+ const [propertyFilterQuery, setPropertyFilterQuery] = useState(() =>
+ requestParamsToTokens({ searchParams, filterKeys }),
+ );
+
+ const clearFilter = () => {
+ if (withSearchParams) {
+ setSearchParams({});
+ }
+ setPropertyFilterQuery(EMPTY_QUERY);
+ };
+
+ const filteringOptions = useMemo(() => {
+ const options: PropertyFilterProps.FilteringOption[] = [...dynamicFilteringOptions];
+
+ targetTypes?.forEach((targetType) => {
+ options.push({
+ propertyKey: filterKeys.INCLUDE_TARGET_TYPES,
+ value: targetType.label,
+ });
+ });
+
+ return options;
+ }, [dynamicFilteringOptions]);
+
+ const setSearchParamsHandle = ({ tokens }: { tokens: PropertyFilterProps.Query['tokens'] }) => {
+ const searchParams = tokensToSearchParams(tokens);
+
+ setSearchParams(searchParams);
+ };
+
+ const onChangePropertyFilterHandle = ({ tokens, operation }: PropertyFilterProps.Query) => {
+ let filteredTokens = [...tokens];
+
+ onlyOneFilterGroupPrefixes.forEach((prefix) => {
+ try {
+ filteredTokens = filterLastElementByPrefix(filteredTokens, prefix);
+ } catch (_) {
+ console.error(_);
+ }
+ });
+
+ if (withSearchParams) {
+ setSearchParamsHandle({ tokens: filteredTokens });
+ }
+
+ setPropertyFilterQuery({
+ operation,
+ tokens: filteredTokens,
+ });
+ };
+
+ const onChangePropertyFilter: PropertyFilterProps['onChange'] = ({ detail }) => {
+ onChangePropertyFilterHandle(detail);
+ };
+
+ const filteringProperties = useMemo(() => {
+ const permanentFiltersKeysMap = new Map();
+
+ for (const prefix of onlyOneFilterGroupPrefixes) {
+ const permanentFilterKey = Object.keys(permanentFilters ?? {}).find((filterKey) => filterKey.startsWith(prefix));
+
+ if (permanentFilterKey) {
+ permanentFiltersKeysMap.set(prefix, permanentFilterKey);
+ }
+ }
+
+ if (permanentFiltersKeysMap.size === 0) {
+ return baseFilteringProperties;
+ }
+
+ return baseFilteringProperties.filter(({ key }) => {
+ const propertyPrefix = onlyOneFilterGroupPrefixes.find((prefix) => key.startsWith(prefix));
+
+ if (!propertyPrefix) {
+ return true;
+ }
+
+ if (permanentFiltersKeysMap.has(propertyPrefix)) {
+ return key === permanentFiltersKeysMap.get(propertyPrefix);
+ }
+
+ return true;
+ });
+ }, [permanentFilters]);
+
+ const filteringRequestParams = useMemo(() => {
+ const params = tokensToRequestParams({
+ tokens: propertyFilterQuery.tokens,
+ arrayFieldKeys: multipleChoiseKeys,
+ });
+
+ const filterParamsWithPermanentFitters = (filterKey: RequestParamsKeys): string[] => {
+ let paramsFilter = params[filterKey] ?? '';
+ const permanentFilter = permanentFilters?.[filterKey] ?? '';
+
+ if (!Array.isArray(paramsFilter) && typeof paramsFilter === 'object') {
+ paramsFilter = '';
+ }
+
+ if (Array.isArray(paramsFilter) && Array.isArray(permanentFilter)) {
+ return [...paramsFilter, ...permanentFilter];
+ }
+
+ if (Array.isArray(paramsFilter) && !Array.isArray(permanentFilter)) {
+ return [...paramsFilter, permanentFilter];
+ }
+
+ if (!Array.isArray(paramsFilter) && Array.isArray(permanentFilter)) {
+ return [paramsFilter, ...permanentFilter];
+ }
+
+ // eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ return [paramsFilter, permanentFilter];
+ };
+
+ const targetProjects = filterParamsWithPermanentFitters(filterKeys.TARGET_PROJECTS).filter(Boolean);
+
+ const withInProjects = filterParamsWithPermanentFitters(filterKeys.WITHIN_PROJECTS).filter(Boolean);
+
+ const targetUsers = filterParamsWithPermanentFitters(filterKeys.TARGET_USERS).filter(Boolean);
+
+ const actors = filterParamsWithPermanentFitters(filterKeys.ACTORS).filter(Boolean);
+
+ const includeTargetTypes = filterParamsWithPermanentFitters(filterKeys.INCLUDE_TARGET_TYPES).filter(Boolean);
+
+ const mappedFields = {
+ ...(targetProjects?.length
+ ? {
+ [filterKeys.TARGET_PROJECTS]: targetProjects,
+ }
+ : {}),
+ ...(withInProjects?.length
+ ? {
+ [filterKeys.WITHIN_PROJECTS]: withInProjects,
+ }
+ : {}),
+
+ ...(targetUsers?.length
+ ? {
+ [filterKeys.TARGET_USERS]: targetUsers,
+ }
+ : {}),
+
+ ...(actors?.length
+ ? {
+ [filterKeys.ACTORS]: actors,
+ }
+ : {}),
+
+ ...(includeTargetTypes?.length
+ ? {
+ [filterKeys.INCLUDE_TARGET_TYPES]: includeTargetTypes,
+ }
+ : {}),
+ };
+
+ return {
+ ...omit(params, [
+ filterKeys.TARGET_PROJECTS,
+ filterKeys.WITHIN_PROJECTS,
+ filterKeys.TARGET_USERS,
+ filterKeys.ACTORS,
+ filterKeys.INCLUDE_TARGET_TYPES,
+ ]),
+ ...permanentFilters,
+ ...mappedFields,
+ } as TEventListFilters;
+ }, [propertyFilterQuery, permanentFilters]);
+
+ const handleLoadItems: PropertyFilterProps['onLoadItems'] = async ({ detail: { filteringProperty, filteringText } }) => {
+ setDynamicFilteringOptions([]);
+
+ setFilteringStatusType('loading');
+
+ if (filteringProperty?.key === filterKeys.TARGET_PROJECTS || filteringProperty?.key === filterKeys.WITHIN_PROJECTS) {
+ await getProjects(getNamePatternFilterRequestParams(filteringText, limit))
+ .unwrap()
+ .then(({ data }) =>
+ data.map(({ project_name, project_id }) => ({
+ propertyKey: filteringProperty?.key,
+ label: project_name,
+ value: project_id,
+ hiddenValue: 'test',
+ })),
+ )
+ .then(setDynamicFilteringOptions);
+ }
+
+ if (filteringProperty?.key === filterKeys.TARGET_USERS || filteringProperty?.key === filterKeys.ACTORS) {
+ await getUsers(getNamePatternFilterRequestParams(filteringText, limit))
+ .unwrap()
+ .then(({ data }) =>
+ data.map(({ username, id }) => ({
+ propertyKey: filteringProperty?.key,
+ label: username,
+ value: id,
+ hiddenValue: 'test2',
+ })),
+ )
+ .then(setDynamicFilteringOptions);
+ }
+
+ setFilteringStatusType(undefined);
+ };
+
+ return {
+ filteringRequestParams,
+ clearFilter,
+ propertyFilterQuery,
+ onChangePropertyFilter,
+ filteringOptions,
+ filteringProperties,
+ filteringStatusType,
+ handleLoadItems,
+ } as const;
+};
diff --git a/frontend/src/pages/Events/List/index.tsx b/frontend/src/pages/Events/List/index.tsx
new file mode 100644
index 0000000000..5b22d245ad
--- /dev/null
+++ b/frontend/src/pages/Events/List/index.tsx
@@ -0,0 +1,116 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Loader, PropertyFilter, Table } from 'components';
+import { TableProps } from 'components';
+
+import { DEFAULT_TABLE_PAGE_SIZE } from 'consts';
+import { useBreadcrumbs, useInfiniteScroll } from 'hooks';
+import { useCollection } from 'hooks';
+import { ROUTES } from 'routes';
+import { useLazyGetAllEventsQuery } from 'services/events';
+
+import { useColumnsDefinitions } from './hooks/useColumnDefinitions';
+import { useFilters } from './hooks/useFilters';
+
+import styles from 'pages/Runs/List/styles.module.scss';
+
+type RenderHeaderArgs = {
+ refreshAction?: () => void;
+ disabledRefresh?: boolean;
+};
+
+type EventListProps = Pick & {
+ withSearchParams?: boolean;
+ renderHeader?: (args: RenderHeaderArgs) => React.ReactNode;
+ permanentFilters?: Partial;
+ showFilters?: boolean;
+};
+
+export const EventList: React.FC = ({
+ withSearchParams,
+ permanentFilters,
+ renderHeader,
+ showFilters = true,
+ ...props
+}) => {
+ const { t } = useTranslation();
+
+ useBreadcrumbs([
+ {
+ text: t('navigation.events'),
+ href: ROUTES.EVENTS.LIST,
+ },
+ ]);
+
+ const {
+ filteringRequestParams,
+ propertyFilterQuery,
+ onChangePropertyFilter,
+ filteringOptions,
+ filteringProperties,
+ filteringStatusType,
+ handleLoadItems,
+ } = useFilters({ permanentFilters, withSearchParams });
+
+ const { data, isLoading, refreshList, isLoadingMore } = useInfiniteScroll({
+ useLazyQuery: useLazyGetAllEventsQuery,
+ args: { ...filteringRequestParams, limit: DEFAULT_TABLE_PAGE_SIZE },
+
+ getPaginationParams: (lastEvent) => ({
+ prev_recorded_at: lastEvent.recorded_at,
+ prev_id: lastEvent.id,
+ }),
+ });
+
+ const { items, collectionProps } = useCollection(data, {
+ filtering: {
+ // empty: renderEmptyMessage(),
+ // noMatch: renderNoMatchMessage(),
+ },
+ selection: {},
+ });
+
+ const { columns } = useColumnsDefinitions();
+
+ const loading = isLoading;
+
+ return (
+
+
+
`Use: ${value}`,
+ }}
+ filteringOptions={filteringOptions}
+ filteringProperties={filteringProperties}
+ filteringStatusType={filteringStatusType}
+ onLoadItems={handleLoadItems}
+ />
+
+
+ )
+ }
+ footer={ }
+ />
+ );
+};
diff --git a/frontend/src/pages/Events/index.tsx b/frontend/src/pages/Events/index.tsx
new file mode 100644
index 0000000000..7171443bc1
--- /dev/null
+++ b/frontend/src/pages/Events/index.tsx
@@ -0,0 +1 @@
+export { ListPage as EventList } from './List/ListPage';
diff --git a/frontend/src/pages/Fleets/Add/FleetFormFields/constants.tsx b/frontend/src/pages/Fleets/Add/FleetFormFields/constants.tsx
new file mode 100644
index 0000000000..7904a17746
--- /dev/null
+++ b/frontend/src/pages/Fleets/Add/FleetFormFields/constants.tsx
@@ -0,0 +1,143 @@
+import React from 'react';
+import { get } from 'lodash';
+import * as yup from 'yup';
+
+import { FleetFormFields } from './type';
+
+export const fleetFormDefaultValues: FleetFormFields = {
+ min_instances: 0,
+ idle_duration: '5m',
+ spot_policy: 'auto',
+};
+
+export const FLEET_MIN_INSTANCES_INFO = {
+ header: Min number of instances ,
+ body: (
+ <>
+
+ If you create a fleet here, it's recommended to set Min number of instances to 0. In
+ this case, dstack will provision instances only when you run a dev environment, task, or service.
+
+
+
+ If you set Min number of instances above 0, dstack will try to provision
+ them right away. Note, setting Min number of instances above 0 is supported for
+ VM-based backends only.
+
+
+
+ To learn more about fleets, see the{' '}
+
+ documentation
+
+ .
+
+ >
+ ),
+};
+
+export const FLEET_MAX_INSTANCES_INFO = {
+ header: Max number of instances ,
+ body: (
+ <>
+
+ Set Max number of instances only if you need to limit the number of instances in the fleet.
+
+
+
+ To learn more about fleets, see the{' '}
+
+ documentation
+
+ .
+
+ >
+ ),
+};
+
+export const FLEET_IDLE_DURATION_INFO = {
+ header: Idle duration ,
+ body: (
+ <>
+ Idle instances can be reused when you submit a dev environment, task, or service.
+
+
+ Set Idle duration to control how long instances stay idle before they are terminated.
+
+
+
+ Set Idle duration to 0s if you want instances to be terminated immediately after they
+ are no longer needed.
+
+
+
+ Note, dstack doesn't terminates if their total number would be below{' '}
+ Min number of instances.
+
+
+
+ To learn more about fleets, see the{' '}
+
+ documentation
+
+ .
+
+ >
+ ),
+};
+
+export const FLEET_SPOT_POLICY_INFO = {
+ header: Spot policy ,
+ body: (
+ <>
+
+ Some backends may support spot instances, also known as preemptive instances. Such instances come at a
+ significantly lower price but can be interrupted by the cloud provider at any time.
+
+
+ If you set spot_policy to auto, the fleet will allow the use of both types of
+ instances: on-demand and spot.
+
+
+ Note that run configurations must specify their own spot_policy, which by default is always{' '}
+ on-demand.
+
+ >
+ ),
+};
+
+const requiredFieldError = 'This is required field';
+const numberFieldError = 'This is number field';
+
+export const getMinInstancesValidator = (maxInstancesFieldPath: string) =>
+ yup
+ .number()
+ .required(requiredFieldError)
+ .typeError(numberFieldError)
+ .min(0)
+ .test('is-smaller-than-max', 'The minimum value must be less than the maximum value.', (value, context) => {
+ const maxInstances = get(context.parent, maxInstancesFieldPath);
+
+ if (typeof maxInstances !== 'number' || typeof value !== 'number') {
+ return true;
+ }
+
+ return value <= maxInstances;
+ });
+
+export const getMaxInstancesValidator = (minInstancesFieldPath: string) =>
+ yup
+ .number()
+ .typeError(numberFieldError)
+ .min(1)
+ .test('is-greater-than-min', 'The maximum value must be greater than the minimum value', (value, context) => {
+ const minInstances = get(context.parent, minInstancesFieldPath);
+
+ if (typeof minInstances !== 'number' || typeof value !== 'number') {
+ return true;
+ }
+
+ return value >= minInstances;
+ });
+
+export const idleDurationValidator = yup.string().matches(/^\d+[smhdw]$/, 'Invalid duration');
diff --git a/frontend/src/pages/Fleets/Add/FleetFormFields/index.tsx b/frontend/src/pages/Fleets/Add/FleetFormFields/index.tsx
new file mode 100644
index 0000000000..4aa04c3935
--- /dev/null
+++ b/frontend/src/pages/Fleets/Add/FleetFormFields/index.tsx
@@ -0,0 +1,100 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { FormInput, FormSelect, InfoLink, SpaceBetween } from 'components';
+
+import { useHelpPanel } from 'hooks';
+
+import {
+ FLEET_IDLE_DURATION_INFO,
+ FLEET_MAX_INSTANCES_INFO,
+ FLEET_MIN_INSTANCES_INFO,
+ FLEET_SPOT_POLICY_INFO,
+} from './constants';
+import { FleetFormFieldsProps } from './type';
+
+import type { FieldValues } from 'react-hook-form/dist/types/fields';
+
+export function FleetFormFields({
+ control,
+ disabledAllFields,
+ fieldNamePrefix,
+}: FleetFormFieldsProps) {
+ const { t } = useTranslation();
+ const [openHelpPanel] = useHelpPanel();
+
+ const getFieldNameWitPrefix = (name: string): string => {
+ if (!fieldNamePrefix) {
+ return name;
+ }
+
+ return [fieldNamePrefix, name].join('.');
+ };
+
+ return (
+
+
+
+ openHelpPanel(FLEET_MIN_INSTANCES_INFO)} />}
+ label={t('fleets.edit.min_instances')}
+ constraintText={t('fleets.edit.min_instances_description')}
+ control={control}
+ //eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ name={getFieldNameWitPrefix(`min_instances`)}
+ disabled={disabledAllFields}
+ type="number"
+ />
+
+ openHelpPanel(FLEET_MAX_INSTANCES_INFO)} />}
+ label={t('fleets.edit.max_instances')}
+ constraintText={t('fleets.edit.max_instances_description')}
+ placeholder={t('fleets.edit.max_instances_placeholder')}
+ control={control}
+ //eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ name={getFieldNameWitPrefix(`max_instances`)}
+ disabled={disabledAllFields}
+ type="number"
+ />
+
+ openHelpPanel(FLEET_SPOT_POLICY_INFO)} />}
+ label={t('fleets.edit.spot_policy')}
+ constraintText={t('fleets.edit.spot_policy_description')}
+ control={control}
+ //eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ name={getFieldNameWitPrefix(`spot_policy`)}
+ disabled={disabledAllFields}
+ options={[
+ { label: 'auto', value: 'auto' },
+ { label: 'on-demand', value: 'on-demand' },
+ { label: 'spot', value: 'spot' },
+ ]}
+ />
+
+ openHelpPanel(FLEET_IDLE_DURATION_INFO)} />}
+ label={t('fleets.edit.idle_duration')}
+ constraintText={t('fleets.edit.idle_duration_description')}
+ control={control}
+ //eslint-disable-next-line @typescript-eslint/ban-ts-comment
+ // @ts-expect-error
+ name={getFieldNameWitPrefix(`idle_duration`)}
+ disabled={disabledAllFields}
+ />
+
+ );
+}
diff --git a/frontend/src/pages/Fleets/Add/FleetFormFields/type.ts b/frontend/src/pages/Fleets/Add/FleetFormFields/type.ts
new file mode 100644
index 0000000000..835ca83732
--- /dev/null
+++ b/frontend/src/pages/Fleets/Add/FleetFormFields/type.ts
@@ -0,0 +1,16 @@
+import type { FieldValues } from 'react-hook-form/dist/types/fields';
+import type { UseFormReturn } from 'react-hook-form/dist/types/form';
+
+export interface FleetFormFieldsProps
+ extends Pick, 'control'> {
+ fieldNamePrefix?: string;
+ disabledAllFields?: boolean;
+}
+
+export type FleetFormFields = {
+ name?: string;
+ min_instances: number;
+ max_instances?: number;
+ idle_duration?: string;
+ spot_policy: TSpotPolicy;
+};
diff --git a/frontend/src/pages/Fleets/Add/index.tsx b/frontend/src/pages/Fleets/Add/index.tsx
new file mode 100644
index 0000000000..d7390fc933
--- /dev/null
+++ b/frontend/src/pages/Fleets/Add/index.tsx
@@ -0,0 +1,266 @@
+import React, { useState } from 'react';
+import { useForm } from 'react-hook-form';
+import { useTranslation } from 'react-i18next';
+import { useNavigate, useParams } from 'react-router-dom';
+import { isNil } from 'lodash';
+import * as yup from 'yup';
+import { Box, WizardProps } from '@cloudscape-design/components';
+
+import { Container, InfoLink, KeyValuePairs, SpaceBetween, Wizard } from 'components';
+
+import { useBreadcrumbs, useConfirmationDialog, useHelpPanel, useNotifications } from 'hooks';
+import { ROUTES } from 'routes';
+import { useApplyFleetMutation } from 'services/fleet';
+
+import { DEFAULT_FLEET_INFO } from 'pages/Project/constants';
+import { useYupValidationResolver } from 'pages/Project/hooks/useYupValidationResolver';
+
+import {
+ fleetFormDefaultValues,
+ getMaxInstancesValidator,
+ getMinInstancesValidator,
+ idleDurationValidator,
+} from './FleetFormFields/constants';
+import { FleetFormFields } from './FleetFormFields';
+
+import { IFleetWizardForm } from './types';
+
+const requiredFieldError = 'This is required field';
+const namesFieldError = 'Only latin characters, dashes, underscores, and digits';
+
+const fleetStepIndex = 0;
+
+const fleetValidationSchema = yup.object({
+ project_name: yup
+ .string()
+ .required(requiredFieldError)
+ .matches(/^[a-zA-Z0-9-_]+$/, namesFieldError),
+ min_instances: getMinInstancesValidator('max_instances'),
+ max_instances: getMaxInstancesValidator('min_instances'),
+ idle_duration: idleDurationValidator,
+ spot_policy: yup.string().required(requiredFieldError),
+});
+
+export const FleetAdd: React.FC = () => {
+ const { t } = useTranslation();
+ const navigate = useNavigate();
+ const params = useParams();
+ const paramProjectName = params.projectName ?? '';
+ const [openHelpPanel] = useHelpPanel();
+ const [pushNotification] = useNotifications();
+ const [openConfirmationDialog] = useConfirmationDialog();
+ const [applyFleet, { isLoading: isApplyingFleet }] = useApplyFleetMutation();
+ const [activeStepIndex, setActiveStepIndex] = useState(0);
+ const resolver = useYupValidationResolver(fleetValidationSchema);
+
+ const loading = isApplyingFleet;
+
+ const formMethods = useForm({
+ resolver,
+ defaultValues: {
+ ...fleetFormDefaultValues,
+ project_name: paramProjectName,
+ },
+ });
+
+ const { handleSubmit, control, clearErrors, trigger, watch, getValues } = formMethods;
+ const formValues = watch();
+
+ const getFormValuesForFleetApplying = (): IApplyFleetPlanRequestRequest => {
+ const { min_instances, max_instances, idle_duration, name, spot_policy } = getValues();
+
+ return {
+ plan: {
+ spec: {
+ configuration: {
+ ...(name ? { name } : {}),
+ nodes: {
+ min: min_instances,
+ ...(max_instances ? { max: max_instances } : {}),
+ },
+ ...(idle_duration ? { idle_duration } : {}),
+ spot_policy,
+ },
+ profile: {},
+ },
+ },
+ force: false,
+ };
+ };
+
+ useBreadcrumbs([
+ {
+ text: t('navigation.project_other'),
+ href: ROUTES.PROJECT.LIST,
+ },
+ {
+ text: paramProjectName,
+ href: ROUTES.PROJECT.DETAILS.FORMAT(paramProjectName),
+ },
+ {
+ text: t('navigation.fleets'),
+ href: ROUTES.FLEETS.LIST,
+ },
+ {
+ text: t('common.create_wit_text', { text: t('navigation.fleet') }),
+ href: ROUTES.FLEETS.ADD.FORMAT(paramProjectName),
+ },
+ ]);
+
+ const validateFleet = async () => {
+ return await trigger(['min_instances', 'max_instances', 'idle_duration']);
+ };
+
+ const emptyValidator = async () => Promise.resolve(true);
+
+ const onNavigate = ({
+ requestedStepIndex,
+ reason,
+ }: {
+ requestedStepIndex: number;
+ reason: WizardProps.NavigationReason;
+ }) => {
+ const stepValidators = [validateFleet, emptyValidator];
+
+ if (reason === 'next') {
+ stepValidators[activeStepIndex]?.().then((isValid) => {
+ if (isValid) {
+ if (activeStepIndex === fleetStepIndex && formValues?.['min_instances'] > 0) {
+ openConfirmationDialog({
+ title: 'Are sure want to set min instances above than 0?',
+ content: null,
+ onConfirm: () => setActiveStepIndex(requestedStepIndex),
+ });
+ } else {
+ setActiveStepIndex(requestedStepIndex);
+ }
+ }
+ });
+ } else {
+ setActiveStepIndex(requestedStepIndex);
+ }
+ };
+
+ const onNavigateHandler: WizardProps['onNavigate'] = ({ detail: { requestedStepIndex, reason } }) => {
+ onNavigate({ requestedStepIndex, reason });
+ };
+
+ const onCancelHandler = () => {
+ navigate(ROUTES.FLEETS.LIST);
+ };
+
+ const onSubmitWizard = async () => {
+ const isValid = await trigger();
+
+ const { project_name } = getValues();
+
+ if (!isValid) {
+ return;
+ }
+
+ clearErrors();
+
+ const request = applyFleet({
+ projectName: project_name,
+ ...getFormValuesForFleetApplying(),
+ }).unwrap();
+
+ request
+ .then((data) => {
+ pushNotification({
+ type: 'success',
+ content: t('fleets.create.success_notification'),
+ });
+
+ navigate(ROUTES.FLEETS.DETAILS.FORMAT(data.project_name, data.id));
+ })
+ .catch((error) => {
+ pushNotification({
+ type: 'error',
+ content: t('common.server_error', { error: error?.error ?? error }),
+ });
+ });
+ };
+
+ const onSubmit = () => {
+ if (activeStepIndex < 2) {
+ onNavigate({ requestedStepIndex: activeStepIndex + 1, reason: 'next' });
+ } else {
+ onSubmitWizard().catch(console.log);
+ }
+ };
+
+ const getDefaultFleetSummary = () => {
+ const summaryFields: Array = [
+ 'name',
+ 'min_instances',
+ 'max_instances',
+ 'idle_duration',
+ 'spot_policy',
+ ];
+
+ const result: string[] = [];
+
+ summaryFields.forEach((fieldName) => {
+ if (!isNil(formValues?.[fieldName])) {
+ result.push(`${t(`fleets.edit.${fieldName}`)}: ${formValues?.[fieldName]}`);
+ }
+ });
+
+ return result.join(', ');
+ };
+
+ return (
+
+ );
+};
diff --git a/frontend/src/pages/Fleets/Add/types.ts b/frontend/src/pages/Fleets/Add/types.ts
new file mode 100644
index 0000000000..9e36ef72a6
--- /dev/null
+++ b/frontend/src/pages/Fleets/Add/types.ts
@@ -0,0 +1,5 @@
+import { FleetFormFields } from './FleetFormFields/type';
+
+export interface IFleetWizardForm extends FleetFormFields {
+ project_name: IProject['project_name'];
+}
diff --git a/frontend/src/pages/Fleets/Details/Events/index.tsx b/frontend/src/pages/Fleets/Details/Events/index.tsx
new file mode 100644
index 0000000000..9a81c7dec3
--- /dev/null
+++ b/frontend/src/pages/Fleets/Details/Events/index.tsx
@@ -0,0 +1,56 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useNavigate, useParams } from 'react-router-dom';
+import Button from '@cloudscape-design/components/button';
+
+import { Header, Loader, Table } from 'components';
+
+import { DEFAULT_TABLE_PAGE_SIZE } from 'consts';
+import { useCollection, useInfiniteScroll } from 'hooks';
+import { ROUTES } from 'routes';
+import { useLazyGetAllEventsQuery } from 'services/events';
+
+import { useColumnsDefinitions } from 'pages/Events/List/hooks/useColumnDefinitions';
+
+export const EventsList = () => {
+ const { t } = useTranslation();
+ const params = useParams();
+ const paramFleetId = params.fleetId ?? '';
+ const navigate = useNavigate();
+
+ const { data, isLoading, isLoadingMore } = useInfiniteScroll({
+ useLazyQuery: useLazyGetAllEventsQuery,
+ args: { limit: DEFAULT_TABLE_PAGE_SIZE, within_fleets: [paramFleetId] },
+
+ getPaginationParams: (lastEvent) => ({
+ prev_recorded_at: lastEvent.recorded_at,
+ prev_id: lastEvent.id,
+ }),
+ });
+
+ const { items, collectionProps } = useCollection(data, {
+ selection: {},
+ });
+
+ const goToFullView = () => {
+ navigate(ROUTES.EVENTS.LIST + `?within_fleets=${paramFleetId}`);
+ };
+
+ const { columns } = useColumnsDefinitions();
+
+ return (
+ {t('common.full_view')}}>
+ {t('navigation.events')}
+
+ }
+ footer={ }
+ />
+ );
+};
diff --git a/frontend/src/pages/Fleets/Details/FleetDetails/index.tsx b/frontend/src/pages/Fleets/Details/FleetDetails/index.tsx
new file mode 100644
index 0000000000..97a09e2f38
--- /dev/null
+++ b/frontend/src/pages/Fleets/Details/FleetDetails/index.tsx
@@ -0,0 +1,114 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useParams } from 'react-router-dom';
+import { format } from 'date-fns';
+
+import { Box, ColumnLayout, Container, Header, Loader, NavigateLink, StatusIndicator } from 'components';
+
+import { DATE_TIME_FORMAT } from 'consts';
+import {
+ formatFleetBackend,
+ formatFleetResources,
+ getFleetInstancesLinkText,
+ getFleetPrice,
+ getFleetStatusIconType,
+} from 'libs/fleet';
+import { ROUTES } from 'routes';
+import { useGetFleetDetailsQuery } from 'services/fleet';
+
+export const FleetDetails = () => {
+ const { t } = useTranslation();
+ const params = useParams();
+ const paramFleetId = params.fleetId ?? '';
+ const paramProjectName = params.projectName ?? '';
+
+ const { data, isLoading } = useGetFleetDetailsQuery(
+ {
+ projectName: paramProjectName,
+ fleetId: paramFleetId,
+ },
+ {
+ refetchOnMountOrArgChange: true,
+ },
+ );
+
+ return (
+ <>
+ {isLoading && (
+
+
+
+ )}
+
+ {data && (
+ {t('common.general')}}>
+
+
+
{t('fleets.fleet')}
+
{data.name}
+
+
+
+
{t('fleets.instances.status')}
+
+
+
+ {t(`fleets.statuses.${data.status}`)}
+
+
+
+
+
+
{t('fleets.instances.project')}
+
+
+
+ {data.project_name}
+
+
+
+
+
+
{t('fleets.instances.backend')}
+
{formatFleetBackend(data.spec.configuration)}
+
+
+
+
{t('fleets.instances.resources')}
+
+ {data.spec.configuration.ssh_config
+ ? '-'
+ : formatFleetResources(data.spec.configuration.resources)}
+
+
+
+
+
{t('fleets.instances.title')}
+
+
+
+ {getFleetInstancesLinkText(data)}
+
+
+
+
+
+
{t('fleets.instances.created')}
+
{format(new Date(data.created_at), DATE_TIME_FORMAT)}
+
+
+
+
{t('fleets.instances.price')}
+
+ {(() => {
+ const p = getFleetPrice(data);
+ return typeof p === 'number' ? `$${p}` : '-';
+ })()}
+
+
+
+
+ )}
+ >
+ );
+};
diff --git a/frontend/src/pages/Fleets/Details/Inspect/index.tsx b/frontend/src/pages/Fleets/Details/Inspect/index.tsx
new file mode 100644
index 0000000000..8d9c5d5095
--- /dev/null
+++ b/frontend/src/pages/Fleets/Details/Inspect/index.tsx
@@ -0,0 +1,73 @@
+import React, { useEffect, useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useParams } from 'react-router-dom';
+
+import { CodeEditor, Container, Header, Loader } from 'components';
+
+import { useGetFleetDetailsQuery } from 'services/fleet';
+
+interface AceEditorElement extends HTMLElement {
+ env?: {
+ editor?: {
+ setReadOnly: (readOnly: boolean) => void;
+ };
+ };
+}
+
+export const FleetInspect = () => {
+ const { t } = useTranslation();
+ const params = useParams();
+ const paramProjectName = params.projectName ?? '';
+ const paramFleetId = params.fleetId ?? '';
+
+ const { data: fleetData, isLoading } = useGetFleetDetailsQuery(
+ {
+ projectName: paramProjectName,
+ fleetId: paramFleetId,
+ },
+ {
+ refetchOnMountOrArgChange: true,
+ },
+ );
+
+ const jsonContent = useMemo(() => {
+ if (!fleetData) return '';
+ return JSON.stringify(fleetData, null, 2);
+ }, [fleetData]);
+
+ // Set editor to read-only after it loads
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ // Find the ace editor instance in the DOM
+ const editorElements = document.querySelectorAll('.ace_editor');
+ editorElements.forEach((element: Element) => {
+ const aceEditor = (element as AceEditorElement).env?.editor;
+ if (aceEditor) {
+ aceEditor.setReadOnly(true);
+ }
+ });
+ }, 100);
+
+ return () => clearTimeout(timer);
+ }, [jsonContent]);
+
+ if (isLoading)
+ return (
+
+
+
+ );
+
+ return (
+ {t('fleets.inspect')}}>
+ {
+ // Prevent editing - onChange is required but we ignore changes
+ }}
+ />
+
+ );
+};
diff --git a/frontend/src/pages/Fleets/Details/index.tsx b/frontend/src/pages/Fleets/Details/index.tsx
new file mode 100644
index 0000000000..6e5d9e6d7a
--- /dev/null
+++ b/frontend/src/pages/Fleets/Details/index.tsx
@@ -0,0 +1,112 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { Outlet, useNavigate, useParams } from 'react-router-dom';
+
+import { Button, ContentLayout, DetailsHeader, Tabs } from 'components';
+
+enum CodeTab {
+ Details = 'details',
+ Events = 'events',
+ Inspect = 'inspect',
+}
+
+import { useBreadcrumbs } from 'hooks';
+import { ROUTES } from 'routes';
+import { useGetFleetDetailsQuery } from 'services/fleet';
+
+import { useDeleteFleet } from '../List/useDeleteFleet';
+
+import styles from './styles.module.scss';
+
+export const FleetDetails: React.FC = () => {
+ const { t } = useTranslation();
+ const params = useParams();
+ const paramFleetId = params.fleetId ?? '';
+ const paramProjectName = params.projectName ?? '';
+ const navigate = useNavigate();
+
+ const { deleteFleets, isDeleting } = useDeleteFleet();
+
+ const { data } = useGetFleetDetailsQuery(
+ {
+ projectName: paramProjectName,
+ fleetId: paramFleetId,
+ },
+ {
+ refetchOnMountOrArgChange: true,
+ },
+ );
+
+ useBreadcrumbs([
+ {
+ text: t('navigation.project_other'),
+ href: ROUTES.PROJECT.LIST,
+ },
+ {
+ text: paramProjectName,
+ href: ROUTES.PROJECT.DETAILS.FORMAT(paramProjectName),
+ },
+ {
+ text: t('navigation.fleets'),
+ href: ROUTES.FLEETS.LIST,
+ },
+ {
+ text: data?.name ?? '',
+ href: ROUTES.FLEETS.DETAILS.FORMAT(paramProjectName, paramFleetId),
+ },
+ ]);
+
+ const deleteClickHandle = () => {
+ if (!data) return;
+
+ deleteFleets([data])
+ .then(() => {
+ navigate(ROUTES.FLEETS.LIST);
+ })
+ .catch(console.log);
+ };
+
+ const isDisabledDeleteButton = !data || isDeleting;
+
+ return (
+
+
+
+ {t('common.delete')}
+
+ >
+ }
+ />
+ }
+ >
+
+
+
+
+
+ );
+};
diff --git a/frontend/src/pages/Fleets/Details/styles.module.scss b/frontend/src/pages/Fleets/Details/styles.module.scss
new file mode 100644
index 0000000000..1a7d41a9c5
--- /dev/null
+++ b/frontend/src/pages/Fleets/Details/styles.module.scss
@@ -0,0 +1,18 @@
+.page {
+ height: 100%;
+
+ & [class^="awsui_tabs-content"] {
+ display: none;
+ }
+
+ & > [class^="awsui_layout"] {
+ height: 100%;
+
+ & > [class^="awsui_content"] {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+ height: 100%;
+ }
+ }
+}
diff --git a/frontend/src/pages/Fleets/List/hooks.tsx b/frontend/src/pages/Fleets/List/hooks.tsx
new file mode 100644
index 0000000000..73286d247a
--- /dev/null
+++ b/frontend/src/pages/Fleets/List/hooks.tsx
@@ -0,0 +1,229 @@
+import React, { useCallback, useMemo, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useSearchParams } from 'react-router-dom';
+import { format } from 'date-fns';
+import { ToggleProps } from '@cloudscape-design/components';
+
+import type { PropertyFilterProps } from 'components';
+import { Button, ListEmptyMessage, NavigateLink, StatusIndicator, TableProps } from 'components';
+
+import { DATE_TIME_FORMAT } from 'consts';
+import { useLocalStorageState } from 'hooks';
+import {
+ EMPTY_QUERY,
+ getNamePatternFilterRequestParams,
+ requestParamsToTokens,
+ tokensToRequestParams,
+ tokensToSearchParams,
+} from 'libs/filters';
+import {
+ formatFleetBackend,
+ formatFleetResources,
+ getFleetInstancesLinkText,
+ getFleetPrice,
+ getFleetStatusIconType,
+} from 'libs/fleet';
+import { ROUTES } from 'routes';
+import { useLazyGetProjectsQuery } from 'services/project';
+
+const limit = 100;
+
+export const useEmptyMessages = ({
+ clearFilter,
+ isDisabledClearFilter,
+}: {
+ clearFilter?: () => void;
+ isDisabledClearFilter?: boolean;
+}) => {
+ const { t } = useTranslation();
+
+ const renderEmptyMessage = useCallback<() => React.ReactNode>(() => {
+ return (
+
+
+ {t('common.clearFilter')}
+
+
+ );
+ }, [clearFilter, isDisabledClearFilter]);
+
+ const renderNoMatchMessage = useCallback<() => React.ReactNode>(() => {
+ return (
+
+
+ {t('common.clearFilter')}
+
+
+ );
+ }, [clearFilter, isDisabledClearFilter]);
+
+ return { renderEmptyMessage, renderNoMatchMessage } as const;
+};
+
+export const useColumnsDefinitions = () => {
+ const { t } = useTranslation();
+
+ const columns: TableProps.ColumnDefinition[] = [
+ {
+ id: 'fleet_name',
+ header: t('fleets.fleet_column_name'),
+ cell: (item) => (
+ {item.name}
+ ),
+ },
+ {
+ id: 'status',
+ header: t('fleets.instances.status'),
+ cell: (item) => (
+
+ {t(`fleets.statuses.${item.status}`)}
+
+ ),
+ },
+ {
+ id: 'project',
+ header: t('fleets.instances.project'),
+ cell: (item) => (
+ {item.project_name}
+ ),
+ },
+ {
+ id: 'backend',
+ header: t('fleets.instances.backend'),
+ cell: (item) => formatFleetBackend(item.spec.configuration),
+ },
+ {
+ id: 'resources',
+ header: t('fleets.instances.resources'),
+ cell: (item) =>
+ item.spec.configuration.ssh_config ? '-' : formatFleetResources(item.spec.configuration.resources),
+ },
+ {
+ id: 'instances',
+ header: t('fleets.instances.title'),
+ cell: (item) => (
+
+ {getFleetInstancesLinkText(item)}
+
+ ),
+ },
+ {
+ id: 'created',
+ header: t('fleets.instances.created'),
+ cell: (item) => format(new Date(item.created_at), DATE_TIME_FORMAT),
+ },
+ {
+ id: 'price',
+ header: t('fleets.instances.price'),
+ cell: (item) => {
+ const price = getFleetPrice(item);
+ return typeof price === 'number' ? `$${price}` : '-';
+ },
+ },
+ ];
+
+ return { columns } as const;
+};
+
+type RequestParamsKeys = keyof Pick;
+
+const filterKeys: Record = {
+ PROJECT_NAME: 'project_name',
+};
+
+export const useFilters = () => {
+ const [searchParams, setSearchParams] = useSearchParams();
+ const [onlyActive, setOnlyActive] = useLocalStorageState('fleet-list-filter-only-active', true);
+ const [dynamicFilteringOptions, setDynamicFilteringOptions] = useState([]);
+ const [filteringStatusType, setFilteringStatusType] = useState();
+ const [getProjects] = useLazyGetProjectsQuery();
+
+ const [propertyFilterQuery, setPropertyFilterQuery] = useState(() =>
+ requestParamsToTokens({ searchParams, filterKeys }),
+ );
+
+ const clearFilter = () => {
+ setSearchParams({});
+ setPropertyFilterQuery(EMPTY_QUERY);
+ };
+
+ const filteringOptions = useMemo(() => {
+ return [...dynamicFilteringOptions];
+ }, [dynamicFilteringOptions]);
+
+ const filteringProperties = [
+ {
+ key: filterKeys.PROJECT_NAME,
+ operators: ['='],
+ propertyLabel: 'Project',
+ groupValuesLabel: 'Project values',
+ },
+ ];
+
+ const onChangePropertyFilter: PropertyFilterProps['onChange'] = ({ detail }) => {
+ const { tokens, operation } = detail;
+
+ const filteredTokens = tokens.filter((token, tokenIndex) => {
+ return !tokens.some((item, index) => token.propertyKey === item.propertyKey && index > tokenIndex);
+ });
+
+ setSearchParams(tokensToSearchParams(filteredTokens, onlyActive));
+
+ setPropertyFilterQuery({
+ operation,
+ tokens: filteredTokens,
+ });
+ };
+
+ const onChangeOnlyActive: ToggleProps['onChange'] = ({ detail }) => {
+ setOnlyActive(detail.checked);
+ };
+
+ const filteringRequestParams = useMemo(() => {
+ const params = tokensToRequestParams({
+ tokens: propertyFilterQuery.tokens,
+ });
+
+ return {
+ ...params,
+ only_active: onlyActive,
+ include_imported: true,
+ } as Partial;
+ }, [propertyFilterQuery, onlyActive]);
+
+ const isDisabledClearFilter = !propertyFilterQuery.tokens.length && !onlyActive;
+
+ const handleLoadItems: PropertyFilterProps['onLoadItems'] = async ({ detail: { filteringProperty, filteringText } }) => {
+ setDynamicFilteringOptions([]);
+
+ setFilteringStatusType('loading');
+
+ if (filteringProperty?.key === filterKeys.PROJECT_NAME) {
+ await getProjects(getNamePatternFilterRequestParams(filteringText, limit))
+ .unwrap()
+ .then(({ data }) =>
+ data.map(({ project_name }) => ({
+ propertyKey: filterKeys.PROJECT_NAME,
+ value: project_name,
+ })),
+ )
+ .then(setDynamicFilteringOptions);
+ }
+
+ setFilteringStatusType(undefined);
+ };
+
+ return {
+ filteringRequestParams,
+ clearFilter,
+ propertyFilterQuery,
+ onChangePropertyFilter,
+ filteringOptions,
+ filteringProperties,
+ onlyActive,
+ onChangeOnlyActive,
+ isDisabledClearFilter,
+ filteringStatusType,
+ handleLoadItems,
+ } as const;
+};
diff --git a/frontend/src/pages/Fleets/List/index.tsx b/frontend/src/pages/Fleets/List/index.tsx
new file mode 100644
index 0000000000..7e5ef21cf5
--- /dev/null
+++ b/frontend/src/pages/Fleets/List/index.tsx
@@ -0,0 +1,151 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Button, Header, Loader, PropertyFilter, SpaceBetween, Table, Toggle } from 'components';
+
+import { DEFAULT_TABLE_PAGE_SIZE } from 'consts';
+import { useBreadcrumbs, useCollection, useInfiniteScroll } from 'hooks';
+import { useCheckingForFleetsInProjects } from 'hooks/useCheckingForFleetsInProjectsOfMember';
+import { ROUTES } from 'routes';
+import { useLazyGetFleetsQuery } from 'services/fleet';
+
+import { NoFleetProjectAlert } from 'pages/Project/components/NoFleetProjectAlert';
+
+import { useColumnsDefinitions, useEmptyMessages, useFilters } from './hooks';
+import { useDeleteFleet } from './useDeleteFleet';
+
+import styles from './styles.module.scss';
+
+export const FleetList: React.FC = () => {
+ const { t } = useTranslation();
+
+ useBreadcrumbs([
+ {
+ text: t('navigation.fleets'),
+ href: ROUTES.FLEETS.LIST,
+ },
+ ]);
+
+ const {
+ clearFilter,
+ propertyFilterQuery,
+ onChangePropertyFilter,
+ filteringOptions,
+ filteringProperties,
+ filteringRequestParams,
+ onlyActive,
+ onChangeOnlyActive,
+ isDisabledClearFilter,
+ filteringStatusType,
+ handleLoadItems,
+ } = useFilters();
+
+ const projectHavingFleetMap = useCheckingForFleetsInProjects({});
+
+ const { data, isLoading, refreshList, isLoadingMore } = useInfiniteScroll({
+ useLazyQuery: useLazyGetFleetsQuery,
+ args: { ...filteringRequestParams, limit: DEFAULT_TABLE_PAGE_SIZE },
+
+ getPaginationParams: (lastFleet) => ({
+ prev_created_at: lastFleet.created_at,
+ prev_id: lastFleet.id,
+ }),
+ });
+
+ const { columns } = useColumnsDefinitions();
+ const { deleteFleets, isDeleting } = useDeleteFleet();
+ const { renderEmptyMessage, renderNoMatchMessage } = useEmptyMessages({ clearFilter, isDisabledClearFilter });
+
+ const { items, collectionProps } = useCollection(data, {
+ filtering: {
+ empty: renderEmptyMessage(),
+ noMatch: renderNoMatchMessage(),
+ },
+ selection: {},
+ });
+
+ const { selectedItems } = collectionProps;
+
+ const isDisabledDeleteButton = !selectedItems?.length || isDeleting;
+
+ const deleteClickHandle = () => {
+ if (!selectedItems?.length) return;
+
+ deleteFleets([...selectedItems]).catch(console.log);
+ };
+
+ const projectDontHasFleet = Object.keys(projectHavingFleetMap).find((project) => !projectHavingFleetMap[project]);
+
+ return (
+
+
+
+
+
+ {t('common.delete')}
+
+
+
+
+ }
+ >
+ {t('navigation.fleets')}
+
+ >
+ }
+ filter={
+
+
+
`Use: ${value}`,
+ }}
+ filteringOptions={filteringOptions}
+ filteringProperties={filteringProperties}
+ filteringStatusType={filteringStatusType}
+ onLoadItems={handleLoadItems}
+ />
+
+
+
+
+ {t('fleets.active_only')}
+
+
+
+ }
+ footer={ }
+ />
+ );
+};
diff --git a/frontend/src/pages/Fleets/List/styles.module.scss b/frontend/src/pages/Fleets/List/styles.module.scss
new file mode 100644
index 0000000000..ec38338c42
--- /dev/null
+++ b/frontend/src/pages/Fleets/List/styles.module.scss
@@ -0,0 +1,23 @@
+.noFleetAlert {
+ margin-bottom: 12px;
+}
+.filters {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0 20px;
+
+ .propertyFilter {
+ max-width: 640px;
+ flex-grow: 1;
+ min-width: 0;
+ }
+
+ .activeOnly {
+ display: flex;
+ padding-top: 7px;
+ }
+
+ .clear {
+
+ }
+}
diff --git a/frontend/src/pages/Fleets/List/useDeleteFleet.ts b/frontend/src/pages/Fleets/List/useDeleteFleet.ts
new file mode 100644
index 0000000000..7e38dd2777
--- /dev/null
+++ b/frontend/src/pages/Fleets/List/useDeleteFleet.ts
@@ -0,0 +1,51 @@
+import { useCallback, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { useNotifications } from 'hooks';
+import { getServerError } from 'libs';
+import { useDeleteFleetMutation } from 'services/fleet';
+
+export const useDeleteFleet = () => {
+ const { t } = useTranslation();
+ const [deleteFleet] = useDeleteFleetMutation();
+ const [pushNotification] = useNotifications();
+ const [isDeleting, setIsDeleting] = useState(() => false);
+
+ const namesOfFleetsGroupByProjectName = (volumes: IFleet[]) => {
+ return volumes.reduce>((acc, fleet) => {
+ if (acc[fleet.project_name]) {
+ acc[fleet.project_name].push(fleet.name);
+ } else {
+ acc[fleet.project_name] = [fleet.name];
+ }
+
+ return acc;
+ }, {});
+ };
+
+ const deleteFleets = useCallback(async (fleets: IFleet[]) => {
+ if (!fleets.length) return Promise.reject('No fleets');
+
+ setIsDeleting(true);
+
+ const groupedFleets = namesOfFleetsGroupByProjectName(fleets);
+
+ const requests = Object.keys(groupedFleets).map((projectName) => {
+ return deleteFleet({
+ projectName: projectName,
+ fleetNames: groupedFleets[projectName],
+ }).unwrap();
+ });
+
+ return Promise.all(requests)
+ .finally(() => setIsDeleting(false))
+ .catch((error) => {
+ pushNotification({
+ type: 'error',
+ content: t('common.server_error', { error: getServerError(error) }),
+ });
+ });
+ }, []);
+
+ return { deleteFleets, isDeleting } as const;
+};
diff --git a/frontend/src/pages/Fleets/index.ts b/frontend/src/pages/Fleets/index.ts
new file mode 100644
index 0000000000..e388010498
--- /dev/null
+++ b/frontend/src/pages/Fleets/index.ts
@@ -0,0 +1,3 @@
+export { FleetList } from './List';
+export { FleetDetails } from './Details';
+export { FleetAdd } from './Add';
diff --git a/frontend/src/pages/Instances/Details/Events/index.tsx b/frontend/src/pages/Instances/Details/Events/index.tsx
new file mode 100644
index 0000000000..53a07f1cdc
--- /dev/null
+++ b/frontend/src/pages/Instances/Details/Events/index.tsx
@@ -0,0 +1,56 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useNavigate, useParams } from 'react-router-dom';
+import Button from '@cloudscape-design/components/button';
+
+import { Header, Loader, Table } from 'components';
+
+import { DEFAULT_TABLE_PAGE_SIZE } from 'consts';
+import { useCollection, useInfiniteScroll } from 'hooks';
+import { ROUTES } from 'routes';
+import { useLazyGetAllEventsQuery } from 'services/events';
+
+import { useColumnsDefinitions } from 'pages/Events/List/hooks/useColumnDefinitions';
+
+export const EventsList = () => {
+ const { t } = useTranslation();
+ const params = useParams();
+ const paramInstanceId = params.instanceId ?? '';
+ const navigate = useNavigate();
+
+ const { data, isLoading, isLoadingMore } = useInfiniteScroll({
+ useLazyQuery: useLazyGetAllEventsQuery,
+ args: { limit: DEFAULT_TABLE_PAGE_SIZE, target_instances: [paramInstanceId] },
+
+ getPaginationParams: (lastEvent) => ({
+ prev_recorded_at: lastEvent.recorded_at,
+ prev_id: lastEvent.id,
+ }),
+ });
+
+ const { items, collectionProps } = useCollection(data, {
+ selection: {},
+ });
+
+ const goToFullView = () => {
+ navigate(ROUTES.EVENTS.LIST + `?target_instances=${paramInstanceId}`);
+ };
+
+ const { columns } = useColumnsDefinitions();
+
+ return (
+ {t('common.full_view')}}>
+ {t('navigation.events')}
+
+ }
+ footer={ }
+ />
+ );
+};
diff --git a/frontend/src/pages/Instances/Details/Inspect/index.tsx b/frontend/src/pages/Instances/Details/Inspect/index.tsx
new file mode 100644
index 0000000000..09205dad75
--- /dev/null
+++ b/frontend/src/pages/Instances/Details/Inspect/index.tsx
@@ -0,0 +1,64 @@
+import React, { useEffect, useMemo } from 'react';
+import { useTranslation } from 'react-i18next';
+import { useParams } from 'react-router-dom';
+
+import { CodeEditor, Container, Header, Loader } from 'components';
+
+import { useGetInstanceDetailsQuery } from 'services/instance';
+
+interface AceEditorElement extends HTMLElement {
+ env?: {
+ editor?: {
+ setReadOnly: (readOnly: boolean) => void;
+ };
+ };
+}
+
+export const InstanceInspect = () => {
+ const { t } = useTranslation();
+ const params = useParams();
+ const paramProjectName = params.projectName ?? '';
+ const paramInstanceId = params.instanceId ?? '';
+
+ const { data, isLoading } = useGetInstanceDetailsQuery(
+ {
+ projectName: paramProjectName,
+ instanceId: paramInstanceId,
+ },
+ {
+ refetchOnMountOrArgChange: true,
+ },
+ );
+
+ const jsonContent = useMemo(() => {
+ if (!data) return '';
+ return JSON.stringify(data, null, 2);
+ }, [data]);
+
+ useEffect(() => {
+ const timer = setTimeout(() => {
+ const editorElements = document.querySelectorAll('.ace_editor');
+ editorElements.forEach((element: Element) => {
+ const aceEditor = (element as AceEditorElement).env?.editor;
+ if (aceEditor) {
+ aceEditor.setReadOnly(true);
+ }
+ });
+ }, 100);
+
+ return () => clearTimeout(timer);
+ }, [jsonContent]);
+
+ if (isLoading)
+ return (
+
+
+
+ );
+
+ return (
+ {t('fleets.instances.inspect')}}>
+ {}} />
+
+ );
+};
diff --git a/frontend/src/pages/Instances/Details/InstanceDetails/index.tsx b/frontend/src/pages/Instances/Details/InstanceDetails/index.tsx
new file mode 100644
index 0000000000..6b048729af
--- /dev/null
+++ b/frontend/src/pages/Instances/Details/InstanceDetails/index.tsx
@@ -0,0 +1,158 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { useParams } from 'react-router-dom';
+import { format } from 'date-fns';
+
+import { Box, ColumnLayout, Container, Header, Loader, NavigateLink, StatusIndicator } from 'components';
+
+import { DATE_TIME_FORMAT } from 'consts';
+import { formatBackend, getStatusIconColor, getStatusIconType } from 'libs/fleet';
+import { getHealthStatusIconType, prettyEnumValue } from 'libs/instance';
+import { formatResources } from 'libs/resources';
+import { ROUTES } from 'routes';
+import { useGetInstanceDetailsQuery } from 'services/instance';
+
+export const InstanceDetails = () => {
+ const { t } = useTranslation();
+ const params = useParams();
+ const paramInstanceId = params.instanceId ?? '';
+ const paramProjectName = params.projectName ?? '';
+
+ const { data, isLoading } = useGetInstanceDetailsQuery(
+ {
+ projectName: paramProjectName,
+ instanceId: paramInstanceId,
+ },
+ {
+ refetchOnMountOrArgChange: true,
+ },
+ );
+
+ return (
+ <>
+ {isLoading && (
+
+
+
+ )}
+
+ {data && (
+ {t('common.general')}}>
+
+
+
{t('fleets.instances.project')}
+
+
+ {data.project_name}
+
+
+
+
+
+
{t('fleets.fleet')}
+
+ {data.fleet_name && data.fleet_id ? (
+
+ {data.fleet_name}
+
+ ) : (
+ '-'
+ )}
+
+
+
+
+
{t('fleets.instances.status')}
+
+
+ {(data.status === 'idle' || data.status === 'busy') &&
+ data.total_blocks !== null &&
+ data.total_blocks > 1
+ ? `${data.busy_blocks}/${data.total_blocks} Busy`
+ : prettyEnumValue(data.status)}
+
+
+
+
+
+
{t('projects.run.error')}
+
+ {data.unreachable ? (
+ Unreachable
+ ) : data.health_status !== 'healthy' ? (
+
+ {prettyEnumValue(data.health_status)}
+
+ ) : (
+ '-'
+ )}
+
+
+
+
+
{t('fleets.instances.started')}
+
{format(new Date(data.created), DATE_TIME_FORMAT)}
+
+
+
+
{t('fleets.instances.finished_at')}
+
{data.finished_at ? format(new Date(data.finished_at), DATE_TIME_FORMAT) : '-'}
+
+
+ {data.termination_reason && (
+
+
{t('fleets.instances.termination_reason')}
+
{data.termination_reason_message ?? prettyEnumValue(data.termination_reason)}
+
+ )}
+
+
+
{t('fleets.instances.resources')}
+
{data.instance_type ? formatResources(data.instance_type.resources) : '-'}
+
+
+
+
{t('fleets.instances.backend')}
+
{formatBackend(data.backend)}
+
+
+
+
{t('fleets.instances.region')}
+
{data.region ?? '-'}
+
+
+
+
{t('fleets.instances.instance_type')}
+
{data.instance_type?.name ?? '-'}
+
+
+
+
{t('fleets.instances.spot')}
+
{data.instance_type?.resources.spot ? t('common.yes') : t('common.no')}
+
+
+
+
{t('fleets.instances.price')}
+
{typeof data.price === 'number' ? `$${data.price}` : '-'}
+
+
+ {data.total_blocks !== null && (
+
+
{t('fleets.instances.blocks')}
+
{data.total_blocks}
+
+ )}
+
+
+
{t('fleets.instances.hostname')}
+
{data.hostname ?? '-'}
+
+
+
+ )}
+ >
+ );
+};
diff --git a/frontend/src/pages/Instances/Details/index.tsx b/frontend/src/pages/Instances/Details/index.tsx
new file mode 100644
index 0000000000..2c7f1a2b5c
--- /dev/null
+++ b/frontend/src/pages/Instances/Details/index.tsx
@@ -0,0 +1,110 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { Outlet, useNavigate, useParams } from 'react-router-dom';
+
+import { Button, ContentLayout, DetailsHeader, Tabs } from 'components';
+
+enum InstanceTab {
+ Details = 'details',
+ Events = 'events',
+ Inspect = 'inspect',
+}
+
+import { useBreadcrumbs } from 'hooks';
+import { ROUTES } from 'routes';
+import { useGetInstanceDetailsQuery } from 'services/instance';
+
+import { useDeleteInstance } from './useDeleteInstance';
+
+import styles from './styles.module.scss';
+
+export const InstanceDetailsPage: React.FC = () => {
+ const { t } = useTranslation();
+ const params = useParams();
+ const paramInstanceId = params.instanceId ?? '';
+ const paramProjectName = params.projectName ?? '';
+ const navigate = useNavigate();
+
+ const { deleteInstance, isDeleting } = useDeleteInstance();
+
+ const { data } = useGetInstanceDetailsQuery(
+ {
+ projectName: paramProjectName,
+ instanceId: paramInstanceId,
+ },
+ {
+ refetchOnMountOrArgChange: true,
+ },
+ );
+
+ useBreadcrumbs([
+ {
+ text: t('navigation.project_other'),
+ href: ROUTES.PROJECT.LIST,
+ },
+ {
+ text: paramProjectName,
+ href: ROUTES.PROJECT.DETAILS.FORMAT(paramProjectName),
+ },
+ {
+ text: t('navigation.instances'),
+ href: ROUTES.INSTANCES.LIST,
+ },
+ {
+ text: data?.name ?? '',
+ href: ROUTES.INSTANCES.DETAILS.FORMAT(paramProjectName, paramInstanceId),
+ },
+ ]);
+
+ const deleteClickHandle = () => {
+ if (!data) return;
+
+ deleteInstance(data)
+ .then(() => {
+ navigate(ROUTES.INSTANCES.LIST);
+ })
+ .catch(console.log);
+ };
+
+ const isDisabledDeleteButton = !data || isDeleting || data.status === 'terminated';
+
+ return (
+
+
+ {t('common.delete')}
+
+ }
+ />
+ }
+ >
+
+
+
+
+
+ );
+};
diff --git a/frontend/src/pages/Instances/Details/styles.module.scss b/frontend/src/pages/Instances/Details/styles.module.scss
new file mode 100644
index 0000000000..1a7d41a9c5
--- /dev/null
+++ b/frontend/src/pages/Instances/Details/styles.module.scss
@@ -0,0 +1,18 @@
+.page {
+ height: 100%;
+
+ & [class^="awsui_tabs-content"] {
+ display: none;
+ }
+
+ & > [class^="awsui_layout"] {
+ height: 100%;
+
+ & > [class^="awsui_content"] {
+ display: flex;
+ flex-direction: column;
+ gap: 20px;
+ height: 100%;
+ }
+ }
+}
diff --git a/frontend/src/pages/Instances/Details/useDeleteInstance.ts b/frontend/src/pages/Instances/Details/useDeleteInstance.ts
new file mode 100644
index 0000000000..b460ed4373
--- /dev/null
+++ b/frontend/src/pages/Instances/Details/useDeleteInstance.ts
@@ -0,0 +1,38 @@
+import { useCallback, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { useNotifications } from 'hooks';
+import { getServerError } from 'libs';
+import { useDeleteInstancesMutation } from 'services/instance';
+
+export const useDeleteInstance = () => {
+ const { t } = useTranslation();
+ const [deleteInstances] = useDeleteInstancesMutation();
+ const [pushNotification] = useNotifications();
+ const [isDeleting, setIsDeleting] = useState(false);
+
+ const deleteInstance = useCallback(async (instance: IInstance) => {
+ if (!instance.project_name || !instance.fleet_name) {
+ return Promise.reject('Missing project or fleet name');
+ }
+
+ setIsDeleting(true);
+
+ return deleteInstances({
+ projectName: instance.project_name,
+ fleetName: instance.fleet_name,
+ instancesNums: [instance.instance_num],
+ })
+ .unwrap()
+ .finally(() => setIsDeleting(false))
+ .catch((error) => {
+ pushNotification({
+ type: 'error',
+ content: t('common.server_error', { error: getServerError(error) }),
+ });
+ throw error;
+ });
+ }, []);
+
+ return { deleteInstance, isDeleting } as const;
+};
diff --git a/frontend/src/pages/Instances/List/hooks/useActions.ts b/frontend/src/pages/Instances/List/hooks/useActions.ts
new file mode 100644
index 0000000000..619bdbae5e
--- /dev/null
+++ b/frontend/src/pages/Instances/List/hooks/useActions.ts
@@ -0,0 +1,56 @@
+import { useCallback, useState } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { useNotifications } from 'hooks';
+import { getServerError } from 'libs';
+import { useDeleteInstancesMutation } from 'services/instance';
+
+export const useActions = () => {
+ const { t } = useTranslation();
+ const [deleteInstances] = useDeleteInstancesMutation();
+ const [pushNotification] = useNotifications();
+ const [isDeleting, setIsDeleting] = useState(() => false);
+
+ const instancesGroupByFleetName = (instances: IInstance[]) => {
+ return instances.reduce>((acc, instance) => {
+ const key = `${instance.project_name}/${instance.fleet_name}`;
+
+ if (acc[key]) {
+ acc[key].push(instance.instance_num);
+ } else {
+ acc[key] = [instance.instance_num];
+ }
+
+ return acc;
+ }, {});
+ };
+
+ const deleteFleets = useCallback(async (instances: IInstance[]) => {
+ if (!instances.length) return Promise.reject('No instances');
+
+ setIsDeleting(true);
+
+ const groupedInstances = instancesGroupByFleetName(instances);
+
+ const requests = Object.keys(groupedInstances).map((key) => {
+ const [projectName, fleetName] = key.split('/');
+
+ return deleteInstances({
+ projectName,
+ fleetName,
+ instancesNums: groupedInstances[key],
+ }).unwrap();
+ });
+
+ return Promise.all(requests)
+ .finally(() => setIsDeleting(false))
+ .catch((error) => {
+ pushNotification({
+ type: 'error',
+ content: t('common.server_error', { error: getServerError(error) }),
+ });
+ });
+ }, []);
+
+ return { deleteFleets, isDeleting } as const;
+};
diff --git a/frontend/src/pages/Instances/List/hooks/useColumnDefinitions.tsx b/frontend/src/pages/Instances/List/hooks/useColumnDefinitions.tsx
new file mode 100644
index 0000000000..98b1ddd2b4
--- /dev/null
+++ b/frontend/src/pages/Instances/List/hooks/useColumnDefinitions.tsx
@@ -0,0 +1,120 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+import { format } from 'date-fns';
+
+import { Icon, NavigateLink, StatusIndicator, TableProps } from 'components';
+
+import { DATE_TIME_FORMAT } from 'consts';
+import { formatBackend, getStatusIconColor, getStatusIconType } from 'libs/fleet';
+import { formatInstanceStatusText, getHealthStatusIconType, prettyEnumValue } from 'libs/instance';
+import { formatResources } from 'libs/resources';
+import { ROUTES } from 'routes';
+
+export const useColumnsDefinitions = () => {
+ const { t } = useTranslation();
+
+ const columns: TableProps.ColumnDefinition[] = [
+ {
+ id: 'name',
+ header: t('fleets.instances.instance_name'),
+ cell: (item) =>
+ item.project_name ? (
+ {item.name}
+ ) : (
+ item.name
+ ),
+ },
+ {
+ id: 'fleet_name',
+ header: t('fleets.fleet'),
+ cell: (item) =>
+ item.fleet_name && item.project_name ? (
+
+ {item.fleet_name}
+
+ ) : (
+ '-'
+ ),
+ },
+ {
+ id: 'project_name',
+ header: t('fleets.instances.project'),
+ cell: (item) =>
+ item.project_name ? (
+ {item.project_name}
+ ) : (
+ item.project_name
+ ),
+ },
+ {
+ id: 'status',
+ header: t('fleets.instances.status'),
+ cell: (item) => (
+
+ {formatInstanceStatusText(item)}
+
+ ),
+ },
+ {
+ id: 'error',
+ header: t('projects.run.error'),
+ cell: (item) => {
+ if (item.unreachable) return Unreachable ;
+ if (item.health_status !== 'healthy')
+ return (
+
+ {prettyEnumValue(item.health_status)}
+
+ );
+ return null;
+ },
+ },
+ {
+ id: 'hostname',
+ header: t('fleets.instances.hostname'),
+ cell: (item) => item.hostname,
+ },
+ {
+ id: 'backend',
+ header: t('fleets.instances.backend'),
+ cell: (item) => formatBackend(item.backend),
+ },
+ {
+ id: 'price',
+ header: t('fleets.instances.price'),
+ cell: (item) => (typeof item.price === 'number' ? `$${item.price}` : '-'),
+ },
+ {
+ id: 'region',
+ header: t('fleets.instances.region'),
+ cell: (item) => item.region,
+ },
+ {
+ id: 'instance_type',
+ header: t('fleets.instances.instance_type'),
+ cell: (item) => item.instance_type?.name ?? '-',
+ },
+ {
+ id: 'resources',
+ header: t('fleets.instances.resources'),
+ cell: (item) => (item.instance_type ? formatResources(item.instance_type.resources) : '-'),
+ },
+ {
+ id: 'spot',
+ header: t('fleets.instances.spot'),
+ cell: (item) => item.instance_type?.resources.spot && ,
+ },
+ {
+ id: 'started',
+ header: t('fleets.instances.started'),
+ cell: (item) => format(new Date(item.created), DATE_TIME_FORMAT),
+ },
+ {
+ id: 'finished_at',
+ header: t('fleets.instances.finished_at'),
+ cell: (item) => (item.finished_at ? format(new Date(item.finished_at), DATE_TIME_FORMAT) : '-'),
+ },
+ ];
+
+ return { columns } as const;
+};
diff --git a/frontend/src/pages/Instances/List/hooks/useEmptyMessage.tsx b/frontend/src/pages/Instances/List/hooks/useEmptyMessage.tsx
new file mode 100644
index 0000000000..a2909c7637
--- /dev/null
+++ b/frontend/src/pages/Instances/List/hooks/useEmptyMessage.tsx
@@ -0,0 +1,42 @@
+import React, { useCallback } from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Button, ListEmptyMessage } from 'components';
+
+export const useEmptyMessages = ({
+ clearFilter,
+ isDisabledClearFilter,
+}: {
+ clearFilter?: () => void;
+ isDisabledClearFilter?: boolean;
+}) => {
+ const { t } = useTranslation();
+
+ const renderEmptyMessage = useCallback<() => React.ReactNode>(() => {
+ return (
+
+
+ {t('common.clearFilter')}
+
+
+ );
+ }, [clearFilter, isDisabledClearFilter]);
+
+ const renderNoMatchMessage = useCallback<() => React.ReactNode>(() => {
+ return (
+
+
+ {t('common.clearFilter')}
+
+
+ );
+ }, [clearFilter, isDisabledClearFilter]);
+
+ return { renderEmptyMessage, renderNoMatchMessage } as const;
+};
diff --git a/frontend/src/pages/Instances/List/hooks/useFilters.ts b/frontend/src/pages/Instances/List/hooks/useFilters.ts
new file mode 100644
index 0000000000..4239ef50c3
--- /dev/null
+++ b/frontend/src/pages/Instances/List/hooks/useFilters.ts
@@ -0,0 +1,124 @@
+import { useMemo, useState } from 'react';
+import { useSearchParams } from 'react-router-dom';
+import { ToggleProps } from '@cloudscape-design/components';
+
+import type { PropertyFilterProps } from 'components';
+
+import { useLocalStorageState } from 'hooks';
+import {
+ EMPTY_QUERY,
+ getNamePatternFilterRequestParams,
+ requestParamsToTokens,
+ tokensToRequestParams,
+ tokensToSearchParams,
+} from 'libs/filters';
+import { useLazyGetProjectsQuery } from 'services/project';
+
+type RequestParamsKeys = keyof Pick;
+
+const filterKeys: Record = {
+ PROJECT_NAMES: 'project_names',
+ FLEET_IDS: 'fleet_ids',
+};
+
+const limit = 100;
+
+export const useFilters = () => {
+ const [searchParams, setSearchParams] = useSearchParams();
+ const [onlyActive, setOnlyActive] = useLocalStorageState('instance-list-filter-only-active', true);
+ const [dynamicFilteringOptions, setDynamicFilteringOptions] = useState([]);
+ const [filteringStatusType, setFilteringStatusType] = useState();
+ const [getProjects] = useLazyGetProjectsQuery();
+
+ const [propertyFilterQuery, setPropertyFilterQuery] = useState(() => {
+ return requestParamsToTokens({ searchParams, filterKeys });
+ });
+
+ const clearFilter = () => {
+ setSearchParams({});
+ setPropertyFilterQuery(EMPTY_QUERY);
+ };
+
+ const filteringOptions = useMemo(() => {
+ return [...dynamicFilteringOptions];
+ }, [dynamicFilteringOptions]);
+
+ const filteringProperties = [
+ {
+ key: filterKeys.PROJECT_NAMES,
+ operators: ['='],
+ propertyLabel: 'Project',
+ groupValuesLabel: 'Project values',
+ },
+ {
+ key: filterKeys.FLEET_IDS,
+ operators: ['='],
+ propertyLabel: 'Fleet ID',
+ groupValuesLabel: 'Fleet ID values',
+ },
+ ];
+
+ const onChangePropertyFilter: PropertyFilterProps['onChange'] = ({ detail }) => {
+ const { tokens, operation } = detail;
+
+ setSearchParams(tokensToSearchParams(tokens, onlyActive));
+
+ setPropertyFilterQuery({
+ operation,
+ tokens,
+ });
+ };
+
+ const onChangeOnlyActive: ToggleProps['onChange'] = ({ detail }) => {
+ setOnlyActive(detail.checked);
+ };
+
+ const filteringRequestParams = useMemo(() => {
+ const params = tokensToRequestParams({
+ tokens: propertyFilterQuery.tokens,
+ arrayFieldKeys: [filterKeys.PROJECT_NAMES, filterKeys.FLEET_IDS],
+ });
+
+ return {
+ ...params,
+ only_active: onlyActive,
+ include_imported: true,
+ } as Partial;
+ }, [propertyFilterQuery, onlyActive]);
+
+ const isDisabledClearFilter = !propertyFilterQuery.tokens.length && !onlyActive;
+
+ const handleLoadItems: PropertyFilterProps['onLoadItems'] = async ({ detail: { filteringProperty, filteringText } }) => {
+ setDynamicFilteringOptions([]);
+
+ setFilteringStatusType('loading');
+
+ if (filteringProperty?.key === filterKeys.PROJECT_NAMES) {
+ await getProjects(getNamePatternFilterRequestParams(filteringText, limit))
+ .unwrap()
+ .then(({ data }) =>
+ data.map(({ project_name }) => ({
+ propertyKey: filterKeys.PROJECT_NAMES,
+ value: project_name,
+ })),
+ )
+ .then(setDynamicFilteringOptions);
+ }
+
+ setFilteringStatusType(undefined);
+ };
+
+ return {
+ filteringRequestParams,
+ clearFilter,
+ propertyFilterQuery,
+ onChangePropertyFilter,
+ filteringOptions,
+ filteringProperties,
+ onlyActive,
+ onChangeOnlyActive,
+ isDisabledClearFilter,
+ filteringStatusType,
+ handleLoadItems,
+ } as const;
+};
diff --git a/frontend/src/pages/Instances/List/index.tsx b/frontend/src/pages/Instances/List/index.tsx
new file mode 100644
index 0000000000..a0cd2be951
--- /dev/null
+++ b/frontend/src/pages/Instances/List/index.tsx
@@ -0,0 +1,140 @@
+import React from 'react';
+import { useTranslation } from 'react-i18next';
+
+import { Button, Header, Loader, PropertyFilter, SpaceBetween, Table, Toggle } from 'components';
+
+import { DEFAULT_TABLE_PAGE_SIZE } from 'consts';
+import { useBreadcrumbs, useInfiniteScroll } from 'hooks';
+import { useCollection } from 'hooks';
+import { ROUTES } from 'routes';
+import { useLazyGetInstancesQuery } from 'services/instance';
+
+import { useActions } from './hooks/useActions';
+import { useColumnsDefinitions } from './hooks/useColumnDefinitions';
+import { useEmptyMessages } from './hooks/useEmptyMessage';
+import { useFilters } from './hooks/useFilters';
+
+import styles from './styles.module.scss';
+
+export const List: React.FC = () => {
+ const { t } = useTranslation();
+
+ useBreadcrumbs([
+ {
+ text: t('navigation.instances'),
+ href: ROUTES.INSTANCES.LIST,
+ },
+ ]);
+
+ const { columns } = useColumnsDefinitions();
+
+ const {
+ filteringRequestParams,
+ clearFilter,
+ propertyFilterQuery,
+ onChangePropertyFilter,
+ filteringOptions,
+ filteringProperties,
+ onlyActive,
+ onChangeOnlyActive,
+ isDisabledClearFilter,
+ filteringStatusType,
+ handleLoadItems,
+ } = useFilters();
+
+ const { data, isLoading, refreshList, isLoadingMore } = useInfiniteScroll({
+ useLazyQuery: useLazyGetInstancesQuery,
+ args: { ...filteringRequestParams, limit: DEFAULT_TABLE_PAGE_SIZE },
+
+ getPaginationParams: (lastInstance) => ({
+ prev_created_at: lastInstance.created,
+ prev_id: lastInstance.id,
+ }),
+ });
+
+ const { deleteFleets, isDeleting } = useActions();
+
+ const { renderEmptyMessage, renderNoMatchMessage } = useEmptyMessages({ clearFilter, isDisabledClearFilter });
+
+ const { items, collectionProps } = useCollection(data, {
+ filtering: {
+ empty: renderEmptyMessage(),
+ noMatch: renderNoMatchMessage(),
+ },
+ selection: {},
+ });
+
+ const { selectedItems } = collectionProps;
+
+ const isDisabledDeleteButton = !selectedItems?.length || isDeleting;
+
+ const deleteClickHandle = () => {
+ if (!selectedItems?.length) return;
+
+ deleteFleets([...selectedItems]).catch(console.log);
+ };
+
+ return (
+
+
+ {t('common.delete')}
+
+
+
+
+ }
+ >
+ {t('navigation.instances')}
+
+ }
+ filter={
+
+
+
`Use: ${value}`,
+ }}
+ filteringOptions={filteringOptions}
+ filteringProperties={filteringProperties}
+ filteringStatusType={filteringStatusType}
+ onLoadItems={handleLoadItems}
+ />
+
+
+
+
+ {t('fleets.instances.active_only')}
+
+
+
+ }
+ footer={ }
+ />
+ );
+};
diff --git a/frontend/src/pages/Instances/List/styles.module.scss b/frontend/src/pages/Instances/List/styles.module.scss
new file mode 100644
index 0000000000..183b03d011
--- /dev/null
+++ b/frontend/src/pages/Instances/List/styles.module.scss
@@ -0,0 +1,15 @@
+.filters {
+ display: flex;
+ flex-wrap: wrap;
+ gap: 0 20px;
+
+ .propertyFilter {
+ max-width: 640px;
+ flex-grow: 1;
+ min-width: 0;
+ }
+ .activeOnly {
+ display: flex;
+ padding-top: 7px;
+ }
+}
diff --git a/frontend/src/pages/Instances/index.ts b/frontend/src/pages/Instances/index.ts
new file mode 100644
index 0000000000..15199c378d
--- /dev/null
+++ b/frontend/src/pages/Instances/index.ts
@@ -0,0 +1,2 @@
+export { List as InstanceList } from './List';
+export { InstanceDetailsPage } from './Details';
diff --git a/frontend/src/pages/Models/Details/helpers.ts b/frontend/src/pages/Models/Details/helpers.ts
new file mode 100644
index 0000000000..54d44e7c7e
--- /dev/null
+++ b/frontend/src/pages/Models/Details/helpers.ts
@@ -0,0 +1,41 @@
+import { getModelGateway } from '../helpers';
+
+import { IModelExtended } from '../List/types';
+
+export const getPythonModelCode = ({ model, token }: { model?: IModelExtended | null; token?: string }) => {
+ return `from openai import OpenAI
+client = OpenAI(
+ api_key="${token}",
+ base_url="${getModelGateway(model?.base_url ?? '')}"
+)
+
+response = client.chat.completions.create(
+ model="${model?.name ?? ''}",
+ messages=[
+ {
+ "role": "user",
+ "content": "Hello world",
+ },
+ ],
+ stream=True,
+ max_tokens=512,
+)`;
+};
+
+export const getCurlModelCode = ({ model, token }: { model?: IModelExtended | null; token?: string }) => {
+ const url = getModelGateway(model?.base_url ?? '').replace(/\/$/, '') + '/chat/completions';
+ return `curl ${url} \\
+ -H "Content-Type: application/json" \\
+ -H "Authorization: Bearer ${token}" \\
+ -d '{
+ "model": "${model?.name ?? ''}",
+ "messages": [
+ {
+ "role": "user",
+ "content": "Hello world"
+ }
+ ],
+ "stream": true,
+ "max_tokens": 512
+}'`;
+};
diff --git a/frontend/src/pages/Models/Details/index.tsx b/frontend/src/pages/Models/Details/index.tsx
new file mode 100644
index 0000000000..ad9906d5b1
--- /dev/null
+++ b/frontend/src/pages/Models/Details/index.tsx
@@ -0,0 +1,466 @@
+import React, { useEffect, useMemo, useRef, useState } from 'react';
+import { useForm } from 'react-hook-form';
+import { useTranslation } from 'react-i18next';
+import { useParams } from 'react-router-dom';
+import reactStringReplace from 'react-string-replace';
+import OpenAI from 'openai';
+
+import {
+ Avatar,
+ Box,
+ Button,
+ ChatBubble,
+ Code,
+ ColumnLayout,
+ Container,
+ ContentLayout,
+ DetailsHeader,
+ FormTextarea,
+ Header,
+ ListEmptyMessage,
+ Loader,
+ Modal,
+ NavigateLink,
+ SpaceBetween,
+ Tabs,
+} from 'components';
+
+import { useAppSelector, useBreadcrumbs, useNotifications } from 'hooks';
+import { copyToClipboard, riseRouterException } from 'libs';
+import { getExtendedModelFromRun } from 'libs/run';
+import { ROUTES } from 'routes';
+import { useGetRunQuery } from 'services/run';
+
+import { selectAuthToken } from 'App/slice';
+import { runIsStopped } from 'pages/Runs/utils';
+
+import { getModelGateway } from '../helpers';
+import { getCurlModelCode, getPythonModelCode } from './helpers';
+
+import { IModelExtended } from '../List/types';
+import { FormValues, Message, Role } from './types';
+
+import css from './styles.module.scss';
+
+const MESSAGE_ROLE_MAP: Record = {
+ tool: 'Tool',
+ system: 'System',
+ user: 'User',
+ assistant: 'Assistant',
+};
+
+enum CodeTab {
+ Python = 'python',
+ Curl = 'curl',
+}
+
+export const ModelDetails: React.FC = () => {
+ const { t } = useTranslation();
+ const token = useAppSelector(selectAuthToken);
+ const [messages, setMessages] = useState([]);
+ const [viewCodeVisible, setViewCodeVisible] = useState(false);
+ const [codeTab, setCodeTab] = useState(CodeTab.Python);
+ const [loading, setLoading] = useState(false);
+ const params = useParams();
+ const paramProjectName = params.projectName ?? '';
+ const paramRunName = params.runName ?? '';
+ const openai = useRef();
+ const textAreaRef = useRef(null);
+ const chatList = useRef();
+ const [pushNotification] = useNotifications();
+
+ const messageForShowing = useMemo