diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json index 3e654335f..a8264a227 100644 --- a/.devcontainer/devcontainer.json +++ b/.devcontainer/devcontainer.json @@ -52,7 +52,9 @@ "mikestead.dotenv", "csstools.postcss", "blanu.vscode-styled-jsx", - "bradlc.vscode-tailwindcss" + "bradlc.vscode-tailwindcss", + "ms-python.isort", + "charliermarsh.ruff" ], "settings": { "remote.autoForwardPorts": false, @@ -68,6 +70,7 @@ "python.testing.unittestArgs": ["-v", "-s", "./frigate/test"], "files.trimTrailingWhitespace": true, "eslint.workingDirectories": ["./web"], + "isort.args": ["--settings-path=./pyproject.toml"], "[python]": { "editor.defaultFormatter": "ms-python.black-formatter", "editor.formatOnSave": true diff --git a/.devcontainer/post_create.sh b/.devcontainer/post_create.sh index 9dd1249c6..9c5dec5bb 100755 --- a/.devcontainer/post_create.sh +++ b/.devcontainer/post_create.sh @@ -2,6 +2,12 @@ set -euxo pipefail +# Cleanup the old github host key +sed -i -e '/AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31\/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXy28G3skua2SmVi\/w4yCE6gbODqnTWlg7+wC604ydGXA8VJiS5ap43JXiUFFAaQ==/d' ~/.ssh/known_hosts +# Add new github host key +curl -L https://api.github.com/meta | jq -r '.ssh_keys | .[]' | \ + sed -e 's/^/github.com /' >> ~/.ssh/known_hosts + # Frigate normal container runs as root, so it have permission to create # the folders. But the devcontainer runs as the host user, so we need to # create the folders and give the host user permission to write to them. diff --git a/.github/workflows/pull_request.yml b/.github/workflows/pull_request.yml index c437e98ee..7e97cfb6c 100644 --- a/.github/workflows/pull_request.yml +++ b/.github/workflows/pull_request.yml @@ -65,24 +65,26 @@ jobs: - name: Check out the repository uses: actions/checkout@v3 - name: Set up Python ${{ env.DEFAULT_PYTHON }} - uses: actions/setup-python@v4.6.0 + uses: actions/setup-python@v4.6.1 with: python-version: ${{ env.DEFAULT_PYTHON }} - name: Install requirements run: | - pip install pip - pip install -r requirements-dev.txt - - name: Lint + python3 -m pip install -U pip + python3 -m pip install -r requirements-dev.txt + - name: Check black run: | - python3 -m black frigate --check + black --check --diff frigate migrations docker *.py + - name: Check isort + run: | + isort --check --diff frigate migrations docker *.py + - name: Check ruff + run: | + ruff check frigate migrations docker *.py python_tests: runs-on: ubuntu-latest name: Python Tests - strategy: - fail-fast: false - matrix: - platform: [amd64,arm64] steps: - name: Check out code uses: actions/checkout@v3 @@ -94,22 +96,13 @@ jobs: - name: Build web run: npm run build working-directory: ./web - - run: make version - name: Set up QEMU uses: docker/setup-qemu-action@v2 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 - name: Build - uses: docker/build-push-action@v4 - with: - context: . - push: false - load: true - platforms: linux/${{ matrix.platform }} - tags: | - frigate:${{ matrix.platform }} - target: frigate + run: make - name: Run mypy - run: docker run --platform linux/${{ matrix.platform }} --rm --entrypoint=python3 frigate:${{ matrix.platform }} -u -m mypy --config-file frigate/mypy.ini frigate + run: docker run --rm --entrypoint=python3 frigate:latest -u -m mypy --config-file frigate/mypy.ini frigate - name: Run tests - run: docker run --platform linux/${{ matrix.platform }} --rm --entrypoint=python3 frigate:${{ matrix.platform }} -u -m unittest + run: docker run --rm --entrypoint=python3 frigate:latest -u -m unittest diff --git a/Dockerfile b/Dockerfile index bb010c780..0c244f901 100644 --- a/Dockerfile +++ b/Dockerfile @@ -227,8 +227,8 @@ CMD ["sleep", "infinity"] # Frigate web build -# force this to run on amd64 because QEMU is painfully slow -FROM --platform=linux/amd64 node:16 AS web-build +# This should be architecture agnostic, so speed up the build on multiarch by not using QEMU. +FROM --platform=$BUILDPLATFORM node:16 AS web-build WORKDIR /work COPY web/package.json web/package-lock.json ./ diff --git a/benchmark.py b/benchmark.py index 3d0cacd87..8ba22d093 100755 --- a/benchmark.py +++ b/benchmark.py @@ -1,11 +1,11 @@ -import os -from statistics import mean -import multiprocessing as mp -import numpy as np import datetime +import multiprocessing as mp +from statistics import mean + +import numpy as np + from frigate.config import DetectorTypeEnum from frigate.object_detection import ( - LocalObjectDetector, ObjectDetectProcess, RemoteObjectDetector, load_labels, @@ -53,7 +53,7 @@ def start(id, num_detections, detection_queue, event): frame_times = [] for x in range(0, num_detections): start_frame = datetime.datetime.now().timestamp() - detections = object_detector.detect(my_frame) + object_detector.detect(my_frame) frame_times.append(datetime.datetime.now().timestamp() - start_frame) duration = datetime.datetime.now().timestamp() - start diff --git a/docker/rootfs/usr/local/go2rtc/create_config.py b/docker/rootfs/usr/local/go2rtc/create_config.py index d201eb381..1397adee8 100644 --- a/docker/rootfs/usr/local/go2rtc/create_config.py +++ b/docker/rootfs/usr/local/go2rtc/create_config.py @@ -3,11 +3,14 @@ import json import os import sys + import yaml sys.path.insert(0, "/opt/frigate") -from frigate.const import BIRDSEYE_PIPE, BTBN_PATH -from frigate.ffmpeg_presets import parse_preset_hardware_acceleration_encode +from frigate.const import BIRDSEYE_PIPE, BTBN_PATH # noqa: E402 +from frigate.ffmpeg_presets import ( # noqa: E402 + parse_preset_hardware_acceleration_encode, +) sys.path.remove("/opt/frigate") diff --git a/docker/rootfs/usr/local/nginx/conf/nginx.conf b/docker/rootfs/usr/local/nginx/conf/nginx.conf index a6b50e317..35703fb2c 100644 --- a/docker/rootfs/usr/local/nginx/conf/nginx.conf +++ b/docker/rootfs/usr/local/nginx/conf/nginx.conf @@ -172,6 +172,27 @@ http { root /media/frigate; } + location /exports/ { + add_header 'Access-Control-Allow-Origin' "$http_origin" always; + add_header 'Access-Control-Allow-Credentials' 'true'; + add_header 'Access-Control-Expose-Headers' 'Content-Length'; + if ($request_method = 'OPTIONS') { + add_header 'Access-Control-Allow-Origin' "$http_origin"; + add_header 'Access-Control-Max-Age' 1728000; + add_header 'Content-Type' 'text/plain charset=UTF-8'; + add_header 'Content-Length' 0; + return 204; + } + + types { + video/mp4 mp4; + } + + autoindex on; + autoindex_format json; + root /media/frigate; + } + location /ws { proxy_pass http://mqtt_ws/; proxy_http_version 1.1; diff --git a/docs/README.md b/docs/README.md index eb435c5b6..bd4aded51 100644 --- a/docs/README.md +++ b/docs/README.md @@ -2,4 +2,4 @@ This website is built using [Docusaurus 2](https://v2.docusaurus.io/), a modern static website generator. -For installation and contributing instructions, please follow the [Contributing Docs](https://blakeblackshear.github.io/frigate/contributing). +For installation and contributing instructions, please follow the [Contributing Docs](https://docs.frigate.video/development/contributing). diff --git a/docs/docs/configuration/record.md b/docs/docs/configuration/record.md index f22f37d02..29a2fb36b 100644 --- a/docs/docs/configuration/record.md +++ b/docs/docs/configuration/record.md @@ -80,3 +80,7 @@ record: dog: 2 car: 7 ``` + +## How do I export recordings? + +The export page in the Frigate WebUI allows for exporting real time clips with a designated start and stop time as well as exporting a timelapse for a designated start and stop time. These exports can take a while so it is important to leave the file until it is no longer in progress. diff --git a/docs/docs/frigate/installation.md b/docs/docs/frigate/installation.md index 115a85c17..1397f8741 100644 --- a/docs/docs/frigate/installation.md +++ b/docs/docs/frigate/installation.md @@ -24,6 +24,7 @@ Frigate uses the following locations for read/write operations in the container. - `/config`: Used to store the Frigate config file and sqlite database. You will also see a few files alongside the database file while Frigate is running. - `/media/frigate/clips`: Used for snapshot storage. In the future, it will likely be renamed from `clips` to `snapshots`. The file structure here cannot be modified and isn't intended to be browsed or managed manually. - `/media/frigate/recordings`: Internal system storage for recording segments. The file structure here cannot be modified and isn't intended to be browsed or managed manually. +- `/media/frigate/exports`: Storage for clips and timelapses that have been exported via the WebUI or API. - `/tmp/cache`: Cache location for recording segments. Initial recordings are written here before being checked and converted to mp4 and moved to the recordings folder. - `/dev/shm`: It is not recommended to modify this directory or map it with docker. This is the location for raw decoded frames in shared memory and it's size is impacted by the `shm-size` calculations below. @@ -221,7 +222,7 @@ These settings were tested on DSM 7.1.1-42962 Update 4 The `Execute container using high privilege` option needs to be enabled in order to give the frigate container the elevated privileges it may need. -The `Enable auto-restart` option can be enabled if you want the container to automatically restart whenever it improperly shuts down due to an error. +The `Enable auto-restart` option can be enabled if you want the container to automatically restart whenever it improperly shuts down due to an error. ![image](https://user-images.githubusercontent.com/4516296/232586790-0b659a82-561d-4bc5-899b-0f5b39c6b11d.png) diff --git a/docs/docs/integrations/api.md b/docs/docs/integrations/api.md index 3e5fdfe3e..f36f33770 100644 --- a/docs/docs/integrations/api.md +++ b/docs/docs/integrations/api.md @@ -271,6 +271,20 @@ HTTP Live Streaming Video on Demand URL for the specified event. Can be viewed i HTTP Live Streaming Video on Demand URL for the camera with the specified time range. Can be viewed in an application like VLC. +### `POST /api/export//start//end/` + +Export recordings from `start-timestamp` to `end-timestamp` for `camera` as a single mp4 file. These recordings will be exported to the `/media/frigate/exports` folder. + +It is also possible to export this recording as a timelapse. + +**Optional Body:** + +```json +{ + "playback": "realtime", // playback factor: realtime or timelapse_25x +} +``` + ### `GET /api//recordings/summary` Hourly summary of recordings data for a camera. diff --git a/docs/package-lock.json b/docs/package-lock.json index 7f946b030..2d808422b 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -8,8 +8,8 @@ "name": "docs", "version": "0.0.0", "dependencies": { - "@docusaurus/core": "^2.4.0", - "@docusaurus/preset-classic": "^2.4.0", + "@docusaurus/core": "^2.4.1", + "@docusaurus/preset-classic": "^2.4.1", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", "prism-react-renderer": "^1.3.5", @@ -26,19 +26,19 @@ } }, "node_modules/@algolia/autocomplete-core": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.7.4.tgz", - "integrity": "sha512-daoLpQ3ps/VTMRZDEBfU8ixXd+amZcNJ4QSP3IERGyzqnL5Ch8uSRFt/4G8pUvW9c3o6GA4vtVv4I4lmnkdXyg==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.8.2.tgz", + "integrity": "sha512-mTeshsyFhAqw/ebqNsQpMtbnjr+qVOSKXArEj4K0d7sqc8It1XD0gkASwecm9mF/jlOQ4Z9RNg1HbdA8JPdRwQ==", "dependencies": { - "@algolia/autocomplete-shared": "1.7.4" + "@algolia/autocomplete-shared": "1.8.2" } }, "node_modules/@algolia/autocomplete-preset-algolia": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.4.tgz", - "integrity": "sha512-s37hrvLEIfcmKY8VU9LsAXgm2yfmkdHT3DnA3SgHaY93yjZ2qL57wzb5QweVkYuEBZkT2PIREvRoLXC2sxTbpQ==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.8.2.tgz", + "integrity": "sha512-J0oTx4me6ZM9kIKPuL3lyU3aB8DEvpVvR6xWmHVROx5rOYJGQcZsdG4ozxwcOyiiu3qxMkIbzntnV1S1VWD8yA==", "dependencies": { - "@algolia/autocomplete-shared": "1.7.4" + "@algolia/autocomplete-shared": "1.8.2" }, "peerDependencies": { "@algolia/client-search": ">= 4.9.1 < 6", @@ -46,79 +46,79 @@ } }, "node_modules/@algolia/autocomplete-shared": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.4.tgz", - "integrity": "sha512-2VGCk7I9tA9Ge73Km99+Qg87w0wzW4tgUruvWAn/gfey1ZXgmxZtyIRBebk35R1O8TbK77wujVtCnpsGpRy1kg==" + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.8.2.tgz", + "integrity": "sha512-b6Z/X4MczChMcfhk6kfRmBzPgjoPzuS9KGR4AFsiLulLNRAAqhP+xZTKtMnZGhLuc61I20d5WqlId02AZvcO6g==" }, "node_modules/@algolia/cache-browser-local-storage": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.0.tgz", - "integrity": "sha512-myRSRZDIMYB8uCkO+lb40YKiYHi0fjpWRtJpR/dgkaiBlSD0plRyB6lLOh1XIfmMcSeBOqDE7y9m8xZMrXYfyQ==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.1.tgz", + "integrity": "sha512-e91Jpu93X3t3mVdQwF3ZDjSFMFIfzSc+I76G4EX8nl9RYXgqcjframoL05VTjcD2YCsI18RIHAWVCBoCXVZnrw==", "dependencies": { - "@algolia/cache-common": "4.17.0" + "@algolia/cache-common": "4.17.1" } }, "node_modules/@algolia/cache-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.0.tgz", - "integrity": "sha512-g8mXzkrcUBIPZaulAuqE7xyHhLAYAcF2xSch7d9dABheybaU3U91LjBX6eJTEB7XVhEsgK4Smi27vWtAJRhIKQ==" + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.1.tgz", + "integrity": "sha512-fvi1WT8aSiGAKrcTw8Qg3RYgcwW8GZMHcqEm4AyDBEy72JZlFBSY80cTQ75MslINjCHXLDT+9EN8AGI9WVY7uA==" }, "node_modules/@algolia/cache-in-memory": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.0.tgz", - "integrity": "sha512-PT32ciC/xI8z919d0oknWVu3kMfTlhQn3MKxDln3pkn+yA7F7xrxSALysxquv+MhFfNAcrtQ/oVvQVBAQSHtdw==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.1.tgz", + "integrity": "sha512-NbBt6eBWlsXc5geSpfPRC5dkIB/0Ptthw8r0yM5Z7D3sPlYdnTZSO9y9XWXIptRMwmZe4cM8iBMN8y0tzbcBkA==", "dependencies": { - "@algolia/cache-common": "4.17.0" + "@algolia/cache-common": "4.17.1" } }, "node_modules/@algolia/client-account": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.0.tgz", - "integrity": "sha512-sSEHx9GA6m7wrlsSMNBGfyzlIfDT2fkz2u7jqfCCd6JEEwmxt8emGmxAU/0qBfbhRSuGvzojoLJlr83BSZAKjA==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.1.tgz", + "integrity": "sha512-3rL/6ofJvyL+q8TiWM3qoM9tig+SY4gB1Vbsj+UeJPnJm8Khm+7OS+r+mFraqR6pTehYqN8yGYoE7x4diEn4aA==", "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.17.1", + "@algolia/client-search": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "node_modules/@algolia/client-analytics": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.0.tgz", - "integrity": "sha512-84ooP8QA3mQ958hQ9wozk7hFUbAO+81CX1CjAuerxBqjKIInh1fOhXKTaku05O/GHBvcfExpPLIQuSuLYziBXQ==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.1.tgz", + "integrity": "sha512-Bepr2w249vODqeBtM7i++tPmUsQ9B81aupUGbDWmjA/FX+jzQqOdhW8w1CFO5kWViNKTbz2WBIJ9U3x8hOa4bA==", "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.17.1", + "@algolia/client-search": "4.17.1", + "@algolia/requester-common": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "node_modules/@algolia/client-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.0.tgz", - "integrity": "sha512-jHMks0ZFicf8nRDn6ma8DNNsdwGgP/NKiAAL9z6rS7CymJ7L0+QqTJl3rYxRW7TmBhsUH40wqzmrG6aMIN/DrQ==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.1.tgz", + "integrity": "sha512-+r7kg4EgbFnGsDnoGSVNtXZO8xvZ0vzf1WAOV7sqV9PMf1bp6cpJP/3IuPrSk4t5w2KVl+pC8jfTM7HcFlfBEQ==", "dependencies": { - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/requester-common": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "node_modules/@algolia/client-personalization": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.0.tgz", - "integrity": "sha512-RMzN4dZLIta1YuwT7QC9o+OeGz2cU6eTOlGNE/6RcUBLOU3l9tkCOdln5dPE2jp8GZXPl2yk54b2nSs1+pAjqw==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.1.tgz", + "integrity": "sha512-gJku9DG/THJpfsSlG/az0a3QIn+VVff9kKh8PG8+7ZfxOHS+C+Y5YSeZVsC+c2cfoKLPo3CuHIiJ/p86erR3bA==", "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.17.1", + "@algolia/requester-common": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "node_modules/@algolia/client-search": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.0.tgz", - "integrity": "sha512-x4P2wKrrRIXszT8gb7eWsMHNNHAJs0wE7/uqbufm4tZenAp+hwU/hq5KVsY50v+PfwM0LcDwwn/1DroujsTFoA==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.1.tgz", + "integrity": "sha512-Q5YfT5gVkx60PZDQBqp/zH9aUbBdC7HVvxupiHUgnCKqRQsRZjOhLest7AI6FahepuZLBZS62COrO7v+JvKY7w==", "dependencies": { - "@algolia/client-common": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.17.1", + "@algolia/requester-common": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "node_modules/@algolia/events": { @@ -127,47 +127,47 @@ "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" }, "node_modules/@algolia/logger-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.0.tgz", - "integrity": "sha512-DGuoZqpTmIKJFDeyAJ7M8E/LOenIjWiOsg1XJ1OqAU/eofp49JfqXxbfgctlVZVmDABIyOz8LqEoJ6ZP4DTyvw==" + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.1.tgz", + "integrity": "sha512-Us28Ot+fLEmX9M96sa65VZ8EyEEzhYPxfhV9aQyKDjfXbUdJlJxKt6wZpoEg9RAPSdO8IjK9nmuW2P8au3rRsg==" }, "node_modules/@algolia/logger-console": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.0.tgz", - "integrity": "sha512-zMPvugQV/gbXUvWBCzihw6m7oxIKp48w37QBIUu/XqQQfxhjoOE9xyfJr1KldUt5FrYOKZJVsJaEjTsu+bIgQg==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.1.tgz", + "integrity": "sha512-iKGQTpOjHiE64W3JIOu6dmDvn+AfYIElI9jf/Nt6umRPmP/JI9rK+OHUoW4pKrBtdG0DPd62ppeNXzSnLxY6/g==", "dependencies": { - "@algolia/logger-common": "4.17.0" + "@algolia/logger-common": "4.17.1" } }, "node_modules/@algolia/requester-browser-xhr": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.0.tgz", - "integrity": "sha512-aSOX/smauyTkP21Pf52pJ1O2LmNFJ5iHRIzEeTh0mwBeADO4GdG94cAWDILFA9rNblq/nK3EDh3+UyHHjplZ1A==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.1.tgz", + "integrity": "sha512-W5mGfGDsyfVR+r4pUFrYLGBEM18gs38+GNt5PE5uPULy4uVTSnnVSkJkWeRkmLBk9zEZ/Nld8m4zavK6dtEuYg==", "dependencies": { - "@algolia/requester-common": "4.17.0" + "@algolia/requester-common": "4.17.1" } }, "node_modules/@algolia/requester-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.0.tgz", - "integrity": "sha512-XJjmWFEUlHu0ijvcHBoixuXfEoiRUdyzQM6YwTuB8usJNIgShua8ouFlRWF8iCeag0vZZiUm4S2WCVBPkdxFgg==" + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.1.tgz", + "integrity": "sha512-HggXdjvVFQR0I5l7hM5WdHgQ1tqcRWeyXZz8apQ7zPWZhirmY2E9D6LVhDh/UnWQNEm7nBtM+eMFONJ3bZccIQ==" }, "node_modules/@algolia/requester-node-http": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.0.tgz", - "integrity": "sha512-bpb/wDA1aC6WxxM8v7TsFspB7yBN3nqCGs2H1OADolQR/hiAIjAxusbuMxVbRFOdaUvAIqioIIkWvZdpYNIn8w==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.1.tgz", + "integrity": "sha512-NzFWecXT6d0PPsQY9L+/qoK2deF74OLcpvqCH+Vh3mh+QzPsFafcBExdguAjZsAWDn1R6JEeFW7/fo/p0SE57w==", "dependencies": { - "@algolia/requester-common": "4.17.0" + "@algolia/requester-common": "4.17.1" } }, "node_modules/@algolia/transporter": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.0.tgz", - "integrity": "sha512-6xL6H6fe+Fi0AEP3ziSgC+G04RK37iRb4uUUqVAH9WPYFI8g+LYFq6iv5HS8Cbuc5TTut+Bwj6G+dh/asdb9uA==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.1.tgz", + "integrity": "sha512-ZM+qhX47Vh46mWH8/U9ihvy98HdTYpYQDSlqBD7IbiUbbyoCMke+qmdSX2MGhR2FCcXBSxejsJKKVAfbpaLVgg==", "dependencies": { - "@algolia/cache-common": "4.17.0", - "@algolia/logger-common": "4.17.0", - "@algolia/requester-common": "4.17.0" + "@algolia/cache-common": "4.17.1", + "@algolia/logger-common": "4.17.1", + "@algolia/requester-common": "4.17.1" } }, "node_modules/@ampproject/remapping": { @@ -1938,18 +1938,18 @@ } }, "node_modules/@docsearch/css": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.3.3.tgz", - "integrity": "sha512-6SCwI7P8ao+se1TUsdZ7B4XzL+gqeQZnBc+2EONZlcVa0dVrk0NjETxozFKgMv0eEGH8QzP1fkN+A1rH61l4eg==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.4.0.tgz", + "integrity": "sha512-Hg8Xfma+rFwRi6Y/pfei4FJoQ1hdVURmmNs/XPoMTCPAImU+d5yxj+M+qdLtNjWRpfWziU4dQcqY94xgFBn2dg==" }, "node_modules/@docsearch/react": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.3.3.tgz", - "integrity": "sha512-pLa0cxnl+G0FuIDuYlW+EBK6Rw2jwLw9B1RHIeS4N4s2VhsfJ/wzeCi3CWcs5yVfxLd5ZK50t//TMA5e79YT7Q==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.4.0.tgz", + "integrity": "sha512-ufrp5879XYGojgS30ZAp8H4qIMbahRHB9M85VDBP36Xgz5QjYM54i1URKj5e219F7gqTtOivfztFTij6itc0MQ==", "dependencies": { - "@algolia/autocomplete-core": "1.7.4", - "@algolia/autocomplete-preset-algolia": "1.7.4", - "@docsearch/css": "3.3.3", + "@algolia/autocomplete-core": "1.8.2", + "@algolia/autocomplete-preset-algolia": "1.8.2", + "@docsearch/css": "3.4.0", "algoliasearch": "^4.0.0" }, "peerDependencies": { @@ -1970,9 +1970,9 @@ } }, "node_modules/@docusaurus/core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.4.0.tgz", - "integrity": "sha512-J55/WEoIpRcLf3afO5POHPguVZosKmJEQWKBL+K7TAnfuE7i+Y0NPLlkKtnWCehagGsgTqClfQEexH/UT4kELA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.4.1.tgz", + "integrity": "sha512-SNsY7PshK3Ri7vtsLXVeAJGS50nJN3RgF836zkyUfAD01Fq+sAk5EwWgLw+nnm5KVNGDu7PRR2kRGDsWvqpo0g==", "dependencies": { "@babel/core": "^7.18.6", "@babel/generator": "^7.18.7", @@ -1984,13 +1984,13 @@ "@babel/runtime": "^7.18.6", "@babel/runtime-corejs3": "^7.18.6", "@babel/traverse": "^7.18.8", - "@docusaurus/cssnano-preset": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", + "@docusaurus/cssnano-preset": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "@slorber/static-site-generator-webpack-plugin": "^4.0.7", "@svgr/webpack": "^6.2.1", "autoprefixer": "^10.4.7", @@ -2058,9 +2058,9 @@ } }, "node_modules/@docusaurus/cssnano-preset": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.4.0.tgz", - "integrity": "sha512-RmdiA3IpsLgZGXRzqnmTbGv43W4OD44PCo+6Q/aYjEM2V57vKCVqNzuafE94jv0z/PjHoXUrjr69SaRymBKYYw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.4.1.tgz", + "integrity": "sha512-ka+vqXwtcW1NbXxWsh6yA1Ckii1klY9E53cJ4O9J09nkMBgrNX3iEFED1fWdv8wf4mJjvGi5RLZ2p9hJNjsLyQ==", "dependencies": { "cssnano-preset-advanced": "^5.3.8", "postcss": "^8.4.14", @@ -2072,9 +2072,9 @@ } }, "node_modules/@docusaurus/logger": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.4.0.tgz", - "integrity": "sha512-T8+qR4APN+MjcC9yL2Es+xPJ2923S9hpzDmMtdsOcUGLqpCGBbU1vp3AAqDwXtVgFkq+NsEk7sHdVsfLWR/AXw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.4.1.tgz", + "integrity": "sha512-5h5ysIIWYIDHyTVd8BjheZmQZmEgWDR54aQ1BX9pjFfpyzFo5puKXKYrYJXbjEHGyVhEzmB9UXwbxGfaZhOjcg==", "dependencies": { "chalk": "^4.1.2", "tslib": "^2.4.0" @@ -2084,14 +2084,14 @@ } }, "node_modules/@docusaurus/mdx-loader": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.4.0.tgz", - "integrity": "sha512-GWoH4izZKOmFoC+gbI2/y8deH/xKLvzz/T5BsEexBye8EHQlwsA7FMrVa48N063bJBH4FUOiRRXxk5rq9cC36g==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.4.1.tgz", + "integrity": "sha512-4KhUhEavteIAmbBj7LVFnrVYDiU51H5YWW1zY6SmBSte/YLhDutztLTBE0PQl1Grux1jzUJeaSvAzHpTn6JJDQ==", "dependencies": { "@babel/parser": "^7.18.8", "@babel/traverse": "^7.18.8", - "@docusaurus/logger": "2.4.0", - "@docusaurus/utils": "2.4.0", + "@docusaurus/logger": "2.4.1", + "@docusaurus/utils": "2.4.1", "@mdx-js/mdx": "^1.6.22", "escape-html": "^1.0.3", "file-loader": "^6.2.0", @@ -2115,12 +2115,12 @@ } }, "node_modules/@docusaurus/module-type-aliases": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.0.tgz", - "integrity": "sha512-YEQO2D3UXs72qCn8Cr+RlycSQXVGN9iEUyuHwTuK4/uL/HFomB2FHSU0vSDM23oLd+X/KibQ3Ez6nGjQLqXcHg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.1.tgz", + "integrity": "sha512-gLBuIFM8Dp2XOCWffUDSjtxY7jQgKvYujt7Mx5s4FCTfoL5dN1EVbnrn+O2Wvh8b0a77D57qoIDY7ghgmatR1A==", "dependencies": { "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "2.4.0", + "@docusaurus/types": "2.4.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2134,17 +2134,17 @@ } }, "node_modules/@docusaurus/plugin-content-blog": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.4.0.tgz", - "integrity": "sha512-YwkAkVUxtxoBAIj/MCb4ohN0SCtHBs4AS75jMhPpf67qf3j+U/4n33cELq7567hwyZ6fMz2GPJcVmctzlGGThQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.4.1.tgz", + "integrity": "sha512-E2i7Knz5YIbE1XELI6RlTnZnGgS52cUO4BlCiCUCvQHbR+s1xeIWz4C6BtaVnlug0Ccz7nFSksfwDpVlkujg5Q==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "cheerio": "^1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^10.1.0", @@ -2164,17 +2164,17 @@ } }, "node_modules/@docusaurus/plugin-content-docs": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.4.0.tgz", - "integrity": "sha512-ic/Z/ZN5Rk/RQo+Io6rUGpToOtNbtPloMR2JcGwC1xT2riMu6zzfSwmBi9tHJgdXH6CB5jG+0dOZZO8QS5tmDg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.4.1.tgz", + "integrity": "sha512-Lo7lSIcpswa2Kv4HEeUcGYqaasMUQNpjTXpV0N8G6jXgZaQurqp7E8NGYeGbDXnb48czmHWbzDL4S3+BbK0VzA==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/module-type-aliases": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "@types/react-router-config": "^5.0.6", "combine-promises": "^1.1.0", "fs-extra": "^10.1.0", @@ -2194,15 +2194,15 @@ } }, "node_modules/@docusaurus/plugin-content-pages": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.4.0.tgz", - "integrity": "sha512-Pk2pOeOxk8MeU3mrTU0XLIgP9NZixbdcJmJ7RUFrZp1Aj42nd0RhIT14BGvXXyqb8yTQlk4DmYGAzqOfBsFyGw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.4.1.tgz", + "integrity": "sha512-/UjuH/76KLaUlL+o1OvyORynv6FURzjurSjvn2lbWTFc4tpYY2qLYTlKpTCBVPhlLUQsfyFnshEJDLmPneq2oA==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "fs-extra": "^10.1.0", "tslib": "^2.4.0", "webpack": "^5.73.0" @@ -2216,13 +2216,13 @@ } }, "node_modules/@docusaurus/plugin-debug": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.4.0.tgz", - "integrity": "sha512-KC56DdYjYT7Txyux71vXHXGYZuP6yYtqwClvYpjKreWIHWus5Zt6VNi23rMZv3/QKhOCrN64zplUbdfQMvddBQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.4.1.tgz", + "integrity": "sha512-7Yu9UPzRShlrH/G8btOpR0e6INFZr0EegWplMjOqelIwAcx3PKyR8mgPTxGTxcqiYj6hxSCRN0D8R7YrzImwNA==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", "fs-extra": "^10.1.0", "react-json-view": "^1.21.3", "tslib": "^2.4.0" @@ -2236,13 +2236,13 @@ } }, "node_modules/@docusaurus/plugin-google-analytics": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.4.0.tgz", - "integrity": "sha512-uGUzX67DOAIglygdNrmMOvEp8qG03X20jMWadeqVQktS6nADvozpSLGx4J0xbkblhJkUzN21WiilsP9iVP+zkw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.4.1.tgz", + "integrity": "sha512-dyZJdJiCoL+rcfnm0RPkLt/o732HvLiEwmtoNzOoz9MSZz117UH2J6U2vUDtzUzwtFLIf32KkeyzisbwUCgcaQ==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "tslib": "^2.4.0" }, "engines": { @@ -2254,13 +2254,13 @@ } }, "node_modules/@docusaurus/plugin-google-gtag": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.4.0.tgz", - "integrity": "sha512-adj/70DANaQs2+TF/nRdMezDXFAV/O/pjAbUgmKBlyOTq5qoMe0Tk4muvQIwWUmiUQxFJe+sKlZGM771ownyOg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.4.1.tgz", + "integrity": "sha512-mKIefK+2kGTQBYvloNEKtDmnRD7bxHLsBcxgnbt4oZwzi2nxCGjPX6+9SQO2KCN5HZbNrYmGo5GJfMgoRvy6uA==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "tslib": "^2.4.0" }, "engines": { @@ -2272,13 +2272,13 @@ } }, "node_modules/@docusaurus/plugin-google-tag-manager": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-2.4.0.tgz", - "integrity": "sha512-E66uGcYs4l7yitmp/8kMEVQftFPwV9iC62ORh47Veqzs6ExwnhzBkJmwDnwIysHBF1vlxnzET0Fl2LfL5fRR3A==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-2.4.1.tgz", + "integrity": "sha512-Zg4Ii9CMOLfpeV2nG74lVTWNtisFaH9QNtEw48R5QE1KIwDBdTVaiSA18G1EujZjrzJJzXN79VhINSbOJO/r3g==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "tslib": "^2.4.0" }, "engines": { @@ -2290,16 +2290,16 @@ } }, "node_modules/@docusaurus/plugin-sitemap": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.0.tgz", - "integrity": "sha512-pZxh+ygfnI657sN8a/FkYVIAmVv0CGk71QMKqJBOfMmDHNN1FeDeFkBjWP49ejBqpqAhjufkv5UWq3UOu2soCw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.1.tgz", + "integrity": "sha512-lZx+ijt/+atQ3FVE8FOHV/+X3kuok688OydDXrqKRJyXBJZKgGjA2Qa8RjQ4f27V2woaXhtnyrdPop/+OjVMRg==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "fs-extra": "^10.1.0", "sitemap": "^7.1.1", "tslib": "^2.4.0" @@ -2313,23 +2313,23 @@ } }, "node_modules/@docusaurus/preset-classic": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.4.0.tgz", - "integrity": "sha512-/5z5o/9bc6+P5ool2y01PbJhoGddEGsC0ej1MF6mCoazk8A+kW4feoUd68l7Bnv01rCnG3xy7kHUQP97Y0grUA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.4.1.tgz", + "integrity": "sha512-P4//+I4zDqQJ+UDgoFrjIFaQ1MeS9UD1cvxVQaI6O7iBmiHQm0MGROP1TbE7HlxlDPXFJjZUK3x3cAoK63smGQ==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/plugin-content-blog": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/plugin-content-pages": "2.4.0", - "@docusaurus/plugin-debug": "2.4.0", - "@docusaurus/plugin-google-analytics": "2.4.0", - "@docusaurus/plugin-google-gtag": "2.4.0", - "@docusaurus/plugin-google-tag-manager": "2.4.0", - "@docusaurus/plugin-sitemap": "2.4.0", - "@docusaurus/theme-classic": "2.4.0", - "@docusaurus/theme-common": "2.4.0", - "@docusaurus/theme-search-algolia": "2.4.0", - "@docusaurus/types": "2.4.0" + "@docusaurus/core": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/plugin-debug": "2.4.1", + "@docusaurus/plugin-google-analytics": "2.4.1", + "@docusaurus/plugin-google-gtag": "2.4.1", + "@docusaurus/plugin-google-tag-manager": "2.4.1", + "@docusaurus/plugin-sitemap": "2.4.1", + "@docusaurus/theme-classic": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-search-algolia": "2.4.1", + "@docusaurus/types": "2.4.1" }, "engines": { "node": ">=16.14" @@ -2352,22 +2352,22 @@ } }, "node_modules/@docusaurus/theme-classic": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.4.0.tgz", - "integrity": "sha512-GMDX5WU6Z0OC65eQFgl3iNNEbI9IMJz9f6KnOyuMxNUR6q0qVLsKCNopFUDfFNJ55UU50o7P7o21yVhkwpfJ9w==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.4.1.tgz", + "integrity": "sha512-Rz0wKUa+LTW1PLXmwnf8mn85EBzaGSt6qamqtmnh9Hflkc+EqiYMhtUJeLdV+wsgYq4aG0ANc+bpUDpsUhdnwg==", "dependencies": { - "@docusaurus/core": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/module-type-aliases": "2.4.0", - "@docusaurus/plugin-content-blog": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/plugin-content-pages": "2.4.0", - "@docusaurus/theme-common": "2.4.0", - "@docusaurus/theme-translations": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", "copy-text-to-clipboard": "^3.0.1", @@ -2391,17 +2391,17 @@ } }, "node_modules/@docusaurus/theme-common": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.4.0.tgz", - "integrity": "sha512-IkG/l5f/FLY6cBIxtPmFnxpuPzc5TupuqlOx+XDN+035MdQcAh8wHXXZJAkTeYDeZ3anIUSUIvWa7/nRKoQEfg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.4.1.tgz", + "integrity": "sha512-G7Zau1W5rQTaFFB3x3soQoZpkgMbl/SYNG8PfMFIjKa3M3q8n0m/GRf5/H/e5BqOvt8c+ZWIXGCiz+kUCSHovA==", "dependencies": { - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/module-type-aliases": "2.4.0", - "@docusaurus/plugin-content-blog": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/plugin-content-pages": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -2421,18 +2421,18 @@ } }, "node_modules/@docusaurus/theme-search-algolia": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.4.0.tgz", - "integrity": "sha512-pPCJSCL1Qt4pu/Z0uxBAuke0yEBbxh0s4fOvimna7TEcBLPq0x06/K78AaABXrTVQM6S0vdocFl9EoNgU17hqA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.4.1.tgz", + "integrity": "sha512-6BcqW2lnLhZCXuMAvPRezFs1DpmEKzXFKlYjruuas+Xy3AQeFzDJKTJFIm49N77WFCTyxff8d3E4Q9pi/+5McQ==", "dependencies": { "@docsearch/react": "^3.1.1", - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/theme-common": "2.4.0", - "@docusaurus/theme-translations": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "algoliasearch": "^4.13.1", "algoliasearch-helper": "^3.10.0", "clsx": "^1.2.1", @@ -2451,9 +2451,9 @@ } }, "node_modules/@docusaurus/theme-translations": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.4.0.tgz", - "integrity": "sha512-kEoITnPXzDPUMBHk3+fzEzbopxLD3fR5sDoayNH0vXkpUukA88/aDL1bqkhxWZHA3LOfJ3f0vJbOwmnXW5v85Q==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.4.1.tgz", + "integrity": "sha512-T1RAGP+f86CA1kfE8ejZ3T3pUU3XcyvrGMfC/zxCtc2BsnoexuNI9Vk2CmuKCb+Tacvhxjv5unhxXce0+NKyvA==", "dependencies": { "fs-extra": "^10.1.0", "tslib": "^2.4.0" @@ -2463,9 +2463,9 @@ } }, "node_modules/@docusaurus/types": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.4.0.tgz", - "integrity": "sha512-xaBXr+KIPDkIaef06c+i2HeTqVNixB7yFut5fBXPGI2f1rrmEV2vLMznNGsFwvZ5XmA3Quuefd4OGRkdo97Dhw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.4.1.tgz", + "integrity": "sha512-0R+cbhpMkhbRXX138UOc/2XZFF8hiZa6ooZAEEJFp5scytzCw4tC1gChMFXrpa3d2tYE6AX8IrOEpSonLmfQuQ==", "dependencies": { "@types/history": "^4.7.11", "@types/react": "*", @@ -2482,11 +2482,11 @@ } }, "node_modules/@docusaurus/utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.4.0.tgz", - "integrity": "sha512-89hLYkvtRX92j+C+ERYTuSUK6nF9bGM32QThcHPg2EDDHVw6FzYQXmX6/p+pU5SDyyx5nBlE4qXR92RxCAOqfg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.4.1.tgz", + "integrity": "sha512-1lvEZdAQhKNht9aPXPoh69eeKnV0/62ROhQeFKKxmzd0zkcuE/Oc5Gpnt00y/f5bIsmOsYMY7Pqfm/5rteT5GA==", "dependencies": { - "@docusaurus/logger": "2.4.0", + "@docusaurus/logger": "2.4.1", "@svgr/webpack": "^6.2.1", "escape-string-regexp": "^4.0.0", "file-loader": "^6.2.0", @@ -2516,9 +2516,9 @@ } }, "node_modules/@docusaurus/utils-common": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.4.0.tgz", - "integrity": "sha512-zIMf10xuKxddYfLg5cS19x44zud/E9I7lj3+0bv8UIs0aahpErfNrGhijEfJpAfikhQ8tL3m35nH3hJ3sOG82A==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.4.1.tgz", + "integrity": "sha512-bCVGdZU+z/qVcIiEQdyx0K13OC5mYwxhSuDUR95oFbKVuXYRrTVrwZIqQljuo1fyJvFTKHiL9L9skQOPokuFNQ==", "dependencies": { "tslib": "^2.4.0" }, @@ -2535,12 +2535,12 @@ } }, "node_modules/@docusaurus/utils-validation": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.4.0.tgz", - "integrity": "sha512-IrBsBbbAp6y7mZdJx4S4pIA7dUyWSA0GNosPk6ZJ0fX3uYIEQgcQSGIgTeSC+8xPEx3c16o03en1jSDpgQgz/w==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.4.1.tgz", + "integrity": "sha512-unII3hlJlDwZ3w8U+pMO3Lx3RhI4YEbY3YNsQj4yzrkZzlpqZOLuAiZK2JyULnD+TKbceKU0WyWkQXtYbLNDFA==", "dependencies": { - "@docusaurus/logger": "2.4.0", - "@docusaurus/utils": "2.4.0", + "@docusaurus/logger": "2.4.1", + "@docusaurus/utils": "2.4.1", "joi": "^17.6.0", "js-yaml": "^4.1.0", "tslib": "^2.4.0" @@ -3257,9 +3257,9 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, "node_modules/@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", + "integrity": "sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==", "dependencies": { "@types/unist": "*" } @@ -3667,30 +3667,30 @@ } }, "node_modules/algoliasearch": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.0.tgz", - "integrity": "sha512-JMRh2Mw6sEnVMiz6+APsi7lx9a2jiDFF+WUtANaUVCv6uSU9UOLdo5h9K3pdP6frRRybaM2fX8b1u0nqICS9aA==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.1.tgz", + "integrity": "sha512-4GDQ1RhP2qUR3x8PevFRbEdqZqIARNViZYjgTJmA1T7wRNtFA3W4Aqc/RsODqa1J8IO/QDla5x4tWuUS8NV8wA==", "dependencies": { - "@algolia/cache-browser-local-storage": "4.17.0", - "@algolia/cache-common": "4.17.0", - "@algolia/cache-in-memory": "4.17.0", - "@algolia/client-account": "4.17.0", - "@algolia/client-analytics": "4.17.0", - "@algolia/client-common": "4.17.0", - "@algolia/client-personalization": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/logger-common": "4.17.0", - "@algolia/logger-console": "4.17.0", - "@algolia/requester-browser-xhr": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/requester-node-http": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/cache-browser-local-storage": "4.17.1", + "@algolia/cache-common": "4.17.1", + "@algolia/cache-in-memory": "4.17.1", + "@algolia/client-account": "4.17.1", + "@algolia/client-analytics": "4.17.1", + "@algolia/client-common": "4.17.1", + "@algolia/client-personalization": "4.17.1", + "@algolia/client-search": "4.17.1", + "@algolia/logger-common": "4.17.1", + "@algolia/logger-console": "4.17.1", + "@algolia/requester-browser-xhr": "4.17.1", + "@algolia/requester-common": "4.17.1", + "@algolia/requester-node-http": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "node_modules/algoliasearch-helper": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.12.0.tgz", - "integrity": "sha512-/j1U3PEwdan0n6P/QqSnSpNSLC5+cEMvyljd5CnmNmUjDlGrys+vFEOwjVEnqELIiAGMHEA/Nl3CiKVFBUYqyQ==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.13.0.tgz", + "integrity": "sha512-kV3c1jMQCvkARtGsSDvAwuht4PAMSsQILqPiH4WFiARoa3jXJ/r1TQoBWAjWyWF48rsNYCv7kzxgB4LTxrvvuw==", "dependencies": { "@algolia/events": "^4.0.1" }, @@ -4881,11 +4881,11 @@ } }, "node_modules/cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.6.tgz", + "integrity": "sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==", "dependencies": { - "node-fetch": "2.6.7" + "node-fetch": "^2.6.11" } }, "node_modules/cross-spawn": { @@ -5447,13 +5447,13 @@ } }, "node_modules/domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "dependencies": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" + "domhandler": "^5.0.3" }, "funding": { "url": "https://github.com/fb55/domutils?sponsor=1" @@ -7968,9 +7968,9 @@ } }, "node_modules/node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "dependencies": { "whatwg-url": "^5.0.0" }, @@ -8983,9 +8983,9 @@ } }, "node_modules/postcss-sort-media-queries": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.3.0.tgz", - "integrity": "sha512-jAl8gJM2DvuIJiI9sL1CuiHtKM4s5aEIomkU8G3LFvbP+p8i7Sz8VV63uieTgoewGqKbi+hxBTiOKJlB35upCg==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz", + "integrity": "sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw==", "dependencies": { "sort-css-media-queries": "2.1.0" }, @@ -11126,7 +11126,8 @@ "node_modules/trim": { "version": "0.0.1", "resolved": "https://registry.npmjs.org/trim/-/trim-0.0.1.tgz", - "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==" + "integrity": "sha512-YzQV+TZg4AxpKxaTHK3c3D+kRDCGVEE7LemdlQZoQXn0iennk10RsIoY6ikzAqJTc9Xjl9C1/waHom/J86ziAQ==", + "deprecated": "Use String.prototype.trim() instead" }, "node_modules/trim-trailing-lines": { "version": "1.1.4", @@ -12338,95 +12339,95 @@ }, "dependencies": { "@algolia/autocomplete-core": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.7.4.tgz", - "integrity": "sha512-daoLpQ3ps/VTMRZDEBfU8ixXd+amZcNJ4QSP3IERGyzqnL5Ch8uSRFt/4G8pUvW9c3o6GA4vtVv4I4lmnkdXyg==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-core/-/autocomplete-core-1.8.2.tgz", + "integrity": "sha512-mTeshsyFhAqw/ebqNsQpMtbnjr+qVOSKXArEj4K0d7sqc8It1XD0gkASwecm9mF/jlOQ4Z9RNg1HbdA8JPdRwQ==", "requires": { - "@algolia/autocomplete-shared": "1.7.4" + "@algolia/autocomplete-shared": "1.8.2" } }, "@algolia/autocomplete-preset-algolia": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.7.4.tgz", - "integrity": "sha512-s37hrvLEIfcmKY8VU9LsAXgm2yfmkdHT3DnA3SgHaY93yjZ2qL57wzb5QweVkYuEBZkT2PIREvRoLXC2sxTbpQ==", + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-preset-algolia/-/autocomplete-preset-algolia-1.8.2.tgz", + "integrity": "sha512-J0oTx4me6ZM9kIKPuL3lyU3aB8DEvpVvR6xWmHVROx5rOYJGQcZsdG4ozxwcOyiiu3qxMkIbzntnV1S1VWD8yA==", "requires": { - "@algolia/autocomplete-shared": "1.7.4" + "@algolia/autocomplete-shared": "1.8.2" } }, "@algolia/autocomplete-shared": { - "version": "1.7.4", - "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.7.4.tgz", - "integrity": "sha512-2VGCk7I9tA9Ge73Km99+Qg87w0wzW4tgUruvWAn/gfey1ZXgmxZtyIRBebk35R1O8TbK77wujVtCnpsGpRy1kg==" + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/@algolia/autocomplete-shared/-/autocomplete-shared-1.8.2.tgz", + "integrity": "sha512-b6Z/X4MczChMcfhk6kfRmBzPgjoPzuS9KGR4AFsiLulLNRAAqhP+xZTKtMnZGhLuc61I20d5WqlId02AZvcO6g==" }, "@algolia/cache-browser-local-storage": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.0.tgz", - "integrity": "sha512-myRSRZDIMYB8uCkO+lb40YKiYHi0fjpWRtJpR/dgkaiBlSD0plRyB6lLOh1XIfmMcSeBOqDE7y9m8xZMrXYfyQ==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-browser-local-storage/-/cache-browser-local-storage-4.17.1.tgz", + "integrity": "sha512-e91Jpu93X3t3mVdQwF3ZDjSFMFIfzSc+I76G4EX8nl9RYXgqcjframoL05VTjcD2YCsI18RIHAWVCBoCXVZnrw==", "requires": { - "@algolia/cache-common": "4.17.0" + "@algolia/cache-common": "4.17.1" } }, "@algolia/cache-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.0.tgz", - "integrity": "sha512-g8mXzkrcUBIPZaulAuqE7xyHhLAYAcF2xSch7d9dABheybaU3U91LjBX6eJTEB7XVhEsgK4Smi27vWtAJRhIKQ==" + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-common/-/cache-common-4.17.1.tgz", + "integrity": "sha512-fvi1WT8aSiGAKrcTw8Qg3RYgcwW8GZMHcqEm4AyDBEy72JZlFBSY80cTQ75MslINjCHXLDT+9EN8AGI9WVY7uA==" }, "@algolia/cache-in-memory": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.0.tgz", - "integrity": "sha512-PT32ciC/xI8z919d0oknWVu3kMfTlhQn3MKxDln3pkn+yA7F7xrxSALysxquv+MhFfNAcrtQ/oVvQVBAQSHtdw==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/cache-in-memory/-/cache-in-memory-4.17.1.tgz", + "integrity": "sha512-NbBt6eBWlsXc5geSpfPRC5dkIB/0Ptthw8r0yM5Z7D3sPlYdnTZSO9y9XWXIptRMwmZe4cM8iBMN8y0tzbcBkA==", "requires": { - "@algolia/cache-common": "4.17.0" + "@algolia/cache-common": "4.17.1" } }, "@algolia/client-account": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.0.tgz", - "integrity": "sha512-sSEHx9GA6m7wrlsSMNBGfyzlIfDT2fkz2u7jqfCCd6JEEwmxt8emGmxAU/0qBfbhRSuGvzojoLJlr83BSZAKjA==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-account/-/client-account-4.17.1.tgz", + "integrity": "sha512-3rL/6ofJvyL+q8TiWM3qoM9tig+SY4gB1Vbsj+UeJPnJm8Khm+7OS+r+mFraqR6pTehYqN8yGYoE7x4diEn4aA==", "requires": { - "@algolia/client-common": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.17.1", + "@algolia/client-search": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "@algolia/client-analytics": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.0.tgz", - "integrity": "sha512-84ooP8QA3mQ958hQ9wozk7hFUbAO+81CX1CjAuerxBqjKIInh1fOhXKTaku05O/GHBvcfExpPLIQuSuLYziBXQ==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-4.17.1.tgz", + "integrity": "sha512-Bepr2w249vODqeBtM7i++tPmUsQ9B81aupUGbDWmjA/FX+jzQqOdhW8w1CFO5kWViNKTbz2WBIJ9U3x8hOa4bA==", "requires": { - "@algolia/client-common": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.17.1", + "@algolia/client-search": "4.17.1", + "@algolia/requester-common": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "@algolia/client-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.0.tgz", - "integrity": "sha512-jHMks0ZFicf8nRDn6ma8DNNsdwGgP/NKiAAL9z6rS7CymJ7L0+QqTJl3rYxRW7TmBhsUH40wqzmrG6aMIN/DrQ==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-4.17.1.tgz", + "integrity": "sha512-+r7kg4EgbFnGsDnoGSVNtXZO8xvZ0vzf1WAOV7sqV9PMf1bp6cpJP/3IuPrSk4t5w2KVl+pC8jfTM7HcFlfBEQ==", "requires": { - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/requester-common": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "@algolia/client-personalization": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.0.tgz", - "integrity": "sha512-RMzN4dZLIta1YuwT7QC9o+OeGz2cU6eTOlGNE/6RcUBLOU3l9tkCOdln5dPE2jp8GZXPl2yk54b2nSs1+pAjqw==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-4.17.1.tgz", + "integrity": "sha512-gJku9DG/THJpfsSlG/az0a3QIn+VVff9kKh8PG8+7ZfxOHS+C+Y5YSeZVsC+c2cfoKLPo3CuHIiJ/p86erR3bA==", "requires": { - "@algolia/client-common": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.17.1", + "@algolia/requester-common": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "@algolia/client-search": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.0.tgz", - "integrity": "sha512-x4P2wKrrRIXszT8gb7eWsMHNNHAJs0wE7/uqbufm4tZenAp+hwU/hq5KVsY50v+PfwM0LcDwwn/1DroujsTFoA==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-4.17.1.tgz", + "integrity": "sha512-Q5YfT5gVkx60PZDQBqp/zH9aUbBdC7HVvxupiHUgnCKqRQsRZjOhLest7AI6FahepuZLBZS62COrO7v+JvKY7w==", "requires": { - "@algolia/client-common": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/client-common": "4.17.1", + "@algolia/requester-common": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "@algolia/events": { @@ -12435,47 +12436,47 @@ "integrity": "sha512-FQzvOCgoFXAbf5Y6mYozw2aj5KCJoA3m4heImceldzPSMbdyS4atVjJzXKMsfX3wnZTFYwkkt8/z8UesLHlSBQ==" }, "@algolia/logger-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.0.tgz", - "integrity": "sha512-DGuoZqpTmIKJFDeyAJ7M8E/LOenIjWiOsg1XJ1OqAU/eofp49JfqXxbfgctlVZVmDABIyOz8LqEoJ6ZP4DTyvw==" + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-common/-/logger-common-4.17.1.tgz", + "integrity": "sha512-Us28Ot+fLEmX9M96sa65VZ8EyEEzhYPxfhV9aQyKDjfXbUdJlJxKt6wZpoEg9RAPSdO8IjK9nmuW2P8au3rRsg==" }, "@algolia/logger-console": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.0.tgz", - "integrity": "sha512-zMPvugQV/gbXUvWBCzihw6m7oxIKp48w37QBIUu/XqQQfxhjoOE9xyfJr1KldUt5FrYOKZJVsJaEjTsu+bIgQg==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/logger-console/-/logger-console-4.17.1.tgz", + "integrity": "sha512-iKGQTpOjHiE64W3JIOu6dmDvn+AfYIElI9jf/Nt6umRPmP/JI9rK+OHUoW4pKrBtdG0DPd62ppeNXzSnLxY6/g==", "requires": { - "@algolia/logger-common": "4.17.0" + "@algolia/logger-common": "4.17.1" } }, "@algolia/requester-browser-xhr": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.0.tgz", - "integrity": "sha512-aSOX/smauyTkP21Pf52pJ1O2LmNFJ5iHRIzEeTh0mwBeADO4GdG94cAWDILFA9rNblq/nK3EDh3+UyHHjplZ1A==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-4.17.1.tgz", + "integrity": "sha512-W5mGfGDsyfVR+r4pUFrYLGBEM18gs38+GNt5PE5uPULy4uVTSnnVSkJkWeRkmLBk9zEZ/Nld8m4zavK6dtEuYg==", "requires": { - "@algolia/requester-common": "4.17.0" + "@algolia/requester-common": "4.17.1" } }, "@algolia/requester-common": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.0.tgz", - "integrity": "sha512-XJjmWFEUlHu0ijvcHBoixuXfEoiRUdyzQM6YwTuB8usJNIgShua8ouFlRWF8iCeag0vZZiUm4S2WCVBPkdxFgg==" + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-common/-/requester-common-4.17.1.tgz", + "integrity": "sha512-HggXdjvVFQR0I5l7hM5WdHgQ1tqcRWeyXZz8apQ7zPWZhirmY2E9D6LVhDh/UnWQNEm7nBtM+eMFONJ3bZccIQ==" }, "@algolia/requester-node-http": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.0.tgz", - "integrity": "sha512-bpb/wDA1aC6WxxM8v7TsFspB7yBN3nqCGs2H1OADolQR/hiAIjAxusbuMxVbRFOdaUvAIqioIIkWvZdpYNIn8w==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-4.17.1.tgz", + "integrity": "sha512-NzFWecXT6d0PPsQY9L+/qoK2deF74OLcpvqCH+Vh3mh+QzPsFafcBExdguAjZsAWDn1R6JEeFW7/fo/p0SE57w==", "requires": { - "@algolia/requester-common": "4.17.0" + "@algolia/requester-common": "4.17.1" } }, "@algolia/transporter": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.0.tgz", - "integrity": "sha512-6xL6H6fe+Fi0AEP3ziSgC+G04RK37iRb4uUUqVAH9WPYFI8g+LYFq6iv5HS8Cbuc5TTut+Bwj6G+dh/asdb9uA==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/@algolia/transporter/-/transporter-4.17.1.tgz", + "integrity": "sha512-ZM+qhX47Vh46mWH8/U9ihvy98HdTYpYQDSlqBD7IbiUbbyoCMke+qmdSX2MGhR2FCcXBSxejsJKKVAfbpaLVgg==", "requires": { - "@algolia/cache-common": "4.17.0", - "@algolia/logger-common": "4.17.0", - "@algolia/requester-common": "4.17.0" + "@algolia/cache-common": "4.17.1", + "@algolia/logger-common": "4.17.1", + "@algolia/requester-common": "4.17.1" } }, "@ampproject/remapping": { @@ -13671,25 +13672,25 @@ "optional": true }, "@docsearch/css": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.3.3.tgz", - "integrity": "sha512-6SCwI7P8ao+se1TUsdZ7B4XzL+gqeQZnBc+2EONZlcVa0dVrk0NjETxozFKgMv0eEGH8QzP1fkN+A1rH61l4eg==" + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docsearch/css/-/css-3.4.0.tgz", + "integrity": "sha512-Hg8Xfma+rFwRi6Y/pfei4FJoQ1hdVURmmNs/XPoMTCPAImU+d5yxj+M+qdLtNjWRpfWziU4dQcqY94xgFBn2dg==" }, "@docsearch/react": { - "version": "3.3.3", - "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.3.3.tgz", - "integrity": "sha512-pLa0cxnl+G0FuIDuYlW+EBK6Rw2jwLw9B1RHIeS4N4s2VhsfJ/wzeCi3CWcs5yVfxLd5ZK50t//TMA5e79YT7Q==", + "version": "3.4.0", + "resolved": "https://registry.npmjs.org/@docsearch/react/-/react-3.4.0.tgz", + "integrity": "sha512-ufrp5879XYGojgS30ZAp8H4qIMbahRHB9M85VDBP36Xgz5QjYM54i1URKj5e219F7gqTtOivfztFTij6itc0MQ==", "requires": { - "@algolia/autocomplete-core": "1.7.4", - "@algolia/autocomplete-preset-algolia": "1.7.4", - "@docsearch/css": "3.3.3", + "@algolia/autocomplete-core": "1.8.2", + "@algolia/autocomplete-preset-algolia": "1.8.2", + "@docsearch/css": "3.4.0", "algoliasearch": "^4.0.0" } }, "@docusaurus/core": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.4.0.tgz", - "integrity": "sha512-J55/WEoIpRcLf3afO5POHPguVZosKmJEQWKBL+K7TAnfuE7i+Y0NPLlkKtnWCehagGsgTqClfQEexH/UT4kELA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/core/-/core-2.4.1.tgz", + "integrity": "sha512-SNsY7PshK3Ri7vtsLXVeAJGS50nJN3RgF836zkyUfAD01Fq+sAk5EwWgLw+nnm5KVNGDu7PRR2kRGDsWvqpo0g==", "requires": { "@babel/core": "^7.18.6", "@babel/generator": "^7.18.7", @@ -13701,13 +13702,13 @@ "@babel/runtime": "^7.18.6", "@babel/runtime-corejs3": "^7.18.6", "@babel/traverse": "^7.18.8", - "@docusaurus/cssnano-preset": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", + "@docusaurus/cssnano-preset": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "@slorber/static-site-generator-webpack-plugin": "^4.0.7", "@svgr/webpack": "^6.2.1", "autoprefixer": "^10.4.7", @@ -13765,9 +13766,9 @@ } }, "@docusaurus/cssnano-preset": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.4.0.tgz", - "integrity": "sha512-RmdiA3IpsLgZGXRzqnmTbGv43W4OD44PCo+6Q/aYjEM2V57vKCVqNzuafE94jv0z/PjHoXUrjr69SaRymBKYYw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/cssnano-preset/-/cssnano-preset-2.4.1.tgz", + "integrity": "sha512-ka+vqXwtcW1NbXxWsh6yA1Ckii1klY9E53cJ4O9J09nkMBgrNX3iEFED1fWdv8wf4mJjvGi5RLZ2p9hJNjsLyQ==", "requires": { "cssnano-preset-advanced": "^5.3.8", "postcss": "^8.4.14", @@ -13776,23 +13777,23 @@ } }, "@docusaurus/logger": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.4.0.tgz", - "integrity": "sha512-T8+qR4APN+MjcC9yL2Es+xPJ2923S9hpzDmMtdsOcUGLqpCGBbU1vp3AAqDwXtVgFkq+NsEk7sHdVsfLWR/AXw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/logger/-/logger-2.4.1.tgz", + "integrity": "sha512-5h5ysIIWYIDHyTVd8BjheZmQZmEgWDR54aQ1BX9pjFfpyzFo5puKXKYrYJXbjEHGyVhEzmB9UXwbxGfaZhOjcg==", "requires": { "chalk": "^4.1.2", "tslib": "^2.4.0" } }, "@docusaurus/mdx-loader": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.4.0.tgz", - "integrity": "sha512-GWoH4izZKOmFoC+gbI2/y8deH/xKLvzz/T5BsEexBye8EHQlwsA7FMrVa48N063bJBH4FUOiRRXxk5rq9cC36g==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/mdx-loader/-/mdx-loader-2.4.1.tgz", + "integrity": "sha512-4KhUhEavteIAmbBj7LVFnrVYDiU51H5YWW1zY6SmBSte/YLhDutztLTBE0PQl1Grux1jzUJeaSvAzHpTn6JJDQ==", "requires": { "@babel/parser": "^7.18.8", "@babel/traverse": "^7.18.8", - "@docusaurus/logger": "2.4.0", - "@docusaurus/utils": "2.4.0", + "@docusaurus/logger": "2.4.1", + "@docusaurus/utils": "2.4.1", "@mdx-js/mdx": "^1.6.22", "escape-html": "^1.0.3", "file-loader": "^6.2.0", @@ -13809,12 +13810,12 @@ } }, "@docusaurus/module-type-aliases": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.0.tgz", - "integrity": "sha512-YEQO2D3UXs72qCn8Cr+RlycSQXVGN9iEUyuHwTuK4/uL/HFomB2FHSU0vSDM23oLd+X/KibQ3Ez6nGjQLqXcHg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/module-type-aliases/-/module-type-aliases-2.4.1.tgz", + "integrity": "sha512-gLBuIFM8Dp2XOCWffUDSjtxY7jQgKvYujt7Mx5s4FCTfoL5dN1EVbnrn+O2Wvh8b0a77D57qoIDY7ghgmatR1A==", "requires": { "@docusaurus/react-loadable": "5.5.2", - "@docusaurus/types": "2.4.0", + "@docusaurus/types": "2.4.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -13824,17 +13825,17 @@ } }, "@docusaurus/plugin-content-blog": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.4.0.tgz", - "integrity": "sha512-YwkAkVUxtxoBAIj/MCb4ohN0SCtHBs4AS75jMhPpf67qf3j+U/4n33cELq7567hwyZ6fMz2GPJcVmctzlGGThQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-blog/-/plugin-content-blog-2.4.1.tgz", + "integrity": "sha512-E2i7Knz5YIbE1XELI6RlTnZnGgS52cUO4BlCiCUCvQHbR+s1xeIWz4C6BtaVnlug0Ccz7nFSksfwDpVlkujg5Q==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "cheerio": "^1.0.0-rc.12", "feed": "^4.2.2", "fs-extra": "^10.1.0", @@ -13847,17 +13848,17 @@ } }, "@docusaurus/plugin-content-docs": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.4.0.tgz", - "integrity": "sha512-ic/Z/ZN5Rk/RQo+Io6rUGpToOtNbtPloMR2JcGwC1xT2riMu6zzfSwmBi9tHJgdXH6CB5jG+0dOZZO8QS5tmDg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-docs/-/plugin-content-docs-2.4.1.tgz", + "integrity": "sha512-Lo7lSIcpswa2Kv4HEeUcGYqaasMUQNpjTXpV0N8G6jXgZaQurqp7E8NGYeGbDXnb48czmHWbzDL4S3+BbK0VzA==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/module-type-aliases": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "@types/react-router-config": "^5.0.6", "combine-promises": "^1.1.0", "fs-extra": "^10.1.0", @@ -13870,100 +13871,100 @@ } }, "@docusaurus/plugin-content-pages": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.4.0.tgz", - "integrity": "sha512-Pk2pOeOxk8MeU3mrTU0XLIgP9NZixbdcJmJ7RUFrZp1Aj42nd0RhIT14BGvXXyqb8yTQlk4DmYGAzqOfBsFyGw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-content-pages/-/plugin-content-pages-2.4.1.tgz", + "integrity": "sha512-/UjuH/76KLaUlL+o1OvyORynv6FURzjurSjvn2lbWTFc4tpYY2qLYTlKpTCBVPhlLUQsfyFnshEJDLmPneq2oA==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "fs-extra": "^10.1.0", "tslib": "^2.4.0", "webpack": "^5.73.0" } }, "@docusaurus/plugin-debug": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.4.0.tgz", - "integrity": "sha512-KC56DdYjYT7Txyux71vXHXGYZuP6yYtqwClvYpjKreWIHWus5Zt6VNi23rMZv3/QKhOCrN64zplUbdfQMvddBQ==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-debug/-/plugin-debug-2.4.1.tgz", + "integrity": "sha512-7Yu9UPzRShlrH/G8btOpR0e6INFZr0EegWplMjOqelIwAcx3PKyR8mgPTxGTxcqiYj6hxSCRN0D8R7YrzImwNA==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", "fs-extra": "^10.1.0", "react-json-view": "^1.21.3", "tslib": "^2.4.0" } }, "@docusaurus/plugin-google-analytics": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.4.0.tgz", - "integrity": "sha512-uGUzX67DOAIglygdNrmMOvEp8qG03X20jMWadeqVQktS6nADvozpSLGx4J0xbkblhJkUzN21WiilsP9iVP+zkw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-analytics/-/plugin-google-analytics-2.4.1.tgz", + "integrity": "sha512-dyZJdJiCoL+rcfnm0RPkLt/o732HvLiEwmtoNzOoz9MSZz117UH2J6U2vUDtzUzwtFLIf32KkeyzisbwUCgcaQ==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "tslib": "^2.4.0" } }, "@docusaurus/plugin-google-gtag": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.4.0.tgz", - "integrity": "sha512-adj/70DANaQs2+TF/nRdMezDXFAV/O/pjAbUgmKBlyOTq5qoMe0Tk4muvQIwWUmiUQxFJe+sKlZGM771ownyOg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-gtag/-/plugin-google-gtag-2.4.1.tgz", + "integrity": "sha512-mKIefK+2kGTQBYvloNEKtDmnRD7bxHLsBcxgnbt4oZwzi2nxCGjPX6+9SQO2KCN5HZbNrYmGo5GJfMgoRvy6uA==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "tslib": "^2.4.0" } }, "@docusaurus/plugin-google-tag-manager": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-2.4.0.tgz", - "integrity": "sha512-E66uGcYs4l7yitmp/8kMEVQftFPwV9iC62ORh47Veqzs6ExwnhzBkJmwDnwIysHBF1vlxnzET0Fl2LfL5fRR3A==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-google-tag-manager/-/plugin-google-tag-manager-2.4.1.tgz", + "integrity": "sha512-Zg4Ii9CMOLfpeV2nG74lVTWNtisFaH9QNtEw48R5QE1KIwDBdTVaiSA18G1EujZjrzJJzXN79VhINSbOJO/r3g==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "tslib": "^2.4.0" } }, "@docusaurus/plugin-sitemap": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.0.tgz", - "integrity": "sha512-pZxh+ygfnI657sN8a/FkYVIAmVv0CGk71QMKqJBOfMmDHNN1FeDeFkBjWP49ejBqpqAhjufkv5UWq3UOu2soCw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/plugin-sitemap/-/plugin-sitemap-2.4.1.tgz", + "integrity": "sha512-lZx+ijt/+atQ3FVE8FOHV/+X3kuok688OydDXrqKRJyXBJZKgGjA2Qa8RjQ4f27V2woaXhtnyrdPop/+OjVMRg==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "fs-extra": "^10.1.0", "sitemap": "^7.1.1", "tslib": "^2.4.0" } }, "@docusaurus/preset-classic": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.4.0.tgz", - "integrity": "sha512-/5z5o/9bc6+P5ool2y01PbJhoGddEGsC0ej1MF6mCoazk8A+kW4feoUd68l7Bnv01rCnG3xy7kHUQP97Y0grUA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/preset-classic/-/preset-classic-2.4.1.tgz", + "integrity": "sha512-P4//+I4zDqQJ+UDgoFrjIFaQ1MeS9UD1cvxVQaI6O7iBmiHQm0MGROP1TbE7HlxlDPXFJjZUK3x3cAoK63smGQ==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/plugin-content-blog": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/plugin-content-pages": "2.4.0", - "@docusaurus/plugin-debug": "2.4.0", - "@docusaurus/plugin-google-analytics": "2.4.0", - "@docusaurus/plugin-google-gtag": "2.4.0", - "@docusaurus/plugin-google-tag-manager": "2.4.0", - "@docusaurus/plugin-sitemap": "2.4.0", - "@docusaurus/theme-classic": "2.4.0", - "@docusaurus/theme-common": "2.4.0", - "@docusaurus/theme-search-algolia": "2.4.0", - "@docusaurus/types": "2.4.0" + "@docusaurus/core": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/plugin-debug": "2.4.1", + "@docusaurus/plugin-google-analytics": "2.4.1", + "@docusaurus/plugin-google-gtag": "2.4.1", + "@docusaurus/plugin-google-tag-manager": "2.4.1", + "@docusaurus/plugin-sitemap": "2.4.1", + "@docusaurus/theme-classic": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-search-algolia": "2.4.1", + "@docusaurus/types": "2.4.1" } }, "@docusaurus/react-loadable": { @@ -13976,22 +13977,22 @@ } }, "@docusaurus/theme-classic": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.4.0.tgz", - "integrity": "sha512-GMDX5WU6Z0OC65eQFgl3iNNEbI9IMJz9f6KnOyuMxNUR6q0qVLsKCNopFUDfFNJ55UU50o7P7o21yVhkwpfJ9w==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-classic/-/theme-classic-2.4.1.tgz", + "integrity": "sha512-Rz0wKUa+LTW1PLXmwnf8mn85EBzaGSt6qamqtmnh9Hflkc+EqiYMhtUJeLdV+wsgYq4aG0ANc+bpUDpsUhdnwg==", "requires": { - "@docusaurus/core": "2.4.0", - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/module-type-aliases": "2.4.0", - "@docusaurus/plugin-content-blog": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/plugin-content-pages": "2.4.0", - "@docusaurus/theme-common": "2.4.0", - "@docusaurus/theme-translations": "2.4.0", - "@docusaurus/types": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/types": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", "copy-text-to-clipboard": "^3.0.1", @@ -14008,17 +14009,17 @@ } }, "@docusaurus/theme-common": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.4.0.tgz", - "integrity": "sha512-IkG/l5f/FLY6cBIxtPmFnxpuPzc5TupuqlOx+XDN+035MdQcAh8wHXXZJAkTeYDeZ3anIUSUIvWa7/nRKoQEfg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-common/-/theme-common-2.4.1.tgz", + "integrity": "sha512-G7Zau1W5rQTaFFB3x3soQoZpkgMbl/SYNG8PfMFIjKa3M3q8n0m/GRf5/H/e5BqOvt8c+ZWIXGCiz+kUCSHovA==", "requires": { - "@docusaurus/mdx-loader": "2.4.0", - "@docusaurus/module-type-aliases": "2.4.0", - "@docusaurus/plugin-content-blog": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/plugin-content-pages": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-common": "2.4.0", + "@docusaurus/mdx-loader": "2.4.1", + "@docusaurus/module-type-aliases": "2.4.1", + "@docusaurus/plugin-content-blog": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/plugin-content-pages": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-common": "2.4.1", "@types/history": "^4.7.11", "@types/react": "*", "@types/react-router-config": "*", @@ -14031,18 +14032,18 @@ } }, "@docusaurus/theme-search-algolia": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.4.0.tgz", - "integrity": "sha512-pPCJSCL1Qt4pu/Z0uxBAuke0yEBbxh0s4fOvimna7TEcBLPq0x06/K78AaABXrTVQM6S0vdocFl9EoNgU17hqA==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-search-algolia/-/theme-search-algolia-2.4.1.tgz", + "integrity": "sha512-6BcqW2lnLhZCXuMAvPRezFs1DpmEKzXFKlYjruuas+Xy3AQeFzDJKTJFIm49N77WFCTyxff8d3E4Q9pi/+5McQ==", "requires": { "@docsearch/react": "^3.1.1", - "@docusaurus/core": "2.4.0", - "@docusaurus/logger": "2.4.0", - "@docusaurus/plugin-content-docs": "2.4.0", - "@docusaurus/theme-common": "2.4.0", - "@docusaurus/theme-translations": "2.4.0", - "@docusaurus/utils": "2.4.0", - "@docusaurus/utils-validation": "2.4.0", + "@docusaurus/core": "2.4.1", + "@docusaurus/logger": "2.4.1", + "@docusaurus/plugin-content-docs": "2.4.1", + "@docusaurus/theme-common": "2.4.1", + "@docusaurus/theme-translations": "2.4.1", + "@docusaurus/utils": "2.4.1", + "@docusaurus/utils-validation": "2.4.1", "algoliasearch": "^4.13.1", "algoliasearch-helper": "^3.10.0", "clsx": "^1.2.1", @@ -14054,18 +14055,18 @@ } }, "@docusaurus/theme-translations": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.4.0.tgz", - "integrity": "sha512-kEoITnPXzDPUMBHk3+fzEzbopxLD3fR5sDoayNH0vXkpUukA88/aDL1bqkhxWZHA3LOfJ3f0vJbOwmnXW5v85Q==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/theme-translations/-/theme-translations-2.4.1.tgz", + "integrity": "sha512-T1RAGP+f86CA1kfE8ejZ3T3pUU3XcyvrGMfC/zxCtc2BsnoexuNI9Vk2CmuKCb+Tacvhxjv5unhxXce0+NKyvA==", "requires": { "fs-extra": "^10.1.0", "tslib": "^2.4.0" } }, "@docusaurus/types": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.4.0.tgz", - "integrity": "sha512-xaBXr+KIPDkIaef06c+i2HeTqVNixB7yFut5fBXPGI2f1rrmEV2vLMznNGsFwvZ5XmA3Quuefd4OGRkdo97Dhw==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/types/-/types-2.4.1.tgz", + "integrity": "sha512-0R+cbhpMkhbRXX138UOc/2XZFF8hiZa6ooZAEEJFp5scytzCw4tC1gChMFXrpa3d2tYE6AX8IrOEpSonLmfQuQ==", "requires": { "@types/history": "^4.7.11", "@types/react": "*", @@ -14078,11 +14079,11 @@ } }, "@docusaurus/utils": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.4.0.tgz", - "integrity": "sha512-89hLYkvtRX92j+C+ERYTuSUK6nF9bGM32QThcHPg2EDDHVw6FzYQXmX6/p+pU5SDyyx5nBlE4qXR92RxCAOqfg==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils/-/utils-2.4.1.tgz", + "integrity": "sha512-1lvEZdAQhKNht9aPXPoh69eeKnV0/62ROhQeFKKxmzd0zkcuE/Oc5Gpnt00y/f5bIsmOsYMY7Pqfm/5rteT5GA==", "requires": { - "@docusaurus/logger": "2.4.0", + "@docusaurus/logger": "2.4.1", "@svgr/webpack": "^6.2.1", "escape-string-regexp": "^4.0.0", "file-loader": "^6.2.0", @@ -14101,20 +14102,20 @@ } }, "@docusaurus/utils-common": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.4.0.tgz", - "integrity": "sha512-zIMf10xuKxddYfLg5cS19x44zud/E9I7lj3+0bv8UIs0aahpErfNrGhijEfJpAfikhQ8tL3m35nH3hJ3sOG82A==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-common/-/utils-common-2.4.1.tgz", + "integrity": "sha512-bCVGdZU+z/qVcIiEQdyx0K13OC5mYwxhSuDUR95oFbKVuXYRrTVrwZIqQljuo1fyJvFTKHiL9L9skQOPokuFNQ==", "requires": { "tslib": "^2.4.0" } }, "@docusaurus/utils-validation": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.4.0.tgz", - "integrity": "sha512-IrBsBbbAp6y7mZdJx4S4pIA7dUyWSA0GNosPk6ZJ0fX3uYIEQgcQSGIgTeSC+8xPEx3c16o03en1jSDpgQgz/w==", + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/@docusaurus/utils-validation/-/utils-validation-2.4.1.tgz", + "integrity": "sha512-unII3hlJlDwZ3w8U+pMO3Lx3RhI4YEbY3YNsQj4yzrkZzlpqZOLuAiZK2JyULnD+TKbceKU0WyWkQXtYbLNDFA==", "requires": { - "@docusaurus/logger": "2.4.0", - "@docusaurus/utils": "2.4.0", + "@docusaurus/logger": "2.4.1", + "@docusaurus/utils": "2.4.1", "joi": "^17.6.0", "js-yaml": "^4.1.0", "tslib": "^2.4.0" @@ -14636,9 +14637,9 @@ "integrity": "sha512-wOuvG1SN4Us4rez+tylwwwCV1psiNVOkJeM3AUWUNWg/jDQY2+HE/444y5gc+jBmRqASOm2Oeh5c1axHobwRKQ==" }, "@types/mdast": { - "version": "3.0.10", - "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.10.tgz", - "integrity": "sha512-W864tg/Osz1+9f4lrGTZpCSO5/z4608eUp19tbozkq2HJK6i3z1kT0H9tlADXuYIb1YYOBByU4Jsqkk75q48qA==", + "version": "3.0.11", + "resolved": "https://registry.npmjs.org/@types/mdast/-/mdast-3.0.11.tgz", + "integrity": "sha512-Y/uImid8aAwrEA24/1tcRZwpxX3pIFTSilcNDKSPn+Y2iDywSEachzRuvgAYYLR3wpGXAsMbv5lvKLDZLeYPAw==", "requires": { "@types/unist": "*" } @@ -15010,30 +15011,30 @@ "requires": {} }, "algoliasearch": { - "version": "4.17.0", - "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.0.tgz", - "integrity": "sha512-JMRh2Mw6sEnVMiz6+APsi7lx9a2jiDFF+WUtANaUVCv6uSU9UOLdo5h9K3pdP6frRRybaM2fX8b1u0nqICS9aA==", + "version": "4.17.1", + "resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-4.17.1.tgz", + "integrity": "sha512-4GDQ1RhP2qUR3x8PevFRbEdqZqIARNViZYjgTJmA1T7wRNtFA3W4Aqc/RsODqa1J8IO/QDla5x4tWuUS8NV8wA==", "requires": { - "@algolia/cache-browser-local-storage": "4.17.0", - "@algolia/cache-common": "4.17.0", - "@algolia/cache-in-memory": "4.17.0", - "@algolia/client-account": "4.17.0", - "@algolia/client-analytics": "4.17.0", - "@algolia/client-common": "4.17.0", - "@algolia/client-personalization": "4.17.0", - "@algolia/client-search": "4.17.0", - "@algolia/logger-common": "4.17.0", - "@algolia/logger-console": "4.17.0", - "@algolia/requester-browser-xhr": "4.17.0", - "@algolia/requester-common": "4.17.0", - "@algolia/requester-node-http": "4.17.0", - "@algolia/transporter": "4.17.0" + "@algolia/cache-browser-local-storage": "4.17.1", + "@algolia/cache-common": "4.17.1", + "@algolia/cache-in-memory": "4.17.1", + "@algolia/client-account": "4.17.1", + "@algolia/client-analytics": "4.17.1", + "@algolia/client-common": "4.17.1", + "@algolia/client-personalization": "4.17.1", + "@algolia/client-search": "4.17.1", + "@algolia/logger-common": "4.17.1", + "@algolia/logger-console": "4.17.1", + "@algolia/requester-browser-xhr": "4.17.1", + "@algolia/requester-common": "4.17.1", + "@algolia/requester-node-http": "4.17.1", + "@algolia/transporter": "4.17.1" } }, "algoliasearch-helper": { - "version": "3.12.0", - "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.12.0.tgz", - "integrity": "sha512-/j1U3PEwdan0n6P/QqSnSpNSLC5+cEMvyljd5CnmNmUjDlGrys+vFEOwjVEnqELIiAGMHEA/Nl3CiKVFBUYqyQ==", + "version": "3.13.0", + "resolved": "https://registry.npmjs.org/algoliasearch-helper/-/algoliasearch-helper-3.13.0.tgz", + "integrity": "sha512-kV3c1jMQCvkARtGsSDvAwuht4PAMSsQILqPiH4WFiARoa3jXJ/r1TQoBWAjWyWF48rsNYCv7kzxgB4LTxrvvuw==", "requires": { "@algolia/events": "^4.0.1" } @@ -15891,11 +15892,11 @@ } }, "cross-fetch": { - "version": "3.1.5", - "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.5.tgz", - "integrity": "sha512-lvb1SBsI0Z7GDwmuid+mU3kWVBwTVUbe7S0H52yaaAdQOXq2YktTCZdlAcNKFzE6QtRz0snpw9bNiPeOIkkQvw==", + "version": "3.1.6", + "resolved": "https://registry.npmjs.org/cross-fetch/-/cross-fetch-3.1.6.tgz", + "integrity": "sha512-riRvo06crlE8HiqOwIpQhxwdOk4fOeR7FVM/wXoxchFEqMNUjvbs3bfo4OTgMEMHzppd4DxFBDbyySj8Cv781g==", "requires": { - "node-fetch": "2.6.7" + "node-fetch": "^2.6.11" } }, "cross-spawn": { @@ -16270,13 +16271,13 @@ } }, "domutils": { - "version": "3.0.1", - "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.0.1.tgz", - "integrity": "sha512-z08c1l761iKhDFtfXO04C7kTdPBLi41zwOZl00WS8b5eiaebNpY00HKbztwBq+e3vyqWNwWF3mP9YLUeqIrF+Q==", + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/domutils/-/domutils-3.1.0.tgz", + "integrity": "sha512-H78uMmQtI2AhgDJjWeQmHwJJ2bLPD3GMmO7Zja/ZZh84wkm+4ut+IUnUdRa8uCGX88DiVx1j6FRe1XfxEgjEZA==", "requires": { "dom-serializer": "^2.0.0", "domelementtype": "^2.3.0", - "domhandler": "^5.0.1" + "domhandler": "^5.0.3" } }, "dot-case": { @@ -18100,9 +18101,9 @@ } }, "node-fetch": { - "version": "2.6.7", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.7.tgz", - "integrity": "sha512-ZjMPFEfVx5j+y2yF35Kzx5sF7kDzxuDj6ziH4FFbOp87zKDZNx8yExJIb05OGF4Nlt9IHFIMBkRl41VdvcNdbQ==", + "version": "2.6.11", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.11.tgz", + "integrity": "sha512-4I6pdBY1EthSqDmJkiNk3JIT8cswwR9nfeW/cPdUagJYEQG7R95WRH74wpz7ma8Gh/9dI9FP+OU+0E4FvtA55w==", "requires": { "whatwg-url": "^5.0.0" } @@ -18753,9 +18754,9 @@ } }, "postcss-sort-media-queries": { - "version": "4.3.0", - "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.3.0.tgz", - "integrity": "sha512-jAl8gJM2DvuIJiI9sL1CuiHtKM4s5aEIomkU8G3LFvbP+p8i7Sz8VV63uieTgoewGqKbi+hxBTiOKJlB35upCg==", + "version": "4.4.1", + "resolved": "https://registry.npmjs.org/postcss-sort-media-queries/-/postcss-sort-media-queries-4.4.1.tgz", + "integrity": "sha512-QDESFzDDGKgpiIh4GYXsSy6sek2yAwQx1JASl5AxBtU1Lq2JfKBljIPNdil989NcSKRQX1ToiaKphImtBuhXWw==", "requires": { "sort-css-media-queries": "2.1.0" } diff --git a/docs/package.json b/docs/package.json index 4ed541a73..d2d68ee83 100644 --- a/docs/package.json +++ b/docs/package.json @@ -14,8 +14,8 @@ "write-heading-ids": "docusaurus write-heading-ids" }, "dependencies": { - "@docusaurus/core": "^2.4.0", - "@docusaurus/preset-classic": "^2.4.0", + "@docusaurus/core": "^2.4.1", + "@docusaurus/preset-classic": "^2.4.1", "@mdx-js/react": "^1.6.22", "clsx": "^1.2.1", "prism-react-renderer": "^1.3.5", diff --git a/frigate/__main__.py b/frigate/__main__.py index b36881151..844206908 100644 --- a/frigate/__main__.py +++ b/frigate/__main__.py @@ -1,13 +1,14 @@ import faulthandler -from flask import cli - -faulthandler.enable() import threading -threading.current_thread().name = "frigate" +from flask import cli from frigate.app import FrigateApp +faulthandler.enable() + +threading.current_thread().name = "frigate" + cli.show_server_banner = lambda *x: None if __name__ == "__main__": diff --git a/frigate/app.py b/frigate/app.py index 5e934cc4b..2db8728b2 100644 --- a/frigate/app.py +++ b/frigate/app.py @@ -1,16 +1,16 @@ import logging import multiprocessing as mp -from multiprocessing.queues import Queue -from multiprocessing.synchronize import Event as MpEvent import os import shutil import signal import sys -from typing import Optional -from types import FrameType -import psutil - import traceback +from multiprocessing.queues import Queue +from multiprocessing.synchronize import Event as MpEvent +from types import FrameType +from typing import Optional + +import psutil from peewee_migrate import Router from playhouse.sqlite_ext import SqliteExtDatabase from playhouse.sqliteq import SqliteQueueDatabase @@ -24,16 +24,17 @@ from frigate.const import ( CLIPS_DIR, CONFIG_DIR, DEFAULT_DB_PATH, + EXPORT_DIR, MODEL_CACHE_DIR, RECORD_DIR, ) -from frigate.object_detection import ObjectDetectProcess from frigate.events.cleanup import EventCleanup from frigate.events.external import ExternalEventProcessor from frigate.events.maintainer import EventProcessor from frigate.http import create_app from frigate.log import log_process, root_configurer from frigate.models import Event, Recordings, Timeline +from frigate.object_detection import ObjectDetectProcess from frigate.object_processing import TrackedObjectProcessor from frigate.output import output_frames from frigate.plus import PlusApi @@ -42,10 +43,10 @@ from frigate.record.record import manage_recordings from frigate.stats import StatsEmitter, stats_init from frigate.storage import StorageMaintainer from frigate.timeline import TimelineProcessor +from frigate.types import CameraMetricsTypes, RecordMetricsTypes from frigate.version import VERSION from frigate.video import capture_camera, track_camera from frigate.watchdog import FrigateWatchdog -from frigate.types import CameraMetricsTypes, RecordMetricsTypes logger = logging.getLogger(__name__) @@ -68,7 +69,14 @@ class FrigateApp: os.environ[key] = value def ensure_dirs(self) -> None: - for d in [CONFIG_DIR, RECORD_DIR, CLIPS_DIR, CACHE_DIR, MODEL_CACHE_DIR]: + for d in [ + CONFIG_DIR, + RECORD_DIR, + CLIPS_DIR, + CACHE_DIR, + MODEL_CACHE_DIR, + EXPORT_DIR, + ]: if not os.path.exists(d) and not os.path.islink(d): logger.info(f"Creating directory: {d}") os.makedirs(d) @@ -133,10 +141,10 @@ class FrigateApp: for log, level in self.config.logger.logs.items(): logging.getLogger(log).setLevel(level.value.upper()) - if not "werkzeug" in self.config.logger.logs: + if "werkzeug" not in self.config.logger.logs: logging.getLogger("werkzeug").setLevel("ERROR") - if not "ws4py" in self.config.logger.logs: + if "ws4py" not in self.config.logger.logs: logging.getLogger("ws4py").setLevel("ERROR") def init_queues(self) -> None: @@ -294,7 +302,7 @@ class FrigateApp: def start_video_output_processor(self) -> None: output_processor = mp.Process( target=output_frames, - name=f"output_processor", + name="output_processor", args=( self.config, self.video_output_queue, @@ -467,7 +475,7 @@ class FrigateApp: self.stop() def stop(self) -> None: - logger.info(f"Stopping...") + logger.info("Stopping...") self.stop_event.set() for detector in self.detectors.values(): diff --git a/frigate/comms/dispatcher.py b/frigate/comms/dispatcher.py index d7fd2b4d4..b7e9e8858 100644 --- a/frigate/comms/dispatcher.py +++ b/frigate/comms/dispatcher.py @@ -1,17 +1,14 @@ """Handle communication between Frigate and other applications.""" import logging - +from abc import ABC, abstractmethod from typing import Any, Callable -from abc import ABC, abstractmethod - from frigate.config import FrigateConfig -from frigate.ptz import OnvifController, OnvifCommandEnum +from frigate.ptz import OnvifCommandEnum, OnvifController from frigate.types import CameraMetricsTypes, RecordMetricsTypes from frigate.util import restart_frigate - logger = logging.getLogger(__name__) @@ -72,7 +69,7 @@ class Dispatcher: camera_name = topic.split("/")[-3] command = topic.split("/")[-2] self._camera_settings_handlers[command](camera_name, payload) - except IndexError as e: + except IndexError: logger.error(f"Received invalid set command: {topic}") return elif topic.endswith("ptz"): @@ -80,7 +77,7 @@ class Dispatcher: # example /cam_name/ptz payload=MOVE_UP|MOVE_DOWN|STOP... camera_name = topic.split("/")[-2] self._on_ptz_command(camera_name, payload) - except IndexError as e: + except IndexError: logger.error(f"Received invalid ptz command: {topic}") return elif topic == "restart": @@ -128,7 +125,7 @@ class Dispatcher: elif payload == "OFF": if self.camera_metrics[camera_name]["detection_enabled"].value: logger.error( - f"Turning off motion is not allowed when detection is enabled." + "Turning off motion is not allowed when detection is enabled." ) return @@ -196,7 +193,7 @@ class Dispatcher: if payload == "ON": if not self.config.cameras[camera_name].record.enabled_in_config: logger.error( - f"Recordings must be enabled in the config to be turned on via MQTT." + "Recordings must be enabled in the config to be turned on via MQTT." ) return diff --git a/frigate/comms/mqtt.py b/frigate/comms/mqtt.py index 37fdd44ae..07799f9da 100644 --- a/frigate/comms/mqtt.py +++ b/frigate/comms/mqtt.py @@ -1,6 +1,5 @@ import logging import threading - from typing import Any, Callable import paho.mqtt.client as mqtt @@ -8,7 +7,6 @@ import paho.mqtt.client as mqtt from frigate.comms.dispatcher import Communicator from frigate.config import FrigateConfig - logger = logging.getLogger(__name__) @@ -177,10 +175,10 @@ class MqttClient(Communicator): # type: ignore[misc] f"{self.mqtt_config.topic_prefix}/restart", self.on_mqtt_command ) - if not self.mqtt_config.tls_ca_certs is None: + if self.mqtt_config.tls_ca_certs is not None: if ( - not self.mqtt_config.tls_client_cert is None - and not self.mqtt_config.tls_client_key is None + self.mqtt_config.tls_client_cert is not None + and self.mqtt_config.tls_client_key is not None ): self.client.tls_set( self.mqtt_config.tls_ca_certs, @@ -189,9 +187,9 @@ class MqttClient(Communicator): # type: ignore[misc] ) else: self.client.tls_set(self.mqtt_config.tls_ca_certs) - if not self.mqtt_config.tls_insecure is None: + if self.mqtt_config.tls_insecure is not None: self.client.tls_insecure_set(self.mqtt_config.tls_insecure) - if not self.mqtt_config.user is None: + if self.mqtt_config.user is not None: self.client.username_pw_set( self.mqtt_config.user, password=self.mqtt_config.password ) diff --git a/frigate/comms/ws.py b/frigate/comms/ws.py index c9cc3988a..3c1d2eb12 100644 --- a/frigate/comms/ws.py +++ b/frigate/comms/ws.py @@ -3,10 +3,9 @@ import json import logging import threading - from typing import Callable - from wsgiref.simple_server import make_server + from ws4py.server.wsgirefserver import ( WebSocketWSGIHandler, WebSocketWSGIRequestHandler, @@ -18,7 +17,6 @@ from ws4py.websocket import WebSocket from frigate.comms.dispatcher import Communicator from frigate.config import FrigateConfig - logger = logging.getLogger(__name__) @@ -45,7 +43,7 @@ class WebSocketClient(Communicator): # type: ignore[misc] "topic": json_message.get("topic"), "payload": json_message.get("payload"), } - except Exception as e: + except Exception: logger.warning( f"Unable to parse websocket message as valid json: {message.data.decode('utf-8')}" ) @@ -82,7 +80,7 @@ class WebSocketClient(Communicator): # type: ignore[misc] "payload": payload, } ) - except Exception as e: + except Exception: # if the payload can't be decoded don't relay to clients logger.debug(f"payload for {topic} wasn't text. Skipping...") return diff --git a/frigate/config.py b/frigate/config.py index 56e4dc496..5c2f27b5a 100644 --- a/frigate/config.py +++ b/frigate/config.py @@ -8,26 +8,14 @@ from typing import Dict, List, Optional, Tuple, Union import matplotlib.pyplot as plt import numpy as np -import yaml -from pydantic import BaseModel, Extra, Field, validator, parse_obj_as +from pydantic import BaseModel, Extra, Field, parse_obj_as, validator from pydantic.fields import PrivateAttr -from frigate.const import ( - CACHE_DIR, - DEFAULT_DB_PATH, - REGEX_CAMERA_NAME, - YAML_EXT, -) +from frigate.const import CACHE_DIR, DEFAULT_DB_PATH, REGEX_CAMERA_NAME, YAML_EXT +from frigate.detectors import DetectorConfig, ModelConfig +from frigate.detectors.detector_config import InputTensorEnum # noqa: F401 +from frigate.detectors.detector_config import PixelFormatEnum # noqa: F401 from frigate.detectors.detector_config import BaseDetectorConfig -from frigate.plus import PlusApi -from frigate.util import ( - create_mask, - deep_merge, - get_ffmpeg_arg_list, - escape_special_characters, - load_config_with_no_duplicates, - load_labels, -) from frigate.ffmpeg_presets import ( parse_preset_hardware_acceleration_decode, parse_preset_hardware_acceleration_scale, @@ -35,14 +23,14 @@ from frigate.ffmpeg_presets import ( parse_preset_output_record, parse_preset_output_rtmp, ) -from frigate.detectors import ( - PixelFormatEnum, - InputTensorEnum, - ModelConfig, - DetectorConfig, +from frigate.plus import PlusApi +from frigate.util import ( + create_mask, + deep_merge, + escape_special_characters, + get_ffmpeg_arg_list, + load_config_with_no_duplicates, ) -from frigate.version import VERSION - logger = logging.getLogger(__name__) @@ -487,7 +475,7 @@ class CameraFfmpegConfig(FfmpegConfig): if len(roles) > len(roles_set): raise ValueError("Each input role may only be used once.") - if not "detect" in roles: + if "detect" not in roles: raise ValueError("The detect role is required.") return v @@ -776,12 +764,12 @@ def verify_config_roles(camera_config: CameraConfig) -> None: set([r for i in camera_config.ffmpeg.inputs for r in i.roles]) ) - if camera_config.record.enabled and not "record" in assigned_roles: + if camera_config.record.enabled and "record" not in assigned_roles: raise ValueError( f"Camera {camera_config.name} has record enabled, but record is not assigned to an input." ) - if camera_config.rtmp.enabled and not "rtmp" in assigned_roles: + if camera_config.rtmp.enabled and "rtmp" not in assigned_roles: raise ValueError( f"Camera {camera_config.name} has rtmp enabled, but rtmp is not assigned to an input." ) @@ -1062,7 +1050,7 @@ class FrigateConfig(FrigateBaseModel): config.model.dict(exclude_unset=True), ) - if not "path" in merged_model: + if "path" not in merged_model: if detector_config.type == "cpu": merged_model["path"] = "/cpu_model.tflite" elif detector_config.type == "edgetpu": diff --git a/frigate/const.py b/frigate/const.py index cfcdc2a53..9b7e177f2 100644 --- a/frigate/const.py +++ b/frigate/const.py @@ -4,6 +4,7 @@ MODEL_CACHE_DIR = f"{CONFIG_DIR}/model_cache" BASE_DIR = "/media/frigate" CLIPS_DIR = f"{BASE_DIR}/clips" RECORD_DIR = f"{BASE_DIR}/recordings" +EXPORT_DIR = f"{BASE_DIR}/exports" BIRDSEYE_PIPE = "/tmp/cache/birdseye" CACHE_DIR = "/tmp/cache" YAML_EXT = (".yaml", ".yml") @@ -13,9 +14,9 @@ BTBN_PATH = "/usr/lib/btbn-ffmpeg" # Regex Consts -REGEX_CAMERA_NAME = "^[a-zA-Z0-9_-]+$" -REGEX_RTSP_CAMERA_USER_PASS = ":\/\/[a-zA-Z0-9_-]+:[\S]+@" -REGEX_HTTP_CAMERA_USER_PASS = "user=[a-zA-Z0-9_-]+&password=[\S]+" +REGEX_CAMERA_NAME = r"^[a-zA-Z0-9_-]+$" +REGEX_RTSP_CAMERA_USER_PASS = r":\/\/[a-zA-Z0-9_-]+:[\S]+@" +REGEX_HTTP_CAMERA_USER_PASS = r"user=[a-zA-Z0-9_-]+&password=[\S]+" # Known Driver Names @@ -28,3 +29,4 @@ DRIVER_INTEL_iHD = "iHD" MAX_SEGMENT_DURATION = 600 SECONDS_IN_DAY = 60 * 60 * 24 +MAX_PLAYLIST_SECONDS = 7200 # support 2 hour segments for a single playlist to account for cameras with inconsistent segment times diff --git a/frigate/detectors/__init__.py b/frigate/detectors/__init__.py index 7cbd82f08..7465ed7c0 100644 --- a/frigate/detectors/__init__.py +++ b/frigate/detectors/__init__.py @@ -1,13 +1,7 @@ import logging -from .detection_api import DetectionApi -from .detector_config import ( - PixelFormatEnum, - InputTensorEnum, - ModelConfig, -) -from .detector_types import DetectorTypeEnum, api_types, DetectorConfig - +from .detector_config import InputTensorEnum, ModelConfig, PixelFormatEnum # noqa: F401 +from .detector_types import DetectorConfig, DetectorTypeEnum, api_types # noqa: F401 logger = logging.getLogger(__name__) diff --git a/frigate/detectors/detection_api.py b/frigate/detectors/detection_api.py index 60a90b1b5..f829da27a 100644 --- a/frigate/detectors/detection_api.py +++ b/frigate/detectors/detection_api.py @@ -1,7 +1,6 @@ import logging from abc import ABC, abstractmethod - logger = logging.getLogger(__name__) diff --git a/frigate/detectors/detector_config.py b/frigate/detectors/detector_config.py index e949065b4..f65826a57 100644 --- a/frigate/detectors/detector_config.py +++ b/frigate/detectors/detector_config.py @@ -1,20 +1,18 @@ import hashlib import json import logging -from enum import Enum import os -from typing import Dict, List, Optional, Tuple, Union, Literal +from enum import Enum +from typing import Dict, Optional, Tuple - -import requests import matplotlib.pyplot as plt -from pydantic import BaseModel, Extra, Field, validator +import requests +from pydantic import BaseModel, Extra, Field from pydantic.fields import PrivateAttr + from frigate.plus import PlusApi - from frigate.util import load_labels - logger = logging.getLogger(__name__) diff --git a/frigate/detectors/detector_types.py b/frigate/detectors/detector_types.py index 5c96b2e16..418fcd625 100644 --- a/frigate/detectors/detector_types.py +++ b/frigate/detectors/detector_types.py @@ -1,16 +1,16 @@ -import logging import importlib +import logging import pkgutil -from typing import Union -from typing_extensions import Annotated from enum import Enum +from typing import Union + from pydantic import Field +from typing_extensions import Annotated from . import plugins from .detection_api import DetectionApi from .detector_config import BaseDetectorConfig - logger = logging.getLogger(__name__) diff --git a/frigate/detectors/plugins/cpu_tfl.py b/frigate/detectors/plugins/cpu_tfl.py index a831a9190..8a54363e1 100644 --- a/frigate/detectors/plugins/cpu_tfl.py +++ b/frigate/detectors/plugins/cpu_tfl.py @@ -1,10 +1,11 @@ import logging + import numpy as np +from pydantic import Field +from typing_extensions import Literal from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detector_config import BaseDetectorConfig -from typing_extensions import Literal -from pydantic import Extra, Field try: from tflite_runtime.interpreter import Interpreter diff --git a/frigate/detectors/plugins/deepstack.py b/frigate/detectors/plugins/deepstack.py index 639cd396c..fd79e27d0 100644 --- a/frigate/detectors/plugins/deepstack.py +++ b/frigate/detectors/plugins/deepstack.py @@ -1,14 +1,14 @@ +import io import logging + import numpy as np import requests -import io +from PIL import Image +from pydantic import Field +from typing_extensions import Literal from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detector_config import BaseDetectorConfig -from typing_extensions import Literal -from pydantic import Extra, Field -from PIL import Image - logger = logging.getLogger(__name__) @@ -64,11 +64,11 @@ class DeepStack(DetectionApi): for i, detection in enumerate(response_json.get("predictions")): logger.debug(f"Response: {detection}") if detection["confidence"] < 0.4: - logger.debug(f"Break due to confidence < 0.4") + logger.debug("Break due to confidence < 0.4") break label = self.get_label_index(detection["label"]) if label < 0: - logger.debug(f"Break due to unknown label") + logger.debug("Break due to unknown label") break detections[i] = [ label, diff --git a/frigate/detectors/plugins/edgetpu_tfl.py b/frigate/detectors/plugins/edgetpu_tfl.py index d671dea4d..ca03d483b 100644 --- a/frigate/detectors/plugins/edgetpu_tfl.py +++ b/frigate/detectors/plugins/edgetpu_tfl.py @@ -1,10 +1,11 @@ import logging + import numpy as np +from pydantic import Field +from typing_extensions import Literal from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detector_config import BaseDetectorConfig -from typing_extensions import Literal -from pydantic import Extra, Field try: from tflite_runtime.interpreter import Interpreter, load_delegate diff --git a/frigate/detectors/plugins/openvino.py b/frigate/detectors/plugins/openvino.py index fe87ac567..5cb1ea39c 100644 --- a/frigate/detectors/plugins/openvino.py +++ b/frigate/detectors/plugins/openvino.py @@ -1,12 +1,12 @@ import logging + import numpy as np import openvino.runtime as ov +from pydantic import Field +from typing_extensions import Literal from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detector_config import BaseDetectorConfig, ModelTypeEnum -from typing_extensions import Literal -from pydantic import Extra, Field - logger = logging.getLogger(__name__) @@ -41,7 +41,7 @@ class OvDetector(DetectionApi): tensor_shape = self.interpreter.output(self.output_indexes).shape logger.info(f"Model Output-{self.output_indexes} Shape: {tensor_shape}") self.output_indexes += 1 - except: + except Exception: logger.info(f"Model has {self.output_indexes} Output Tensors") break if self.ov_model_type == ModelTypeEnum.yolox: diff --git a/frigate/detectors/plugins/tensorrt.py b/frigate/detectors/plugins/tensorrt.py index ac0c4befc..7251b8751 100644 --- a/frigate/detectors/plugins/tensorrt.py +++ b/frigate/detectors/plugins/tensorrt.py @@ -1,6 +1,6 @@ +import ctypes import logging -import ctypes import numpy as np try: @@ -8,13 +8,14 @@ try: from cuda import cuda TRT_SUPPORT = True -except ModuleNotFoundError as e: +except ModuleNotFoundError: TRT_SUPPORT = False +from pydantic import Field +from typing_extensions import Literal + from frigate.detectors.detection_api import DetectionApi from frigate.detectors.detector_config import BaseDetectorConfig -from typing_extensions import Literal -from pydantic import Field logger = logging.getLogger(__name__) @@ -172,7 +173,7 @@ class TensorRtDetector(DetectionApi): if not self.context.execute_async_v2( bindings=self.bindings, stream_handle=self.stream ): - logger.warn(f"Execute returned false") + logger.warn("Execute returned false") # Transfer predictions back from the GPU. [ diff --git a/frigate/events/cleanup.py b/frigate/events/cleanup.py index 09b1964fd..ada45e6fa 100644 --- a/frigate/events/cleanup.py +++ b/frigate/events/cleanup.py @@ -4,17 +4,13 @@ import datetime import logging import os import threading - +from multiprocessing.synchronize import Event as MpEvent from pathlib import Path -from peewee import fn - from frigate.config import FrigateConfig from frigate.const import CLIPS_DIR from frigate.models import Event -from multiprocessing.synchronize import Event as MpEvent - logger = logging.getLogger(__name__) @@ -45,9 +41,9 @@ class EventCleanup(threading.Thread): ) # loop over object types in db - for l in distinct_labels: + for event in distinct_labels: # get expiration time for this label - expire_days = retain_config.objects.get(l.label, retain_config.default) + expire_days = retain_config.objects.get(event.label, retain_config.default) expire_after = ( datetime.datetime.now() - datetime.timedelta(days=expire_days) ).timestamp() @@ -55,8 +51,8 @@ class EventCleanup(threading.Thread): expired_events = Event.select().where( Event.camera.not_in(self.camera_keys), Event.start_time < expire_after, - Event.label == l.label, - Event.retain_indefinitely == False, + Event.label == event.label, + Event.retain_indefinitely is False, ) # delete the media from disk for event in expired_events: @@ -75,8 +71,8 @@ class EventCleanup(threading.Thread): update_query = Event.update(update_params).where( Event.camera.not_in(self.camera_keys), Event.start_time < expire_after, - Event.label == l.label, - Event.retain_indefinitely == False, + Event.label == event.label, + Event.retain_indefinitely is False, ) update_query.execute() @@ -92,9 +88,11 @@ class EventCleanup(threading.Thread): ) # loop over object types in db - for l in distinct_labels: + for event in distinct_labels: # get expiration time for this label - expire_days = retain_config.objects.get(l.label, retain_config.default) + expire_days = retain_config.objects.get( + event.label, retain_config.default + ) expire_after = ( datetime.datetime.now() - datetime.timedelta(days=expire_days) ).timestamp() @@ -102,8 +100,8 @@ class EventCleanup(threading.Thread): expired_events = Event.select().where( Event.camera == name, Event.start_time < expire_after, - Event.label == l.label, - Event.retain_indefinitely == False, + Event.label == event.label, + Event.retain_indefinitely is False, ) # delete the grabbed clips from disk for event in expired_events: @@ -121,8 +119,8 @@ class EventCleanup(threading.Thread): update_query = Event.update(update_params).where( Event.camera == name, Event.start_time < expire_after, - Event.label == l.label, - Event.retain_indefinitely == False, + Event.label == event.label, + Event.retain_indefinitely is False, ) update_query.execute() @@ -131,9 +129,9 @@ class EventCleanup(threading.Thread): select id, label, camera, - has_snapshot, - has_clip, - row_number() over ( + has_snapshot, + has_clip, + row_number() over ( partition by label, camera, round(start_time/5,0)*5 order by end_time-start_time desc ) as copy_number @@ -169,8 +167,8 @@ class EventCleanup(threading.Thread): # drop events from db where has_clip and has_snapshot are false delete_query = Event.delete().where( - Event.has_clip == False, Event.has_snapshot == False + Event.has_clip is False, Event.has_snapshot is False ) delete_query.execute() - logger.info(f"Exiting event cleanup...") + logger.info("Exiting event cleanup...") diff --git a/frigate/events/external.py b/frigate/events/external.py index ee2906e02..5422de260 100644 --- a/frigate/events/external.py +++ b/frigate/events/external.py @@ -1,17 +1,15 @@ """Handle external events created by the user.""" import base64 -import cv2 import datetime -import glob import logging import os import random import string - +from multiprocessing.queues import Queue from typing import Optional -from multiprocessing.queues import Queue +import cv2 from frigate.config import CameraConfig, FrigateConfig from frigate.const import CLIPS_DIR diff --git a/frigate/events/maintainer.py b/frigate/events/maintainer.py index 898218ef0..5459fea6c 100644 --- a/frigate/events/maintainer.py +++ b/frigate/events/maintainer.py @@ -2,20 +2,16 @@ import datetime import logging import queue import threading - from enum import Enum - -from peewee import fn +from multiprocessing.queues import Queue +from multiprocessing.synchronize import Event as MpEvent +from typing import Dict from frigate.config import EventsConfig, FrigateConfig from frigate.models import Event from frigate.types import CameraMetricsTypes from frigate.util import to_relative_box -from multiprocessing.queues import Queue -from multiprocessing.synchronize import Event as MpEvent -from typing import Dict - logger = logging.getLogger(__name__) @@ -65,7 +61,7 @@ class EventProcessor(threading.Thread): def run(self) -> None: # set an end_time on events without an end_time on startup Event.update(end_time=Event.start_time + 30).where( - Event.end_time == None + Event.end_time is None ).execute() while not self.stop_event.is_set(): @@ -99,9 +95,9 @@ class EventProcessor(threading.Thread): # set an end_time on events without an end_time before exiting Event.update(end_time=datetime.datetime.now().timestamp()).where( - Event.end_time == None + Event.end_time is None ).execute() - logger.info(f"Exiting event processor...") + logger.info("Exiting event processor...") def handle_object_detection( self, diff --git a/frigate/ffmpeg_presets.py b/frigate/ffmpeg_presets.py index 353a8b922..dde158916 100644 --- a/frigate/ffmpeg_presets.py +++ b/frigate/ffmpeg_presets.py @@ -2,13 +2,12 @@ import logging import os - +from enum import Enum from typing import Any -from frigate.version import VERSION from frigate.const import BTBN_PATH from frigate.util import vainfo_hwaccel - +from frigate.version import VERSION logger = logging.getLogger(__name__) @@ -118,7 +117,7 @@ PRESETS_HW_ACCEL_SCALE = { "default": "-r {0} -s {1}x{2}", } -PRESETS_HW_ACCEL_ENCODE = { +PRESETS_HW_ACCEL_ENCODE_BIRDSEYE = { "preset-rpi-32-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m {1}", "preset-rpi-64-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m {1}", "preset-vaapi": "ffmpeg -hide_banner -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device {2} {0} -c:v h264_vaapi -g 50 -bf 0 -profile:v high -level:v 4.1 -sei:v 0 -an -vf format=vaapi|nv12,hwupload {1}", @@ -129,6 +128,17 @@ PRESETS_HW_ACCEL_ENCODE = { "default": "ffmpeg -hide_banner {0} -c:v libx264 -g 50 -profile:v high -level:v 4.1 -preset:v superfast -tune:v zerolatency {1}", } +PRESETS_HW_ACCEL_ENCODE_TIMELAPSE = { + "preset-rpi-32-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m {1}", + "preset-rpi-64-h264": "ffmpeg -hide_banner {0} -c:v h264_v4l2m2m {1}", + "preset-vaapi": "ffmpeg -hide_banner -hwaccel vaapi -hwaccel_output_format vaapi -hwaccel_device {2} {0} -c:v h264_vaapi {1}", + "preset-intel-qsv-h264": "ffmpeg -hide_banner {0} -c:v h264_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {1}", + "preset-intel-qsv-h265": "ffmpeg -hide_banner {0} -c:v hevc_qsv -g 50 -bf 0 -profile:v high -level:v 4.1 -async_depth:v 1 {1}", + "preset-nvidia-h264": "ffmpeg -hide_banner -hwaccel cuda -hwaccel_output_format cuda -extra_hw_frames 8 {0} -c:v h264_nvenc {1}", + "preset-nvidia-h265": "ffmpeg -hide_banner -hwaccel cuda -hwaccel_output_format cuda -extra_hw_frames 8 {0} -c:v hevc_nvenc {1}", + "default": "ffmpeg -hide_banner {0} -c:v libx264 -preset:v ultrafast -tune:v zerolatency {1}", +} + def parse_preset_hardware_acceleration_decode(arg: Any) -> list[str]: """Return the correct preset if in preset format otherwise return None.""" @@ -163,12 +173,24 @@ def parse_preset_hardware_acceleration_scale( return scale -def parse_preset_hardware_acceleration_encode(arg: Any, input: str, output: str) -> str: - """Return the correct scaling preset or default preset if none is set.""" - if not isinstance(arg, str): - return PRESETS_HW_ACCEL_ENCODE["default"].format(input, output) +class EncodeTypeEnum(str, Enum): + birdseye = "birdseye" + timelapse = "timelapse" - return PRESETS_HW_ACCEL_ENCODE.get(arg, PRESETS_HW_ACCEL_ENCODE["default"]).format( + +def parse_preset_hardware_acceleration_encode( + arg: Any, input: str, output: str, type: EncodeTypeEnum = EncodeTypeEnum.birdseye +) -> str: + """Return the correct scaling preset or default preset if none is set.""" + if type == EncodeTypeEnum.birdseye: + arg_map = PRESETS_HW_ACCEL_ENCODE_BIRDSEYE + elif type == EncodeTypeEnum.timelapse: + arg_map = PRESETS_HW_ACCEL_ENCODE_TIMELAPSE + + if not isinstance(arg, str): + return arg_map["default"].format(input, output) + + return arg_map.get(arg, arg_map["default"]).format( input, output, _gpu_selector.get_selected_gpu(), diff --git a/frigate/http.py b/frigate/http.py index de9fd033c..7ee4c7f43 100644 --- a/frigate/http.py +++ b/frigate/http.py @@ -1,23 +1,20 @@ import base64 -from datetime import datetime, timedelta, timezone import copy -import logging import glob import json +import logging import os import subprocess as sp -import pytz import time import traceback - +from datetime import datetime, timedelta, timezone from functools import reduce from pathlib import Path -from tzlocal import get_localzone_name from urllib.parse import unquote import cv2 - import numpy as np +import pytz from flask import ( Blueprint, Flask, @@ -27,26 +24,27 @@ from flask import ( make_response, request, ) - -from peewee import SqliteDatabase, operator, fn, DoesNotExist +from peewee import DoesNotExist, SqliteDatabase, fn, operator from playhouse.shortcuts import model_to_dict +from tzlocal import get_localzone_name from frigate.config import FrigateConfig from frigate.const import CLIPS_DIR, MAX_SEGMENT_DURATION, RECORD_DIR -from frigate.models import Event, Recordings, Timeline from frigate.events.external import ExternalEventProcessor +from frigate.models import Event, Recordings, Timeline from frigate.object_processing import TrackedObject from frigate.plus import PlusApi from frigate.ptz import OnvifController +from frigate.record.export import PlaybackFactorEnum, RecordingExporter from frigate.stats import stats_snapshot +from frigate.storage import StorageMaintainer from frigate.util import ( clean_camera_user_pass, ffprobe_stream, + get_tz_modifiers, restart_frigate, vainfo_hwaccel, - get_tz_modifiers, ) -from frigate.storage import StorageMaintainer from frigate.version import VERSION logger = logging.getLogger(__name__) @@ -105,10 +103,10 @@ def events_summary(): clauses = [] - if not has_clip is None: + if has_clip is not None: clauses.append((Event.has_clip == has_clip)) - if not has_snapshot is None: + if has_snapshot is not None: clauses.append((Event.has_snapshot == has_snapshot)) if len(clauses) == 0: @@ -253,7 +251,7 @@ def send_to_plus(id): event.plus_id = plus_id event.save() - if not include_annotation is None: + if include_annotation is not None: box = event.data["box"] try: @@ -296,12 +294,12 @@ def false_positive(id): # events from before the conversion to relative dimensions cant include annotations if event.data.get("box") is None: - message = f"Events prior to 0.13 cannot be submitted as false positives" + message = "Events prior to 0.13 cannot be submitted as false positives" logger.error(message) return make_response(jsonify({"success": False, "message": message}), 400) if event.false_positive: - message = f"False positive already submitted to Frigate+" + message = "False positive already submitted to Frigate+" logger.error(message) return make_response(jsonify({"success": False, "message": message}), 400) @@ -437,7 +435,7 @@ def get_sub_labels(): parts = label.split(",") for part in parts: - if not (part.strip()) in sub_labels: + if part.strip() not in sub_labels: sub_labels.append(part.strip()) sub_labels.sort() @@ -476,7 +474,7 @@ def event_thumbnail(id, max_cache_age=2592000): event_complete = False try: event = Event.get(Event.id == id) - if not event.end_time is None: + if event.end_time is not None: event_complete = True thumbnail_bytes = base64.b64decode(event.thumbnail) except DoesNotExist: @@ -486,9 +484,9 @@ def event_thumbnail(id, max_cache_age=2592000): for camera_state in camera_states: if id in camera_state.tracked_objects: tracked_obj = camera_state.tracked_objects.get(id) - if not tracked_obj is None: + if tracked_obj is not None: thumbnail_bytes = tracked_obj.get_thumbnail() - except: + except Exception: return "Event not found", 404 if thumbnail_bytes is None: @@ -593,7 +591,7 @@ def event_snapshot(id): event_complete = False jpg_bytes = None try: - event = Event.get(Event.id == id, Event.end_time != None) + event = Event.get(Event.id == id, Event.end_time is not None) event_complete = True if not event.has_snapshot: return "Snapshot not available", 404 @@ -609,7 +607,7 @@ def event_snapshot(id): for camera_state in camera_states: if id in camera_state.tracked_objects: tracked_obj = camera_state.tracked_objects.get(id) - if not tracked_obj is None: + if tracked_obj is not None: jpg_bytes = tracked_obj.get_jpg_bytes( timestamp=request.args.get("timestamp", type=int), bounding_box=request.args.get("bbox", type=int), @@ -617,9 +615,9 @@ def event_snapshot(id): height=request.args.get("h", type=int), quality=request.args.get("quality", default=70, type=int), ) - except: + except Exception: return "Event not found", 404 - except: + except Exception: return "Event not found", 404 if jpg_bytes is None: @@ -645,7 +643,7 @@ def label_snapshot(camera_name, label): event_query = ( Event.select() .where(Event.camera == camera_name) - .where(Event.has_snapshot == True) + .where(Event.has_snapshot is True) .order_by(Event.start_time.desc()) ) else: @@ -653,7 +651,7 @@ def label_snapshot(camera_name, label): Event.select() .where(Event.camera == camera_name) .where(Event.label == label) - .where(Event.has_snapshot == True) + .where(Event.has_snapshot is True) .order_by(Event.start_time.desc()) ) @@ -820,13 +818,13 @@ def events(): if before: clauses.append((Event.start_time < before)) - if not has_clip is None: + if has_clip is not None: clauses.append((Event.has_clip == has_clip)) - if not has_snapshot is None: + if has_snapshot is not None: clauses.append((Event.has_snapshot == has_snapshot)) - if not in_progress is None: + if in_progress is not None: clauses.append((Event.end_time.is_null(in_progress))) if not include_thumbnails: @@ -894,12 +892,12 @@ def create_event(camera_name, label): def end_event(event_id): try: current_app.external_processor.finish_manual_event(event_id) - except: + except Exception: return jsonify( {"success": False, "message": f"{event_id} must be set and valid."}, 404 ) - return jsonify({"success": True, "message": f"Event successfully ended."}, 200) + return jsonify({"success": True, "message": "Event successfully ended."}, 200) @bp.route("/config") @@ -959,9 +957,8 @@ def config_save(): # Validate the config schema try: - new_yaml = FrigateConfig.parse_raw(new_config) - check_runtime = new_yaml.runtime_config - except Exception as e: + FrigateConfig.parse_raw(new_config) + except Exception: return make_response( jsonify( { @@ -985,12 +982,12 @@ def config_save(): with open(config_file, "w") as f: f.write(new_config) f.close() - except Exception as e: + except Exception: return make_response( jsonify( { "success": False, - "message": f"Could not write config file, be sure that Frigate has write permission on the config file.", + "message": "Could not write config file, be sure that Frigate has write permission on the config file.", } ), 400, @@ -1351,6 +1348,7 @@ def recording_clip(camera_name, start_ts, end_ts): if not os.path.exists(path): ffmpeg_cmd = [ "ffmpeg", + "-hide_banner", "-y", "-protocol_whitelist", "pipe,file", @@ -1507,6 +1505,22 @@ def vod_event(id): ) +@bp.route("/export//start//end/", methods=["POST"]) +def export_recording(camera_name: str, start_time: int, end_time: int): + playback_factor = request.get_json(silent=True).get("playback", "realtime") + exporter = RecordingExporter( + current_app.frigate_config, + camera_name, + int(start_time), + int(end_time), + PlaybackFactorEnum[playback_factor] + if playback_factor in PlaybackFactorEnum.__members__.values() + else PlaybackFactorEnum.realtime, + ) + exporter.start() + return "Starting export of recording", 200 + + def imagestream(detected_frames_processor, camera_name, fps, height, draw_options): while True: # max out at specified FPS @@ -1531,7 +1545,7 @@ def ffprobe(): if not path_param: return jsonify( - {"success": False, "message": f"Path needs to be provided."}, "404" + {"success": False, "message": "Path needs to be provided."}, "404" ) if path_param.startswith("camera"): diff --git a/frigate/log.py b/frigate/log.py index 67866942c..5dbf4eed0 100644 --- a/frigate/log.py +++ b/frigate/log.py @@ -1,18 +1,17 @@ # adapted from https://medium.com/@jonathonbao/python3-logging-with-multiprocessing-f51f460b8778 import logging -import threading -import os -import signal -import queue import multiprocessing as mp -from multiprocessing.queues import Queue -from logging import handlers -from typing import Optional -from types import FrameType -from setproctitle import setproctitle -from typing import Deque, Optional -from types import FrameType +import os +import queue +import signal +import threading from collections import deque +from logging import handlers +from multiprocessing.queues import Queue +from types import FrameType +from typing import Deque, Optional + +from setproctitle import setproctitle from frigate.util import clean_camera_user_pass @@ -44,7 +43,7 @@ def root_configurer(queue: Queue) -> None: def log_process(log_queue: Queue) -> None: - threading.current_thread().name = f"logger" + threading.current_thread().name = "logger" setproctitle("frigate.logger") listener_configurer() @@ -63,6 +62,8 @@ def log_process(log_queue: Queue) -> None: if stop_event.is_set(): break continue + if record.msg.startswith("You are using a scalar distance function"): + continue logger = logging.getLogger(record.name) logger.handle(record) diff --git a/frigate/models.py b/frigate/models.py index 9a7b6c640..8591b33b5 100644 --- a/frigate/models.py +++ b/frigate/models.py @@ -1,12 +1,11 @@ -from numpy import unique from peewee import ( - Model, + BooleanField, CharField, DateTimeField, FloatField, - BooleanField, - TextField, IntegerField, + Model, + TextField, ) from playhouse.sqlite_ext import JSONField diff --git a/frigate/motion.py b/frigate/motion.py index 5580803a3..19d162956 100644 --- a/frigate/motion.py +++ b/frigate/motion.py @@ -1,6 +1,7 @@ import cv2 import imutils import numpy as np + from frigate.config import MotionConfig diff --git a/frigate/object_detection.py b/frigate/object_detection.py index 129fd6b26..9201dfcd1 100644 --- a/frigate/object_detection.py +++ b/frigate/object_detection.py @@ -12,7 +12,6 @@ from setproctitle import setproctitle from frigate.config import InputTensorEnum from frigate.detectors import create_detector - from frigate.util import EventsPerSecond, SharedMemoryFrameManager, listen, load_labels logger = logging.getLogger(__name__) @@ -161,7 +160,7 @@ class ObjectDetectProcess: def start_or_restart(self): self.detection_start.value = 0.0 - if (not self.detect_process is None) and self.detect_process.is_alive(): + if (self.detect_process is not None) and self.detect_process.is_alive(): self.stop() self.detect_process = mp.Process( target=run_detector, diff --git a/frigate/object_processing.py b/frigate/object_processing.py index 3088857fa..f9046d0ab 100644 --- a/frigate/object_processing.py +++ b/frigate/object_processing.py @@ -15,10 +15,10 @@ import numpy as np from frigate.comms.dispatcher import Dispatcher from frigate.config import ( CameraConfig, - MqttConfig, - SnapshotsConfig, - RecordConfig, FrigateConfig, + MqttConfig, + RecordConfig, + SnapshotsConfig, ) from frigate.const import CLIPS_DIR from frigate.events.maintainer import EventTypeEnum @@ -141,7 +141,7 @@ class TrackedObject: # check each zone for name, zone in self.camera_config.zones.items(): # if the zone is not for this object type, skip - if len(zone.objects) > 0 and not obj_data["label"] in zone.objects: + if len(zone.objects) > 0 and obj_data["label"] not in zone.objects: continue contour = zone.contour # check if the object is in the zone @@ -177,11 +177,7 @@ class TrackedObject: return (thumb_update, significant_change) def to_dict(self, include_thumbnail: bool = False): - snapshot_time = ( - self.thumbnail_data["frame_time"] - if not self.thumbnail_data is None - else 0.0 - ) + (self.thumbnail_data["frame_time"] if self.thumbnail_data is not None else 0.0) event = { "id": self.obj_data["id"], "camera": self.camera, @@ -526,7 +522,7 @@ class CameraState: for id in removed_ids: # publish events to mqtt removed_obj = tracked_objects[id] - if not "end_time" in removed_obj.obj_data: + if "end_time" not in removed_obj.obj_data: removed_obj.obj_data["end_time"] = frame_time for c in self.callbacks["end"]: c(self.name, removed_obj, frame_time) @@ -1028,4 +1024,4 @@ class TrackedObjectProcessor(threading.Thread): event_id, camera = self.event_processed_queue.get() self.camera_states[camera].finished(event_id) - logger.info(f"Exiting object processor...") + logger.info("Exiting object processor...") diff --git a/frigate/output.py b/frigate/output.py index 79a081837..1a394d79f 100644 --- a/frigate/output.py +++ b/frigate/output.py @@ -4,7 +4,6 @@ import logging import math import multiprocessing as mp import os -import operator import queue import signal import subprocess as sp @@ -149,7 +148,7 @@ class BroadcastThread(threading.Thread): ): try: ws.send(buf, binary=True) - except: + except ValueError: pass elif self.converter.process.poll() is not None: break @@ -185,7 +184,7 @@ class BirdsEyeFrameManager: if len(logo_files) > 0: birdseye_logo = cv2.imread(logo_files[0], cv2.IMREAD_UNCHANGED) - if not birdseye_logo is None: + if birdseye_logo is not None: transparent_layer = birdseye_logo[:, :, 3] y_offset = height // 2 - transparent_layer.shape[0] // 2 x_offset = width // 2 - transparent_layer.shape[1] // 2 @@ -229,7 +228,7 @@ class BirdsEyeFrameManager: self.last_output_time = 0.0 def clear_frame(self): - logger.debug(f"Clearing the birdseye frame") + logger.debug("Clearing the birdseye frame") self.frame[:] = self.blank_frame def copy_to_position(self, position, camera=None, frame_time=None): @@ -301,7 +300,7 @@ class BirdsEyeFrameManager: # reset the layout if it needs to be different if layout_dim != self.layout_dim or reset_layout: if reset_layout: - logger.debug(f"Added new cameras, resetting layout...") + logger.debug("Added new cameras, resetting layout...") logger.debug(f"Changing layout size from {self.layout_dim} to {layout_dim}") self.layout_dim = layout_dim @@ -385,7 +384,7 @@ class BirdsEyeFrameManager: ] # if not an empty spot and the camera has a newer frame, copy it elif ( - not camera is None + camera is not None and self.cameras[camera]["current_frame"] != self.cameras[camera]["layout_frame"] ): @@ -423,8 +422,8 @@ class BirdsEyeFrameManager: def output_frames(config: FrigateConfig, video_output_queue): - threading.current_thread().name = f"output" - setproctitle(f"frigate.output") + threading.current_thread().name = "output" + setproctitle("frigate.output") stop_event = mp.Event() diff --git a/frigate/plus.py b/frigate/plus.py index 7ba67a62d..b219e02a2 100644 --- a/frigate/plus.py +++ b/frigate/plus.py @@ -3,12 +3,14 @@ import json import logging import os import re -from typing import Any, Dict, List -import requests -from frigate.const import PLUS_ENV_VAR, PLUS_API_HOST -from requests.models import Response +from typing import Any, List + import cv2 +import requests from numpy import ndarray +from requests.models import Response + +from frigate.const import PLUS_API_HOST, PLUS_ENV_VAR logger = logging.getLogger(__name__) diff --git a/frigate/ptz.py b/frigate/ptz.py index a52006b5c..385a230bc 100644 --- a/frigate/ptz.py +++ b/frigate/ptz.py @@ -2,13 +2,12 @@ import logging import site - from enum import Enum + from onvif import ONVIFCamera, ONVIFError from frigate.config import FrigateConfig - logger = logging.getLogger(__name__) @@ -145,7 +144,7 @@ class OnvifController: onvif.get_service("ptz").ContinuousMove(move_request) def _move_to_preset(self, camera_name: str, preset: str) -> None: - if not preset in self.cams[camera_name]["presets"]: + if preset not in self.cams[camera_name]["presets"]: logger.error(f"{preset} is not a valid preset for {camera_name}") return diff --git a/frigate/record/cleanup.py b/frigate/record/cleanup.py index 14818ec35..dbe5ff549 100644 --- a/frigate/record/cleanup.py +++ b/frigate/record/cleanup.py @@ -275,7 +275,7 @@ class RecordingCleanup(threading.Thread): # Expire tmp clips every minute, recordings and clean directories every hour. for counter in itertools.cycle(range(self.config.record.expire_interval)): if self.stop_event.wait(60): - logger.info(f"Exiting recording cleanup...") + logger.info("Exiting recording cleanup...") break self.clean_tmp_clips() diff --git a/frigate/record/export.py b/frigate/record/export.py new file mode 100644 index 000000000..077f24638 --- /dev/null +++ b/frigate/record/export.py @@ -0,0 +1,101 @@ +"""Export recordings to storage.""" + +import datetime +import logging +import os +import subprocess as sp +import threading +from enum import Enum + +from frigate.config import FrigateConfig +from frigate.const import EXPORT_DIR, MAX_PLAYLIST_SECONDS +from frigate.ffmpeg_presets import ( + EncodeTypeEnum, + parse_preset_hardware_acceleration_encode, +) + +logger = logging.getLogger(__name__) + + +class PlaybackFactorEnum(str, Enum): + realtime = "realtime" + timelapse_25x = "timelapse_25x" + + +class RecordingExporter(threading.Thread): + """Exports a specific set of recordings for a camera to storage as a single file.""" + + def __init__( + self, + config: FrigateConfig, + camera: str, + start_time: int, + end_time: int, + playback_factor: PlaybackFactorEnum, + ) -> None: + threading.Thread.__init__(self) + self.config = config + self.camera = camera + self.start_time = start_time + self.end_time = end_time + self.playback_factor = playback_factor + + def get_datetime_from_timestamp(self, timestamp: int) -> str: + """Convenience fun to get a simple date time from timestamp.""" + return datetime.datetime.fromtimestamp(timestamp).strftime("%Y_%m_%d_%I:%M") + + def run(self) -> None: + logger.debug( + f"Beginning export for {self.camera} from {self.start_time} to {self.end_time}" + ) + file_name = f"{EXPORT_DIR}/in_progress.{self.camera}@{self.get_datetime_from_timestamp(self.start_time)}__{self.get_datetime_from_timestamp(self.end_time)}.mp4" + final_file_name = f"{EXPORT_DIR}/{self.camera}_{self.get_datetime_from_timestamp(self.start_time)}__{self.get_datetime_from_timestamp(self.end_time)}.mp4" + + if (self.end_time - self.start_time) <= MAX_PLAYLIST_SECONDS: + playlist_lines = f"http://127.0.0.1:5000/vod/{self.camera}/start/{self.start_time}/end/{self.end_time}/index.m3u8" + ffmpeg_input = ( + f"-y -protocol_whitelist pipe,file,http,tcp -i {playlist_lines}" + ) + else: + playlist_lines = [] + playlist_start = self.start_time + + while playlist_start < self.end_time: + playlist_lines.append( + f"file 'http://127.0.0.1:5000/vod/{self.camera}/start/{playlist_start}/end/{min(playlist_start + MAX_PLAYLIST_SECONDS, self.end_time)}/index.m3u8'" + ) + playlist_start += MAX_PLAYLIST_SECONDS + + ffmpeg_input = "-y -protocol_whitelist pipe,file,http,tcp -f concat -safe 0 -i /dev/stdin" + + if self.playback_factor == PlaybackFactorEnum.realtime: + ffmpeg_cmd = ( + f"ffmpeg -hide_banner {ffmpeg_input} -c copy {file_name}" + ).split(" ") + elif self.playback_factor == PlaybackFactorEnum.timelapse_25x: + ffmpeg_cmd = ( + parse_preset_hardware_acceleration_encode( + self.config.ffmpeg.hwaccel_args, + ffmpeg_input, + f"-vf setpts=0.04*PTS -r 30 -an {file_name}", + EncodeTypeEnum.timelapse, + ) + ).split(" ") + + p = sp.run( + ffmpeg_cmd, + input="\n".join(playlist_lines), + encoding="ascii", + capture_output=True, + ) + + if p.returncode != 0: + logger.error( + f"Failed to export recording for command {' '.join(ffmpeg_cmd)}" + ) + logger.error(p.stderr) + return + + logger.debug(f"Updating finalized export {file_name}") + os.rename(file_name, final_file_name) + logger.debug(f"Finished exporting {file_name}") diff --git a/frigate/record/maintainer.py b/frigate/record/maintainer.py index 651bd1214..079c4ffa9 100644 --- a/frigate/record/maintainer.py +++ b/frigate/record/maintainer.py @@ -9,14 +9,14 @@ import random import string import subprocess as sp import threading -import psutil - from collections import defaultdict from multiprocessing.synchronize import Event as MpEvent from pathlib import Path from typing import Any, Tuple -from frigate.config import RetainModeEnum, FrigateConfig +import psutil + +from frigate.config import FrigateConfig, RetainModeEnum from frigate.const import CACHE_DIR, MAX_SEGMENT_DURATION, RECORD_DIR from frigate.models import Event, Recordings from frigate.types import RecordMetricsTypes @@ -63,7 +63,7 @@ class RecordingMaintainer(threading.Thread): for nt in flist: if nt.path.startswith(CACHE_DIR): files_in_use.append(nt.path.split("/")[-1]) - except: + except psutil.Error: continue # group recordings by camera @@ -115,7 +115,7 @@ class RecordingMaintainer(threading.Thread): Event.select() .where( Event.camera == camera, - (Event.end_time == None) + (Event.end_time is None) | (Event.end_time >= recordings[0]["start_time"].timestamp()), Event.has_clip, ) @@ -127,7 +127,7 @@ class RecordingMaintainer(threading.Thread): # Just delete files if recordings are turned off if ( - not camera in self.config.cameras + camera not in self.config.cameras or not self.process_info[camera]["record_enabled"].value ): Path(cache_path).unlink(missing_ok=True) @@ -296,6 +296,7 @@ class RecordingMaintainer(threading.Thread): # add faststart to kept segments to improve metadata reading ffmpeg_cmd = [ "ffmpeg", + "-hide_banner", "-y", "-i", cache_path, @@ -394,4 +395,4 @@ class RecordingMaintainer(threading.Thread): duration = datetime.datetime.now().timestamp() - run_start wait_time = max(0, 5 - duration) - logger.info(f"Exiting recording maintenance...") + logger.info("Exiting recording maintenance...") diff --git a/frigate/record/record.py b/frigate/record/record.py index 518df327e..ba927d126 100644 --- a/frigate/record/record.py +++ b/frigate/record/record.py @@ -4,12 +4,11 @@ import logging import multiprocessing as mp import signal import threading - -from setproctitle import setproctitle from types import FrameType from typing import Optional from playhouse.sqliteq import SqliteQueueDatabase +from setproctitle import setproctitle from frigate.config import FrigateConfig from frigate.models import Event, Recordings, RecordingsToDelete, Timeline diff --git a/frigate/stats.py b/frigate/stats.py index 55db809d3..3fd881029 100644 --- a/frigate/stats.py +++ b/frigate/stats.py @@ -1,23 +1,30 @@ import asyncio import json import logging +import os +import shutil import threading import time -import psutil -import shutil -import os -import requests -from typing import Optional, Any from multiprocessing.synchronize import Event as MpEvent +from typing import Any, Optional + +import psutil +import requests +from requests.exceptions import RequestException from frigate.comms.dispatcher import Dispatcher from frigate.config import FrigateConfig -from frigate.const import DRIVER_AMD, DRIVER_ENV_VAR, RECORD_DIR, CLIPS_DIR, CACHE_DIR -from frigate.types import StatsTrackingTypes, CameraMetricsTypes -from frigate.util import get_amd_gpu_stats, get_intel_gpu_stats, get_nvidia_gpu_stats -from frigate.version import VERSION -from frigate.util import get_cpu_stats, get_bandwidth_stats +from frigate.const import CACHE_DIR, CLIPS_DIR, DRIVER_AMD, DRIVER_ENV_VAR, RECORD_DIR from frigate.object_detection import ObjectDetectProcess +from frigate.types import CameraMetricsTypes, StatsTrackingTypes +from frigate.util import ( + get_amd_gpu_stats, + get_bandwidth_stats, + get_cpu_stats, + get_intel_gpu_stats, + get_nvidia_gpu_stats, +) +from frigate.version import VERSION logger = logging.getLogger(__name__) @@ -31,7 +38,7 @@ def get_latest_version(config: FrigateConfig) -> str: "https://api.github.com/repos/blakeblackshear/frigate/releases/latest", timeout=10, ) - except: + except RequestException: return "unknown" response = request.json() @@ -308,4 +315,4 @@ class StatsEmitter(threading.Thread): ) self.dispatcher.publish("stats", json.dumps(stats), retain=False) logger.debug("Finished stats collection") - logger.info(f"Exiting stats emitter...") + logger.info("Exiting stats emitter...") diff --git a/frigate/storage.py b/frigate/storage.py index 5b66abbdc..6cdd54bdc 100644 --- a/frigate/storage.py +++ b/frigate/storage.py @@ -1,9 +1,9 @@ """Handle storage retention and usage.""" import logging -from pathlib import Path import shutil import threading +from pathlib import Path from peewee import fn @@ -107,7 +107,7 @@ class StorageMaintainer(threading.Thread): retained_events: Event = ( Event.select() .where( - Event.retain_indefinitely == True, + Event.retain_indefinitely is True, Event.has_clip, ) .order_by(Event.start_time.asc()) @@ -188,4 +188,4 @@ class StorageMaintainer(threading.Thread): if self.check_storage_needs_cleanup(): self.reduce_storage_consumption() - logger.info(f"Exiting storage maintainer...") + logger.info("Exiting storage maintainer...") diff --git a/frigate/test/test_config.py b/frigate/test/test_config.py index 7cd5e2217..8c1b5b586 100644 --- a/frigate/test/test_config.py +++ b/frigate/test/test_config.py @@ -1,13 +1,11 @@ import json import os import unittest + import numpy as np from pydantic import ValidationError -from frigate.config import ( - BirdseyeModeEnum, - FrigateConfig, -) +from frigate.config import BirdseyeModeEnum, FrigateConfig from frigate.const import MODEL_CACHE_DIR from frigate.detectors import DetectorTypeEnum from frigate.plus import PlusApi @@ -675,7 +673,7 @@ class TestConfig(unittest.TestCase): runtime_config = frigate_config.runtime_config() ffmpeg_cmds = runtime_config.cameras["back"].ffmpeg_cmds assert len(ffmpeg_cmds) == 1 - assert not "clips" in ffmpeg_cmds[0]["roles"] + assert "clips" not in ffmpeg_cmds[0]["roles"] def test_max_disappeared_default(self): config = { @@ -986,7 +984,7 @@ class TestConfig(unittest.TestCase): } frigate_config = FrigateConfig(**config) - runtime_config = frigate_config.runtime_config() + frigate_config.runtime_config() def test_global_detect(self): config = { @@ -1145,7 +1143,7 @@ class TestConfig(unittest.TestCase): assert config == frigate_config.dict(exclude_unset=True) runtime_config = frigate_config.runtime_config() - assert runtime_config.cameras["back"].snapshots.bounding_box == False + assert runtime_config.cameras["back"].snapshots.bounding_box is False assert runtime_config.cameras["back"].snapshots.height == 150 assert runtime_config.cameras["back"].snapshots.enabled diff --git a/frigate/test/test_copy_yuv_to_position.py b/frigate/test/test_copy_yuv_to_position.py index 16c97b79d..33582e2d1 100644 --- a/frigate/test/test_copy_yuv_to_position.py +++ b/frigate/test/test_copy_yuv_to_position.py @@ -1,7 +1,9 @@ +from unittest import TestCase, main + import cv2 import numpy as np -from unittest import TestCase, main -from frigate.util import get_yuv_crop, copy_yuv_to_position + +from frigate.util import copy_yuv_to_position, get_yuv_crop class TestCopyYuvToPosition(TestCase): diff --git a/frigate/test/test_ffmpeg_presets.py b/frigate/test/test_ffmpeg_presets.py index 92e0fa3bd..0d3dab856 100644 --- a/frigate/test/test_ffmpeg_presets.py +++ b/frigate/test/test_ffmpeg_presets.py @@ -1,4 +1,5 @@ import unittest + from frigate.config import FFMPEG_INPUT_ARGS_DEFAULT, FrigateConfig from frigate.ffmpeg_presets import parse_preset_input diff --git a/frigate/test/test_gpu_stats.py b/frigate/test/test_gpu_stats.py index 5742a583d..2cf92def1 100644 --- a/frigate/test/test_gpu_stats.py +++ b/frigate/test/test_gpu_stats.py @@ -1,7 +1,7 @@ import unittest from unittest.mock import MagicMock, patch -from frigate.util import get_amd_gpu_stats, get_intel_gpu_stats, get_nvidia_gpu_stats +from frigate.util import get_amd_gpu_stats, get_intel_gpu_stats class TestGpuStats(unittest.TestCase): diff --git a/frigate/test/test_http.py b/frigate/test/test_http.py index ecb500383..3557eccd3 100644 --- a/frigate/test/test_http.py +++ b/frigate/test/test_http.py @@ -6,15 +6,14 @@ import unittest from unittest.mock import patch from peewee_migrate import Router +from playhouse.shortcuts import model_to_dict from playhouse.sqlite_ext import SqliteExtDatabase from playhouse.sqliteq import SqliteQueueDatabase -from playhouse.shortcuts import model_to_dict from frigate.config import FrigateConfig from frigate.http import create_app from frigate.models import Event, Recordings from frigate.plus import PlusApi - from frigate.test.const import TEST_DB, TEST_DB_CLEANUPS @@ -128,22 +127,22 @@ class TestHttp(unittest.TestCase): with app.test_client() as client: _insert_mock_event(id) - events = client.get(f"/events").json + events = client.get("/events").json assert events assert len(events) == 1 assert events[0]["id"] == id _insert_mock_event(id2) - events = client.get(f"/events").json + events = client.get("/events").json assert events assert len(events) == 2 events = client.get( - f"/events", + "/events", query_string={"limit": 1}, ).json assert events assert len(events) == 1 events = client.get( - f"/events", + "/events", query_string={"has_clip": 0}, ).json assert not events @@ -230,12 +229,12 @@ class TestHttp(unittest.TestCase): event = client.get(f"/events/{id}").json assert event assert event["id"] == id - assert event["retain_indefinitely"] == True + assert event["retain_indefinitely"] is True client.delete(f"/events/{id}/retain") event = client.get(f"/events/{id}").json assert event assert event["id"] == id - assert event["retain_indefinitely"] == False + assert event["retain_indefinitely"] is False def test_set_delete_sub_label(self): app = create_app( diff --git a/frigate/test/test_object_detector.py b/frigate/test/test_object_detector.py index 9cdeeb6c7..1e1efa957 100644 --- a/frigate/test/test_object_detector.py +++ b/frigate/test/test_object_detector.py @@ -4,10 +4,10 @@ from unittest.mock import Mock, patch import numpy as np from pydantic import parse_obj_as -from frigate.config import DetectorConfig, InputTensorEnum, ModelConfig -from frigate.detectors import DetectorTypeEnum import frigate.detectors as detectors import frigate.object_detection +from frigate.config import DetectorConfig, InputTensorEnum, ModelConfig +from frigate.detectors import DetectorTypeEnum class TestLocalObjectDetector(unittest.TestCase): diff --git a/frigate/test/test_reduce_boxes.py b/frigate/test/test_reduce_boxes.py index 69d6f7177..d26fcd40c 100644 --- a/frigate/test/test_reduce_boxes.py +++ b/frigate/test/test_reduce_boxes.py @@ -1,5 +1,5 @@ -import numpy as np from unittest import TestCase, main + from frigate.video import box_overlaps, reduce_boxes diff --git a/frigate/test/test_storage.py b/frigate/test/test_storage.py index 22ea6fc1e..468d31916 100644 --- a/frigate/test/test_storage.py +++ b/frigate/test/test_storage.py @@ -1,21 +1,17 @@ import datetime -import json import logging import os import unittest -from unittest.mock import MagicMock, patch +from unittest.mock import MagicMock from peewee import DoesNotExist from peewee_migrate import Router from playhouse.sqlite_ext import SqliteExtDatabase from playhouse.sqliteq import SqliteQueueDatabase -from playhouse.shortcuts import model_to_dict from frigate.config import FrigateConfig -from frigate.http import create_app from frigate.models import Event, Recordings from frigate.storage import StorageMaintainer - from frigate.test.const import TEST_DB, TEST_DB_CLEANUPS diff --git a/frigate/test/test_yuv_region_2_rgb.py b/frigate/test/test_yuv_region_2_rgb.py index 96f421565..a56a78b1c 100644 --- a/frigate/test/test_yuv_region_2_rgb.py +++ b/frigate/test/test_yuv_region_2_rgb.py @@ -1,6 +1,8 @@ +from unittest import TestCase, main + import cv2 import numpy as np -from unittest import TestCase, main + from frigate.util import yuv_region_2_rgb @@ -33,7 +35,7 @@ class TestYuvRegion2RGB(TestCase): # cv2.imwrite(f"bgr_frame.jpg", self.bgr_frame) yuv_frame = cv2.cvtColor(bgr_frame, cv2.COLOR_BGR2YUV_I420) - cropped = yuv_region_2_rgb(yuv_frame, (0, 852, 648, 1500)) + yuv_region_2_rgb(yuv_frame, (0, 852, 648, 1500)) # cv2.imwrite(f"cropped.jpg", cv2.cvtColor(cropped, cv2.COLOR_RGB2BGR)) diff --git a/frigate/timeline.py b/frigate/timeline.py index e40549d08..9ca617ba9 100644 --- a/frigate/timeline.py +++ b/frigate/timeline.py @@ -1,16 +1,14 @@ """Record events for object, audio, etc. detections.""" import logging -import threading import queue +import threading +from multiprocessing.queues import Queue +from multiprocessing.synchronize import Event as MpEvent from frigate.config import FrigateConfig from frigate.events.maintainer import EventTypeEnum from frigate.models import Timeline - -from multiprocessing.queues import Queue -from multiprocessing.synchronize import Event as MpEvent - from frigate.util import to_relative_box logger = logging.getLogger(__name__) diff --git a/frigate/track/__init__.py b/frigate/track/__init__.py new file mode 100644 index 000000000..421a968da --- /dev/null +++ b/frigate/track/__init__.py @@ -0,0 +1,13 @@ +from abc import ABC, abstractmethod + +from frigate.config import DetectConfig + + +class ObjectTracker(ABC): + @abstractmethod + def __init__(self, config: DetectConfig): + pass + + @abstractmethod + def match_and_update(self, detections): + pass diff --git a/frigate/objects.py b/frigate/track/centroid_tracker.py similarity index 95% rename from frigate/objects.py rename to frigate/track/centroid_tracker.py index ed04ae191..fd4a293f9 100644 --- a/frigate/objects.py +++ b/frigate/track/centroid_tracker.py @@ -1,22 +1,16 @@ -import copy -import datetime -import itertools -import multiprocessing as mp import random import string -import threading -import time from collections import defaultdict -import cv2 import numpy as np from scipy.spatial import distance as dist from frigate.config import DetectConfig +from frigate.track import ObjectTracker from frigate.util import intersection_over_union -class ObjectTracker: +class CentroidTracker(ObjectTracker): def __init__(self, config: DetectConfig): self.tracked_objects = {} self.disappeared = {} @@ -141,11 +135,11 @@ class ObjectTracker: if self.is_expired(id): self.deregister(id) - def match_and_update(self, frame_time, new_objects): + def match_and_update(self, frame_time, detections): # group by name - new_object_groups = defaultdict(lambda: []) - for obj in new_objects: - new_object_groups[obj[0]].append( + detection_groups = defaultdict(lambda: []) + for obj in detections: + detection_groups[obj[0]].append( { "label": obj[0], "score": obj[1], @@ -160,17 +154,17 @@ class ObjectTracker: # update any tracked objects with labels that are not # seen in the current objects and deregister if needed for obj in list(self.tracked_objects.values()): - if not obj["label"] in new_object_groups: + if obj["label"] not in detection_groups: if self.disappeared[obj["id"]] >= self.max_disappeared: self.deregister(obj["id"]) else: self.disappeared[obj["id"]] += 1 - if len(new_objects) == 0: + if len(detections) == 0: return # track objects for each label type - for label, group in new_object_groups.items(): + for label, group in detection_groups.items(): current_objects = [ o for o in self.tracked_objects.values() if o["label"] == label ] diff --git a/frigate/track/norfair_tracker.py b/frigate/track/norfair_tracker.py new file mode 100644 index 000000000..76f50fd73 --- /dev/null +++ b/frigate/track/norfair_tracker.py @@ -0,0 +1,285 @@ +import random +import string + +import numpy as np +from norfair import Detection, Drawable, Tracker, draw_boxes +from norfair.drawing.drawer import Drawer + +from frigate.config import DetectConfig +from frigate.track import ObjectTracker +from frigate.util import intersection_over_union + + +# Normalizes distance from estimate relative to object size +# Other ideas: +# - if estimates are inaccurate for first N detections, compare with last_detection (may be fine) +# - could be variable based on time since last_detection +# - include estimated velocity in the distance (car driving by of a parked car) +# - include some visual similarity factor in the distance for occlusions +def distance(detection: np.array, estimate: np.array) -> float: + # ultimately, this should try and estimate distance in 3-dimensional space + # consider change in location, width, and height + + estimate_dim = np.diff(estimate, axis=0).flatten() + detection_dim = np.diff(detection, axis=0).flatten() + + # get bottom center positions + detection_position = np.array( + [np.average(detection[:, 0]), np.max(detection[:, 1])] + ) + estimate_position = np.array([np.average(estimate[:, 0]), np.max(estimate[:, 1])]) + + distance = (detection_position - estimate_position).astype(float) + # change in x relative to w + distance[0] /= estimate_dim[0] + # change in y relative to h + distance[1] /= estimate_dim[1] + + # get ratio of widths and heights + # normalize to 1 + widths = np.sort([estimate_dim[0], detection_dim[0]]) + heights = np.sort([estimate_dim[1], detection_dim[1]]) + width_ratio = widths[1] / widths[0] - 1.0 + height_ratio = heights[1] / heights[0] - 1.0 + + # change vector is relative x,y change and w,h ratio + change = np.append(distance, np.array([width_ratio, height_ratio])) + + # calculate euclidean distance of the change vector + return np.linalg.norm(change) + + +def frigate_distance(detection: Detection, tracked_object) -> float: + return distance(detection.points, tracked_object.estimate) + + +class NorfairTracker(ObjectTracker): + def __init__(self, config: DetectConfig): + self.tracked_objects = {} + self.disappeared = {} + self.positions = {} + self.max_disappeared = config.max_disappeared + self.detect_config = config + self.track_id_map = {} + # TODO: could also initialize a tracker per object class if there + # was a good reason to have different distance calculations + self.tracker = Tracker( + distance_function=frigate_distance, + distance_threshold=2.5, + initialization_delay=0, + hit_counter_max=self.max_disappeared, + ) + + def register(self, track_id, obj): + rand_id = "".join(random.choices(string.ascii_lowercase + string.digits, k=6)) + id = f"{obj['frame_time']}-{rand_id}" + self.track_id_map[track_id] = id + obj["id"] = id + obj["start_time"] = obj["frame_time"] + obj["motionless_count"] = 0 + obj["position_changes"] = 0 + self.tracked_objects[id] = obj + self.disappeared[id] = 0 + self.positions[id] = { + "xmins": [], + "ymins": [], + "xmaxs": [], + "ymaxs": [], + "xmin": 0, + "ymin": 0, + "xmax": self.detect_config.width, + "ymax": self.detect_config.height, + } + + def deregister(self, id): + del self.tracked_objects[id] + del self.disappeared[id] + + # tracks the current position of the object based on the last N bounding boxes + # returns False if the object has moved outside its previous position + def update_position(self, id, box): + position = self.positions[id] + position_box = ( + position["xmin"], + position["ymin"], + position["xmax"], + position["ymax"], + ) + + xmin, ymin, xmax, ymax = box + + iou = intersection_over_union(position_box, box) + + # if the iou drops below the threshold + # assume the object has moved to a new position and reset the computed box + if iou < 0.6: + self.positions[id] = { + "xmins": [xmin], + "ymins": [ymin], + "xmaxs": [xmax], + "ymaxs": [ymax], + "xmin": xmin, + "ymin": ymin, + "xmax": xmax, + "ymax": ymax, + } + return False + + # if there are less than 10 entries for the position, add the bounding box + # and recompute the position box + if len(position["xmins"]) < 10: + position["xmins"].append(xmin) + position["ymins"].append(ymin) + position["xmaxs"].append(xmax) + position["ymaxs"].append(ymax) + # by using percentiles here, we hopefully remove outliers + position["xmin"] = np.percentile(position["xmins"], 15) + position["ymin"] = np.percentile(position["ymins"], 15) + position["xmax"] = np.percentile(position["xmaxs"], 85) + position["ymax"] = np.percentile(position["ymaxs"], 85) + + return True + + def is_expired(self, id): + obj = self.tracked_objects[id] + # get the max frames for this label type or the default + max_frames = self.detect_config.stationary.max_frames.objects.get( + obj["label"], self.detect_config.stationary.max_frames.default + ) + + # if there is no max_frames for this label type, continue + if max_frames is None: + return False + + # if the object has exceeded the max_frames setting, deregister + if ( + obj["motionless_count"] - self.detect_config.stationary.threshold + > max_frames + ): + return True + + return False + + def update(self, track_id, obj): + id = self.track_id_map[track_id] + self.disappeared[id] = 0 + # update the motionless count if the object has not moved to a new position + if self.update_position(id, obj["box"]): + self.tracked_objects[id]["motionless_count"] += 1 + if self.is_expired(id): + self.deregister(id) + return + else: + # register the first position change and then only increment if + # the object was previously stationary + if ( + self.tracked_objects[id]["position_changes"] == 0 + or self.tracked_objects[id]["motionless_count"] + >= self.detect_config.stationary.threshold + ): + self.tracked_objects[id]["position_changes"] += 1 + self.tracked_objects[id]["motionless_count"] = 0 + + self.tracked_objects[id].update(obj) + + def update_frame_times(self, frame_time): + # if the object was there in the last frame, assume it's still there + detections = [ + ( + obj["label"], + obj["score"], + obj["box"], + obj["area"], + obj["ratio"], + obj["region"], + ) + for id, obj in self.tracked_objects.items() + if self.disappeared[id] == 0 + ] + self.match_and_update(frame_time, detections=detections) + + def match_and_update(self, frame_time, detections): + norfair_detections = [] + + for obj in detections: + # centroid is used for other things downstream + centroid_x = int((obj[2][0] + obj[2][2]) / 2.0) + centroid_y = int((obj[2][1] + obj[2][3]) / 2.0) + + # track based on top,left and bottom,right corners instead of centroid + points = np.array([[obj[2][0], obj[2][1]], [obj[2][2], obj[2][3]]]) + + norfair_detections.append( + Detection( + points=points, + label=obj[0], + data={ + "label": obj[0], + "score": obj[1], + "box": obj[2], + "area": obj[3], + "ratio": obj[4], + "region": obj[5], + "frame_time": frame_time, + "centroid": (centroid_x, centroid_y), + }, + ) + ) + + tracked_objects = self.tracker.update(detections=norfair_detections) + + # update or create new tracks + active_ids = [] + for t in tracked_objects: + active_ids.append(t.global_id) + if t.global_id not in self.track_id_map: + self.register(t.global_id, t.last_detection.data) + # if there wasn't a detection in this frame, increment disappeared + elif t.last_detection.data["frame_time"] != frame_time: + id = self.track_id_map[t.global_id] + self.disappeared[id] += 1 + # else update it + else: + self.update(t.global_id, t.last_detection.data) + + # clear expired tracks + expired_ids = [k for k in self.track_id_map.keys() if k not in active_ids] + for e_id in expired_ids: + self.deregister(self.track_id_map[e_id]) + del self.track_id_map[e_id] + + def debug_draw(self, frame, frame_time): + active_detections = [ + Drawable(id=obj.id, points=obj.last_detection.points, label=obj.label) + for obj in self.tracker.tracked_objects + if obj.last_detection.data["frame_time"] == frame_time + ] + missing_detections = [ + Drawable(id=obj.id, points=obj.last_detection.points, label=obj.label) + for obj in self.tracker.tracked_objects + if obj.last_detection.data["frame_time"] != frame_time + ] + # draw the estimated bounding box + draw_boxes(frame, self.tracker.tracked_objects, color="green", draw_ids=True) + # draw the detections that were detected in the current frame + draw_boxes(frame, active_detections, color="blue", draw_ids=True) + # draw the detections that are missing in the current frame + draw_boxes(frame, missing_detections, color="red", draw_ids=True) + + # draw the distance calculation for the last detection + # estimate vs detection + for obj in self.tracker.tracked_objects: + ld = obj.last_detection + # bottom right + text_anchor = ( + ld.points[1, 0], + ld.points[1, 1], + ) + frame = Drawer.text( + frame, + f"{obj.id}: {str(obj.last_distance)}", + position=text_anchor, + size=None, + color=(255, 0, 0), + thickness=None, + ) diff --git a/frigate/types.py b/frigate/types.py index 3cc401ebb..8c3e54654 100644 --- a/frigate/types.py +++ b/frigate/types.py @@ -1,7 +1,7 @@ -from typing import Optional, TypedDict +from multiprocessing.context import Process from multiprocessing.queues import Queue from multiprocessing.sharedctypes import Synchronized -from multiprocessing.context import Process +from typing import Optional, TypedDict from frigate.object_detection import ObjectDetectProcess diff --git a/frigate/util.py b/frigate/util.py index 47b7b4323..e624e877a 100755 --- a/frigate/util.py +++ b/frigate/util.py @@ -1,28 +1,26 @@ import copy import datetime -import logging -import shlex -import subprocess as sp import json +import logging +import os import re +import shlex import signal +import subprocess as sp import traceback import urllib.parse -import yaml -import os - from abc import ABC, abstractmethod from collections import Counter from collections.abc import Mapping from multiprocessing import shared_memory from typing import Any, AnyStr, Optional, Tuple -import py3nvml.py3nvml as nvml import cv2 import numpy as np -import os import psutil +import py3nvml.py3nvml as nvml import pytz +import yaml from frigate.const import REGEX_HTTP_CAMERA_USER_PASS, REGEX_RTSP_CAMERA_USER_PASS @@ -457,7 +455,7 @@ def copy_yuv_to_position( # clear v2 destination_frame[v2[1] : v2[3], v2[0] : v2[2]] = 128 - if not source_frame is None: + if source_frame is not None: # calculate the resized frame, maintaining the aspect ratio source_aspect_ratio = source_frame.shape[1] / (source_frame.shape[0] // 3 * 2) dest_aspect_ratio = destination_shape[1] / destination_shape[0] @@ -840,7 +838,7 @@ def get_cpu_stats() -> dict[str, dict]: "mem": f"{mem_pct}", "cmdline": " ".join(cmdline), } - except: + except Exception: continue return usages @@ -865,13 +863,13 @@ def get_bandwidth_stats() -> dict[str, dict]: stats = list(filter(lambda a: a != "", line.strip().split("\t"))) try: if re.search( - "(^ffmpeg|\/go2rtc|frigate\.detector\.[a-z]+)/([0-9]+)/", stats[0] + r"(^ffmpeg|\/go2rtc|frigate\.detector\.[a-z]+)/([0-9]+)/", stats[0] ): process = stats[0].split("/") usages[process[len(process) - 2]] = { "bandwidth": round(float(stats[1]) + float(stats[2]), 1), } - except: + except (IndexError, ValueError): continue return usages @@ -932,7 +930,7 @@ def get_intel_gpu_stats() -> dict[str, str]: # render is used for qsv render = [] - for result in re.findall('"Render/3D/0":{[a-z":\d.,%]+}', reading): + for result in re.findall(r'"Render/3D/0":{[a-z":\d.,%]+}', reading): packet = json.loads(result[14:]) single = packet.get("busy", 0.0) render.append(float(single)) @@ -991,11 +989,11 @@ def get_nvidia_gpu_stats() -> dict[int, dict]: "gpu": gpu_util, "mem": gpu_mem_util, } - except: + except Exception: + pass + finally: return results - return results - def ffprobe_stream(path: str) -> sp.CompletedProcess: """Run ffprobe on stream.""" diff --git a/frigate/video.py b/frigate/video.py index a3356a586..08808038e 100755 --- a/frigate/video.py +++ b/frigate/video.py @@ -10,16 +10,17 @@ import threading import time from collections import defaultdict -import numpy as np import cv2 +import numpy as np from setproctitle import setproctitle from frigate.config import CameraConfig, DetectConfig, PixelFormatEnum from frigate.const import CACHE_DIR -from frigate.object_detection import RemoteObjectDetector from frigate.log import LogPipe from frigate.motion import MotionDetector -from frigate.objects import ObjectTracker +from frigate.object_detection import RemoteObjectDetector +from frigate.track import ObjectTracker +from frigate.track.norfair_tracker import NorfairTracker from frigate.util import ( EventsPerSecond, FrameManager, @@ -30,8 +31,8 @@ from frigate.util import ( intersection, intersection_over_union, listen, - yuv_region_2_rgb, yuv_region_2_bgr, + yuv_region_2_rgb, yuv_region_2_yuv, ) @@ -45,7 +46,7 @@ def filtered(obj, objects_to_track, object_filters): object_area = obj[3] object_ratio = obj[4] - if not object_name in objects_to_track: + if object_name not in objects_to_track: return True if object_name in object_filters: @@ -73,7 +74,7 @@ def filtered(obj, objects_to_track, object_filters): if obj_settings.max_ratio < object_ratio: return True - if not obj_settings.mask is None: + if obj_settings.mask is not None: # compute the coordinates of the object and make sure # the location isn't outside the bounds of the image (can happen from rounding) object_xmin = object_box[0] @@ -169,20 +170,20 @@ def capture_frames( skipped_eps.start() while True: fps.value = frame_rate.eps() - skipped_fps = skipped_eps.eps() + skipped_eps.eps() current_frame.value = datetime.datetime.now().timestamp() frame_name = f"{camera_name}{current_frame.value}" frame_buffer = frame_manager.create(frame_name, frame_size) try: frame_buffer[:] = ffmpeg_process.stdout.read(frame_size) - except Exception as e: + except Exception: # shutdown has been initiated if stop_event.is_set(): break logger.error(f"{camera_name}: Unable to read frames from ffmpeg process.") - if ffmpeg_process.poll() != None: + if ffmpeg_process.poll() is not None: logger.error( f"{camera_name}: ffmpeg process is not running. exiting capture thread..." ) @@ -472,7 +473,7 @@ def track_camera( name, labelmap, detection_queue, result_connection, model_config, stop_event ) - object_tracker = ObjectTracker(config.detect) + object_tracker = NorfairTracker(config.detect) frame_manager = SharedMemoryFrameManager() @@ -604,7 +605,7 @@ def process_frames( while not stop_event.is_set(): if exit_on_empty and frame_queue.empty(): - logger.info(f"Exiting track_objects...") + logger.info("Exiting track_objects...") break try: @@ -655,7 +656,7 @@ def process_frames( tracked_object_boxes = [ obj["box"] for obj in object_tracker.tracked_objects.values() - if not obj["id"] in stationary_object_ids + if obj["id"] not in stationary_object_ids ] # combine motion boxes with known locations of existing objects @@ -847,6 +848,17 @@ def process_frames( else: object_tracker.update_frame_times(frame_time) + # debug tracking by writing frames + if False: + bgr_frame = cv2.cvtColor( + frame, + cv2.COLOR_YUV2BGR_I420, + ) + object_tracker.debug_draw(bgr_frame, frame_time) + cv2.imwrite( + f"debug/frames/track-{'{:.6f}'.format(frame_time)}.jpg", bgr_frame + ) + # add to the queue if not full if detected_objects_queue.full(): frame_manager.delete(f"{camera_name}{frame_time}") diff --git a/frigate/watchdog.py b/frigate/watchdog.py index 5df826f0e..d1573f0b0 100644 --- a/frigate/watchdog.py +++ b/frigate/watchdog.py @@ -2,12 +2,10 @@ import datetime import logging import threading import time -import os -import signal +from multiprocessing.synchronize import Event as MpEvent from frigate.object_detection import ObjectDetectProcess from frigate.util import restart_frigate -from multiprocessing.synchronize import Event as MpEvent logger = logging.getLogger(__name__) @@ -39,4 +37,4 @@ class FrigateWatchdog(threading.Thread): logger.info("Detection appears to have stopped. Exiting Frigate...") restart_frigate() - logger.info(f"Exiting watchdog...") + logger.info("Exiting watchdog...") diff --git a/migrations/001_create_events_table.py b/migrations/001_create_events_table.py index d9b0f0853..9e8ad1b60 100644 --- a/migrations/001_create_events_table.py +++ b/migrations/001_create_events_table.py @@ -21,14 +21,7 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from decimal import ROUND_HALF_EVEN - -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass SQL = pw.SQL diff --git a/migrations/002_add_clip_snapshot.py b/migrations/002_add_clip_snapshot.py index aaa4a03c9..1431c9c85 100644 --- a/migrations/002_add_clip_snapshot.py +++ b/migrations/002_add_clip_snapshot.py @@ -21,15 +21,9 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from decimal import ROUND_HALF_EVEN -from frigate.models import Event -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Event SQL = pw.SQL diff --git a/migrations/003_create_recordings_table.py b/migrations/003_create_recordings_table.py index e13ae657e..82b15eb9c 100644 --- a/migrations/003_create_recordings_table.py +++ b/migrations/003_create_recordings_table.py @@ -22,8 +22,6 @@ Some examples (model - class or model name):: """ import peewee as pw -from frigate.models import Recordings - SQL = pw.SQL diff --git a/migrations/004_add_bbox_region_area.py b/migrations/004_add_bbox_region_area.py index bcc362aac..da4ca7ac8 100644 --- a/migrations/004_add_bbox_region_area.py +++ b/migrations/004_add_bbox_region_area.py @@ -21,16 +21,10 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Event +from playhouse.sqlite_ext import JSONField -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Event SQL = pw.SQL diff --git a/migrations/005_make_end_time_nullable.py b/migrations/005_make_end_time_nullable.py index 5c8cf6505..87d0e3fd4 100644 --- a/migrations/005_make_end_time_nullable.py +++ b/migrations/005_make_end_time_nullable.py @@ -21,16 +21,9 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Event -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Event SQL = pw.SQL diff --git a/migrations/006_add_motion_active_objects.py b/migrations/006_add_motion_active_objects.py index 6bd564b8c..2980b441d 100644 --- a/migrations/006_add_motion_active_objects.py +++ b/migrations/006_add_motion_active_objects.py @@ -21,16 +21,9 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Recordings -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Recordings SQL = pw.SQL diff --git a/migrations/007_add_retain_indefinitely.py b/migrations/007_add_retain_indefinitely.py index a46b72e29..cb5f9da92 100644 --- a/migrations/007_add_retain_indefinitely.py +++ b/migrations/007_add_retain_indefinitely.py @@ -21,16 +21,9 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Event -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Event SQL = pw.SQL diff --git a/migrations/008_add_sub_label.py b/migrations/008_add_sub_label.py index 00603c63e..56c4bb75a 100644 --- a/migrations/008_add_sub_label.py +++ b/migrations/008_add_sub_label.py @@ -21,16 +21,9 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Event -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Event SQL = pw.SQL diff --git a/migrations/009_add_object_filter_ratio.py b/migrations/009_add_object_filter_ratio.py index cc23e1d86..e5a00683d 100644 --- a/migrations/009_add_object_filter_ratio.py +++ b/migrations/009_add_object_filter_ratio.py @@ -22,6 +22,7 @@ Some examples (model - class or model name):: """ import peewee as pw + from frigate.models import Event SQL = pw.SQL diff --git a/migrations/010_add_plus_image_id.py b/migrations/010_add_plus_image_id.py index 0e239e58b..6b8c7ccc6 100644 --- a/migrations/010_add_plus_image_id.py +++ b/migrations/010_add_plus_image_id.py @@ -21,16 +21,9 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Event -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Event SQL = pw.SQL diff --git a/migrations/012_add_segment_size.py b/migrations/012_add_segment_size.py index c5ac1ed93..7a1c79736 100644 --- a/migrations/012_add_segment_size.py +++ b/migrations/012_add_segment_size.py @@ -21,16 +21,9 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Recordings -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Recordings SQL = pw.SQL diff --git a/migrations/013_create_timeline_table.py b/migrations/013_create_timeline_table.py index fea7867af..7a83d96c7 100644 --- a/migrations/013_create_timeline_table.py +++ b/migrations/013_create_timeline_table.py @@ -21,16 +21,7 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Recordings - -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass SQL = pw.SQL @@ -39,9 +30,15 @@ def migrate(migrator, database, fake=False, **kwargs): migrator.sql( 'CREATE TABLE IF NOT EXISTS "timeline" ("timestamp" DATETIME NOT NULL, "camera" VARCHAR(20) NOT NULL, "source" VARCHAR(20) NOT NULL, "source_id" VARCHAR(30), "class_type" VARCHAR(50) NOT NULL, "data" JSON)' ) - migrator.sql('CREATE INDEX IF NOT EXISTS "timeline_camera" ON "timeline" ("camera")') - migrator.sql('CREATE INDEX IF NOT EXISTS "timeline_source" ON "timeline" ("source")') - migrator.sql('CREATE INDEX IF NOT EXISTS "timeline_source_id" ON "timeline" ("source_id")') + migrator.sql( + 'CREATE INDEX IF NOT EXISTS "timeline_camera" ON "timeline" ("camera")' + ) + migrator.sql( + 'CREATE INDEX IF NOT EXISTS "timeline_source" ON "timeline" ("source")' + ) + migrator.sql( + 'CREATE INDEX IF NOT EXISTS "timeline_source_id" ON "timeline" ("source_id")' + ) def rollback(migrator, database, fake=False, **kwargs): diff --git a/migrations/014_event_updates_for_fp.py b/migrations/014_event_updates_for_fp.py index 5d075596b..caa609bfa 100644 --- a/migrations/014_event_updates_for_fp.py +++ b/migrations/014_event_updates_for_fp.py @@ -21,16 +21,9 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Event -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Event SQL = pw.SQL diff --git a/migrations/015_event_refactor.py b/migrations/015_event_refactor.py index d8a8a387c..1bcb9c510 100644 --- a/migrations/015_event_refactor.py +++ b/migrations/015_event_refactor.py @@ -21,16 +21,10 @@ Some examples (model - class or model name):: """ -import datetime as dt import peewee as pw -from playhouse.sqlite_ext import * -from decimal import ROUND_HALF_EVEN -from frigate.models import Event +from playhouse.sqlite_ext import JSONField -try: - import playhouse.postgres_ext as pw_pext -except ImportError: - pass +from frigate.models import Event SQL = pw.SQL diff --git a/migrations/016_sublabel_increase.py b/migrations/016_sublabel_increase.py index b46b9fc79..536ea0a61 100644 --- a/migrations/016_sublabel_increase.py +++ b/migrations/016_sublabel_increase.py @@ -1,6 +1,5 @@ import peewee as pw -from playhouse.migrate import * -from playhouse.sqlite_ext import * + from frigate.models import Event diff --git a/process_clip.py b/process_clip.py index d8dabbedd..16bf7afa4 100644 --- a/process_clip.py +++ b/process_clip.py @@ -1,8 +1,4 @@ -import sys -from typing_extensions import runtime - -sys.path.append("/lab/frigate") - +import csv import json import logging import multiprocessing as mp @@ -11,21 +7,26 @@ import subprocess as sp import sys import click -import csv import cv2 import numpy as np -from frigate.config import FrigateConfig -from frigate.object_detection import LocalObjectDetector -from frigate.motion import MotionDetector -from frigate.object_processing import CameraState -from frigate.objects import ObjectTracker -from frigate.util import ( +sys.path.append("/workspace/frigate") + +from frigate.config import FrigateConfig # noqa: E402 +from frigate.motion import MotionDetector # noqa: E402 +from frigate.object_detection import LocalObjectDetector # noqa: E402 +from frigate.object_processing import CameraState # noqa: E402 +from frigate.track.centroid_tracker import CentroidTracker # noqa: E402 +from frigate.util import ( # noqa: E402 EventsPerSecond, SharedMemoryFrameManager, draw_box_with_label, ) -from frigate.video import capture_frames, process_frames, start_or_restart_ffmpeg +from frigate.video import ( # noqa: E402 + capture_frames, + process_frames, + start_or_restart_ffmpeg, +) logging.basicConfig() logging.root.setLevel(logging.DEBUG) @@ -107,7 +108,7 @@ class ProcessClip: motion_detector = MotionDetector(self.frame_shape, self.camera_config.motion) motion_detector.save_images = False - object_tracker = ObjectTracker(self.camera_config.detect) + object_tracker = CentroidTracker(self.camera_config.detect) process_info = { "process_fps": mp.Value("d", 0.0), "detection_fps": mp.Value("d", 0.0), @@ -247,7 +248,7 @@ def process(path, label, output, debug_path): clips.append(path) json_config = { - "mqtt": {"host": "mqtt"}, + "mqtt": {"enabled": False}, "detectors": {"coral": {"type": "edgetpu", "device": "usb"}}, "cameras": { "camera": { @@ -281,7 +282,7 @@ def process(path, label, output, debug_path): json_config["cameras"]["camera"]["ffmpeg"]["inputs"][0]["path"] = c frigate_config = FrigateConfig(**json_config) - runtime_config = frigate_config.runtime_config + runtime_config = frigate_config.runtime_config() runtime_config.cameras["camera"].create_ffmpeg_cmds() process_clip = ProcessClip(c, frame_shape, runtime_config) @@ -310,7 +311,6 @@ def process(path, label, output, debug_path): for result in results: if count == 0: - # Writing headers of CSV file header = ["file"] + list(result[1].keys()) csv_writer.writerow(header) diff --git a/pyproject.toml b/pyproject.toml new file mode 100644 index 000000000..e3ef3faf5 --- /dev/null +++ b/pyproject.toml @@ -0,0 +1,5 @@ +[tool.isort] +profile = "black" + +[tool.ruff] +ignore = ["E501"] \ No newline at end of file diff --git a/requirements-dev.txt b/requirements-dev.txt index 29f004455..0acd15ae4 100644 --- a/requirements-dev.txt +++ b/requirements-dev.txt @@ -1,2 +1,3 @@ -pylint == 2.17.* black == 23.3.* +isort +ruff diff --git a/requirements-wheels.txt b/requirements-wheels.txt index d785df5d6..f02317e41 100644 --- a/requirements-wheels.txt +++ b/requirements-wheels.txt @@ -8,17 +8,18 @@ onvif_zeep == 0.2.12 opencv-python-headless == 4.5.5.* paho-mqtt == 1.6.* peewee == 3.16.* -peewee_migrate == 1.7.* +peewee_migrate == 1.10.* psutil == 5.9.* pydantic == 1.10.* git+https://github.com/fbcotter/py3nvml#egg=py3nvml PyYAML == 6.0 pytz == 2023.3 -tzlocal == 4.3 +tzlocal == 5.0.* types-PyYAML == 6.0.* -requests == 2.30.* -types-requests == 2.28.* +requests == 2.31.* +types-requests == 2.31.* scipy == 1.10.* +norfair == 2.2.* setproctitle == 1.3.* ws4py == 0.5.* # Openvino Library - Custom built with MYRIAD support diff --git a/web/package-lock.json b/web/package-lock.json index 26720e3ea..d1076106f 100644 --- a/web/package-lock.json +++ b/web/package-lock.json @@ -71,12 +71,12 @@ } }, "node_modules/@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "dependencies": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { @@ -175,20 +175,6 @@ "node": ">=6.9.0" } }, - "node_modules/@babel/generator/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/@babel/helper-annotate-as-pure": { "version": "7.18.6", "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.18.6.tgz", @@ -908,14 +894,14 @@ } }, "node_modules/@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "dependencies": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -958,9 +944,9 @@ } }, "node_modules/@eslint/js": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", - "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1120,13 +1106,14 @@ } }, "node_modules/@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "dependencies": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" }, "engines": { "node": ">=6.0.0" @@ -1593,9 +1580,9 @@ "dev": true }, "node_modules/@types/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", + "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", "dev": true }, "node_modules/@types/chai-subset": { @@ -1787,15 +1774,15 @@ "dev": true }, "node_modules/@typescript-eslint/eslint-plugin": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz", - "integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.8.tgz", + "integrity": "sha512-JDMOmhXteJ4WVKOiHXGCoB96ADWg9q7efPWHRViT/f09bA8XOMLAVHHju3l0MkZnG1izaWXYmgvQcUjTRcpShQ==", "dev": true, "dependencies": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/type-utils": "5.59.2", - "@typescript-eslint/utils": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.8", + "@typescript-eslint/type-utils": "5.59.8", + "@typescript-eslint/utils": "5.59.8", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -1821,13 +1808,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", - "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz", + "integrity": "sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2" + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1838,9 +1825,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/types": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", - "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.8.tgz", + "integrity": "sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -1851,13 +1838,13 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", - "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz", + "integrity": "sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -1878,17 +1865,17 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz", - "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.8.tgz", + "integrity": "sha512-Tr65630KysnNn9f9G7ROF3w1b5/7f6QVCJ+WK9nhIocWmx9F+TmCAcglF26Vm7z8KCTwoKcNEBZrhlklla3CKg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.8", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/typescript-estree": "5.59.8", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -1904,12 +1891,12 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", - "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz", + "integrity": "sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/types": "5.59.8", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -1943,9 +1930,9 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -1977,14 +1964,14 @@ } }, "node_modules/@typescript-eslint/parser": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz", - "integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.8.tgz", + "integrity": "sha512-AnR19RjJcpjoeGojmwZtCwBX/RidqDZtzcbG3xHrmz0aHHoOcbWnpDllenRDmDvsV0RQ6+tbb09/kyc+UT9Orw==", "dev": true, "dependencies": { - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.8", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/typescript-estree": "5.59.8", "debug": "^4.3.4" }, "engines": { @@ -2004,13 +1991,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", - "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz", + "integrity": "sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2" + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2021,9 +2008,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/types": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", - "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.8.tgz", + "integrity": "sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2034,13 +2021,13 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", - "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz", + "integrity": "sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2061,12 +2048,12 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", - "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz", + "integrity": "sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/types": "5.59.8", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2078,9 +2065,9 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -2110,13 +2097,13 @@ } }, "node_modules/@typescript-eslint/type-utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz", - "integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.8.tgz", + "integrity": "sha512-+5M518uEIHFBy3FnyqZUF3BMP+AXnYn4oyH8RF012+e7/msMY98FhGL5SrN29NQ9xDgvqCgYnsOiKp1VjZ/fpA==", "dev": true, "dependencies": { - "@typescript-eslint/typescript-estree": "5.59.2", - "@typescript-eslint/utils": "5.59.2", + "@typescript-eslint/typescript-estree": "5.59.8", + "@typescript-eslint/utils": "5.59.8", "debug": "^4.3.4", "tsutils": "^3.21.0" }, @@ -2137,13 +2124,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/scope-manager": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", - "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz", + "integrity": "sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2" + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2154,9 +2141,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/types": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", - "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.8.tgz", + "integrity": "sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -2167,13 +2154,13 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/typescript-estree": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", - "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz", + "integrity": "sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -2194,17 +2181,17 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz", - "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.8.tgz", + "integrity": "sha512-Tr65630KysnNn9f9G7ROF3w1b5/7f6QVCJ+WK9nhIocWmx9F+TmCAcglF26Vm7z8KCTwoKcNEBZrhlklla3CKg==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.8", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/typescript-estree": "5.59.8", "eslint-scope": "^5.1.1", "semver": "^7.3.7" }, @@ -2220,12 +2207,12 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/@typescript-eslint/visitor-keys": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", - "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz", + "integrity": "sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==", "dev": true, "dependencies": { - "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/types": "5.59.8", "eslint-visitor-keys": "^3.3.0" }, "engines": { @@ -2259,9 +2246,9 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -2455,12 +2442,12 @@ } }, "node_modules/@vitest/coverage-c8": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.31.0.tgz", - "integrity": "sha512-h72qN1D962AO7UefQVulm9JFP5ACS7OfhCdBHioXU8f7ohH/+NTZCgAqmgcfRNHHO/8wLFxx+93YVxhodkEJVA==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.31.4.tgz", + "integrity": "sha512-VPx368m4DTcpA/P0v3YdVxl4QOSh1DbUcXURLRvDShrIB5KxOgfzw4Bn2R8AhAe/GyiWW/FIsJ/OJdYXCCiC1w==", "dev": true, "dependencies": { - "@ampproject/remapping": "^2.2.0", + "@ampproject/remapping": "^2.2.1", "c8": "^7.13.0", "magic-string": "^0.30.0", "picocolors": "^1.0.0", @@ -2474,13 +2461,13 @@ } }, "node_modules/@vitest/expect": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.31.0.tgz", - "integrity": "sha512-Jlm8ZTyp6vMY9iz9Ny9a0BHnCG4fqBa8neCF6Pk/c/6vkUk49Ls6UBlgGAU82QnzzoaUs9E/mUhq/eq9uMOv/g==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.31.4.tgz", + "integrity": "sha512-tibyx8o7GUyGHZGyPgzwiaPaLDQ9MMuCOrc03BYT0nryUuhLbL7NV2r/q98iv5STlwMgaKuFJkgBW/8iPKwlSg==", "dev": true, "dependencies": { - "@vitest/spy": "0.31.0", - "@vitest/utils": "0.31.0", + "@vitest/spy": "0.31.4", + "@vitest/utils": "0.31.4", "chai": "^4.3.7" }, "funding": { @@ -2488,12 +2475,12 @@ } }, "node_modules/@vitest/runner": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.31.0.tgz", - "integrity": "sha512-H1OE+Ly7JFeBwnpHTrKyCNm/oZgr+16N4qIlzzqSG/YRQDATBYmJb/KUn3GrZaiQQyL7GwpNHVZxSQd6juLCgw==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.31.4.tgz", + "integrity": "sha512-Wgm6UER+gwq6zkyrm5/wbpXGF+g+UBB78asJlFkIOwyse0pz8lZoiC6SW5i4gPnls/zUcPLWS7Zog0LVepXnpg==", "dev": true, "dependencies": { - "@vitest/utils": "0.31.0", + "@vitest/utils": "0.31.4", "concordance": "^5.0.4", "p-limit": "^4.0.0", "pathe": "^1.1.0" @@ -2530,9 +2517,9 @@ } }, "node_modules/@vitest/snapshot": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.31.0.tgz", - "integrity": "sha512-5dTXhbHnyUMTMOujZPB0wjFjQ6q5x9c8TvAsSPUNKjp1tVU7i9pbqcKPqntyu2oXtmVxKbuHCqrOd+Ft60r4tg==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.31.4.tgz", + "integrity": "sha512-LemvNumL3NdWSmfVAMpXILGyaXPkZbG5tyl6+RQSdcHnTj6hvA49UAI8jzez9oQyE/FWLKRSNqTGzsHuk89LRA==", "dev": true, "dependencies": { "magic-string": "^0.30.0", @@ -2544,9 +2531,9 @@ } }, "node_modules/@vitest/spy": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.31.0.tgz", - "integrity": "sha512-IzCEQ85RN26GqjQNkYahgVLLkULOxOm5H/t364LG0JYb3Apg0PsYCHLBYGA006+SVRMWhQvHlBBCyuByAMFmkg==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.31.4.tgz", + "integrity": "sha512-3ei5ZH1s3aqbEyftPAzSuunGICRuhE+IXOmpURFdkm5ybUADk+viyQfejNk6q8M5QGX8/EVKw+QWMEP3DTJDag==", "dev": true, "dependencies": { "tinyspy": "^2.1.0" @@ -2556,18 +2543,18 @@ } }, "node_modules/@vitest/ui": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.31.0.tgz", - "integrity": "sha512-Dy86l6r3/dbJposgm7w+oqb/15UWJ0lDBbEQaS1ived3+0CTaMbT8OMkUf9vNBkSL47kvBHEBnZLa5fw5i9gUQ==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.31.4.tgz", + "integrity": "sha512-sKM16ITX6HrNFF+lNZ2AQAen4/6Bx2i6KlBfIvkUjcTgc5YII/j2ltcX14oCUv4EA0OTWGQuGhO3zDoAsTENGA==", "dev": true, "dependencies": { - "@vitest/utils": "0.31.0", + "@vitest/utils": "0.31.4", "fast-glob": "^3.2.12", "fflate": "^0.7.4", "flatted": "^3.2.7", "pathe": "^1.1.0", "picocolors": "^1.0.0", - "sirv": "^2.0.2" + "sirv": "^2.0.3" }, "funding": { "url": "https://opencollective.com/vitest" @@ -2577,9 +2564,9 @@ } }, "node_modules/@vitest/utils": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.31.0.tgz", - "integrity": "sha512-kahaRyLX7GS1urekRXN2752X4gIgOGVX4Wo8eDUGUkTWlGpXzf5ZS6N9RUUS+Re3XEE8nVGqNyxkSxF5HXlGhQ==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.31.4.tgz", + "integrity": "sha512-DobZbHacWznoGUfYU8XDPY78UubJxXfMNY1+SUdOp1NsI34eopSA6aZMeaGu10waSOeYwE8lxrd/pLfT0RMxjQ==", "dev": true, "dependencies": { "concordance": "^5.0.4", @@ -3457,9 +3444,9 @@ } }, "node_modules/concordance/node_modules/semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "dependencies": { "lru-cache": "^6.0.0" @@ -3969,15 +3956,15 @@ } }, "node_modules/eslint": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", - "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "dependencies": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.39.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.41.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -3988,8 +3975,8 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -3997,13 +3984,12 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -4237,9 +4223,9 @@ } }, "node_modules/eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4358,14 +4344,14 @@ } }, "node_modules/espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "dependencies": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "eslint-visitor-keys": "^3.4.1" }, "engines": { "node": "^12.22.0 || ^14.17.0 || >=16.0.0" @@ -4489,9 +4475,9 @@ "dev": true }, "node_modules/fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "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": { @@ -4908,6 +4894,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "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/graphql": { "version": "16.6.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", @@ -5114,12 +5106,9 @@ } }, "node_modules/idb-keyval": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.0.tgz", - "integrity": "sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==", - "dependencies": { - "safari-14-idb-fix": "^3.0.0" - } + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", + "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==" }, "node_modules/ieee754": { "version": "1.2.1", @@ -5151,9 +5140,9 @@ } }, "node_modules/immer": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.1.tgz", - "integrity": "sha512-zg++jJLsKKTwXGeSYIw0HgChSYQGtu0UDTnbKx5aGLYgte4CwTmH9eJDYyQ6FheyUtBe+lQW9FrGxya1G+Dtmg==", + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==", "funding": { "type": "opencollective", "url": "https://opencollective.com/immer" @@ -6217,12 +6206,6 @@ "node": ">=0.10.0" } }, - "node_modules/js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, "node_modules/js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -6251,9 +6234,9 @@ } }, "node_modules/jsdom": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.0.0.tgz", - "integrity": "sha512-p5ZTEb5h+O+iU02t0GfEjAnkdYPrQSkfuTSMkMYyIoMvUNEHsbG0bHHbfXIcfTqD2UfvjQX7mmgiFsyRwGscVw==", + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", + "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", "dev": true, "dependencies": { "abab": "^2.0.6", @@ -6749,15 +6732,15 @@ } }, "node_modules/mlly": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.2.0.tgz", - "integrity": "sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.3.0.tgz", + "integrity": "sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==", "dev": true, "dependencies": { "acorn": "^8.8.2", "pathe": "^1.1.0", - "pkg-types": "^1.0.2", - "ufo": "^1.1.1" + "pkg-types": "^1.0.3", + "ufo": "^1.1.2" } }, "node_modules/monaco-editor": { @@ -7555,9 +7538,9 @@ } }, "node_modules/postcss": { - "version": "8.4.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", - "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "version": "8.4.24", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", + "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", "dev": true, "funding": [ { @@ -7686,9 +7669,9 @@ "dev": true }, "node_modules/preact": { - "version": "10.13.2", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.13.2.tgz", - "integrity": "sha512-q44QFLhOhty2Bd0Y46fnYW0gD/cbVM9dUVtNTDKPcdXSMA7jfY+Jpd6rk3GB0lcQss0z5s/6CmVP0Z/hV+g6pw==", + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.15.1.tgz", + "integrity": "sha512-qs2ansoQEwzNiV5eAcRT1p1EC/dmEzaATVDJNiB3g2sRDWdA7b7MurXdJjB2+/WQktGWZwxvDrnuRFbWuIr64g==", "funding": { "type": "opencollective", "url": "https://opencollective.com/preact" @@ -7700,9 +7683,9 @@ "integrity": "sha512-8bg1007akXs3YDmzYT4McaTe6ji2FIzcc0/NTlu+vjJaKPNQ8lNG/HQ6LP+FoIxQ4m/KH5vvJCHJN5ADp2iNGA==" }, "node_modules/preact-router": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/preact-router/-/preact-router-4.1.0.tgz", - "integrity": "sha512-y1w2YvVpKAju9FMV+fAVR1NpH4MW5q07BZrziMZeg6F/rGJ9KvLUZtjOqsy2I8fDYiX36AM1AQTXIIK3jigBhA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/preact-router/-/preact-router-4.1.1.tgz", + "integrity": "sha512-+LGrB3b2nR7+8vzyHw8i2/TjZazs3oMJovIEgBChPBXMDSISmwj2WDynZh8KDxZRK2GuXlqHPk15mMjaYWZH4g==", "peerDependencies": { "preact": ">=10" } @@ -8136,11 +8119,6 @@ "tslib": "^2.1.0" } }, - "node_modules/safari-14-idb-fix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/safari-14-idb-fix/-/safari-14-idb-fix-3.0.0.tgz", - "integrity": "sha512-eBNFLob4PMq8JA1dGyFn6G97q3/WzNtFK4RnzT1fnLq+9RyrGknzYiM/9B12MnKAxuj1IXr7UKYtTNtjyKMBog==" - }, "node_modules/safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -8250,9 +8228,9 @@ "dev": true }, "node_modules/sirv": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.2.tgz", - "integrity": "sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", + "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", "dev": true, "dependencies": { "@polka/url": "^1.0.0-next.20", @@ -8315,9 +8293,9 @@ "dev": true }, "node_modules/strftime": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.1.tgz", - "integrity": "sha512-nVvH6JG8KlXFPC0f8lojLgEsPA18lRpLZ+RrJh/NkQV2tqOgZfbas8gcU8SFgnnqR3rWzZPYu6N2A3xzs/8rQg==", + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.2.tgz", + "integrity": "sha512-Y6IZaTVM80chcMe7j65Gl/0nmlNdtt+KWPle5YeCAjmsBfw+id2qdaJ5MDrxUq+OmHKab+jHe7mUjU/aNMSZZg==", "engines": { "node": ">=0.2.0" } @@ -8471,20 +8449,6 @@ "node": ">=8" } }, - "node_modules/sucrase/node_modules/@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "dependencies": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - }, - "engines": { - "node": ">=6.0.0" - } - }, "node_modules/sucrase/node_modules/glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -8697,9 +8661,9 @@ } }, "node_modules/tinybench": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.4.0.tgz", - "integrity": "sha512-iyziEiyFxX4kyxSp+MtY1oCH/lvjH3PxFN8PGCDeqcZWAJ/i+9y+nL85w99PxVzrIvew/GSkSbDYtiGVa85Afg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz", + "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==", "dev": true }, "node_modules/tinypool": { @@ -8712,9 +8676,9 @@ } }, "node_modules/tinyspy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.0.tgz", - "integrity": "sha512-7eORpyqImoOvkQJCSkL0d0mB4NHHIFAy4b1u8PHdDa7SjGS2njzl6/lyGoZLm+eyYEtlUmFGE0rFj66SWxZgQQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.1.tgz", + "integrity": "sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==", "dev": true, "engines": { "node": ">=14.0.0" @@ -8759,9 +8723,9 @@ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" }, "node_modules/totalist": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz", - "integrity": "sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true, "engines": { "node": ">=6" @@ -9108,9 +9072,9 @@ } }, "node_modules/vite": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.5.tgz", - "integrity": "sha512-0gEnL9wiRFxgz40o/i/eTBwm+NEbpUeTWhzKrZDSdKm6nplj+z4lKz8ANDgildxHm47Vg8EUia0aicKbawUVVA==", + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", + "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", "dev": true, "dependencies": { "esbuild": "^0.17.5", @@ -9156,9 +9120,9 @@ } }, "node_modules/vite-node": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.31.0.tgz", - "integrity": "sha512-8x1x1LNuPvE2vIvkSB7c1mApX5oqlgsxzHQesYF7l5n1gKrEmrClIiZuOFbFDQcjLsmcWSwwmrWrcGWm9Fxc/g==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.31.4.tgz", + "integrity": "sha512-uzL377GjJtTbuc5KQxVbDu2xfU/x0wVjUtXQR2ihS21q/NK6ROr4oG0rsSkBBddZUVCwzfx22in76/0ZZHXgkQ==", "dev": true, "dependencies": { "cac": "^6.7.14", @@ -9187,19 +9151,19 @@ } }, "node_modules/vitest": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.31.0.tgz", - "integrity": "sha512-JwWJS9p3GU9GxkG7eBSmr4Q4x4bvVBSswaCFf1PBNHiPx00obfhHRJfgHcnI0ffn+NMlIh9QGvG75FlaIBdKGA==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.31.4.tgz", + "integrity": "sha512-GoV0VQPmWrUFOZSg3RpQAPN+LPmHg2/gxlMNJlyxJihkz6qReHDV6b0pPDcqFLNEPya4tWJ1pgwUNP9MLmUfvQ==", "dev": true, "dependencies": { - "@types/chai": "^4.3.4", + "@types/chai": "^4.3.5", "@types/chai-subset": "^1.3.3", "@types/node": "*", - "@vitest/expect": "0.31.0", - "@vitest/runner": "0.31.0", - "@vitest/snapshot": "0.31.0", - "@vitest/spy": "0.31.0", - "@vitest/utils": "0.31.0", + "@vitest/expect": "0.31.4", + "@vitest/runner": "0.31.4", + "@vitest/snapshot": "0.31.4", + "@vitest/spy": "0.31.4", + "@vitest/utils": "0.31.4", "acorn": "^8.8.2", "acorn-walk": "^8.2.0", "cac": "^6.7.14", @@ -9212,10 +9176,10 @@ "picocolors": "^1.0.0", "std-env": "^3.3.2", "strip-literal": "^1.0.1", - "tinybench": "^2.4.0", + "tinybench": "^2.5.0", "tinypool": "^0.5.0", "vite": "^3.0.0 || ^4.0.0", - "vite-node": "0.31.0", + "vite-node": "0.31.4", "why-is-node-running": "^2.2.2" }, "bin": { @@ -9627,12 +9591,12 @@ "dev": true }, "@ampproject/remapping": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.0.tgz", - "integrity": "sha512-qRmjj8nj9qmLTQXXmaR1cck3UXSRMPrbsLJAasZpF+t3riI71BXed5ebIOYwQntykeZuhjsdweEc9BxH5Jc26w==", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz", + "integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==", "dev": true, "requires": { - "@jridgewell/gen-mapping": "^0.1.0", + "@jridgewell/gen-mapping": "^0.3.0", "@jridgewell/trace-mapping": "^0.3.9" } }, @@ -9702,19 +9666,6 @@ "@babel/types": "^7.20.2", "@jridgewell/gen-mapping": "^0.3.2", "jsesc": "^2.5.1" - }, - "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.2", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.2.tgz", - "integrity": "sha512-mh65xKQAzI6iBcFzwv28KVWSmCkdRBWoOh+bYQGW3+6OZvbbN3TqMGo5hqYxQniRcH9F2VZIoJCm4pa3BPDK/A==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - } } }, "@babel/helper-annotate-as-pure": { @@ -10136,14 +10087,14 @@ "dev": true }, "@eslint/eslintrc": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.2.tgz", - "integrity": "sha512-3W4f5tDUra+pA+FzgugqL2pRimUTDJWKr7BINqOpkZrC0uYI0NIc0/JFgBROCU07HR6GieA5m3/rsPIhDmCXTQ==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-2.0.3.tgz", + "integrity": "sha512-+5gy6OQfk+xx3q0d6jGZZC3f3KzAkXc/IanVxd1is/VIIziRqqt3ongQz0FiTUXqTk0c7aDB3OaFuKnuSoJicQ==", "dev": true, "requires": { "ajv": "^6.12.4", "debug": "^4.3.2", - "espree": "^9.5.1", + "espree": "^9.5.2", "globals": "^13.19.0", "ignore": "^5.2.0", "import-fresh": "^3.2.1", @@ -10170,9 +10121,9 @@ } }, "@eslint/js": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.39.0.tgz", - "integrity": "sha512-kf9RB0Fg7NZfap83B3QOqOGg9QmD9yBudqQXzzOtn3i4y7ZUXe5ONeW34Gwi+TxhH4mvj72R1Zc300KUMa9Bng==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/@eslint/js/-/js-8.41.0.tgz", + "integrity": "sha512-LxcyMGxwmTh2lY9FwHPGWOHmYFCZvbrFCBZL4FzSSsxsRPuhrYUg/49/0KDfW8tnIEaEHtfmn6+NPN+1DqaNmA==", "dev": true }, "@humanwhocodes/config-array": { @@ -10288,13 +10239,14 @@ } }, "@jridgewell/gen-mapping": { - "version": "0.1.1", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.1.1.tgz", - "integrity": "sha512-sQXCasFk+U8lWYEe66WxRDOE9PjVz4vSM51fTu3Hw+ClTpUSQb718772vH3pyS5pShp6lvQM7SxgIDXXXmOX7w==", + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", + "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", "dev": true, "requires": { - "@jridgewell/set-array": "^1.0.0", - "@jridgewell/sourcemap-codec": "^1.4.10" + "@jridgewell/set-array": "^1.0.1", + "@jridgewell/sourcemap-codec": "^1.4.10", + "@jridgewell/trace-mapping": "^0.3.9" } }, "@jridgewell/resolve-uri": { @@ -10659,9 +10611,9 @@ "dev": true }, "@types/chai": { - "version": "4.3.4", - "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.4.tgz", - "integrity": "sha512-KnRanxnpfpjUTqTCXslZSEdLfXExwgNxYPdiO2WGUj8+HDjFi8R3k5RVKPeSCzLjCcshCAtVO2QBbVuAV4kTnw==", + "version": "4.3.5", + "resolved": "https://registry.npmjs.org/@types/chai/-/chai-4.3.5.tgz", + "integrity": "sha512-mEo1sAde+UCE6b2hxn332f1g1E8WfYRu6p5SvTKr2ZKC1f7gFJXk4h5PyGP9Dt6gCaG8y8XhwnXWC6Iy2cmBng==", "dev": true }, "@types/chai-subset": { @@ -10846,15 +10798,15 @@ "dev": true }, "@typescript-eslint/eslint-plugin": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.2.tgz", - "integrity": "sha512-yVrXupeHjRxLDcPKL10sGQ/QlVrA8J5IYOEWVqk0lJaSZP7X5DfnP7Ns3cc74/blmbipQ1htFNVGsHX6wsYm0A==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-5.59.8.tgz", + "integrity": "sha512-JDMOmhXteJ4WVKOiHXGCoB96ADWg9q7efPWHRViT/f09bA8XOMLAVHHju3l0MkZnG1izaWXYmgvQcUjTRcpShQ==", "dev": true, "requires": { "@eslint-community/regexpp": "^4.4.0", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/type-utils": "5.59.2", - "@typescript-eslint/utils": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.8", + "@typescript-eslint/type-utils": "5.59.8", + "@typescript-eslint/utils": "5.59.8", "debug": "^4.3.4", "grapheme-splitter": "^1.0.4", "ignore": "^5.2.0", @@ -10864,29 +10816,29 @@ }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", - "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz", + "integrity": "sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2" + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8" } }, "@typescript-eslint/types": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", - "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.8.tgz", + "integrity": "sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", - "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz", + "integrity": "sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -10895,28 +10847,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz", - "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.8.tgz", + "integrity": "sha512-Tr65630KysnNn9f9G7ROF3w1b5/7f6QVCJ+WK9nhIocWmx9F+TmCAcglF26Vm7z8KCTwoKcNEBZrhlklla3CKg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.8", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/typescript-estree": "5.59.8", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", - "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz", + "integrity": "sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/types": "5.59.8", "eslint-visitor-keys": "^3.3.0" } }, @@ -10937,9 +10889,9 @@ "dev": true }, "semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -10957,41 +10909,41 @@ } }, "@typescript-eslint/parser": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.2.tgz", - "integrity": "sha512-uq0sKyw6ao1iFOZZGk9F8Nro/8+gfB5ezl1cA06SrqbgJAt0SRoFhb9pXaHvkrxUpZaoLxt8KlovHNk8Gp6/HQ==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-5.59.8.tgz", + "integrity": "sha512-AnR19RjJcpjoeGojmwZtCwBX/RidqDZtzcbG3xHrmz0aHHoOcbWnpDllenRDmDvsV0RQ6+tbb09/kyc+UT9Orw==", "dev": true, "requires": { - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.8", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/typescript-estree": "5.59.8", "debug": "^4.3.4" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", - "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz", + "integrity": "sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2" + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8" } }, "@typescript-eslint/types": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", - "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.8.tgz", + "integrity": "sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", - "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz", + "integrity": "sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -11000,19 +10952,19 @@ } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", - "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz", + "integrity": "sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/types": "5.59.8", "eslint-visitor-keys": "^3.3.0" } }, "semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -11031,41 +10983,41 @@ } }, "@typescript-eslint/type-utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.2.tgz", - "integrity": "sha512-b1LS2phBOsEy/T381bxkkywfQXkV1dWda/z0PhnIy3bC5+rQWQDS7fk9CSpcXBccPY27Z6vBEuaPBCKCgYezyQ==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-5.59.8.tgz", + "integrity": "sha512-+5M518uEIHFBy3FnyqZUF3BMP+AXnYn4oyH8RF012+e7/msMY98FhGL5SrN29NQ9xDgvqCgYnsOiKp1VjZ/fpA==", "dev": true, "requires": { - "@typescript-eslint/typescript-estree": "5.59.2", - "@typescript-eslint/utils": "5.59.2", + "@typescript-eslint/typescript-estree": "5.59.8", + "@typescript-eslint/utils": "5.59.8", "debug": "^4.3.4", "tsutils": "^3.21.0" }, "dependencies": { "@typescript-eslint/scope-manager": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.2.tgz", - "integrity": "sha512-dB1v7ROySwQWKqQ8rEWcdbTsFjh2G0vn8KUyvTXdPoyzSL6lLGkiXEV5CvpJsEe9xIdKV+8Zqb7wif2issoOFA==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-5.59.8.tgz", + "integrity": "sha512-/w08ndCYI8gxGf+9zKf1vtx/16y8MHrZs5/tnjHhMLNSixuNcJavSX4wAiPf4aS5x41Es9YPCn44MIe4cxIlig==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2" + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8" } }, "@typescript-eslint/types": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.2.tgz", - "integrity": "sha512-LbJ/HqoVs2XTGq5shkiKaNTuVv5tTejdHgfdjqRUGdYhjW1crm/M7og2jhVskMt8/4wS3T1+PfFvL1K3wqYj4w==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-5.59.8.tgz", + "integrity": "sha512-+uWuOhBTj/L6awoWIg0BlWy0u9TyFpCHrAuQ5bNfxDaZ1Ppb3mx6tUigc74LHcbHpOHuOTOJrBoAnhdHdaea1w==", "dev": true }, "@typescript-eslint/typescript-estree": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.2.tgz", - "integrity": "sha512-+j4SmbwVmZsQ9jEyBMgpuBD0rKwi9RxRpjX71Brr73RsYnEr3Lt5QZ624Bxphp8HUkSKfqGnPJp1kA5nl0Sh7Q==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-5.59.8.tgz", + "integrity": "sha512-Jy/lPSDJGNow14vYu6IrW790p7HIf/SOV1Bb6lZ7NUkLc2iB2Z9elESmsaUtLw8kVqogSbtLH9tut5GCX1RLDg==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/visitor-keys": "5.59.2", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/visitor-keys": "5.59.8", "debug": "^4.3.4", "globby": "^11.1.0", "is-glob": "^4.0.3", @@ -11074,28 +11026,28 @@ } }, "@typescript-eslint/utils": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.2.tgz", - "integrity": "sha512-kSuF6/77TZzyGPhGO4uVp+f0SBoYxCDf+lW3GKhtKru/L8k/Hd7NFQxyWUeY7Z/KGB2C6Fe3yf2vVi4V9TsCSQ==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-5.59.8.tgz", + "integrity": "sha512-Tr65630KysnNn9f9G7ROF3w1b5/7f6QVCJ+WK9nhIocWmx9F+TmCAcglF26Vm7z8KCTwoKcNEBZrhlklla3CKg==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@types/json-schema": "^7.0.9", "@types/semver": "^7.3.12", - "@typescript-eslint/scope-manager": "5.59.2", - "@typescript-eslint/types": "5.59.2", - "@typescript-eslint/typescript-estree": "5.59.2", + "@typescript-eslint/scope-manager": "5.59.8", + "@typescript-eslint/types": "5.59.8", + "@typescript-eslint/typescript-estree": "5.59.8", "eslint-scope": "^5.1.1", "semver": "^7.3.7" } }, "@typescript-eslint/visitor-keys": { - "version": "5.59.2", - "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.2.tgz", - "integrity": "sha512-EEpsO8m3RASrKAHI9jpavNv9NlEUebV4qmF1OWxSTtKSFBpC1NCmWazDQHFivRf0O1DV11BA645yrLEVQ0/Lig==", + "version": "5.59.8", + "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-5.59.8.tgz", + "integrity": "sha512-pJhi2ms0x0xgloT7xYabil3SGGlojNNKjK/q6dB3Ey0uJLMjK2UDGJvHieiyJVW/7C3KI+Z4Q3pEHkm4ejA+xQ==", "dev": true, "requires": { - "@typescript-eslint/types": "5.59.2", + "@typescript-eslint/types": "5.59.8", "eslint-visitor-keys": "^3.3.0" } }, @@ -11116,9 +11068,9 @@ "dev": true }, "semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -11247,12 +11199,12 @@ } }, "@vitest/coverage-c8": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.31.0.tgz", - "integrity": "sha512-h72qN1D962AO7UefQVulm9JFP5ACS7OfhCdBHioXU8f7ohH/+NTZCgAqmgcfRNHHO/8wLFxx+93YVxhodkEJVA==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/coverage-c8/-/coverage-c8-0.31.4.tgz", + "integrity": "sha512-VPx368m4DTcpA/P0v3YdVxl4QOSh1DbUcXURLRvDShrIB5KxOgfzw4Bn2R8AhAe/GyiWW/FIsJ/OJdYXCCiC1w==", "dev": true, "requires": { - "@ampproject/remapping": "^2.2.0", + "@ampproject/remapping": "^2.2.1", "c8": "^7.13.0", "magic-string": "^0.30.0", "picocolors": "^1.0.0", @@ -11260,23 +11212,23 @@ } }, "@vitest/expect": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.31.0.tgz", - "integrity": "sha512-Jlm8ZTyp6vMY9iz9Ny9a0BHnCG4fqBa8neCF6Pk/c/6vkUk49Ls6UBlgGAU82QnzzoaUs9E/mUhq/eq9uMOv/g==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/expect/-/expect-0.31.4.tgz", + "integrity": "sha512-tibyx8o7GUyGHZGyPgzwiaPaLDQ9MMuCOrc03BYT0nryUuhLbL7NV2r/q98iv5STlwMgaKuFJkgBW/8iPKwlSg==", "dev": true, "requires": { - "@vitest/spy": "0.31.0", - "@vitest/utils": "0.31.0", + "@vitest/spy": "0.31.4", + "@vitest/utils": "0.31.4", "chai": "^4.3.7" } }, "@vitest/runner": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.31.0.tgz", - "integrity": "sha512-H1OE+Ly7JFeBwnpHTrKyCNm/oZgr+16N4qIlzzqSG/YRQDATBYmJb/KUn3GrZaiQQyL7GwpNHVZxSQd6juLCgw==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/runner/-/runner-0.31.4.tgz", + "integrity": "sha512-Wgm6UER+gwq6zkyrm5/wbpXGF+g+UBB78asJlFkIOwyse0pz8lZoiC6SW5i4gPnls/zUcPLWS7Zog0LVepXnpg==", "dev": true, "requires": { - "@vitest/utils": "0.31.0", + "@vitest/utils": "0.31.4", "concordance": "^5.0.4", "p-limit": "^4.0.0", "pathe": "^1.1.0" @@ -11300,9 +11252,9 @@ } }, "@vitest/snapshot": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.31.0.tgz", - "integrity": "sha512-5dTXhbHnyUMTMOujZPB0wjFjQ6q5x9c8TvAsSPUNKjp1tVU7i9pbqcKPqntyu2oXtmVxKbuHCqrOd+Ft60r4tg==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/snapshot/-/snapshot-0.31.4.tgz", + "integrity": "sha512-LemvNumL3NdWSmfVAMpXILGyaXPkZbG5tyl6+RQSdcHnTj6hvA49UAI8jzez9oQyE/FWLKRSNqTGzsHuk89LRA==", "dev": true, "requires": { "magic-string": "^0.30.0", @@ -11311,33 +11263,33 @@ } }, "@vitest/spy": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.31.0.tgz", - "integrity": "sha512-IzCEQ85RN26GqjQNkYahgVLLkULOxOm5H/t364LG0JYb3Apg0PsYCHLBYGA006+SVRMWhQvHlBBCyuByAMFmkg==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/spy/-/spy-0.31.4.tgz", + "integrity": "sha512-3ei5ZH1s3aqbEyftPAzSuunGICRuhE+IXOmpURFdkm5ybUADk+viyQfejNk6q8M5QGX8/EVKw+QWMEP3DTJDag==", "dev": true, "requires": { "tinyspy": "^2.1.0" } }, "@vitest/ui": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.31.0.tgz", - "integrity": "sha512-Dy86l6r3/dbJposgm7w+oqb/15UWJ0lDBbEQaS1ived3+0CTaMbT8OMkUf9vNBkSL47kvBHEBnZLa5fw5i9gUQ==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/ui/-/ui-0.31.4.tgz", + "integrity": "sha512-sKM16ITX6HrNFF+lNZ2AQAen4/6Bx2i6KlBfIvkUjcTgc5YII/j2ltcX14oCUv4EA0OTWGQuGhO3zDoAsTENGA==", "dev": true, "requires": { - "@vitest/utils": "0.31.0", + "@vitest/utils": "0.31.4", "fast-glob": "^3.2.12", "fflate": "^0.7.4", "flatted": "^3.2.7", "pathe": "^1.1.0", "picocolors": "^1.0.0", - "sirv": "^2.0.2" + "sirv": "^2.0.3" } }, "@vitest/utils": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.31.0.tgz", - "integrity": "sha512-kahaRyLX7GS1urekRXN2752X4gIgOGVX4Wo8eDUGUkTWlGpXzf5ZS6N9RUUS+Re3XEE8nVGqNyxkSxF5HXlGhQ==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/@vitest/utils/-/utils-0.31.4.tgz", + "integrity": "sha512-DobZbHacWznoGUfYU8XDPY78UubJxXfMNY1+SUdOp1NsI34eopSA6aZMeaGu10waSOeYwE8lxrd/pLfT0RMxjQ==", "dev": true, "requires": { "concordance": "^5.0.4", @@ -11985,9 +11937,9 @@ }, "dependencies": { "semver": { - "version": "7.5.0", - "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.0.tgz", - "integrity": "sha512-+XC0AD/R7Q2mPSRuy2Id0+CGTZ98+8f+KvwirxOKIEyid+XSx6HbC63p+O4IndTHuX5Z+JxQ0TghCkO5Cg/2HA==", + "version": "7.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.5.1.tgz", + "integrity": "sha512-Wvss5ivl8TMRZXXESstBA4uR5iXgEN/VC5/sOcuXdVLzcdkz4HWetIoRfG5gb5X+ij/G9rw9YoGn3QoQ8OCSpw==", "dev": true, "requires": { "lru-cache": "^6.0.0" @@ -12388,15 +12340,15 @@ "dev": true }, "eslint": { - "version": "8.39.0", - "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.39.0.tgz", - "integrity": "sha512-mwiok6cy7KTW7rBpo05k6+p4YVZByLNjAZ/ACB9DRCu4YDRwjXI01tWHp6KAUWelsBetTxKK/2sHB0vdS8Z2Og==", + "version": "8.41.0", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-8.41.0.tgz", + "integrity": "sha512-WQDQpzGBOP5IrXPo4Hc0814r4/v2rrIsB0rhT7jtunIalgg6gYXWhRMOejVO8yH21T/FGaxjmFjBMNqcIlmH1Q==", "dev": true, "requires": { "@eslint-community/eslint-utils": "^4.2.0", "@eslint-community/regexpp": "^4.4.0", - "@eslint/eslintrc": "^2.0.2", - "@eslint/js": "8.39.0", + "@eslint/eslintrc": "^2.0.3", + "@eslint/js": "8.41.0", "@humanwhocodes/config-array": "^0.11.8", "@humanwhocodes/module-importer": "^1.0.1", "@nodelib/fs.walk": "^1.2.8", @@ -12407,8 +12359,8 @@ "doctrine": "^3.0.0", "escape-string-regexp": "^4.0.0", "eslint-scope": "^7.2.0", - "eslint-visitor-keys": "^3.4.0", - "espree": "^9.5.1", + "eslint-visitor-keys": "^3.4.1", + "espree": "^9.5.2", "esquery": "^1.4.2", "esutils": "^2.0.2", "fast-deep-equal": "^3.1.3", @@ -12416,13 +12368,12 @@ "find-up": "^5.0.0", "glob-parent": "^6.0.2", "globals": "^13.19.0", - "grapheme-splitter": "^1.0.4", + "graphemer": "^1.4.0", "ignore": "^5.2.0", "import-fresh": "^3.0.0", "imurmurhash": "^0.1.4", "is-glob": "^4.0.0", "is-path-inside": "^3.0.3", - "js-sdsl": "^4.1.4", "js-yaml": "^4.1.0", "json-stable-stringify-without-jsonify": "^1.0.1", "levn": "^0.4.1", @@ -12652,20 +12603,20 @@ } }, "eslint-visitor-keys": { - "version": "3.4.0", - "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.0.tgz", - "integrity": "sha512-HPpKPUBQcAsZOsHAFwTtIKcYlCje62XB7SEAcxjtmW6TD1WVpkS6i6/hOVtTZIl4zGj/mBqpFVGvaDneik+VoQ==", + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.1.tgz", + "integrity": "sha512-pZnmmLwYzf+kWaM/Qgrvpen51upAktaaiI01nsJD/Yr3lMOdNtq0cxkrrg16w64VtisN6okbs7Q8AfGqj4c9fA==", "dev": true }, "espree": { - "version": "9.5.1", - "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.1.tgz", - "integrity": "sha512-5yxtHSZXRSW5pvv3hAlXM5+/Oswi1AUFqBmbibKb5s6bp3rGIDkyXU6xCoyuuLhijr4SFwPrXRoZjz0AZDN9tg==", + "version": "9.5.2", + "resolved": "https://registry.npmjs.org/espree/-/espree-9.5.2.tgz", + "integrity": "sha512-7OASN1Wma5fum5SrNhFMAMJxOUAbhyfQ8dQ//PJaJbNw0URTPWqIghHWt1MmAANKhHZIYOHruW4Kw4ruUWOdGw==", "dev": true, "requires": { "acorn": "^8.8.0", "acorn-jsx": "^5.3.2", - "eslint-visitor-keys": "^3.4.0" + "eslint-visitor-keys": "^3.4.1" } }, "esquery": { @@ -12761,9 +12712,9 @@ "dev": true }, "fast-diff": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/fast-diff/-/fast-diff-1.2.0.tgz", - "integrity": "sha512-xJuoT5+L99XlZ8twedaRf6Ax2TgQVxvgZOYoPKqZufmJib0tL2tegPBOZb1pVNgIhlqDlA0eO0c3wBvQcmzx4w==", + "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 }, "fast-glob": { @@ -13070,6 +13021,12 @@ "integrity": "sha512-bzh50DW9kTPM00T8y4o8vQg89Di9oLJVLW/KaOGIXJWP/iqCN6WKYkbNOF04vFLJhwcpYUh9ydh/+5vpOqV4YQ==", "dev": true }, + "graphemer": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz", + "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==", + "dev": true + }, "graphql": { "version": "16.6.0", "resolved": "https://registry.npmjs.org/graphql/-/graphql-16.6.0.tgz", @@ -13233,12 +13190,9 @@ } }, "idb-keyval": { - "version": "6.2.0", - "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.0.tgz", - "integrity": "sha512-uw+MIyQn2jl3+hroD7hF8J7PUviBU7BPKWw4f/ISf32D4LoGu98yHjrzWWJDASu9QNrX10tCJqk9YY0ClWm8Ng==", - "requires": { - "safari-14-idb-fix": "^3.0.0" - } + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/idb-keyval/-/idb-keyval-6.2.1.tgz", + "integrity": "sha512-8Sb3veuYCyrZL+VBt9LJfZjLUPWVvqn8tG28VqYNFCo43KHcKuq+b4EiXGeuaLAQWL2YmyDgMp2aSpH9JHsEQg==" }, "ieee754": { "version": "1.2.1", @@ -13253,9 +13207,9 @@ "dev": true }, "immer": { - "version": "10.0.1", - "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.1.tgz", - "integrity": "sha512-zg++jJLsKKTwXGeSYIw0HgChSYQGtu0UDTnbKx5aGLYgte4CwTmH9eJDYyQ6FheyUtBe+lQW9FrGxya1G+Dtmg==" + "version": "10.0.2", + "resolved": "https://registry.npmjs.org/immer/-/immer-10.0.2.tgz", + "integrity": "sha512-Rx3CqeqQ19sxUtYV9CU911Vhy8/721wRFnJv3REVGWUmoAcIwzifTsdmJte/MV+0/XpM35LZdQMBGkRIoLPwQA==" }, "import-fresh": { "version": "3.3.0", @@ -14030,12 +13984,6 @@ "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==", "dev": true }, - "js-sdsl": { - "version": "4.1.5", - "resolved": "https://registry.npmjs.org/js-sdsl/-/js-sdsl-4.1.5.tgz", - "integrity": "sha512-08bOAKweV2NUC1wqTtf3qZlnpOX/R2DU9ikpjOHs0H+ibQv3zpncVQg6um4uYtRtrwIX8M4Nh3ytK4HGlYAq7Q==", - "dev": true - }, "js-string-escape": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/js-string-escape/-/js-string-escape-1.0.1.tgz", @@ -14058,9 +14006,9 @@ } }, "jsdom": { - "version": "22.0.0", - "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.0.0.tgz", - "integrity": "sha512-p5ZTEb5h+O+iU02t0GfEjAnkdYPrQSkfuTSMkMYyIoMvUNEHsbG0bHHbfXIcfTqD2UfvjQX7mmgiFsyRwGscVw==", + "version": "22.1.0", + "resolved": "https://registry.npmjs.org/jsdom/-/jsdom-22.1.0.tgz", + "integrity": "sha512-/9AVW7xNbsBv6GfWho4TTNjEo9fe6Zhf9O7s0Fhhr3u+awPwAJMKwAMXnkk5vBxflqLW9hTHX/0cs+P3gW+cQw==", "dev": true, "requires": { "abab": "^2.0.6", @@ -14433,15 +14381,15 @@ } }, "mlly": { - "version": "1.2.0", - "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.2.0.tgz", - "integrity": "sha512-+c7A3CV0KGdKcylsI6khWyts/CYrGTrRVo4R/I7u/cUsy0Conxa6LUhiEzVKIw14lc2L5aiO4+SeVe4TeGRKww==", + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/mlly/-/mlly-1.3.0.tgz", + "integrity": "sha512-HT5mcgIQKkOrZecOjOX3DJorTikWXwsBfpcr/MGBkhfWcjiqvnaL/9ppxvIUXfjT6xt4DVIAsN9fMUz1ev4bIw==", "dev": true, "requires": { "acorn": "^8.8.2", "pathe": "^1.1.0", - "pkg-types": "^1.0.2", - "ufo": "^1.1.1" + "pkg-types": "^1.0.3", + "ufo": "^1.1.2" } }, "monaco-editor": { @@ -15017,9 +14965,9 @@ } }, "postcss": { - "version": "8.4.23", - "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.23.tgz", - "integrity": "sha512-bQ3qMcpF6A/YjR55xtoTr0jGOlnPOKAIMdOWiv0EIT6HVPEaJiJB4NLljSbiHoC2RX7DN5Uvjtpbg1NPdwv1oA==", + "version": "8.4.24", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.24.tgz", + "integrity": "sha512-M0RzbcI0sO/XJNucsGjvWU9ERWxb/ytp1w6dKtxTKgixdtQDq4rmx/g8W1hnaheq9jgwL/oyEdH5Bc4WwJKMqg==", "dev": true, "requires": { "nanoid": "^3.3.6", @@ -15083,9 +15031,9 @@ "dev": true }, "preact": { - "version": "10.13.2", - "resolved": "https://registry.npmjs.org/preact/-/preact-10.13.2.tgz", - "integrity": "sha512-q44QFLhOhty2Bd0Y46fnYW0gD/cbVM9dUVtNTDKPcdXSMA7jfY+Jpd6rk3GB0lcQss0z5s/6CmVP0Z/hV+g6pw==" + "version": "10.15.1", + "resolved": "https://registry.npmjs.org/preact/-/preact-10.15.1.tgz", + "integrity": "sha512-qs2ansoQEwzNiV5eAcRT1p1EC/dmEzaATVDJNiB3g2sRDWdA7b7MurXdJjB2+/WQktGWZwxvDrnuRFbWuIr64g==" }, "preact-async-route": { "version": "2.2.1", @@ -15093,9 +15041,9 @@ "integrity": "sha512-8bg1007akXs3YDmzYT4McaTe6ji2FIzcc0/NTlu+vjJaKPNQ8lNG/HQ6LP+FoIxQ4m/KH5vvJCHJN5ADp2iNGA==" }, "preact-router": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/preact-router/-/preact-router-4.1.0.tgz", - "integrity": "sha512-y1w2YvVpKAju9FMV+fAVR1NpH4MW5q07BZrziMZeg6F/rGJ9KvLUZtjOqsy2I8fDYiX36AM1AQTXIIK3jigBhA==", + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/preact-router/-/preact-router-4.1.1.tgz", + "integrity": "sha512-+LGrB3b2nR7+8vzyHw8i2/TjZazs3oMJovIEgBChPBXMDSISmwj2WDynZh8KDxZRK2GuXlqHPk15mMjaYWZH4g==", "requires": {} }, "prelude-ls": { @@ -15417,11 +15365,6 @@ "tslib": "^2.1.0" } }, - "safari-14-idb-fix": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/safari-14-idb-fix/-/safari-14-idb-fix-3.0.0.tgz", - "integrity": "sha512-eBNFLob4PMq8JA1dGyFn6G97q3/WzNtFK4RnzT1fnLq+9RyrGknzYiM/9B12MnKAxuj1IXr7UKYtTNtjyKMBog==" - }, "safe-buffer": { "version": "5.1.2", "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", @@ -15513,9 +15456,9 @@ "dev": true }, "sirv": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.2.tgz", - "integrity": "sha512-4Qog6aE29nIjAOKe/wowFTxOdmbEZKb+3tsLljaBRzJwtqto0BChD2zzH0LhgCSXiI+V7X+Y45v14wBZQ1TK3w==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.3.tgz", + "integrity": "sha512-O9jm9BsID1P+0HOi81VpXPoDxYP374pkOLzACAoyUQ/3OUVndNpsz6wMnY2z+yOxzbllCKZrM+9QrWsv4THnyA==", "dev": true, "requires": { "@polka/url": "^1.0.0-next.20", @@ -15565,9 +15508,9 @@ "dev": true }, "strftime": { - "version": "0.10.1", - "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.1.tgz", - "integrity": "sha512-nVvH6JG8KlXFPC0f8lojLgEsPA18lRpLZ+RrJh/NkQV2tqOgZfbas8gcU8SFgnnqR3rWzZPYu6N2A3xzs/8rQg==" + "version": "0.10.2", + "resolved": "https://registry.npmjs.org/strftime/-/strftime-0.10.2.tgz", + "integrity": "sha512-Y6IZaTVM80chcMe7j65Gl/0nmlNdtt+KWPle5YeCAjmsBfw+id2qdaJ5MDrxUq+OmHKab+jHe7mUjU/aNMSZZg==" }, "strict-event-emitter": { "version": "0.2.8", @@ -15684,17 +15627,6 @@ "ts-interface-checker": "^0.1.9" }, "dependencies": { - "@jridgewell/gen-mapping": { - "version": "0.3.3", - "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz", - "integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==", - "dev": true, - "requires": { - "@jridgewell/set-array": "^1.0.1", - "@jridgewell/sourcemap-codec": "^1.4.10", - "@jridgewell/trace-mapping": "^0.3.9" - } - }, "glob": { "version": "7.1.6", "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.6.tgz", @@ -15872,9 +15804,9 @@ "dev": true }, "tinybench": { - "version": "2.4.0", - "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.4.0.tgz", - "integrity": "sha512-iyziEiyFxX4kyxSp+MtY1oCH/lvjH3PxFN8PGCDeqcZWAJ/i+9y+nL85w99PxVzrIvew/GSkSbDYtiGVa85Afg==", + "version": "2.5.0", + "resolved": "https://registry.npmjs.org/tinybench/-/tinybench-2.5.0.tgz", + "integrity": "sha512-kRwSG8Zx4tjF9ZiyH4bhaebu+EDz1BOx9hOigYHlUW4xxI/wKIUQUqo018UlU4ar6ATPBsaMrdbKZ+tmPdohFA==", "dev": true }, "tinypool": { @@ -15884,9 +15816,9 @@ "dev": true }, "tinyspy": { - "version": "2.1.0", - "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.0.tgz", - "integrity": "sha512-7eORpyqImoOvkQJCSkL0d0mB4NHHIFAy4b1u8PHdDa7SjGS2njzl6/lyGoZLm+eyYEtlUmFGE0rFj66SWxZgQQ==", + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/tinyspy/-/tinyspy-2.1.1.tgz", + "integrity": "sha512-XPJL2uSzcOyBMky6OFrusqWlzfFrXtE0hPuMgW8A2HmaqrPo4ZQHRN/V0QXN3FSjKxpsbRrFc5LI7KOwBsT1/w==", "dev": true }, "tmp": { @@ -15919,9 +15851,9 @@ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ==" }, "totalist": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.0.tgz", - "integrity": "sha512-eM+pCBxXO/njtF7vdFsHuqb+ElbxqtI4r5EAvk6grfAFyJ6IvWlSkfZ5T9ozC6xWw3Fj1fGoSmrl0gUs46JVIw==", + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", "dev": true }, "tough-cookie": { @@ -16191,9 +16123,9 @@ } }, "vite": { - "version": "4.3.5", - "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.5.tgz", - "integrity": "sha512-0gEnL9wiRFxgz40o/i/eTBwm+NEbpUeTWhzKrZDSdKm6nplj+z4lKz8ANDgildxHm47Vg8EUia0aicKbawUVVA==", + "version": "4.3.9", + "resolved": "https://registry.npmjs.org/vite/-/vite-4.3.9.tgz", + "integrity": "sha512-qsTNZjO9NoJNW7KnOrgYwczm0WctJ8m/yqYAMAK9Lxt4SoySUfS5S8ia9K7JHpa3KEeMfyF8LoJ3c5NeBJy6pg==", "dev": true, "requires": { "esbuild": "^0.17.5", @@ -16203,9 +16135,9 @@ } }, "vite-node": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.31.0.tgz", - "integrity": "sha512-8x1x1LNuPvE2vIvkSB7c1mApX5oqlgsxzHQesYF7l5n1gKrEmrClIiZuOFbFDQcjLsmcWSwwmrWrcGWm9Fxc/g==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/vite-node/-/vite-node-0.31.4.tgz", + "integrity": "sha512-uzL377GjJtTbuc5KQxVbDu2xfU/x0wVjUtXQR2ihS21q/NK6ROr4oG0rsSkBBddZUVCwzfx22in76/0ZZHXgkQ==", "dev": true, "requires": { "cac": "^6.7.14", @@ -16223,19 +16155,19 @@ "requires": {} }, "vitest": { - "version": "0.31.0", - "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.31.0.tgz", - "integrity": "sha512-JwWJS9p3GU9GxkG7eBSmr4Q4x4bvVBSswaCFf1PBNHiPx00obfhHRJfgHcnI0ffn+NMlIh9QGvG75FlaIBdKGA==", + "version": "0.31.4", + "resolved": "https://registry.npmjs.org/vitest/-/vitest-0.31.4.tgz", + "integrity": "sha512-GoV0VQPmWrUFOZSg3RpQAPN+LPmHg2/gxlMNJlyxJihkz6qReHDV6b0pPDcqFLNEPya4tWJ1pgwUNP9MLmUfvQ==", "dev": true, "requires": { - "@types/chai": "^4.3.4", + "@types/chai": "^4.3.5", "@types/chai-subset": "^1.3.3", "@types/node": "*", - "@vitest/expect": "0.31.0", - "@vitest/runner": "0.31.0", - "@vitest/snapshot": "0.31.0", - "@vitest/spy": "0.31.0", - "@vitest/utils": "0.31.0", + "@vitest/expect": "0.31.4", + "@vitest/runner": "0.31.4", + "@vitest/snapshot": "0.31.4", + "@vitest/spy": "0.31.4", + "@vitest/utils": "0.31.4", "acorn": "^8.8.2", "acorn-walk": "^8.2.0", "cac": "^6.7.14", @@ -16248,10 +16180,10 @@ "picocolors": "^1.0.0", "std-env": "^3.3.2", "strip-literal": "^1.0.1", - "tinybench": "^2.4.0", + "tinybench": "^2.5.0", "tinypool": "^0.5.0", "vite": "^3.0.0 || ^4.0.0", - "vite-node": "0.31.0", + "vite-node": "0.31.4", "why-is-node-running": "^2.2.2" } }, diff --git a/web/src/Sidebar.jsx b/web/src/Sidebar.jsx index a7d7639e8..4497dba15 100644 --- a/web/src/Sidebar.jsx +++ b/web/src/Sidebar.jsx @@ -44,6 +44,7 @@ export default function Sidebar() { {birdseye?.enabled ? : null} + diff --git a/web/src/app.tsx b/web/src/app.tsx index 124a0f3cb..4e5123563 100644 --- a/web/src/app.tsx +++ b/web/src/app.tsx @@ -31,6 +31,7 @@ export default function App() { + { + if (camera == 'select') { + setMessage({ text: 'A camera needs to be selected.', error: true }); + return; + } + + if (playback == 'select') { + setMessage({ text: 'A playback factor needs to be selected.', error: true }); + return; + } + + const start = new Date(document.getElementById('start').value).getTime() / 1000; + const end = new Date(document.getElementById('end').value).getTime() / 1000; + + if (!start || !end) { + setMessage({ text: 'A start and end time needs to be selected', error: true }); + return; + } + + setMessage({ text: 'Successfully started export. View the file in the /exports folder.', error: false }); + axios.post(`export/${camera}/start/${start}/end/${end}`, { playback }); + }; + + return ( +
+ Export + + {message.text && ( +
{message.text}
+ )} + +
+ + +
+ +
+ + From: + + + + To: + + +
+ +
+ ); +} diff --git a/web/src/routes/index.js b/web/src/routes/index.js index eeadbbb4f..322a2b69a 100644 --- a/web/src/routes/index.js +++ b/web/src/routes/index.js @@ -23,6 +23,11 @@ export async function getEvents(_url, _cb, _props) { return module.default; } +export async function getExports(_url, _cb, _props) { + const module = await import('./Export.jsx'); + return module.default; +} + export async function getRecording(_url, _cb, _props) { const module = await import('./Recording.jsx'); return module.default;