diff --git a/.devcontainer/Dockerfile b/.devcontainer/Dockerfile
new file mode 100644
index 0000000..3ec5024
--- /dev/null
+++ b/.devcontainer/Dockerfile
@@ -0,0 +1,42 @@
+FROM python:3.10.14-slim-bookworm
+
+RUN apt-get update && apt-get install -y \
+ sudo \
+ vim \
+ git \
+ curl \
+ wget \
+ gcc \
+ g++ \
+ libpq-dev \
+ make \
+ cmake \
+ libcairo2-dev \
+ libgirepository1.0-dev \
+ python3-dev \
+ gir1.2-gtk-3.0\
+ pkg-config \
+ libhdf5-dev \
+ jq \
+ && rm -rf /var/lib/apt/lists/*
+
+
+RUN curl https://bootstrap.pypa.io/get-pip.py -o get-pip.py && python get-pip.py && rm get-pip.py
+
+WORKDIR /workspace/qdash
+
+COPY ./.devcontainer/requirements.txt .
+COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
+RUN uv pip install --system --no-cache -r requirements.txt
+
+RUN curl -fsSL https://deb.nodesource.com/setup_18.x | bash -
+RUN apt-get install -y nodejs
+
+# COPY ./client/package*.json ./client/pnpm-lock.yaml ./
+# RUN npm install -g pnpm
+# RUN pnpm install
+COPY ./client/package*.json ./
+# pnpm をインストール
+#RUN npm install -g pnpm
+RUN npm install
+RUN npm install -g @go-task/cli
diff --git a/.devcontainer/devcontainer.json b/.devcontainer/devcontainer.json
new file mode 100644
index 0000000..e7e92c1
--- /dev/null
+++ b/.devcontainer/devcontainer.json
@@ -0,0 +1,25 @@
+{
+ "name": "qdash",
+ "dockerComposeFile": ["../compose.dev.yaml"],
+ "service": "devcontainer",
+ "workspaceFolder": "/workspace/qdash",
+ "customizations": {
+ "vscode": {
+ "extensions": [
+ "MS-CEINTL.vscode-language-pack-ja",
+ "esbenp.prettier-vscode",
+ "charliermarsh.ruff",
+ "ms-python.python",
+ "markdownlint.markdownlint",
+ "ms-azuretools.vscode-docker",
+ "EditorConfig.EditorConfig",
+ "dbaeumer.vscode-eslint",
+ "ms-python.mypy-type-checker"
+ ],
+ "settings": {
+ "python.defaultInterpreterPath": ".venv/bin/python"
+ }
+ }
+ },
+ "remoteUser": "root"
+}
diff --git a/.devcontainer/requirements.txt b/.devcontainer/requirements.txt
new file mode 100644
index 0000000..430a4ca
--- /dev/null
+++ b/.devcontainer/requirements.txt
@@ -0,0 +1,187 @@
+annotated-types==0.7.0 ; python_version >= "3.10" and python_version < "3.13"
+anyio==4.6.2.post1 ; python_version >= "3.10" and python_version < "3.13"
+asgi-lifespan==2.1.0 ; python_version >= "3.10" and python_version < "3.13"
+asteval==1.0.5 ; python_version >= "3.10" and python_version < "3.13"
+asttokens==3.0.0 ; python_version >= "3.10" and python_version < "3.13"
+attrs==24.2.0 ; python_version >= "3.10" and python_version < "3.13"
+automat==24.8.1 ; python_version >= "3.10" and python_version < "3.13"
+bcrypt==4.2.1 ; python_version >= "3.10" and python_version < "3.13"
+bunnet==1.3.0 ; python_version >= "3.10" and python_version < "3.13"
+cachetools==5.5.0 ; python_version >= "3.10" and python_version < "3.13"
+certifi==2024.8.30 ; python_version >= "3.10" and python_version < "3.13"
+cffi==1.17.1 ; python_version >= "3.10" and python_version < "3.13"
+charset-normalizer==3.4.0 ; python_version >= "3.10" and python_version < "3.13"
+cirq-aqt==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-core==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-google==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-ionq==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-pasqal==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-rigetti==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-web==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+click==8.1.7 ; python_version >= "3.10" and python_version < "3.13"
+cloudpickle==3.1.0 ; python_version >= "3.10" and python_version < "3.13"
+colorama==0.4.6 ; python_version >= "3.10" and python_version < "3.13"
+constantly==23.10.4 ; python_version >= "3.10" and python_version < "3.13"
+contourpy==1.3.1 ; python_version >= "3.10" and python_version < "3.13"
+coolname==2.2.0 ; python_version >= "3.10" and python_version < "3.13"
+coverage[toml]==7.6.8 ; python_version >= "3.10" and python_version < "3.13"
+croniter==2.0.7 ; python_version >= "3.10" and python_version < "3.13"
+cryptography==44.0.0 ; python_version >= "3.10" and python_version < "3.13"
+cycler==0.12.1 ; python_version >= "3.10" and python_version < "3.13"
+decorator==5.1.1 ; python_version >= "3.10" and python_version < "3.13"
+deprecated==1.2.15 ; python_version >= "3.10" and python_version < "3.13"
+dill==0.3.9 ; python_version >= "3.10" and python_version < "3.13"
+dnspython==2.7.0 ; python_version >= "3.10" and python_version < "3.13"
+duet==0.2.9 ; python_version >= "3.10" and python_version < "3.13"
+email-validator==2.2.0 ; python_version >= "3.10" and python_version < "3.13"
+exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.13"
+executing==2.1.0 ; python_version >= "3.10" and python_version < "3.13"
+fastapi-cli==0.0.5 ; python_version >= "3.10" and python_version < "3.13"
+fastapi==0.111.1 ; python_version >= "3.10" and python_version < "3.13"
+filelock==3.16.1 ; python_version >= "3.10" and python_version < "3.13"
+fonttools==4.55.1 ; python_version >= "3.10" and python_version < "3.13"
+fsspec==2024.10.0 ; python_version >= "3.10" and python_version < "3.13"
+google-api-core[grpc]==2.23.0 ; python_version >= "3.10" and python_version < "3.13"
+google-auth==2.36.0 ; python_version >= "3.10" and python_version < "3.13"
+googleapis-common-protos==1.66.0 ; python_version >= "3.10" and python_version < "3.13"
+graphviz==0.20.3 ; python_version >= "3.10" and python_version < "3.13"
+griffe==1.5.1 ; python_version >= "3.10" and python_version < "3.13"
+grpc-interceptor==0.15.4 ; python_version >= "3.10" and python_version < "3.13"
+grpcio-status==1.62.3 ; python_version >= "3.10" and python_version < "3.13"
+grpcio==1.68.1 ; python_version >= "3.10" and python_version < "3.13"
+gunicorn==22.0.0 ; python_version >= "3.10" and python_version < "3.13"
+h11==0.14.0 ; python_version >= "3.10" and python_version < "3.13"
+h2==4.1.0 ; python_version >= "3.10" and python_version < "3.13"
+h5py==3.12.1 ; python_version >= "3.10" and python_version < "3.13"
+hpack==4.0.0 ; python_version >= "3.10" and python_version < "3.13"
+httpcore==1.0.7 ; python_version >= "3.10" and python_version < "3.13"
+httptools==0.6.4 ; python_version >= "3.10" and python_version < "3.13"
+httpx==0.28.0 ; python_version >= "3.10" and python_version < "3.13"
+httpx[http2]==0.28.0 ; python_version >= "3.10" and python_version < "3.13"
+hyperframe==6.0.1 ; python_version >= "3.10" and python_version < "3.13"
+hyperlink==21.0.0 ; python_version >= "3.10" and python_version < "3.13"
+idna==3.10 ; python_version >= "3.10" and python_version < "3.13"
+importlib-resources==6.4.5 ; python_version >= "3.10" and python_version < "3.13"
+incremental==24.7.2 ; python_version >= "3.10" and python_version < "3.13"
+iniconfig==2.0.0 ; python_version >= "3.10" and python_version < "3.13"
+ipython==8.30.0 ; python_version >= "3.10" and python_version < "3.13"
+itsdangerous==2.2.0 ; python_version >= "3.10" and python_version < "3.13"
+jedi==0.19.2 ; python_version >= "3.10" and python_version < "3.13"
+jinja2==3.1.4 ; python_version >= "3.10" and python_version < "3.13"
+joblib==1.4.2 ; python_version >= "3.10" and python_version < "3.13"
+jsonpatch==1.33 ; python_version >= "3.10" and python_version < "3.13"
+jsonpointer==3.0.0 ; python_version >= "3.10" and python_version < "3.13"
+jsonschema-specifications==2024.10.1 ; python_version >= "3.10" and python_version < "3.13"
+jsonschema==4.23.0 ; python_version >= "3.10" and python_version < "3.13"
+kiwisolver==1.4.7 ; python_version >= "3.10" and python_version < "3.13"
+lazy-model==0.2.0 ; python_version >= "3.10" and python_version < "3.13"
+lmfit==1.3.2 ; python_version >= "3.10" and python_version < "3.13"
+markdown-it-py==3.0.0 ; python_version >= "3.10" and python_version < "3.13"
+markupsafe==3.0.2 ; python_version >= "3.10" and python_version < "3.13"
+matplotlib-inline==0.1.7 ; python_version >= "3.10" and python_version < "3.13"
+matplotlib==3.9.3 ; python_version >= "3.10" and python_version < "3.13"
+mdurl==0.1.2 ; python_version >= "3.10" and python_version < "3.13"
+mpmath==1.3.0 ; python_version >= "3.10" and python_version < "3.13"
+msgpack==1.1.0 ; python_version >= "3.10" and python_version < "3.13"
+mypy-extensions==1.0.0 ; python_version >= "3.10" and python_version < "3.13"
+mypy==1.13.0 ; python_version >= "3.10" and python_version < "3.13"
+networkx==2.8.8 ; python_version >= "3.10" and python_version < "3.13"
+numpy==1.26.4 ; python_version >= "3.10" and python_version < "3.13"
+orjson==3.10.12 ; python_version >= "3.10" and python_version < "3.13"
+packaging==23.2 ; python_version >= "3.10" and python_version < "3.13"
+pandas==2.2.3 ; python_version >= "3.10" and python_version < "3.13"
+paramiko==3.5.0 ; python_version >= "3.10" and python_version < "3.13"
+parso==0.8.4 ; python_version >= "3.10" and python_version < "3.13"
+pathspec==0.12.1 ; python_version >= "3.10" and python_version < "3.13"
+pendulum==2.1.2 ; python_version >= "3.10" and python_version < "3.12"
+pendulum==3.0.0 ; python_version >= "3.12" and python_version < "3.13"
+pexpect==4.9.0 ; python_version >= "3.10" and python_version < "3.13" and (sys_platform != "win32" and sys_platform != "emscripten")
+pillow==11.0.0 ; python_version >= "3.10" and python_version < "3.13"
+pluggy==1.5.0 ; python_version >= "3.10" and python_version < "3.13"
+prefect-client==2.20.10 ; python_version >= "3.10" and python_version < "3.13"
+prompt-toolkit==3.0.48 ; python_version >= "3.10" and python_version < "3.13"
+proto-plus==1.25.0 ; python_version >= "3.10" and python_version < "3.13"
+protobuf==4.25.5 ; python_version >= "3.10" and python_version < "3.13"
+ptyprocess==0.7.0 ; python_version >= "3.10" and python_version < "3.13" and (sys_platform != "win32" and sys_platform != "emscripten")
+pure-eval==0.2.3 ; python_version >= "3.10" and python_version < "3.13"
+pyasn1-modules==0.4.1 ; python_version >= "3.10" and python_version < "3.13"
+pyasn1==0.6.1 ; python_version >= "3.10" and python_version < "3.13"
+pycparser==2.22 ; python_version >= "3.10" and python_version < "3.13"
+pydantic-core==2.27.1 ; python_version >= "3.10" and python_version < "3.13"
+pydantic-settings==2.6.1 ; python_version >= "3.10" and python_version < "3.13"
+pydantic==2.10.2 ; python_version >= "3.10" and python_version < "3.13"
+pydantic[email]==2.10.2 ; python_version >= "3.10" and python_version < "3.13"
+pygments==2.18.0 ; python_version >= "3.10" and python_version < "3.13"
+pylabrad==0.98.3 ; python_version >= "3.10" and python_version < "3.13"
+pymongo==4.10.1 ; python_version >= "3.10" and python_version < "3.13"
+pynacl==1.5.0 ; python_version >= "3.10" and python_version < "3.13"
+pyopenssl==24.3.0 ; python_version >= "3.10" and python_version < "3.13"
+pyparsing==3.2.0 ; python_version >= "3.10" and python_version < "3.13"
+pyquil==4.14.3 ; python_version >= "3.10" and python_version < "3.13"
+pytest-cov==5.0.0 ; python_version >= "3.10" and python_version < "3.13"
+pytest-env==1.1.5 ; python_version >= "3.10" and python_version < "3.13"
+pytest-mypy==0.10.3 ; python_version >= "3.10" and python_version < "3.13"
+pytest==8.3.4 ; python_version >= "3.10" and python_version < "3.13"
+python-dateutil==2.9.0.post0 ; python_version >= "3.10" and python_version < "3.13"
+python-dotenv==1.0.1 ; python_version >= "3.10" and python_version < "3.13"
+python-multipart==0.0.19 ; python_version >= "3.10" and python_version < "3.13"
+python-rapidjson==1.20 ; python_version >= "3.10" and python_version < "3.13"
+python-slugify==8.0.4 ; python_version >= "3.10" and python_version < "3.13"
+pytz==2024.2 ; python_version >= "3.10" and python_version < "3.13"
+pytzdata==2020.1 ; python_version >= "3.10" and python_version < "3.12"
+pyyaml==6.0.2 ; python_version >= "3.10" and python_version < "3.13"
+pyzmq==26.2.0 ; python_version >= "3.10" and python_version < "3.13"
+qcs-api-client-common==0.10.0 ; python_version >= "3.10" and python_version < "3.13"
+qcs-sdk-python==0.21.4 ; python_version >= "3.10" and python_version < "3.13"
+quil==0.13.2 ; python_version >= "3.10" and python_version < "3.13"
+qupy==1.1.1 ; python_version >= "3.10" and python_version < "3.13"
+qutip==5.0.4 ; python_version >= "3.10" and python_version < "3.13"
+referencing==0.35.1 ; python_version >= "3.10" and python_version < "3.13"
+requests==2.32.3 ; python_version >= "3.10" and python_version < "3.13"
+rfc3339-validator==0.1.4 ; python_version >= "3.10" and python_version < "3.13"
+rich==13.9.4 ; python_version >= "3.10" and python_version < "3.13"
+rpcq==3.11.0 ; python_version >= "3.10" and python_version < "3.13"
+rpds-py==0.22.0 ; python_version >= "3.10" and python_version < "3.13"
+rsa==4.9 ; python_version >= "3.10" and python_version < "3.13"
+ruamel-yaml-clib==0.2.12 ; platform_python_implementation == "CPython" and python_version < "3.13" and python_version >= "3.10"
+ruamel-yaml==0.18.6 ; python_version >= "3.10" and python_version < "3.13"
+ruff==0.5.7 ; python_version >= "3.10" and python_version < "3.13"
+scikit-learn==1.5.0 ; python_version >= "3.10" and python_version < "3.13"
+scipy==1.14.1 ; python_version >= "3.10" and python_version < "3.13"
+sentry-sdk==2.19.0 ; python_version >= "3.10" and python_version < "3.13"
+service-identity==24.2.0 ; python_version >= "3.10" and python_version < "3.13"
+setuptools==75.6.0 ; python_version >= "3.10" and python_version < "3.13"
+shellingham==1.5.4 ; python_version >= "3.10" and python_version < "3.13"
+six==1.16.0 ; python_version >= "3.10" and python_version < "3.13"
+slack-sdk==3.33.4 ; python_version >= "3.10" and python_version < "3.13"
+sniffio==1.3.1 ; python_version >= "3.10" and python_version < "3.13"
+sortedcontainers==2.4.0 ; python_version >= "3.10" and python_version < "3.13"
+sqe-fitting @ git+https://github.com/orangekame3/sqe_fitting@3106ac41b120cd1ff27077a02a6befac5d41636f ; python_version >= "3.10" and python_version < "3.13"
+stack-data==0.6.3 ; python_version >= "3.10" and python_version < "3.13"
+starlette==0.37.2 ; python_version >= "3.10" and python_version < "3.13"
+sympy==1.13.3 ; python_version >= "3.10" and python_version < "3.13"
+text-unidecode==1.3 ; python_version >= "3.10" and python_version < "3.13"
+threadpoolctl==3.5.0 ; python_version >= "3.10" and python_version < "3.13"
+toml==0.10.2 ; python_version >= "3.10" and python_version < "3.13"
+tomli==2.2.1 ; python_version >= "3.10" and python_full_version <= "3.11.0a6"
+tqdm==4.67.1 ; python_version >= "3.10" and python_version < "3.13"
+traitlets==5.14.3 ; python_version >= "3.10" and python_version < "3.13"
+twisted==24.11.0 ; python_version >= "3.10" and python_version < "3.13"
+typer==0.14.0 ; python_version >= "3.10" and python_version < "3.13"
+types-deprecated==1.2.15.20241117 ; python_version >= "3.10" and python_version < "3.13"
+types-paramiko==3.5.0.20240928 ; python_version >= "3.10" and python_version < "3.13"
+types-python-dateutil==2.9.0.20241003 ; python_version >= "3.10" and python_version < "3.13"
+typing-extensions==4.12.2 ; python_version >= "3.10" and python_version < "3.13"
+tzdata==2024.2 ; python_version >= "3.10" and python_version < "3.13"
+ujson==5.10.0 ; python_version >= "3.10" and python_version < "3.13"
+uncertainties==3.2.2 ; python_version >= "3.10" and python_version < "3.13"
+urllib3==2.2.3 ; python_version >= "3.10" and python_version < "3.13"
+uvicorn==0.30.6 ; python_version >= "3.10" and python_version < "3.13"
+uvicorn[standard]==0.30.6 ; python_version >= "3.10" and python_version < "3.13"
+uvloop==0.21.0 ; (sys_platform != "win32" and sys_platform != "cygwin") and platform_python_implementation != "PyPy" and python_version >= "3.10" and python_version < "3.13"
+watchfiles==1.0.0 ; python_version >= "3.10" and python_version < "3.13"
+wcwidth==0.2.13 ; python_version >= "3.10" and python_version < "3.13"
+websockets==13.1 ; python_version >= "3.10" and python_version < "3.13"
+wrapt==1.17.0 ; python_version >= "3.10" and python_version < "3.13"
+zope-interface==7.2 ; python_version >= "3.10" and python_version < "3.13"
diff --git a/.dockerignore b/.dockerignore
new file mode 100644
index 0000000..eb4d255
--- /dev/null
+++ b/.dockerignore
@@ -0,0 +1,5 @@
+.venv
+node_modules
+calib_data
+mongo_data
+postgres_data
diff --git a/.editorconfig b/.editorconfig
new file mode 100644
index 0000000..4655bd5
--- /dev/null
+++ b/.editorconfig
@@ -0,0 +1,26 @@
+root = true
+
+[*]
+indent_style = space
+indent_size = 2
+end_of_line = lf
+charset = utf-8
+trim_trailing_whitespace = true
+insert_final_newline = true
+
+
+[*.{js,json}]
+indent_size = 2
+
+[*.{tf,tftfvars}]
+indent_size = 2
+indent_style = space
+
+[*.md]
+max_line_length = 0
+trim_trailing_whitespace = false
+
+[{Makefile,**.mk}]
+indent_style = tab
+[*.py]
+indent_size = 4
diff --git a/.github/workflows/deploy-pages.yml b/.github/workflows/deploy-pages.yml
new file mode 100644
index 0000000..cff0837
--- /dev/null
+++ b/.github/workflows/deploy-pages.yml
@@ -0,0 +1,55 @@
+# Sample workflow for building and deploying a VitePress site to GitHub Pages
+#
+name: Deploy VitePress site to Pages
+
+on:
+ push:
+ branches: [main]
+ workflow_dispatch:
+
+permissions:
+ contents: read
+ pages: write
+ id-token: write
+
+concurrency:
+ group: pages
+ cancel-in-progress: false
+
+jobs:
+ build:
+ runs-on: ubuntu-latest
+ steps:
+ - name: Checkout
+ uses: actions/checkout@v4
+ with:
+ fetch-depth: 0
+ - name: Setup Node
+ uses: actions/setup-node@v3
+ with:
+ node-version: 18
+ cache: npm
+ cache-dependency-path: ./docs/package-lock.json
+ - name: Setup Pages
+ uses: actions/configure-pages@v4
+ - name: Install dependencies
+ run: npm ci
+ working-directory: docs # 作業ディレクトリを指定
+ - name: Build with VitePress
+ run: npm run docs:build
+ working-directory: docs # 作業ディレクトリを指定
+ - name: Upload artifact
+ uses: actions/upload-pages-artifact@v3
+ with:
+ path: docs/.vitepress/dist
+
+ deploy:
+ environment:
+ name: github-pages
+ url: ${{ steps.deployment.outputs.page_url }}
+ needs: build
+ runs-on: ubuntu-latest
+ steps:
+ - name: Deploy to GitHub Pages
+ id: deployment
+ uses: actions/deploy-pages@v4
diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..d403b95
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,217 @@
+# Created by https://www.toptal.com/developers/gitignore/api/python,react
+# Edit at https://www.toptal.com/developers/gitignore?templates=python,react
+
+### Python ###
+# Byte-compiled / optimized / DLL files
+__pycache__/
+*.py[cod]
+*$py.class
+
+# C extensions
+*.so
+
+# Distribution / packaging
+.Python
+build/
+develop-eggs/
+dist/
+downloads/
+eggs/
+.eggs/
+# lib/
+lib64/
+parts/
+sdist/
+var/
+wheels/
+share/python-wheels/
+*.egg-info/
+.installed.cfg
+*.egg
+MANIFEST
+
+# PyInstaller
+# Usually these files are written by a python script from a template
+# before PyInstaller builds the exe, so as to inject date/other infos into it.
+*.manifest
+*.spec
+
+# Installer logs
+pip-log.txt
+pip-delete-this-directory.txt
+
+# Unit test / coverage reports
+htmlcov/
+.tox/
+.nox/
+.coverage
+.coverage.*
+.cache
+nosetests.xml
+coverage.xml
+*.cover
+*.py,cover
+.hypothesis/
+.pytest_cache/
+cover/
+
+# Translations
+*.mo
+*.pot
+
+# Django stuff:
+*.log
+local_settings.py
+db.sqlite3
+db.sqlite3-journal
+
+# Flask stuff:
+instance/
+.webassets-cache
+
+# Scrapy stuff:
+.scrapy
+
+# Sphinx documentation
+docs/_build/
+
+# PyBuilder
+.pybuilder/
+target/
+
+# Jupyter Notebook
+.ipynb_checkpoints
+
+# IPython
+profile_default/
+ipython_config.py
+
+# pyenv
+# For a library or package, you might want to ignore these files since the code is
+# intended to run in multiple environments; otherwise, check them in:
+# .python-version
+
+# pipenv
+# According to pypa/pipenv#598, it is recommended to include Pipfile.lock in version control.
+# However, in case of collaboration, if having platform-specific dependencies or dependencies
+# having no cross-platform support, pipenv may install dependencies that don't work, or not
+# install all needed dependencies.
+#Pipfile.lock
+
+# poetry
+# Similar to Pipfile.lock, it is generally recommended to include poetry.lock in version control.
+# This is especially recommended for binary packages to ensure reproducibility, and is more
+# commonly ignored for libraries.
+# https://python-poetry.org/docs/basic-usage/#commit-your-poetrylock-file-to-version-control
+#poetry.lock
+
+# pdm
+# Similar to Pipfile.lock, it is generally recommended to include pdm.lock in version control.
+#pdm.lock
+# pdm stores project-wide configurations in .pdm.toml, but it is recommended to not include it
+# in version control.
+# https://pdm.fming.dev/#use-with-ide
+.pdm.toml
+
+# PEP 582; used by e.g. github.com/David-OConnor/pyflow and github.com/pdm-project/pdm
+__pypackages__/
+
+# Celery stuff
+celerybeat-schedule
+celerybeat.pid
+
+# SageMath parsed files
+*.sage.py
+
+# Environments
+*.env
+.venv
+env/
+venv/
+ENV/
+env.bak/
+venv.bak/
+
+# Spyder project settings
+.spyderproject
+.spyproject
+
+# Rope project settings
+.ropeproject
+
+# mkdocs documentation
+/site
+
+# mypy
+.mypy_cache/
+.dmypy.json
+dmypy.json
+
+# Pyre type checker
+.pyre/
+
+# pytype static type analyzer
+.pytype/
+
+# Cython debug symbols
+cython_debug/
+
+# PyCharm
+# JetBrains specific template is maintained in a separate JetBrains.gitignore that can
+# be found at https://github.com/github/gitignore/blob/main/Global/JetBrains.gitignore
+# and can be added to the global gitignore or merged into this file. For a more nuclear
+# option (not recommended) you can uncomment the following to ignore the entire idea folder.
+#.idea/
+
+### Python Patch ###
+# Poetry local configuration file - https://python-poetry.org/docs/configuration/#local-configuration
+poetry.toml
+
+# ruff
+.ruff_cache/
+
+# LSP config files
+pyrightconfig.json
+
+### react ###
+.DS_*
+logs
+**/*.backup.*
+**/*.back.*
+
+node_modules
+bower_components
+
+*.sublime*
+
+psd
+thumb
+sketch
+
+# End of https://www.toptal.com/developers/gitignore/api/python,react
+
+.env
+
+# Databases
+*.db
+.qdash
+memo_store.toml
+prefect.db-shm
+prefect.db-wal
+.next
+next-env.d.ts
+# tailwind.config.js
+data/
+backend/qcflow/storage
+postgres_data/
+mongo_data/
+calib_data/
+*.env*
+docker_node_modules/
+.venv/src/
+log/
+quel.json
+.pnpm-store/
+qpu_data/
+docs/.vitepress/cache/
+client/.vite/
diff --git a/.gitmessage b/.gitmessage
new file mode 100644
index 0000000..75439b9
--- /dev/null
+++ b/.gitmessage
@@ -0,0 +1,18 @@
+# Overview (Uncomment one of the following templates)
+#feat:
+# └ A new feature
+#fix:
+# └ A bug fix
+#docs:
+# └ Documentation only changes
+#style:
+# └ Changes that do not affect the meaning of the code
+# (white-space, formatting, missing semi-colons, etc)
+#refactor:
+# └ A code change that neither fixes a bug nor adds a featur
+#test:
+# └ Adding missing or correcting existing tests
+#ci:
+# └ Changes to our CI configuration files and scripts
+#chore:
+# └ Updating grunt tasks etc; no production code change
diff --git a/.vscode/settings.json b/.vscode/settings.json
new file mode 100644
index 0000000..65c33c9
--- /dev/null
+++ b/.vscode/settings.json
@@ -0,0 +1,26 @@
+{
+ "editor.defaultFormatter": "esbenp.prettier-vscode",
+ "editor.formatOnSave": true,
+ "files.associations": {
+ "*.env.qiqb": "plaintext",
+ ".gitmessage": "plaintext"
+ },
+ "[python]": {
+ "editor.formatOnSave": true,
+ "editor.codeActionsOnSave": {
+ "source.fixAll.ruff": "explicit",
+ "source.organizeImports.ruff": "explicit"
+ },
+ "editor.defaultFormatter": "charliermarsh.ruff"
+ },
+ "ruff.path": ["${workspaceFolder}/.venv/bin/ruff"],
+ "ruff.lint.args": ["--config=${workspaceFolder}/pyproject.toml"],
+ "markdownlint.config": {
+ "MD024": false,
+ "MD033": false,
+ "MD041": false
+ },
+ "[markdown]": {
+ "editor.defaultFormatter": "esbenp.prettier-vscode"
+ }
+}
diff --git a/CITATION.cff b/CITATION.cff
new file mode 100644
index 0000000..dfd3a0b
--- /dev/null
+++ b/CITATION.cff
@@ -0,0 +1,21 @@
+cff-version: 1.2.0
+message: "If you use this software, please cite it as below."
+title: "QDash"
+authors:
+ - family-names: "Masumoto"
+ given-names: "Naoyuki"
+ - family-names: "Miyaji"
+ given-names: "Kosuke"
+ - family-names: "Miyanaga"
+ given-names: "Takafumi"
+ orcid: "https://orcid.org/0009-0001-5094-6035"
+ - family-names: "Mori"
+ given-names: "Toshio"
+ - family-names: "Tsukano"
+ given-names: "Satoyuki"
+ orcid: "https://orcid.org/0009-0000-3825-9083"
+version: 0.1.0
+date-released: 2024-12-05
+license: Apache-2.0
+repository-code: "https://github.com/oqtopus-team/qdash"
+url: "https://github.com/oqtopus-team.github.io/qdash"
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..3e023eb
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,201 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "[]"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright xxxx-xx-xx Takafumi Miyanaga
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
diff --git a/README copy.md b/README copy.md
new file mode 100644
index 0000000..3faac67
--- /dev/null
+++ b/README copy.md
@@ -0,0 +1,67 @@
+# QDash
+
+QDash is a web application that provides a user-friendly interface to manage and monitor the execution of calibration workflows.
+
+## Key Features
+
+- **⚡ Workflows**: Centrally manage and track the progress of calibration workflows, from creation to completion.
+
+- **📊 Observations**: Access and analyze the observational data utilized in calibration processes, ensuring transparency and insight.
+
+- **⚙️ Settings**: Configure calibration parameters and adjust workflow settings to meet specific requirements seamlessly.
+
+## Quick Start
+
+### Initial Setup
+
+Run the following commands to create the necessary directories and environment files.
+
+```bash
+chmod +x scripts/create_directory.sh scripts/create_env.sh scripts/init.sh
+scripts/init.sh
+```
+
+### Start the Development Environment
+
+```bash
+docker compose up -d
+```
+
+### Initialize the Database
+
+```bash
+ docker compose -f compose.dev.yaml up -d
+```
+
+```bash
+docker exec -it qdash-devcontainer /bin/bash -c "python init/setup.py init-all"
+```
+
+You can now access the application at [http://localhost:5714](http://localhost:5714).
+
+### Delete the Database
+
+```bash
+docker exec -it qdash-devcontainer /bin/bash -c "python init/setup.py teardown-all"
+```
+
+## Documentation
+
+- [Documentation Home](https://oqtopus-team.github.io/qdash/)
+
+## CITATION
+
+You can use the DOI to cite QDash in your research.
+
+Citation information is also available in the [CITATION](https://github.com/oqtopus-team/qdash/blob/main/CITATION.cff) file.
+
+## Contact
+
+You can contact us by creating an issue in this repository,
+or you can contact us by email:
+
+- [oqtopus-team[at]googlegroups.com](mailto:oqtopus-team[at]googlegroups.com)
+
+## LICENSE
+
+OQTOPUS Cloud is released under the [Apache License 2.0](https://github.com/oqtopus-team/qdash/blob/main/LICENSE).
diff --git a/README.md b/README.md
index b347ffb..3faac67 100644
--- a/README.md
+++ b/README.md
@@ -1 +1,67 @@
-# qdash
+# QDash
+
+QDash is a web application that provides a user-friendly interface to manage and monitor the execution of calibration workflows.
+
+## Key Features
+
+- **⚡ Workflows**: Centrally manage and track the progress of calibration workflows, from creation to completion.
+
+- **📊 Observations**: Access and analyze the observational data utilized in calibration processes, ensuring transparency and insight.
+
+- **⚙️ Settings**: Configure calibration parameters and adjust workflow settings to meet specific requirements seamlessly.
+
+## Quick Start
+
+### Initial Setup
+
+Run the following commands to create the necessary directories and environment files.
+
+```bash
+chmod +x scripts/create_directory.sh scripts/create_env.sh scripts/init.sh
+scripts/init.sh
+```
+
+### Start the Development Environment
+
+```bash
+docker compose up -d
+```
+
+### Initialize the Database
+
+```bash
+ docker compose -f compose.dev.yaml up -d
+```
+
+```bash
+docker exec -it qdash-devcontainer /bin/bash -c "python init/setup.py init-all"
+```
+
+You can now access the application at [http://localhost:5714](http://localhost:5714).
+
+### Delete the Database
+
+```bash
+docker exec -it qdash-devcontainer /bin/bash -c "python init/setup.py teardown-all"
+```
+
+## Documentation
+
+- [Documentation Home](https://oqtopus-team.github.io/qdash/)
+
+## CITATION
+
+You can use the DOI to cite QDash in your research.
+
+Citation information is also available in the [CITATION](https://github.com/oqtopus-team/qdash/blob/main/CITATION.cff) file.
+
+## Contact
+
+You can contact us by creating an issue in this repository,
+or you can contact us by email:
+
+- [oqtopus-team[at]googlegroups.com](mailto:oqtopus-team[at]googlegroups.com)
+
+## LICENSE
+
+OQTOPUS Cloud is released under the [Apache License 2.0](https://github.com/oqtopus-team/qdash/blob/main/LICENSE).
diff --git a/Taskfile.yaml b/Taskfile.yaml
new file mode 100644
index 0000000..af1386a
--- /dev/null
+++ b/Taskfile.yaml
@@ -0,0 +1,75 @@
+version: 3
+
+tasks:
+ default:
+ desc: Display available tasks
+ cmds:
+ - task -l
+ generate:
+ dir: client
+ cmds:
+ - curl http://localhost:5715/openapi.json | jq > ../docs/oas/openapi.json
+ - npx orval --config ./orval.config.cjs
+ - npx prettier . --write
+ - npx eslint . --fix
+ desc: Generate the client
+
+ docs:
+ dir: docs
+ cmds:
+ - npm run docs:dev
+
+ build-docs:
+ dir: docs
+ cmds:
+ - npm run docs:build
+ # - poetry run mkdocs serve
+
+ fmt-client:
+ dir: client
+ cmds:
+ - npx prettier . --write
+ - npx eslint . --fix
+ desc: Format the client
+
+ fmt:
+ cmds:
+ - poetry run ruff format .
+ - npx prettier . --write
+ - npx eslint . --fix
+ desc: Format common code
+
+ tbls-docs:
+ cmds:
+ - tbls doc -c .tbls.yml -f
+ desc: Generate DB Schema Docs
+
+ export-server:
+ cmds:
+ - poetry export -f requirements.txt --output ./backend/server/requirements.txt --without-hashes --with=server,dev
+ desc: Export server requirements
+
+ export-qcflow:
+ cmds:
+ - poetry export -f requirements.txt --output ./backend/qcflow/requirements.txt --without-hashes --with=qcflow,dev
+ desc: Export qcflow requirements
+
+ export-all:
+ cmds:
+ - poetry export -f requirements.txt --output ./.devcontainer/requirements.txt --without-hashes --with=server,qcflow,dev
+ desc: Export all requirements
+
+ build-server:
+ cmds:
+ - poetry export -f requirements.txt --output ./backend/server/requirements.txt --without-hashes --with=server,dev
+ - docker compose build --no-cache server
+
+ build-qcflow:
+ cmds:
+ - poetry export -f requirements.txt --output qcflow.requirements.txt --without-hashes --with=qcflow,dev
+ - docker compose build --no-cache qcflow
+
+ requirements:
+ cmds:
+ - poetry export -f requirements.txt --output requirements.txt --without-hashes
+ desc: Generate requirements.txt
diff --git a/backend/__init__.py b/backend/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/dbmodel/__init__.py b/backend/dbmodel/__init__.py
new file mode 100644
index 0000000..8e24f34
--- /dev/null
+++ b/backend/dbmodel/__init__.py
@@ -0,0 +1,55 @@
+# import os
+
+# from bunnet import init_bunnet
+# from dbmodel.bluefors import BlueforsModel
+# from dbmodel.execution_lock import ExecutionLockModel
+# from dbmodel.execution_run import ExecutionRunModel
+# from dbmodel.execution_run_history import ExecutionRunHistoryModel
+# from dbmodel.experiment import ExperimentModel
+# from dbmodel.experiment_history import ExperimentHistoryModel
+# from dbmodel.fridge_status import FridgeStatusModel
+# from dbmodel.menu import MenuModel
+# from dbmodel.one_qubit_calib import OneQubitCalibModel
+# from dbmodel.one_qubit_calib_all_history import OneQubitCalibAllHistoryModel
+# from dbmodel.one_qubit_calib_daily_summary import OneQubitCalibDailySummaryModel
+# from dbmodel.one_qubit_calib_history import OneQubitCalibHistoryModel
+# from dbmodel.one_qubit_calib_history_all import OneQubitCalibHistoryAllModel
+# from dbmodel.qpu import QPUModel
+# from dbmodel.session_info import SessionInfoModel
+# from dbmodel.two_qubit_calib import TwoQubitCalibModel
+# from dbmodel.two_qubit_calib_daily_summary import TwoQubitCalibDailySummaryModel
+# from dbmodel.two_qubit_calib_history import TwoQubitCalibHistoryModel
+# from dbmodel.wiring_info import WiringInfoModel
+# from pymongo import MongoClient
+
+# mongo_ip = os.getenv("MONGO_HOST")
+# client: MongoClient = MongoClient(mongo_ip, 27017, username="root", password="example")
+# # client: MongoClient = MongoClient(mongo_uri)
+# # client: MongoClient = MongoClient(
+# # "localhost", 27017, username="root", password="example"
+# # )
+# # client: MongoClient = MongoClient(mongo_uri)
+# init_bunnet(
+# database=client.cloud,
+# document_models=[
+# OneQubitCalibModel,
+# TwoQubitCalibModel,
+# MenuModel,
+# OneQubitCalibHistoryModel,
+# OneQubitCalibDailySummaryModel,
+# TwoQubitCalibHistoryModel,
+# TwoQubitCalibDailySummaryModel,
+# SessionInfoModel,
+# WiringInfoModel,
+# QPUModel,
+# BlueforsModel,
+# OneQubitCalibHistoryAllModel,
+# ExecutionLockModel,
+# ExperimentHistoryModel,
+# ExperimentModel,
+# ExecutionRunModel,
+# ExecutionRunHistoryModel,
+# FridgeStatusModel,
+# OneQubitCalibAllHistoryModel,
+# ], # type: ignore
+# )
diff --git a/backend/dbmodel/bluefors.py b/backend/dbmodel/bluefors.py
new file mode 100644
index 0000000..a9758aa
--- /dev/null
+++ b/backend/dbmodel/bluefors.py
@@ -0,0 +1,37 @@
+from datetime import datetime
+from typing import Optional
+
+from bunnet import Document, Granularity, TimeSeriesConfig
+from pydantic import ConfigDict, Field
+from pymongo import IndexModel
+
+
+class BlueforsModel(Document):
+ id: str
+ device_id: str
+ timestamp: datetime
+ resistance: float
+ reactance: float
+ temperature: float
+ rez: float
+ imz: float
+ magnitude: float
+ angle: float
+ channel_nr: int
+ status_flags: Optional[int] = Field(None)
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+ class Settings:
+ name = "bluefors"
+ # collection.create_index("_id")
+ # collection.create_index("channel_nr")
+ indexes = [IndexModel(["channel_nr"])]
+
+ timeseries = TimeSeriesConfig(
+ time_field="timestamp", # Required
+ meta_field="metadata", # Optional
+ granularity=Granularity.hours, # Optional
+ expire_after_seconds=604800 * 4, # Optional
+ )
diff --git a/backend/dbmodel/cooling_down.py b/backend/dbmodel/cooling_down.py
new file mode 100644
index 0000000..f5e0862
--- /dev/null
+++ b/backend/dbmodel/cooling_down.py
@@ -0,0 +1,22 @@
+from bunnet import Document
+from pydantic import ConfigDict
+from pymongo import ASCENDING, IndexModel
+
+
+class CoolingDownModel(Document):
+ cooling_down_id: int
+ date: str
+ qpu_name: str
+ size: int
+
+ class Settings:
+ name = "cooling_down"
+ indexes = [IndexModel([("date", ASCENDING)], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+ @classmethod
+ def get_latest_cooling_down_id(cls):
+ return cls.find_one(sort=[("cooling_down_id", -1)]).run().cooling_down_id
diff --git a/backend/dbmodel/execution_lock.py b/backend/dbmodel/execution_lock.py
new file mode 100644
index 0000000..6d896cc
--- /dev/null
+++ b/backend/dbmodel/execution_lock.py
@@ -0,0 +1,16 @@
+from datetime import datetime
+
+from bunnet import Document
+from pydantic import ConfigDict, Field
+
+
+class ExecutionLockModel(Document):
+ lock: bool
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+ class Settings:
+ name = "execution_lock"
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/execution_run.py b/backend/dbmodel/execution_run.py
new file mode 100644
index 0000000..81551a6
--- /dev/null
+++ b/backend/dbmodel/execution_run.py
@@ -0,0 +1,19 @@
+from datetime import datetime
+
+from bunnet import Document
+from pydantic import ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+
+class ExecutionRunModel(Document):
+ date: str
+ index: int
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+ class Settings:
+ name = "execution_run"
+ indexes = [IndexModel([("date", ASCENDING)], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/execution_run_history.py b/backend/dbmodel/execution_run_history.py
new file mode 100644
index 0000000..1bc9f3d
--- /dev/null
+++ b/backend/dbmodel/execution_run_history.py
@@ -0,0 +1,61 @@
+from datetime import datetime
+from typing import Optional
+
+from bunnet import Document
+from bunnet.odm.operators.update.general import Set
+from pydantic import ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+from .one_qubit_calib_all_history import OneQubitCalibAllHistoryModel
+
+
+class ExecutionRunHistoryModel(Document):
+ date: str
+ timestamp: datetime = Field(default_factory=datetime.now)
+ status: Optional[str] = Field(None)
+ execution_id: str
+ updated_at: datetime = Field(default_factory=datetime.now)
+ qpu_name: Optional[str] = Field(None)
+ menu: dict
+ tags: Optional[list[str]] = Field(None)
+ fridge_temperature: Optional[float] = Field(None)
+ flow_url: Optional[str] = Field(None)
+
+ class Settings:
+ name = "execution_run_history"
+ indexes = [IndexModel([("execution_id", ASCENDING)], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+ @classmethod
+ def get_by_execution_id(cls, execution_id: str):
+ return cls.find_one(cls.execution_id == execution_id).run()
+
+ def add_tags(self, new_tags: list[str]):
+ if self.tags is None:
+ self.tags = new_tags
+ else:
+ # 重複していないタグのみを追加
+ self.tags.extend(tag for tag in new_tags if tag not in self.tags)
+ self.save()
+
+ # OneQubitCalibAllHistoryModel の対応するドキュメントを更新
+ histories = OneQubitCalibAllHistoryModel.find(
+ OneQubitCalibAllHistoryModel.execution_id == self.execution_id
+ )
+ for history in histories:
+ history.update(Set({OneQubitCalibAllHistoryModel.tags: self.tags}))
+
+ def remove_tags(self, tags_to_remove: list[str]):
+ if self.tags is not None:
+ self.tags = [tag for tag in self.tags if tag not in tags_to_remove]
+ self.save()
+
+ # OneQubitCalibAllHistoryModel の対応するドキュメントを更新
+ histories = OneQubitCalibAllHistoryModel.find(
+ OneQubitCalibAllHistoryModel.execution_id == self.execution_id
+ )
+ for history in histories:
+ history.update(Set({OneQubitCalibAllHistoryModel.tags: self.tags}))
diff --git a/backend/dbmodel/experiment.py b/backend/dbmodel/experiment.py
new file mode 100644
index 0000000..071fae1
--- /dev/null
+++ b/backend/dbmodel/experiment.py
@@ -0,0 +1,18 @@
+from datetime import datetime
+
+from bunnet import Document
+from pydantic import ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+
+class ExperimentModel(Document):
+ experiment_name: str
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+ class Settings:
+ name = "experiment"
+ indexes = [IndexModel([("experiment_name", ASCENDING)], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/experiment_history.py b/backend/dbmodel/experiment_history.py
new file mode 100644
index 0000000..91e32c7
--- /dev/null
+++ b/backend/dbmodel/experiment_history.py
@@ -0,0 +1,43 @@
+from datetime import datetime
+from enum import Enum
+from typing import Optional
+
+from bunnet import Document
+from pydantic import ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+
+class Status(str, Enum):
+ SCHEDULED: str = "scheduled"
+ RUNNING: str = "running"
+ SUCCESS: str = "success"
+ FAILED: str = "failed"
+ UNKNOWN: str = "unknown"
+
+
+class ExperimentHistoryModel(Document):
+ experiment_name: str
+ label: str
+ timestamp: datetime = Field(default_factory=datetime.now)
+ status: Optional[str] = Field("running")
+ fig_path: Optional[str] = Field(None)
+ input_parameter: dict
+ output_parameter: dict
+ execution_id: Optional[str] = Field(None) # 20241116#0
+
+ class Settings:
+ name = "experiment_history"
+ indexes = [
+ IndexModel(
+ [
+ ("label", ASCENDING),
+ ("timestamp", ASCENDING),
+ ("experiment_name", ASCENDING),
+ ],
+ unique=True,
+ )
+ ]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/fridge_status.py b/backend/dbmodel/fridge_status.py
new file mode 100644
index 0000000..1a148fa
--- /dev/null
+++ b/backend/dbmodel/fridge_status.py
@@ -0,0 +1,32 @@
+from typing import Optional
+
+from bunnet import Document
+from pydantic import BaseModel, ConfigDict, Field
+from pymongo import IndexModel
+
+
+class ChannelInfo(BaseModel):
+ status: str = "normal" # normal, abnormal
+ threshold: Optional[float] = Field(None)
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+
+class FridgeStatusModel(Document):
+ device_id: str
+ ch1: Optional[ChannelInfo] = Field(None)
+ ch2: Optional[ChannelInfo] = Field(None)
+ ch5: Optional[ChannelInfo] = Field(None)
+ ch6: Optional[ChannelInfo] = Field(None)
+
+ class Settings:
+ name = "fridge_status"
+ # collection.create_index("_id")
+ # collection.create_index("channel_nr")
+ indexes = [IndexModel(["device_id"], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/instrument.py b/backend/dbmodel/instrument.py
new file mode 100644
index 0000000..4958538
--- /dev/null
+++ b/backend/dbmodel/instrument.py
@@ -0,0 +1,32 @@
+from typing import Optional
+
+from bunnet import Document
+from pydantic import BaseModel, ConfigDict, Field
+from pymongo import IndexModel
+
+
+class PortConfig(BaseModel):
+ port: Optional[int] = Field(default=0)
+ direction: Optional[str] = Field(default="")
+ lo_freq: Optional[float] = Field(default=0)
+ cnco_freq: Optional[float] = Field(default=0)
+ fullscale_current: Optional[int] = Field(default=0)
+ sideband: Optional[str] = Field(default="")
+
+
+class InstrumentModel(Document):
+ label: str
+ name: str
+ type: str
+ status: str
+ address: str
+ adapter: str
+ detail: Optional[list[PortConfig]] = None
+
+ class Settings:
+ name = "instrument"
+ indexes = [IndexModel([("address", 1)], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/menu.py b/backend/dbmodel/menu.py
new file mode 100644
index 0000000..ccda183
--- /dev/null
+++ b/backend/dbmodel/menu.py
@@ -0,0 +1,36 @@
+from enum import Enum
+from typing import Optional
+
+from bunnet import Document
+from pydantic import ConfigDict, Field
+
+# OneQubitOperation = int
+# TwoQubitOperation = tuple[int, int]
+
+# OneQubitCalibPlan = list[list[OneQubitOperation]]
+# TwoQubitCalibPlan = list[list[TwoQubitOperation]]
+
+
+class Mode(Enum):
+ DEFAULT: str = "default"
+ DRAG: str = "drag"
+ FILTER: str = "filter"
+ CUSTOM: str = "custom"
+
+
+class MenuModel(Document):
+ name: str
+ description: str
+ one_qubit_calib_plan: list[list[int]]
+ two_qubit_calib_plan: list[list[tuple[int, int]]]
+ mode: str
+ notify_bool: bool = True
+ flow: list[str]
+ exp_list: Optional[list[str]] = Field(default=None, exclude=True)
+ tags: Optional[list[str]] = Field(default=None)
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+ class Settings:
+ name = "menu"
diff --git a/backend/dbmodel/one_qubit_calib.py b/backend/dbmodel/one_qubit_calib.py
new file mode 100644
index 0000000..1cc7ef4
--- /dev/null
+++ b/backend/dbmodel/one_qubit_calib.py
@@ -0,0 +1,112 @@
+from datetime import datetime
+from enum import Enum
+from typing import Any, Optional, Union
+
+import numpy as np
+from bunnet import Document
+from dbmodel.qpu import QPUModel
+from labrad.units import Value as LabradValue
+from pydantic import BaseModel, ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+
+class Data(BaseModel):
+ value: Union[float, list, list[list]]
+ unit: str
+ type: str
+
+
+class Position(BaseModel):
+ x: float
+ y: float
+
+
+class NodeInfo(BaseModel):
+ fill: str
+ position: Position
+
+
+class Status(str, Enum):
+ SCHEDULED: str = "scheduled"
+ RUNNING: str = "running"
+ SUCCESS: str = "success"
+ FAILED: str = "failed"
+ UNKNOWN: str = "unknown"
+
+
+class OneQubitCalibData(BaseModel):
+ resonator_frequency: Optional[Data] = Field(None)
+ qubit_frequency: Optional[Data] = Field(None)
+ t1: Optional[Data] = Field(None)
+ t2_echo: Optional[Data] = Field(None)
+ t2_star: Optional[Data] = Field(None)
+ average_gate_fidelity: Optional[Data] = Field(None)
+
+ def simplify(self):
+ for field in self.__fields__:
+ value = getattr(self, field)
+ if isinstance(value, Data):
+ setattr(self, field, value.value)
+ elif isinstance(value, list):
+ setattr(
+ self,
+ field,
+ [item.value if isinstance(item, Data) else item for item in value],
+ )
+
+
+class OneQubitCalibModel(Document):
+ qpu_name: str
+ cooling_down_id: int
+ label: str
+ status: str
+ node_info: NodeInfo
+ one_qubit_calib_data: Optional[OneQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+ class Settings:
+ name = "one_qubit_calib"
+ indexes = [
+ IndexModel([("label", ASCENDING), ("qpu_name", ASCENDING)], unique=True)
+ ]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+ @classmethod
+ def get_qubit_info(cls) -> dict[str, Any]:
+ qpu_name = QPUModel.get_active_qpu_name()
+ one_qubit_calib_list = cls.find(cls.qpu_name == qpu_name).run()
+ return {
+ item.label: item.one_qubit_calib_data.dict()
+ for item in one_qubit_calib_list
+ }
+
+ @classmethod
+ def convert_from_json_dict(cls, json_dict: dict) -> dict[str, Any]:
+ """Convert json with array and labrad values to normal dict"""
+ qubit_dict = {}
+ for key, val in json_dict.items():
+ if val is None:
+ continue
+ if val["type"] == "float_value":
+ qubit_dict[key] = val["value"]
+ elif val["type"] == "complex_array":
+ arr = np.array(val["value"])
+ if arr.size == 0:
+ qubit_dict[key] = np.array([], dtype=complex)
+ continue
+ qubit_dict[key] = arr[0] + 1.0j * arr[1]
+ elif val["type"] == "real_array":
+ arr = np.array(val["value"])
+ if arr.size == 0:
+ qubit_dict[key] = np.array([], dtype=float)
+ continue
+ qubit_dict[key] = arr
+ elif val["type"] == "labrad_value":
+ qubit_dict[key] = LabradValue(val["value"], val["unit"])
+ else:
+ raise ValueError("invalid type")
+ return qubit_dict
diff --git a/backend/dbmodel/one_qubit_calib_all_history.py b/backend/dbmodel/one_qubit_calib_all_history.py
new file mode 100644
index 0000000..2535f5d
--- /dev/null
+++ b/backend/dbmodel/one_qubit_calib_all_history.py
@@ -0,0 +1,32 @@
+from datetime import datetime
+from typing import Optional
+
+from bunnet import Document
+from dbmodel.one_qubit_calib import OneQubitCalibData
+from pydantic import ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+
+class OneQubitCalibAllHistoryModel(Document):
+ label: str
+ timestamp: str = Field(
+ default_factory=lambda: datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ )
+ qpu_name: str
+ execution_id: str
+ cooling_down_id: int
+ menu: dict
+ tags: Optional[list[str]] = Field(None)
+ one_qubit_calib_data: Optional[OneQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+ class Settings:
+ name = "one_qubit_calib_all_history"
+ indexes = [
+ IndexModel([("timestamp", ASCENDING), ("label", ASCENDING)], unique=True)
+ ]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/one_qubit_calib_daily_summary.py b/backend/dbmodel/one_qubit_calib_daily_summary.py
new file mode 100644
index 0000000..64d7892
--- /dev/null
+++ b/backend/dbmodel/one_qubit_calib_daily_summary.py
@@ -0,0 +1,39 @@
+from typing import Optional
+
+from bunnet import Document
+from pydantic import BaseModel, ConfigDict
+from pymongo import ASCENDING, IndexModel
+
+from dbmodel.one_qubit_calib import OneQubitCalibData
+
+
+class OneQubitCalibSummary(BaseModel):
+ label: str
+ one_qubit_calib_data: Optional[OneQubitCalibData]
+
+
+class OneQubitCalibDailySummaryModel(Document):
+ date: str
+ labels: list[str]
+ qpu_name: str
+ cooling_down_id: int
+ summary: list[OneQubitCalibSummary]
+ note: str = ""
+
+ class Settings:
+ name = "one_qubit_calib_daily_summary"
+ indexes = [IndexModel([("date", ASCENDING)], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+ def simplify(self) -> list[dict]:
+ simplified_data = []
+ for item in self.summary:
+ if item.one_qubit_calib_data:
+ item.one_qubit_calib_data.simplify() # 簡略化
+ simplified_data.append(
+ {"label": item.label, **item.one_qubit_calib_data.dict()}
+ )
+ return simplified_data
diff --git a/backend/dbmodel/one_qubit_calib_history.py b/backend/dbmodel/one_qubit_calib_history.py
new file mode 100644
index 0000000..8b3c8df
--- /dev/null
+++ b/backend/dbmodel/one_qubit_calib_history.py
@@ -0,0 +1,26 @@
+from datetime import date, datetime
+from typing import Optional
+
+from bunnet import Document
+from pydantic import ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+from dbmodel.one_qubit_calib import OneQubitCalibData
+
+
+class OneQubitCalibHistoryModel(Document):
+ label: str
+ date: str = Field(default_factory=lambda: date.today().strftime("%Y%m%d"))
+ qpu_name: str
+ cooling_down_id: int
+ one_qubit_calib_data: Optional[OneQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+ class Settings:
+ name = "one_qubit_calib_history"
+ indexes = [IndexModel([("date", ASCENDING), ("label", ASCENDING)], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/one_qubit_calib_history_all.py b/backend/dbmodel/one_qubit_calib_history_all.py
new file mode 100644
index 0000000..e7cb582
--- /dev/null
+++ b/backend/dbmodel/one_qubit_calib_history_all.py
@@ -0,0 +1,29 @@
+from datetime import datetime
+from typing import Optional
+
+from bunnet import Document
+from dbmodel.one_qubit_calib import OneQubitCalibData
+from pydantic import ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+
+class OneQubitCalibHistoryAllModel(Document):
+ label: str
+ timestamp: str = Field(
+ default_factory=lambda: datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ )
+ qpu_name: str
+ cooling_down_id: int
+ one_qubit_calib_data: Optional[OneQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+ class Settings:
+ name = "one_qubit_calib_history_all"
+ indexes = [
+ IndexModel([("timestamp", ASCENDING), ("label", ASCENDING)], unique=True)
+ ]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/qpu.py b/backend/dbmodel/qpu.py
new file mode 100644
index 0000000..aa90089
--- /dev/null
+++ b/backend/dbmodel/qpu.py
@@ -0,0 +1,28 @@
+from datetime import datetime
+
+from bunnet import Document
+from pydantic import ConfigDict, Field
+
+
+class QPUModel(Document):
+ name: str
+ size: int
+ nodes: list[str]
+ edges: list[str]
+ active: bool = Field(default=False)
+ installed_at: datetime = Field(default_factory=datetime.now)
+
+ class Settings:
+ name = "qpu"
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+ @classmethod
+ def get_active_qpu(cls):
+ return cls.find_one(cls.active == True).run()
+
+ @classmethod
+ def get_active_qpu_name(cls):
+ return cls.find_one(cls.active == True).run().name
diff --git a/backend/dbmodel/qube.py b/backend/dbmodel/qube.py
new file mode 100644
index 0000000..695bd39
--- /dev/null
+++ b/backend/dbmodel/qube.py
@@ -0,0 +1,18 @@
+from bunnet import Document
+from pydantic import ConfigDict
+
+
+class QubeModel(Document):
+ label: str
+ name: str
+ type: str
+ status: str
+ address: str
+ adapter: str
+
+ class Settings:
+ name = "quel"
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/session_info.py b/backend/dbmodel/session_info.py
new file mode 100644
index 0000000..d2b80fb
--- /dev/null
+++ b/backend/dbmodel/session_info.py
@@ -0,0 +1,28 @@
+from bunnet import Document
+from pydantic import ConfigDict
+from pymongo import IndexModel
+
+
+class SessionInfoModel(Document):
+ labrad_hostname: str
+ labrad_username: str
+ labrad_password: str
+ cooling_down_id: str
+ experiment_username: str
+ package_name: str
+ active: bool
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+ class Settings:
+ name = "session_info"
+ indexes = [IndexModel([("experiment_username", 1)], unique=True)]
+
+ @classmethod
+ def get_active_session_info(cls):
+ return cls.find_one(cls.active == True).run()
+
+ @classmethod
+ def get_active_session_info_dict(cls):
+ return cls.get_active_session_info().dict()
diff --git a/backend/dbmodel/two_qubit_calib.py b/backend/dbmodel/two_qubit_calib.py
new file mode 100644
index 0000000..2a1c38c
--- /dev/null
+++ b/backend/dbmodel/two_qubit_calib.py
@@ -0,0 +1,54 @@
+from datetime import datetime
+from typing import Optional, Union
+
+from bunnet import Document
+from pydantic import BaseModel, ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+
+class Data(BaseModel):
+ value: Union[float, list, list[list]]
+ unit: str
+ type: str
+
+
+class EdgeInfo(BaseModel):
+ source: str
+ target: str
+ size: int
+ fill: str
+
+
+class TwoQubitCalibData(BaseModel):
+ cross_resonance_power: Optional[Data] = Field(None)
+ average_gate_fidelity: Optional[Data] = Field(None)
+
+ def simplify(self):
+ for field in self.__fields__:
+ value = getattr(self, field)
+ if isinstance(value, Data):
+ setattr(self, field, value.value)
+ elif isinstance(value, list):
+ setattr(
+ self,
+ field,
+ [item.value if isinstance(item, Data) else item for item in value],
+ )
+
+
+class TwoQubitCalibModel(Document):
+ qpu_name: str
+ cooling_down_id: int
+ label: str
+ status: str
+ edge_info: EdgeInfo
+ two_qubit_calib_data: Optional[TwoQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+ model_config = ConfigDict(from_attributes=True)
+
+ class Settings:
+ name = "two_qubit_calib"
+ indexes = [
+ IndexModel([("label", ASCENDING), ("qpu_name", ASCENDING)], unique=True)
+ ]
diff --git a/backend/dbmodel/two_qubit_calib_daily_summary.py b/backend/dbmodel/two_qubit_calib_daily_summary.py
new file mode 100644
index 0000000..bffdb59
--- /dev/null
+++ b/backend/dbmodel/two_qubit_calib_daily_summary.py
@@ -0,0 +1,29 @@
+from typing import Optional
+
+from bunnet import Document
+from pydantic import BaseModel, ConfigDict
+from pymongo import ASCENDING, IndexModel
+
+from dbmodel.two_qubit_calib import TwoQubitCalibData
+
+
+class TwoQubitCalibSummary(BaseModel):
+ label: str
+ two_qubit_calib_data: Optional[TwoQubitCalibData]
+
+
+class TwoQubitCalibDailySummaryModel(Document):
+ date: str
+ labels: list[str]
+ qpu_name: str
+ cooling_down_id: int
+ summary: list[TwoQubitCalibSummary]
+ note: str = ""
+
+ class Settings:
+ name = "two_qubit_calib_daily_summary"
+ indexes = [IndexModel([("date", ASCENDING)], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/two_qubit_calib_history.py b/backend/dbmodel/two_qubit_calib_history.py
new file mode 100644
index 0000000..d38f7d0
--- /dev/null
+++ b/backend/dbmodel/two_qubit_calib_history.py
@@ -0,0 +1,26 @@
+from datetime import date, datetime
+from typing import Optional
+
+from bunnet import Document
+from pydantic import ConfigDict, Field
+from pymongo import ASCENDING, IndexModel
+
+from dbmodel.two_qubit_calib import TwoQubitCalibData
+
+
+class TwoQubitCalibHistoryModel(Document):
+ label: str
+ date: str = Field(default_factory=lambda: date.today().strftime("%Y%m%d"))
+ qpu_name: str
+ cooling_down_id: int
+ two_qubit_calib_data: Optional[TwoQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+ class Settings:
+ name = "two_qubit_calib_history"
+ indexes = [IndexModel([("date", ASCENDING), ("label", ASCENDING)], unique=True)]
+
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
diff --git a/backend/dbmodel/wiring_info.py b/backend/dbmodel/wiring_info.py
new file mode 100644
index 0000000..1f9c54f
--- /dev/null
+++ b/backend/dbmodel/wiring_info.py
@@ -0,0 +1,37 @@
+from typing import Optional
+
+from bunnet import Document
+from pydantic import BaseModel, ConfigDict, Field
+from pymongo import IndexModel
+
+
+class Wiring(BaseModel):
+ control: dict[str, dict[str, str]]
+ readout: dict[str, dict[str, str]]
+ bias: Optional[dict[str, dict[str, str]]] = Field(default=None, exclude=True)
+ pump: Optional[dict[str, dict[str, str]]] = Field(default=None, exclude=True)
+
+
+class WiringInfoModel(Document):
+ name: str
+ wiring_dict: Wiring
+ active: bool
+ model_config = ConfigDict(
+ from_attributes=True,
+ )
+
+ class Settings:
+ name = "wiring_info"
+ indexes = [IndexModel([("name", 1)], unique=True)]
+
+ @classmethod
+ def get_active_wiring(cls):
+ return cls.find_one(cls.active == True).run()
+
+ @classmethod
+ def get_active_wiring_dict(cls):
+ return cls.get_active_wiring().wiring_dict.dict()
+
+ @classmethod
+ def get_active_wiring_name(cls):
+ return cls.get_active_wiring().name
diff --git a/backend/qcflow/Dockerfile b/backend/qcflow/Dockerfile
new file mode 100644
index 0000000..7cd6510
--- /dev/null
+++ b/backend/qcflow/Dockerfile
@@ -0,0 +1,34 @@
+FROM prefecthq/prefect:2-python3.11 AS builder
+
+WORKDIR /app
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ build-essential \
+ pkg-config \
+ libhdf5-dev \
+ tzdata \
+ curl \
+ wget \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+ENV TZ=Asia/Tokyo
+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
+
+COPY ./backend/qcflow/requirements.txt ./
+
+COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
+RUN uv pip install --system --no-cache-dir -r requirements.txt
+
+FROM prefecthq/prefect:2-python3.11
+
+WORKDIR /app
+
+ENV TZ=Asia/Tokyo
+RUN ln -snf /usr/share/zoneinfo/$TZ /etc/localtime && echo $TZ > /etc/timezone
+
+COPY --from=builder /usr/local/lib/python3.11/site-packages /usr/local/lib/python3.11/site-packages
+COPY --from=builder /usr/local/bin /usr/local/bin
+
+RUN prefect config set PREFECT_EXPERIMENTAL_ENABLE_ENHANCED_CANCELLATION=True
diff --git a/backend/qcflow/__init__.py b/backend/qcflow/__init__.py
new file mode 100644
index 0000000..4f219bb
--- /dev/null
+++ b/backend/qcflow/__init__.py
@@ -0,0 +1,12 @@
+import sentry_sdk
+
+sentry_sdk.init(
+ dsn="",
+ # Set traces_sample_rate to 1.0 to capture 100%
+ # of transactions for performance monitoring.
+ traces_sample_rate=1.0,
+ # Set profiles_sample_rate to 1.0 to profile 100%
+ # of sampled transactions.
+ # We recommend adjusting this value in production.
+ profiles_sample_rate=1.0,
+)
diff --git a/backend/qcflow/db/__init__.py b/backend/qcflow/db/__init__.py
new file mode 100644
index 0000000..228193e
--- /dev/null
+++ b/backend/qcflow/db/__init__.py
@@ -0,0 +1,57 @@
+import os
+
+from bunnet import init_bunnet
+from dbmodel.bluefors import BlueforsModel
+from dbmodel.cooling_down import CoolingDownModel
+from dbmodel.execution_lock import ExecutionLockModel
+from dbmodel.execution_run import ExecutionRunModel
+from dbmodel.execution_run_history import ExecutionRunHistoryModel
+from dbmodel.experiment import ExperimentModel
+from dbmodel.experiment_history import ExperimentHistoryModel
+from dbmodel.fridge_status import FridgeStatusModel
+from dbmodel.menu import MenuModel
+from dbmodel.one_qubit_calib import OneQubitCalibModel
+from dbmodel.one_qubit_calib_all_history import OneQubitCalibAllHistoryModel
+from dbmodel.one_qubit_calib_daily_summary import OneQubitCalibDailySummaryModel
+from dbmodel.one_qubit_calib_history import OneQubitCalibHistoryModel
+from dbmodel.one_qubit_calib_history_all import OneQubitCalibHistoryAllModel
+from dbmodel.qpu import QPUModel
+from dbmodel.session_info import SessionInfoModel
+from dbmodel.two_qubit_calib import TwoQubitCalibModel
+from dbmodel.two_qubit_calib_daily_summary import TwoQubitCalibDailySummaryModel
+from dbmodel.two_qubit_calib_history import TwoQubitCalibHistoryModel
+from dbmodel.wiring_info import WiringInfoModel
+from pymongo import MongoClient
+
+mongo_ip = os.getenv("MONGO_HOST")
+client: MongoClient = MongoClient(mongo_ip, 27017, username="root", password="example")
+# client: MongoClient = MongoClient(mongo_uri)
+# client: MongoClient = MongoClient(
+# "localhost", 27017, username="root", password="example"
+# )
+# client: MongoClient = MongoClient(mongo_uri)
+init_bunnet(
+ database=client.cloud,
+ document_models=[
+ OneQubitCalibModel,
+ TwoQubitCalibModel,
+ MenuModel,
+ OneQubitCalibHistoryModel,
+ OneQubitCalibDailySummaryModel,
+ TwoQubitCalibHistoryModel,
+ TwoQubitCalibDailySummaryModel,
+ SessionInfoModel,
+ WiringInfoModel,
+ QPUModel,
+ BlueforsModel,
+ OneQubitCalibHistoryAllModel,
+ ExecutionLockModel,
+ ExperimentHistoryModel,
+ ExperimentModel,
+ ExecutionRunModel,
+ ExecutionRunHistoryModel,
+ FridgeStatusModel,
+ OneQubitCalibAllHistoryModel,
+ CoolingDownModel,
+ ], # type: ignore
+)
diff --git a/backend/qcflow/db/bluefors.py b/backend/qcflow/db/bluefors.py
new file mode 100644
index 0000000..62eb4e4
--- /dev/null
+++ b/backend/qcflow/db/bluefors.py
@@ -0,0 +1,53 @@
+from datetime import datetime, timezone
+
+from dbmodel.bluefors import BlueforsModel
+
+
+def get_latest_temperature(device_id, channel_nr):
+ latest_record = BlueforsModel.find_one(
+ BlueforsModel.device_id == device_id,
+ BlueforsModel.channel_nr == channel_nr,
+ sort=[("timestamp", -1)],
+ ).run()
+ if latest_record is not None:
+ return latest_record.temperature
+ else:
+ return 0
+
+
+def upsert_metrics(data, device_id):
+ fields = data["fields"]
+ measurements = data["measurements"]
+ num_measurements = len(measurements["timestamp"])
+ transformed_data: list[BlueforsModel] = []
+ for i in range(num_measurements):
+ record = {field: measurements[field][i] for field in fields}
+ r = BlueforsModel(
+ id=f"{device_id}_{data['channel_nr']}_{record['timestamp']}",
+ device_id=device_id,
+ timestamp=datetime.fromtimestamp(record["timestamp"], tz=timezone.utc),
+ resistance=record["resistance"],
+ reactance=record["reactance"],
+ temperature=record["temperature"],
+ rez=record["rez"],
+ imz=record["imz"],
+ magnitude=record["magnitude"],
+ angle=record["angle"],
+ channel_nr=data["channel_nr"],
+ )
+ transformed_data.append(r)
+ for d in transformed_data:
+ existing_record = BlueforsModel.get(d.id).run()
+ if not existing_record:
+ d.insert()
+
+
+# def get_existing_record(id: str):
+# existing_record = BlueforsModel.get(id).run()
+# print(existing_record)
+# return existing_record
+
+
+# def save_record(record: BlueforsModel):
+# record.save()
+# print(record)
diff --git a/backend/qcflow/db/execution_lock.py b/backend/qcflow/db/execution_lock.py
new file mode 100644
index 0000000..b9bdd02
--- /dev/null
+++ b/backend/qcflow/db/execution_lock.py
@@ -0,0 +1,23 @@
+from dbmodel.execution_lock import ExecutionLockModel
+from prefect import get_run_logger
+
+
+def get_execution_lock():
+ item = ExecutionLockModel.find_one().run()
+ return item.lock
+
+
+def lock_execution():
+ logger = get_run_logger()
+ logger.info("Locking the execution")
+ item = ExecutionLockModel.find_one().run()
+ item.lock = True
+ item.save()
+
+
+def unlock_execution():
+ logger = get_run_logger()
+ logger.info("Unlocking the execution")
+ item = ExecutionLockModel.find_one().run()
+ item.lock = False
+ item.save()
diff --git a/backend/qcflow/db/execution_run.py b/backend/qcflow/db/execution_run.py
new file mode 100644
index 0000000..0caa215
--- /dev/null
+++ b/backend/qcflow/db/execution_run.py
@@ -0,0 +1,12 @@
+from dbmodel.execution_run import ExecutionRunModel
+
+
+def get_next_execution_index(date: str) -> int:
+ execution_run = ExecutionRunModel.find_one({"date": date}).run()
+ if execution_run:
+ execution_run.index += 1
+ execution_run.save()
+ else:
+ execution_run = ExecutionRunModel(date=date, index=1)
+ execution_run.insert()
+ return int(execution_run.index)
diff --git a/backend/qcflow/db/execution_run_history.py b/backend/qcflow/db/execution_run_history.py
new file mode 100644
index 0000000..7e70696
--- /dev/null
+++ b/backend/qcflow/db/execution_run_history.py
@@ -0,0 +1,30 @@
+from datetime import datetime
+
+from dbmodel.execution_run_history import ExecutionRunHistoryModel
+from dbmodel.qpu import QPUModel
+
+
+def insert_execution_run(
+ date: str, execution_id: str, menu: dict, fridge_temperature: float, flow_url: str
+) -> None:
+ qpu = QPUModel.get_active_qpu()
+ execution_run = ExecutionRunHistoryModel(
+ timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
+ status="running",
+ date=date,
+ qpu_name=qpu.name,
+ execution_id=execution_id,
+ tags=menu["tags"],
+ menu=menu,
+ fridge_temperature=fridge_temperature,
+ flow_url=flow_url,
+ )
+ execution_run.insert()
+
+
+def update_execution_run(execution_id: str, status: str) -> None:
+ execution_run = ExecutionRunHistoryModel.find_one(
+ {"execution_id": execution_id}
+ ).run()
+ execution_run.status = status
+ execution_run.save()
diff --git a/backend/qcflow/db/experiment.py b/backend/qcflow/db/experiment.py
new file mode 100644
index 0000000..99e5d17
--- /dev/null
+++ b/backend/qcflow/db/experiment.py
@@ -0,0 +1,16 @@
+from datetime import datetime
+
+from dbmodel.experiment import ExperimentModel
+
+
+def put_experiment(experiment_name: str):
+ experiment = ExperimentModel.find_one(
+ ExperimentModel.experiment_name == experiment_name
+ ).run()
+
+ if experiment is None:
+ experiment = ExperimentModel(experiment_name=experiment_name)
+ experiment.insert()
+ else:
+ experiment.updated_at = datetime.now()
+ experiment.save()
diff --git a/backend/qcflow/db/experiment_history.py b/backend/qcflow/db/experiment_history.py
new file mode 100644
index 0000000..507e110
--- /dev/null
+++ b/backend/qcflow/db/experiment_history.py
@@ -0,0 +1,45 @@
+from datetime import datetime
+from typing import Any
+
+from dbmodel.experiment_history import ExperimentHistoryModel
+
+
+def insert_experiment_history(
+ label: str,
+ exp_name: str,
+ input_params: dict[str, Any],
+ output_params: dict[str, Any],
+ fig_path: str,
+ timestamp: datetime,
+ execution_id: str,
+) -> None:
+ execution = ExperimentHistoryModel(
+ experiment_name=exp_name,
+ timestamp=timestamp,
+ label=label,
+ status="running",
+ input_parameter=input_params,
+ output_parameter={},
+ fig_path=f"{fig_path}/{label}_{exp_name}.png",
+ execution_id=execution_id,
+ )
+ execution.insert()
+
+
+def update_experiment_history(
+ label: str,
+ exp_name: str,
+ status: str,
+ output_params: dict[str, Any],
+ timestamp: datetime,
+) -> None:
+ execution = ExperimentHistoryModel.find_one(
+ {
+ "experiment_name": exp_name,
+ "label": label,
+ "timestamp": timestamp,
+ }
+ ).run()
+ execution.status = status
+ execution.output_parameter = output_params
+ execution.save()
diff --git a/backend/qcflow/db/fridge_status.py b/backend/qcflow/db/fridge_status.py
new file mode 100644
index 0000000..29a44dd
--- /dev/null
+++ b/backend/qcflow/db/fridge_status.py
@@ -0,0 +1,36 @@
+from dbmodel.fridge_status import ChannelInfo, FridgeStatusModel
+
+
+def get_fridge_status(device_id):
+ fridge_status = FridgeStatusModel.find_one(
+ FridgeStatusModel.device_id == device_id
+ ).run()
+ if fridge_status:
+ return fridge_status
+ return None
+
+
+def insert_fridge_status(device_id):
+ fridge_status = FridgeStatusModel(
+ device_id=device_id,
+ ch2=ChannelInfo(status="normal", threshold=5.0),
+ ch6=ChannelInfo(status="normal", threshold=0.02),
+ )
+ fridge_status.insert()
+ return fridge_status
+
+
+def update_fridge_status(device_id, channel, status):
+ fridge_status = FridgeStatusModel.find_one(
+ FridgeStatusModel.device_id == device_id
+ ).run()
+ if channel == 1:
+ fridge_status.ch1 = ChannelInfo(status=status, threshold=0.00)
+ elif channel == 2:
+ fridge_status.ch2 = ChannelInfo(status=status, threshold=5.00)
+ elif channel == 5:
+ fridge_status.ch5 = ChannelInfo(status=status, threshold=0.00)
+ elif channel == 6:
+ fridge_status.ch6 = ChannelInfo(status=status, threshold=0.02)
+ fridge_status.save()
+ return fridge_status
diff --git a/backend/qcflow/db/mongo.py b/backend/qcflow/db/mongo.py
new file mode 100644
index 0000000..2698277
--- /dev/null
+++ b/backend/qcflow/db/mongo.py
@@ -0,0 +1,301 @@
+from datetime import date, datetime
+
+from dbmodel.cooling_down import CoolingDownModel
+from dbmodel.one_qubit_calib import OneQubitCalibModel, Status
+from dbmodel.one_qubit_calib_all_history import OneQubitCalibAllHistoryModel
+from dbmodel.one_qubit_calib_daily_summary import (
+ OneQubitCalibDailySummaryModel,
+ OneQubitCalibSummary,
+)
+from dbmodel.one_qubit_calib_history import OneQubitCalibHistoryModel
+from dbmodel.one_qubit_calib_history_all import OneQubitCalibHistoryAllModel
+from dbmodel.qpu import QPUModel
+from dbmodel.two_qubit_calib import TwoQubitCalibModel
+from dbmodel.two_qubit_calib_daily_summary import (
+ TwoQubitCalibDailySummaryModel,
+ TwoQubitCalibSummary,
+)
+from dbmodel.two_qubit_calib_history import TwoQubitCalibHistoryModel
+from dbmodel.wiring_info import WiringInfoModel
+from prefect import get_run_logger
+from qcflow.schema.menu import Menu
+
+
+def get_wiring_info(name: str):
+ wiring_info = WiringInfoModel.find_one(WiringInfoModel.name == name).run()
+ if wiring_info is None:
+ raise
+ return wiring_info.wiring_dict.dict()
+
+
+def get_one_qubit_calibration(label: str):
+ qpu_name = QPUModel.get_active_qpu_name()
+ one_qubit = OneQubitCalibModel.find_one(
+ OneQubitCalibModel.qpu_name == qpu_name, OneQubitCalibModel.label == label
+ ).run()
+ if one_qubit is None:
+ raise
+ return one_qubit.one_qubit_calib_data
+
+
+def update_one_qubit_calibration(label: str, data):
+ qpu_name = QPUModel.get_active_qpu_name()
+ one_qubit = OneQubitCalibModel.find_one(
+ OneQubitCalibModel.qpu_name == qpu_name, OneQubitCalibModel.label == label
+ ).run()
+ if one_qubit is None:
+ raise
+ one_qubit.one_qubit_calib_data = data
+ one_qubit.updated_at = datetime.now()
+ one_qubit.save()
+
+
+def update_two_qubit_calibration(label: str, data):
+ qpu_name = QPUModel.get_active_qpu_name()
+ two_qubit = TwoQubitCalibModel.find_one(
+ TwoQubitCalibModel.qpu_name == qpu_name, TwoQubitCalibModel.label == label
+ ).run()
+ if two_qubit is None:
+ raise
+ two_qubit.two_qubit_calib_data = data
+ two_qubit.updated_at = datetime.now()
+ two_qubit.save()
+
+
+def update_node_status(qubit_index: int, status: Status):
+ qpu_name = QPUModel.get_active_qpu_name()
+ qubit_index = str(qubit_index) # type: ignore
+ if status == Status.SUCCESS:
+ color = "green"
+ elif status == Status.RUNNING:
+ color = "blue"
+ elif status == Status.FAILED:
+ color = "red"
+ elif status == Status.SCHEDULED:
+ color = "grey"
+ else:
+ color = ""
+ one_qubit = OneQubitCalibModel.find_one(
+ OneQubitCalibModel.qpu_name == qpu_name,
+ OneQubitCalibModel.label == f"Q{qubit_index}",
+ )
+ if one_qubit is None:
+ raise
+ resp = one_qubit.run()
+ resp.status = status.value
+ resp.node_info.fill = color
+ resp.updated_at = datetime.now()
+ resp.save()
+ return resp
+
+
+def update_edge_status(qubit_pair: list[int], status: Status):
+ qpu_name = QPUModel.get_active_qpu_name()
+ label = f"Q{qubit_pair[0]}_Q{qubit_pair[1]}" # type: ignore
+ if status == Status.SUCCESS:
+ color = "green"
+ elif status == Status.RUNNING:
+ color = "blue"
+ elif status == Status.FAILED:
+ color = "red"
+ elif status == Status.SCHEDULED:
+ color = "grey"
+ else:
+ color = ""
+ two_qubit = TwoQubitCalibModel.find_one(
+ TwoQubitCalibModel.qpu_name == qpu_name, TwoQubitCalibModel.label == label
+ )
+ if two_qubit is None:
+ raise
+ resp = two_qubit.run()
+ resp.status = status.value
+ resp.edge_info.fill = color
+ resp.updated_at = datetime.now()
+ resp.save()
+ return resp
+
+
+def upsert_one_qubit_history(menu: Menu, label: str, data):
+ qpu = QPUModel.get_active_qpu()
+ one_qubit = OneQubitCalibHistoryModel.find_one(
+ {"label": label, "date": date.today().strftime("%Y%m%d")}
+ ).run()
+ if one_qubit is None:
+ one_qubit = OneQubitCalibHistoryModel(
+ label=label,
+ ymd=date.today().strftime("%Y%m%d"),
+ qpu_name=qpu.name,
+ one_qubit_calib_data=data,
+ cooling_down_id=CoolingDownModel.get_latest_cooling_down_id(),
+ created_at=datetime.now(),
+ )
+
+ logger = get_run_logger()
+ logger.info(f"one_qubit: {one_qubit}")
+ logger.info(f"data: {data}")
+ one_qubit.one_qubit_calib_data = data
+ one_qubit.updated_at = datetime.now()
+ one_qubit.save()
+
+
+def upsert_two_qubit_history(menu: Menu, label: str, data):
+ qpu = QPUModel.get_active_qpu()
+ two_qubit = TwoQubitCalibHistoryModel.find_one(
+ {"label": label, "date": date.today().strftime("%Y%m%d")}
+ ).run()
+ if two_qubit is None:
+ two_qubit = TwoQubitCalibHistoryModel(
+ label=label,
+ ymd=date.today().strftime("%Y%m%d"),
+ qpu_name=qpu.name,
+ two_qubit_calib_data=data,
+ cooling_down_id=CoolingDownModel.get_latest_cooling_down_id(),
+ created_at=datetime.now(),
+ )
+ from prefect import get_run_logger
+
+ logger = get_run_logger()
+ logger.info(f"two_qubit: {two_qubit}")
+ logger.info(f"data: {data}")
+ two_qubit.two_qubit_calib_data = data
+ two_qubit.updated_at = datetime.now()
+ two_qubit.save()
+
+
+def upsert_one_qubit_daily_summary():
+ ymd = date.today().strftime("%Y%m%d")
+ resp = OneQubitCalibHistoryModel.find(OneQubitCalibHistoryModel.date == ymd)
+ if len(resp.run()) == 0:
+ return
+ summary = []
+ labels = []
+ for r in resp.to_list():
+ summary.append(
+ OneQubitCalibSummary(
+ label=r.label,
+ one_qubit_calib_data=r.one_qubit_calib_data,
+ )
+ )
+ labels.append(r.label)
+ qpu_name = r.qpu_name
+ cooling_down_id = r.cooling_down_id
+ exsting_summary = OneQubitCalibDailySummaryModel.find_one(
+ OneQubitCalibDailySummaryModel.date == ymd
+ ).run()
+ if exsting_summary:
+ exsting_summary.summary = summary
+ exsting_summary.labels = labels
+ exsting_summary.save()
+ else:
+ one_qubit_daily_summary = OneQubitCalibDailySummaryModel(
+ date=ymd,
+ summary=summary,
+ labels=labels,
+ qpu_name=qpu_name,
+ cooling_down_id=cooling_down_id,
+ note="",
+ )
+ one_qubit_daily_summary.save()
+
+
+def upsert_two_qubit_daily_summary():
+ ymd = date.today().strftime("%Y%m%d")
+ resp = TwoQubitCalibHistoryModel.find(TwoQubitCalibHistoryModel.date == ymd)
+ if len(resp.run()) == 0:
+ return
+ summary = []
+ labels = []
+ for r in resp.to_list():
+ summary.append(
+ TwoQubitCalibSummary(
+ label=r.label,
+ two_qubit_calib_data=r.two_qubit_calib_data,
+ )
+ )
+ labels.append(r.label)
+ qpu_name = r.qpu_name
+ cooling_down_id = r.cooling_down_id
+ exsting_summary = TwoQubitCalibDailySummaryModel.find_one(
+ TwoQubitCalibDailySummaryModel.date == ymd
+ ).run()
+ if exsting_summary:
+ exsting_summary.summary = summary
+ exsting_summary.labels = labels
+ exsting_summary.save()
+ else:
+ two_qubit_daily_summary = TwoQubitCalibDailySummaryModel(
+ date=ymd,
+ summary=summary,
+ labels=labels,
+ qpu_name=qpu_name,
+ cooling_down_id=cooling_down_id,
+ note="",
+ )
+ two_qubit_daily_summary.save()
+
+
+def get_cw_info():
+ qpu_name = QPUModel.get_active_qpu_name()
+ one_qubit_calib_list = OneQubitCalibModel.find(
+ OneQubitCalibModel.qpu_name == qpu_name
+ ).run()
+ # one_qubit_calib_list = OneQubitCalibModel.find_all().to_list()
+
+ cw_info_dict = {}
+ for one_qubit_calib in one_qubit_calib_list:
+ cw_info_dict[one_qubit_calib.label] = (
+ one_qubit_calib.one_qubit_calib_data.dict()
+ )
+ return cw_info_dict
+
+
+def get_qpu(name: str = "AIST13th#14(1,0)"):
+ qpu = QPUModel.find_one(QPUModel.name == name).run()
+ return qpu
+
+
+def get_wiring_infos():
+ wiring_info = WiringInfoModel.find_one(
+ WiringInfoModel.name == "RIKEN_CURRENT_WIRING"
+ ).run()
+ # print(wiring_info)
+ return wiring_info
+
+
+def upsert_one_qubit_history_all(menu: Menu, label: str, data):
+ qpu = QPUModel.get_active_qpu()
+ one_qubit = OneQubitCalibHistoryAllModel(
+ label=label,
+ timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
+ qpu_name=qpu.name,
+ one_qubit_calib_data=data,
+ cooling_down_id=CoolingDownModel.get_latest_cooling_down_id(),
+ created_at=datetime.now(),
+ )
+ logger = get_run_logger()
+ logger.info(f"one_qubit: {one_qubit}")
+ logger.info(f"data: {data}")
+ one_qubit.one_qubit_calib_data = data
+ one_qubit.updated_at = datetime.now()
+ one_qubit.insert()
+
+
+def upsert_one_qubit_all_history(menu: Menu, label: str, data, execution_id: str):
+ qpu = QPUModel.get_active_qpu()
+ one_qubit = OneQubitCalibAllHistoryModel(
+ label=label,
+ timestamp=datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
+ execution_id=execution_id,
+ tags=menu.tags,
+ menu=menu.model_dump(),
+ qpu_name=qpu.name,
+ one_qubit_calib_data=data,
+ cooling_down_id=CoolingDownModel.get_latest_cooling_down_id(),
+ created_at=datetime.now(),
+ )
+ logger = get_run_logger()
+ logger.info(f"one_qubit: {one_qubit}")
+ logger.info(f"data: {data}")
+ one_qubit.one_qubit_calib_data = data
+ one_qubit.updated_at = datetime.now()
+ one_qubit.insert()
diff --git a/backend/qcflow/db/session_info.py b/backend/qcflow/db/session_info.py
new file mode 100644
index 0000000..f2d63a1
--- /dev/null
+++ b/backend/qcflow/db/session_info.py
@@ -0,0 +1,21 @@
+# from dbmodel.session_info import SessionInfoModel
+
+# from qcflow.schema.session_info import SessionInfo
+
+
+# def get_session_info(username: str) -> SessionInfo:
+# session_info = SessionInfoModel.find_one(
+# SessionInfoModel.experiment_username == username
+# ).run()
+
+# if session_info is None:
+# raise Exception("SessionInfo is not found.")
+
+# return SessionInfo(
+# labrad_hostname=session_info.labrad_hostname,
+# labrad_username=session_info.labrad_username,
+# labrad_password=session_info.labrad_password,
+# cooling_down_id=session_info.cooling_down_id,
+# experiment_username=session_info.experiment_username,
+# package_name=session_info.package_name,
+# )
diff --git a/backend/qcflow/db/wiring_info.py b/backend/qcflow/db/wiring_info.py
new file mode 100644
index 0000000..6ebe58d
--- /dev/null
+++ b/backend/qcflow/db/wiring_info.py
@@ -0,0 +1,14 @@
+from dbmodel.wiring_info import WiringInfoModel
+from qcflow.schema.wiring_info import WiringInfo
+
+
+def get_wiring_info() -> WiringInfo:
+ wiring_info = WiringInfoModel.get_active_wiring()
+
+ if wiring_info is None:
+ raise Exception("WiringInfo is not found.")
+
+ return WiringInfo(
+ name=wiring_info.name,
+ wiring_dict=wiring_info.wiring_dict.model_dump(),
+ )
diff --git a/backend/qcflow/deployment/oqtopus/__init__.py b/backend/qcflow/deployment/oqtopus/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/deployment/oqtopus/main.py b/backend/qcflow/deployment/oqtopus/main.py
new file mode 100644
index 0000000..cb0896b
--- /dev/null
+++ b/backend/qcflow/deployment/oqtopus/main.py
@@ -0,0 +1,136 @@
+from prefect import serve
+from prefect.client.schemas.schedules import CronSchedule
+from qcflow.main import main_flow
+from qcflow.subflow.one_qubit_daily_summary.flow import one_qubit_daily_summary_flow
+from qcflow.subflow.scheduler.flow import scheduler_flow
+from qcflow.subflow.service_close.service_close import (
+ qpu_close_flow,
+ simulator_close_flow,
+)
+from qcflow.subflow.service_open.service_open import qpu_open_flow, simulator_open_flow
+
+deployment_name = "oqtopus"
+
+if __name__ == "__main__":
+ main_deploy = main_flow.to_deployment(
+ name=f"{deployment_name}-main",
+ description="""This is a flow for E2E calibration.
+ """,
+ tags=["calibration"],
+ parameters={
+ "menu": {
+ "name": "mux9-calibration",
+ "description": "Single qubit calibration for mux1",
+ "one_qubit_calib_plan": [
+ [0, 1, 2, 3],
+ [4, 5, 6, 7],
+ [8, 9, 10, 11],
+ [12, 13, 14, 15],
+ [16, 17, 18, 19],
+ [20, 21, 22, 23],
+ [24, 25, 26, 27],
+ [28, 29, 30, 31],
+ [32, 33, 34, 35],
+ [36, 37, 38, 39],
+ [40, 41, 42, 43],
+ [44, 45, 46, 47],
+ [48, 49, 50, 51],
+ [52, 53, 54, 55],
+ [56, 57, 58, 59],
+ [60, 61, 62, 63],
+ ],
+ "two_qubit_calib_plan": [[0, 5, 10, 15], [1, 6, 11, 16]],
+ "notify_bool": False,
+ "mode": "calib",
+ "flow": [
+ "one-qubit-calibration-flow",
+ ],
+ }
+ },
+ )
+ scheduler_deploy = scheduler_flow.to_deployment(
+ name=f"{deployment_name}-scheduler",
+ description="""This is a scheduler.
+ """,
+ tags=["calibration"],
+ parameters={
+ "menu": {
+ "name": "mux1-single",
+ "description": "Single qubit calibration for mux1",
+ "one_qubit_calib_plan": [[1, 2, 3], [4, 5, 6]],
+ "two_qubit_calib_plan": [[1, 2, 3], [4, 5, 6]],
+ "notify_bool": True,
+ "mode": "calib",
+ "flow": [
+ "one-qubit-calibration",
+ ],
+ }
+ },
+ )
+ qpu_open_deploy = qpu_open_flow.to_deployment(
+ name=f"{deployment_name}-qpu-open",
+ description="""Open QPU access.
+ """,
+ tags=["cloud"],
+ schedule=CronSchedule(
+ cron="0 10 * * 2",
+ timezone="Asia/Tokyo",
+ ),
+ is_schedule_active=True,
+ )
+ qpu_close_deploy = qpu_close_flow.to_deployment(
+ name=f"{deployment_name}-qpu-close",
+ description="""Close QPU access.
+ """,
+ tags=["cloud"],
+ schedule=CronSchedule(
+ cron="0 12 * * 2",
+ timezone="Asia/Tokyo",
+ ),
+ is_schedule_active=True,
+ )
+ simulator_open_deploy = simulator_open_flow.to_deployment(
+ name=f"{deployment_name}-simulator-open",
+ description="""Open Simulator access.
+ """,
+ tags=["cloud"],
+ schedule=CronSchedule(
+ cron="0 12 * * 1-5",
+ timezone="Asia/Tokyo",
+ ),
+ is_schedule_active=True,
+ )
+ simulator_close_deploy = simulator_close_flow.to_deployment(
+ name=f"{deployment_name}-simulator-close",
+ description="""Close Simulator access.
+ """,
+ tags=["cloud"],
+ schedule=CronSchedule(
+ cron="0 17 * * 1-5",
+ timezone="Asia/Tokyo",
+ ),
+ is_schedule_active=True,
+ )
+ one_qubit_daily_summary_deploy = one_qubit_daily_summary_flow.to_deployment(
+ name=f"{deployment_name}-one-qubit-daily-summary",
+ description="""This is a one-qubit-daily-summary.
+ """,
+ tags=["cloud"],
+ schedule=CronSchedule(
+ cron="*/5 * * * *",
+ timezone="Asia/Tokyo",
+ ),
+ is_schedule_active=True,
+ )
+
+ _ = serve(
+ main_deploy, # type: ignore
+ scheduler_deploy, # type: ignore
+ qpu_open_deploy, # type: ignore
+ qpu_close_deploy, # type: ignore
+ simulator_open_deploy, # type: ignore
+ simulator_close_deploy, # type: ignore
+ one_qubit_daily_summary_deploy, # type: ignore
+ webserver=True,
+ limit=50,
+ )
diff --git a/backend/qcflow/main.py b/backend/qcflow/main.py
new file mode 100644
index 0000000..b25f577
--- /dev/null
+++ b/backend/qcflow/main.py
@@ -0,0 +1,106 @@
+import datetime
+from os.path import dirname, join
+
+from db.execution_lock import (
+ get_execution_lock,
+ lock_execution,
+ unlock_execution,
+)
+from dotenv import load_dotenv
+from prefect import flow, get_run_logger, runtime
+from qcflow.db.bluefors import get_latest_temperature
+from qcflow.db.execution_run import get_next_execution_index
+from qcflow.db.execution_run_history import insert_execution_run, update_execution_run
+from qcflow.schema.menu import Menu
+from qcflow.subflow.one_qubit_calibration.flow import one_qubit_calibration_flow
+from qcflow.utils.slack import SlackContents, Status
+from qcflow.utiltask.create_directory import (
+ create_directory_task,
+)
+from qcflow.utiltask.save_wiring_info import (
+ save_wiring_info,
+)
+
+calibration_flow_map = {
+ "one-qubit-calibration-flow": one_qubit_calibration_flow,
+}
+
+load_dotenv(verbose=True)
+dotenv_path = join(dirname(__file__), ".env")
+load_dotenv(dotenv_path)
+
+
+def generate_execution_id():
+ date_str = datetime.date.today().strftime("%Y%m%d")
+ execution_index = get_next_execution_index(date_str)
+ execution_id = f"{date_str}-{execution_index:03d}"
+ return execution_id
+
+
+@flow(name="main", log_prints=True, flow_run_name=generate_execution_id)
+def main_flow(
+ menu: Menu,
+):
+ logger = get_run_logger()
+
+ execution_id = runtime.flow_run.get_flow_name()
+ ui_url = runtime.flow_run.get_flow_run_ui_url()
+ if ui_url:
+ ui_url = ui_url.replace("172.22.0.5", "localhost")
+ logger.info(f"UI URL: {ui_url}")
+ logger.info(f"Execution ID: {execution_id}")
+ if get_execution_lock():
+ logger.error("Calibration is already running.")
+ raise Exception("Calibration is already running.")
+ lock_execution()
+ contents = SlackContents(
+ status=Status.RUNNING,
+ title=f"Start calibration for {menu.flow}",
+ header="All flow will finish at",
+ msg="Start calibration for",
+ notify=menu.notify_bool,
+ ts="",
+ path="",
+ )
+ contents.send_slack()
+ execution_id = runtime.flow_run.name
+ if execution_id:
+ date_str, index = execution_id.split("-")
+ else:
+ logger.error("Execution ID is None.")
+ raise ValueError("Execution ID is None.")
+ insert_execution_run(
+ date_str,
+ execution_id,
+ menu.model_dump(),
+ get_latest_temperature(device_id="XLD", channel_nr=6),
+ flow_url=ui_url,
+ )
+ calib_dir = f"/app/calib_data/{date_str}/{index}"
+ create_directory_task.submit(calib_dir).result()
+ latest_calib_dir = f"/app/calib_data/{date_str}/latest"
+ create_directory_task.submit(latest_calib_dir).result()
+ save_wiring_info.submit(menu).result()
+ successMap = {flow_name: False for flow_name in menu.flow}
+ try:
+ for flow_name in menu.flow:
+ try:
+ successMap = calibration_flow_map[flow_name](
+ menu, calib_dir, successMap, execution_id
+ ) # type: ignore
+ except Exception as e:
+ logger.error(f"Error: {e}")
+ update_execution_run(execution_id, "failed")
+ contents.status = Status.FAILED
+ contents.title = f"Failed calibration for {menu.flow}"
+ contents.msg = str(e)
+ contents.send_slack()
+ raise e
+ logger.info("All flows were successful!")
+ update_execution_run(execution_id, "success")
+ contents.status = Status.SUCCESS
+ contents.title = f"Calibration for {menu.flow} is successful"
+ contents.msg = "Calibration for is successful :tada:"
+ contents.send_slack()
+ finally:
+ unlock_execution()
diff --git a/backend/qcflow/plugin/bluefors/__init__.py b/backend/qcflow/plugin/bluefors/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/plugin/bluefors/blocks.py b/backend/qcflow/plugin/bluefors/blocks.py
new file mode 100644
index 0000000..2c7a3e4
--- /dev/null
+++ b/backend/qcflow/plugin/bluefors/blocks.py
@@ -0,0 +1,8 @@
+from prefect.blocks.core import Block
+
+
+class BlueforsBlock(Block):
+ bluefors_server_url: str = ""
+ mongo_url: str = ""
+ mongo_database: str = ""
+ mongo_collection: str = ""
diff --git a/backend/qcflow/plugin/bluefors/flows.py b/backend/qcflow/plugin/bluefors/flows.py
new file mode 100644
index 0000000..c0c11f8
--- /dev/null
+++ b/backend/qcflow/plugin/bluefors/flows.py
@@ -0,0 +1,127 @@
+from datetime import datetime, timedelta, timezone
+
+from prefect import flow, get_run_logger
+
+from .tasks import (
+ get_latest_temperature,
+ # output_metrics,
+ input_metrics,
+)
+
+
+@flow
+def bluefors_collector():
+ logger = get_run_logger()
+ # メトリクスを取得するためのパラメータ
+ channel_list = [1, 2, 5, 6]
+ device_id = "XLD"
+ stop_time = datetime.now(timezone.utc)
+ start_time = stop_time - timedelta(seconds=70)
+
+ start_time_str = start_time.strftime("%Y-%m-%dT%H:%M:%SZ")
+ stop_time_str = stop_time.strftime("%Y-%m-%dT%H:%M:%SZ")
+ logger.info(f"start_time={start_time_str}, stop_time={stop_time_str}")
+ for channel_nr in channel_list:
+ try:
+ logger.info(f"Processing channel={channel_nr}")
+ import os
+
+ print(os.environ.get("BLUEFORS_HOST"))
+ api_url = (
+ f"http://{os.environ.get('BLUEFORS_HOST')}:5001/channel/historical-data"
+ )
+ metrics = input_metrics(
+ api_url,
+ channel_nr,
+ start_time_str,
+ stop_time_str,
+ )
+ from .tasks import output_metrics
+
+ output_metrics(metrics, device_id)
+ logger.info(f"Processing channel={channel_nr} completed")
+ except Exception as e:
+ print(f"Error occurred for channel={channel_nr}: {e}")
+
+
+@flow(flow_run_name="Fridge Alert")
+def fridge_alert():
+ for channel in [2, 6]:
+ check_and_update_fridge_status(channel, "XLD")
+
+
+def check_and_update_fridge_status(channel: int, id: str):
+ """
+ This alert notifies the user when the temperature of the fridge is higher than the threshold, (e.g., 5.0K for channel 2 and 0.02K for channel 6).
+ Also, it notifies the user when the temperature is back to normal.
+ """
+ import os
+
+ from qcflow.db.fridge_status import (
+ get_fridge_status,
+ insert_fridge_status,
+ update_fridge_status,
+ )
+ from qcflow.utils.slack import SlackContents, Status
+
+ fridge_status = get_fridge_status(id)
+ if fridge_status is None:
+ fridge_status = insert_fridge_status(id)
+
+ channel_info = None
+ channel_name = ""
+ if channel == 2:
+ channel_info = fridge_status.ch2
+ channel_name = "4K-FLANGE"
+ elif channel == 6:
+ channel_info = fridge_status.ch6
+ channel_name = "MXC-FLANGE"
+
+ if channel_info is None:
+ return
+
+ prev_status = channel_info.status
+ logger = get_run_logger()
+ logger.info(f"Processing channel={channel} status={prev_status}")
+ threshold = channel_info.threshold
+ temp = get_latest_temperature(id, channel)
+ current_status = "normal"
+ if temp > threshold:
+ current_status = "abnormal"
+ logger.info(f"Temperature is high! channel={channel} temperature={temp}[K]")
+ if prev_status == "normal" and current_status == "abnormal":
+ logger.info(f"Temperature is high! channel={channel} temperature={temp}[K]")
+ update_fridge_status(id, channel, "abnormal")
+ contents = SlackContents(
+ status=Status.FAILED,
+ title=":rotating_light:ABNORMAL",
+ header=" Temperature is high!!",
+ msg=f"channel={channel}: {channel_name} temperature={temp}[K] > threshold={threshold}[K]",
+ notify=True,
+ ts="",
+ path="",
+ channel="#qiqb超伝導班",
+ token=os.environ.get("FRIDGE_ALERT_SLACK_BOT_TOKEN"),
+ )
+ contents.send_slack()
+ elif prev_status == "abnormal" and current_status == "normal":
+ logger.info(
+ f"Temperature is back to normal. channel={channel} temperature={temp}[K]"
+ )
+ update_fridge_status(id, channel, "normal")
+ contents = SlackContents(
+ status=Status.SUCCESS,
+ title=":white_check_mark:NORMAL",
+ header=" Temperature is back to normal.",
+ msg=f"channel={channel}: {channel_name} temperature={temp}[K] < threshold={threshold}[K]",
+ notify=True,
+ ts="",
+ path="",
+ channel="#qiqb超伝導班",
+ token=os.environ.get("FRIDGE_ALERT_SLACK_BOT_TOKEN"),
+ )
+ contents.send_slack()
+
+
+if __name__ == "__main__":
+ bluefors_collector()
diff --git a/backend/qcflow/plugin/bluefors/tasks.py b/backend/qcflow/plugin/bluefors/tasks.py
new file mode 100644
index 0000000..3780554
--- /dev/null
+++ b/backend/qcflow/plugin/bluefors/tasks.py
@@ -0,0 +1,65 @@
+import requests
+from prefect import task
+
+
+@task
+def input_metrics(bluefors_server_url, channel_nr, start_time_str, stop_time_str):
+ payload = {
+ "channel_nr": channel_nr,
+ "start_time": start_time_str,
+ "stop_time": stop_time_str,
+ "fields": [
+ "timestamp",
+ "resistance",
+ "reactance",
+ "temperature",
+ "rez",
+ "imz",
+ "magnitude",
+ "angle",
+ "status_flags",
+ ],
+ }
+ headers = {"Content-Type": "application/json"}
+ response = requests.post(bluefors_server_url, headers=headers, json=payload)
+ metrics = response.json()
+ return metrics
+
+
+@task
+def get_latest_temperature(device_id, channel_nr):
+ from qcflow.db.bluefors import get_latest_temperature
+
+ return get_latest_temperature(device_id, channel_nr)
+
+
+@task
+def output_metrics(metrics, device_id):
+ from qcflow.db.bluefors import upsert_metrics
+
+ upsert_metrics(metrics, device_id)
+
+
+@task
+def check_and_alert(transformed_data, slack_webhook_url):
+ for record in transformed_data:
+ # TODO 各channelの閾値
+ if (
+ (record["channel_nr"] == 1 and record["temperature"] > 41)
+ or (record["channel_nr"] == 2 and record["temperature"] > 5)
+ or (record["channel_nr"] == 5 and record["temperature"] > 2)
+ or (record["channel_nr"] == 6 and record["temperature"] > 1)
+ ):
+ channel_nr = record["channel_nr"]
+ temperature = record["temperature"]
+
+ # TODO Slackにアラートを送信
+ message = f"Warning: Temperature is high! channel={channel_nr} temperature={temperature}[K]"
+ payload = {"text": message}
+ response = requests.post(slack_webhook_url, json=payload)
+ if response.status_code == 200:
+ print("Slack alert sent.")
+ else:
+ print(
+ f"Failed to send Slack alert. Status code: {response.status_code}"
+ )
diff --git a/backend/qcflow/profiles.toml b/backend/qcflow/profiles.toml
new file mode 100644
index 0000000..2711af9
--- /dev/null
+++ b/backend/qcflow/profiles.toml
@@ -0,0 +1,5 @@
+active = "default"
+
+[profiles.default]
+PREFECT_API_KEY = ""
+PREFECT_API_URL = "http://127.0.0.1:4200/api"
diff --git a/backend/qcflow/requirements.txt b/backend/qcflow/requirements.txt
new file mode 100644
index 0000000..5587ff6
--- /dev/null
+++ b/backend/qcflow/requirements.txt
@@ -0,0 +1,132 @@
+annotated-types==0.7.0 ; python_version >= "3.10" and python_version < "3.13"
+anyio==4.6.2.post1 ; python_version >= "3.10" and python_version < "3.13"
+asteval==1.0.5 ; python_version >= "3.10" and python_version < "3.13"
+asttokens==2.4.1 ; python_version >= "3.10" and python_version < "3.13"
+attrs==24.2.0 ; python_version >= "3.10" and python_version < "3.13"
+automat==24.8.1 ; python_version >= "3.10" and python_version < "3.13"
+bunnet==1.3.0 ; python_version >= "3.10" and python_version < "3.13"
+cachetools==5.5.0 ; python_version >= "3.10" and python_version < "3.13"
+certifi==2024.8.30 ; python_version >= "3.10" and python_version < "3.13"
+cffi==1.17.1 ; python_version >= "3.10" and python_version < "3.13" and (platform_python_implementation != "PyPy" or implementation_name == "pypy")
+charset-normalizer==3.4.0 ; python_version >= "3.10" and python_version < "3.13"
+cirq-aqt==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-core==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-google==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-ionq==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-pasqal==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-rigetti==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq-web==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+cirq==1.4.1 ; python_version >= "3.10" and python_version < "3.13"
+click==8.1.7 ; python_version >= "3.10" and python_version < "3.13"
+colorama==0.4.6 ; python_version >= "3.10" and python_version < "3.13" and (sys_platform == "win32" or platform_system == "Windows")
+constantly==23.10.4 ; python_version >= "3.10" and python_version < "3.13"
+contourpy==1.3.0 ; python_version >= "3.10" and python_version < "3.13"
+coverage[toml]==7.6.4 ; python_version >= "3.10" and python_version < "3.13"
+cryptography==43.0.3 ; python_version >= "3.10" and python_version < "3.13"
+cycler==0.12.1 ; python_version >= "3.10" and python_version < "3.13"
+decorator==5.1.1 ; python_version >= "3.10" and python_version < "3.13"
+deprecated==1.2.14 ; python_version >= "3.10" and python_version < "3.13"
+dill==0.3.9 ; python_version >= "3.10" and python_version < "3.13"
+dnspython==2.7.0 ; python_version >= "3.10" and python_version < "3.13"
+duet==0.2.9 ; python_version >= "3.10" and python_version < "3.13"
+exceptiongroup==1.2.2 ; python_version >= "3.10" and python_version < "3.11"
+executing==2.1.0 ; python_version >= "3.10" and python_version < "3.13"
+filelock==3.16.1 ; python_version >= "3.10" and python_version < "3.13"
+fonttools==4.54.1 ; python_version >= "3.10" and python_version < "3.13"
+google-api-core[grpc]==2.22.0 ; python_version >= "3.10" and python_version < "3.13"
+google-auth==2.35.0 ; python_version >= "3.10" and python_version < "3.13"
+googleapis-common-protos==1.65.0 ; python_version >= "3.10" and python_version < "3.13"
+grpc-interceptor==0.15.4 ; python_version >= "3.10" and python_version < "3.13"
+grpcio-status==1.62.3 ; python_version >= "3.10" and python_version < "3.13"
+grpcio==1.67.1 ; python_version >= "3.10" and python_version < "3.13"
+h11==0.14.0 ; python_version >= "3.10" and python_version < "3.13"
+h5py==3.12.1 ; python_version >= "3.10" and python_version < "3.13"
+httpcore==1.0.6 ; python_version >= "3.10" and python_version < "3.13"
+httpx==0.27.2 ; python_version >= "3.10" and python_version < "3.13"
+hyperlink==21.0.0 ; python_version >= "3.10" and python_version < "3.13"
+idna==3.10 ; python_version >= "3.10" and python_version < "3.13"
+incremental==24.7.2 ; python_version >= "3.10" and python_version < "3.13"
+iniconfig==2.0.0 ; python_version >= "3.10" and python_version < "3.13"
+ipython==8.29.0 ; python_version >= "3.10" and python_version < "3.13"
+jedi==0.19.1 ; python_version >= "3.10" and python_version < "3.13"
+joblib==1.4.2 ; python_version >= "3.10" and python_version < "3.13"
+kiwisolver==1.4.7 ; python_version >= "3.10" and python_version < "3.13"
+lazy-model==0.2.0 ; python_version >= "3.10" and python_version < "3.13"
+lmfit==1.3.2 ; python_version >= "3.10" and python_version < "3.13"
+matplotlib-inline==0.1.7 ; python_version >= "3.10" and python_version < "3.13"
+matplotlib==3.9.2 ; python_version >= "3.10" and python_version < "3.13"
+mpmath==1.3.0 ; python_version >= "3.10" and python_version < "3.13"
+msgpack==1.1.0 ; python_version >= "3.10" and python_version < "3.13"
+mypy-extensions==1.0.0 ; python_version >= "3.10" and python_version < "3.13"
+mypy==1.13.0 ; python_version >= "3.10" and python_version < "3.13"
+networkx==2.8.8 ; python_version >= "3.10" and python_version < "3.13"
+numpy==1.26.4 ; python_version >= "3.10" and python_version < "3.13"
+packaging==23.2 ; python_version >= "3.10" and python_version < "3.13"
+pandas==2.2.3 ; python_version >= "3.10" and python_version < "3.13"
+parso==0.8.4 ; python_version >= "3.10" and python_version < "3.13"
+pexpect==4.9.0 ; python_version >= "3.10" and python_version < "3.13" and (sys_platform != "win32" and sys_platform != "emscripten")
+pillow==11.0.0 ; python_version >= "3.10" and python_version < "3.13"
+pluggy==1.5.0 ; python_version >= "3.10" and python_version < "3.13"
+prompt-toolkit==3.0.48 ; python_version >= "3.10" and python_version < "3.13"
+proto-plus==1.25.0 ; python_version >= "3.10" and python_version < "3.13"
+protobuf==4.25.5 ; python_version >= "3.10" and python_version < "3.13"
+ptyprocess==0.7.0 ; python_version >= "3.10" and python_version < "3.13" and (sys_platform != "win32" and sys_platform != "emscripten")
+pure-eval==0.2.3 ; python_version >= "3.10" and python_version < "3.13"
+pyasn1-modules==0.4.1 ; python_version >= "3.10" and python_version < "3.13"
+pyasn1==0.6.1 ; python_version >= "3.10" and python_version < "3.13"
+pycparser==2.22 ; python_version >= "3.10" and python_version < "3.13" and (platform_python_implementation != "PyPy" or implementation_name == "pypy")
+pydantic-core==2.23.4 ; python_version >= "3.10" and python_version < "3.13"
+pydantic==2.9.2 ; python_version >= "3.10" and python_version < "3.13"
+pygments==2.18.0 ; python_version >= "3.10" and python_version < "3.13"
+pylabrad==0.98.3 ; python_version >= "3.10" and python_version < "3.13"
+pymongo==4.10.1 ; python_version >= "3.10" and python_version < "3.13"
+pyopenssl==24.2.1 ; python_version >= "3.10" and python_version < "3.13"
+pyparsing==3.2.0 ; python_version >= "3.10" and python_version < "3.13"
+pyquil==4.14.3 ; python_version >= "3.10" and python_version < "3.13"
+pytest-cov==5.0.0 ; python_version >= "3.10" and python_version < "3.13"
+pytest-env==1.1.5 ; python_version >= "3.10" and python_version < "3.13"
+pytest-mypy==0.10.3 ; python_version >= "3.10" and python_version < "3.13"
+pytest==8.3.3 ; python_version >= "3.10" and python_version < "3.13"
+python-dateutil==2.9.0.post0 ; python_version >= "3.10" and python_version < "3.13"
+python-dotenv==1.0.1 ; python_version >= "3.10" and python_version < "3.13"
+python-rapidjson==1.20 ; python_version >= "3.10" and python_version < "3.13"
+pytz==2024.2 ; python_version >= "3.10" and python_version < "3.13"
+pyyaml==6.0.2 ; python_version >= "3.10" and python_version < "3.13"
+pyzmq==26.2.0 ; python_version >= "3.10" and python_version < "3.13"
+qcs-api-client-common==0.10.0 ; python_version >= "3.10" and python_version < "3.13"
+qcs-sdk-python==0.20.1 ; python_version >= "3.10" and python_version < "3.13"
+quil==0.13.1 ; python_version >= "3.10" and python_version < "3.13"
+qupy==1.1.1 ; python_version >= "3.10" and python_version < "3.13"
+qutip==5.0.4 ; python_version >= "3.10" and python_version < "3.13"
+requests==2.32.3 ; python_version >= "3.10" and python_version < "3.13"
+rpcq==3.11.0 ; python_version >= "3.10" and python_version < "3.13"
+rsa==4.9 ; python_version >= "3.10" and python_version < "3.13"
+ruamel-yaml-clib==0.2.12 ; platform_python_implementation == "CPython" and python_version < "3.13" and python_version >= "3.10"
+ruamel-yaml==0.18.6 ; python_version >= "3.10" and python_version < "3.13"
+ruff==0.5.7 ; python_version >= "3.10" and python_version < "3.13"
+scikit-learn==1.5.0 ; python_version >= "3.10" and python_version < "3.13"
+scipy==1.14.1 ; python_version >= "3.10" and python_version < "3.13"
+sentry-sdk==2.17.0 ; python_version >= "3.10" and python_version < "3.13"
+service-identity==24.2.0 ; python_version >= "3.10" and python_version < "3.13"
+setuptools==75.3.0 ; python_version >= "3.10" and python_version < "3.13"
+six==1.16.0 ; python_version >= "3.10" and python_version < "3.13"
+slack-sdk==3.33.3 ; python_version >= "3.10" and python_version < "3.13"
+sniffio==1.3.1 ; python_version >= "3.10" and python_version < "3.13"
+sortedcontainers==2.4.0 ; python_version >= "3.10" and python_version < "3.13"
+sqe-fitting @ git+https://github.com/orangekame3/sqe_fitting@3106ac41b120cd1ff27077a02a6befac5d41636f ; python_version >= "3.10" and python_version < "3.13"
+stack-data==0.6.3 ; python_version >= "3.10" and python_version < "3.13"
+sympy==1.13.3 ; python_version >= "3.10" and python_version < "3.13"
+threadpoolctl==3.5.0 ; python_version >= "3.10" and python_version < "3.13"
+toml==0.10.2 ; python_version >= "3.10" and python_version < "3.13"
+tomli==2.0.2 ; python_version >= "3.10" and python_full_version <= "3.11.0a6"
+tqdm==4.66.6 ; python_version >= "3.10" and python_version < "3.13"
+traitlets==5.14.3 ; python_version >= "3.10" and python_version < "3.13"
+twisted==24.10.0 ; python_version >= "3.10" and python_version < "3.13"
+types-deprecated==1.2.9.20240311 ; python_version >= "3.10" and python_version < "3.13"
+typing-extensions==4.12.2 ; python_version >= "3.10" and python_version < "3.13"
+tzdata==2024.2 ; python_version >= "3.10" and python_version < "3.13"
+uncertainties==3.2.2 ; python_version >= "3.10" and python_version < "3.13"
+urllib3==2.2.3 ; python_version >= "3.10" and python_version < "3.13"
+wcwidth==0.2.13 ; python_version >= "3.10" and python_version < "3.13"
+wrapt==1.16.0 ; python_version >= "3.10" and python_version < "3.13"
+zope-interface==7.1.1 ; python_version >= "3.10" and python_version < "3.13"
diff --git a/backend/qcflow/schema/menu.py b/backend/qcflow/schema/menu.py
new file mode 100644
index 0000000..687791b
--- /dev/null
+++ b/backend/qcflow/schema/menu.py
@@ -0,0 +1,57 @@
+from enum import Enum
+from typing import Optional
+
+from pydantic import BaseModel, Field
+
+
+class Mode(Enum):
+ DEFAULT: str = "default"
+ PRESET1: str = "preset1"
+ PRESET2: str = "preset2"
+ CUSTOM: str = "custom"
+
+
+class Menu(BaseModel):
+ """
+ Represents a base menu.
+
+ Attributes:
+ name (str): The name of the menu.
+ description (str): The description of the menu.
+ plan (list[list[int]]): The plan for the menu.
+ mux_index_list (list[int]): The mux index list for the menu.
+ mode (str): The mode of the menu.
+ notify_bool (bool, optional): Whether to notify or not. Defaults to True.
+ flow (list[str]): The flow of the menu.
+ exp_list (list[str], optional): The list of experiments. Defaults to None.
+ """
+
+ name: str
+ description: str
+ one_qubit_calib_plan: list[list[int]]
+ two_qubit_calib_plan: list[list[tuple[int, int]]]
+ mode: str
+ notify_bool: bool = True
+ flow: list[str]
+ exp_list: Optional[list[str]] = Field(default=[])
+ tags: Optional[list[str]] = Field(default=None)
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "name": "sample-menu",
+ "description": "menu description",
+ "one_qubit_calib_plan": [[0, 1, 2], [4, 5, 6], [7, 8, 9]],
+ "two_qubit_calib_plan": [
+ [[0, 1], [0, 2], [3, 4]],
+ [[5, 6], [7, 8]],
+ ],
+ "mode": "calib",
+ "notify_bool": False,
+ "flow": ["one-qubit-calibration-flow"],
+ "tags": ["tag1", "tag2"],
+ },
+ ]
+ }
+ }
diff --git a/backend/qcflow/schema/session_info.py b/backend/qcflow/schema/session_info.py
new file mode 100644
index 0000000..10a6476
--- /dev/null
+++ b/backend/qcflow/schema/session_info.py
@@ -0,0 +1,10 @@
+from pydantic import BaseModel
+
+
+class SessionInfo(BaseModel):
+ labrad_hostname: str
+ labrad_username: str
+ labrad_password: str
+ cooling_down_id: str
+ experiment_username: str
+ package_name: str
diff --git a/backend/qcflow/schema/wiring_info.py b/backend/qcflow/schema/wiring_info.py
new file mode 100644
index 0000000..6fa3b09
--- /dev/null
+++ b/backend/qcflow/schema/wiring_info.py
@@ -0,0 +1,15 @@
+from typing import Optional
+
+from pydantic import BaseModel, Field
+
+
+class Wiring(BaseModel):
+ control: dict[str, dict[str, str]]
+ readout: dict[str, dict[str, str]]
+ bias: Optional[dict[str, dict[str, str]]] = Field(default=None, exclude=True)
+ pump: Optional[dict[str, dict[str, str]]] = Field(default=None, exclude=True)
+
+
+class WiringInfo(BaseModel):
+ name: str
+ wiring_dict: Wiring
diff --git a/backend/qcflow/session/__init__.py b/backend/qcflow/session/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/session/labrad.py b/backend/qcflow/session/labrad.py
new file mode 100644
index 0000000..700167d
--- /dev/null
+++ b/backend/qcflow/session/labrad.py
@@ -0,0 +1,74 @@
+import contextlib
+
+from dbmodel.session_info import SessionInfoModel
+from prefect import get_run_logger
+
+
+class QubeServer:
+ def select_device(self, device_name):
+ pass
+
+ def frequency_sideband(self):
+ pass
+
+ def list_devices(self):
+ # 実際の実装をここに追加
+ return ["device1"]
+
+
+class Connection:
+ def __init__(self):
+ self.qube_server = QubeServer()
+
+ def disconnect(self):
+ pass
+
+
+class Session(object):
+ labrad_hostname: str
+ labrad_username: str
+ labrad_password: str
+ cooling_down_id: str
+ experiment_username: str
+ package_name: str
+ connection: Connection
+
+ def __init__(
+ self,
+ labrad_hostname,
+ labrad_username,
+ labrad_password,
+ cooling_down_id,
+ experiment_username,
+ package_name,
+ ):
+ self.labrad_hostname = labrad_hostname
+ self.labrad_username = labrad_username
+ self.labrad_password = labrad_password
+ self.cooling_down_id = cooling_down_id
+ self.experiment_username = experiment_username
+ self.package_name = package_name
+ self.connection = Connection()
+
+ def save_wiring_info(self, wiring_name, wiring_dict):
+ pass
+
+
+@contextlib.contextmanager
+def labrad_session():
+ logger = get_run_logger()
+ logger.info("session connected!")
+ session_info = SessionInfoModel.get_active_session_info()
+ session = Session(
+ labrad_hostname=session_info.labrad_hostname,
+ labrad_username=session_info.labrad_username,
+ labrad_password=session_info.labrad_password,
+ cooling_down_id=session_info.cooling_down_id,
+ experiment_username=session_info.experiment_username,
+ package_name=session_info.package_name,
+ )
+ try:
+ yield session
+ finally:
+ session.connection.disconnect()
+ logger.info("session disconnected!")
diff --git a/backend/qcflow/subflow/__init__.py b/backend/qcflow/subflow/__init__.py
new file mode 100644
index 0000000..4f219bb
--- /dev/null
+++ b/backend/qcflow/subflow/__init__.py
@@ -0,0 +1,12 @@
+import sentry_sdk
+
+sentry_sdk.init(
+ dsn="",
+ # Set traces_sample_rate to 1.0 to capture 100%
+ # of transactions for performance monitoring.
+ traces_sample_rate=1.0,
+ # Set profiles_sample_rate to 1.0 to profile 100%
+ # of sampled transactions.
+ # We recommend adjusting this value in production.
+ profiles_sample_rate=1.0,
+)
diff --git a/backend/qcflow/subflow/one_qubit_calibration/__init__.py b/backend/qcflow/subflow/one_qubit_calibration/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/subflow/one_qubit_calibration/experiment.py b/backend/qcflow/subflow/one_qubit_calibration/experiment.py
new file mode 100644
index 0000000..de459de
--- /dev/null
+++ b/backend/qcflow/subflow/one_qubit_calibration/experiment.py
@@ -0,0 +1,131 @@
+import abc
+import time
+from io import BytesIO
+
+import matplotlib.pyplot as plt
+from PIL import Image
+from requests import get
+
+from .util import TDM
+
+
+def generate_dummy_figure(save_path: str, text):
+ url = f"https://placehold.jp/3d4070/ffffff/100x50.png?text={text}"
+ response = get(url)
+ img = Image.open(BytesIO(response.content))
+ fig, ax = plt.subplots()
+ ax.imshow(img)
+ ax.axis("off")
+ plt.savefig(save_path, bbox_inches="tight")
+ return fig
+
+
+class IExperiment(metaclass=abc.ABCMeta):
+ experiment_name: str
+ input_parameters: list[str]
+ output_parameters: list[str]
+
+ def __init__(self, **kwargs: object):
+ pass
+
+ @abc.abstractmethod
+ def take_data(self, tdm: TDM, notes: dict, save: bool) -> object:
+ return object
+
+ @abc.abstractmethod
+ def analyze(self, dataset: object, notes: dict, savefig: bool, savepath: str):
+ if savefig:
+ for qubit_name in notes.keys():
+ generate_dummy_figure(
+ f"{savepath}/{qubit_name}_{self.__class__.experiment_name}.png",
+ self.__class__.experiment_name,
+ )
+ pass
+
+
+class Example1(IExperiment):
+ experiment_name = "Example1"
+ input_parameters = ["param1", "param2"]
+ output_parameters = ["output1", "output2"]
+
+ def take_data(self, tdm: TDM, notes: dict, save: bool) -> object:
+ time.sleep(2)
+ return object
+
+ def analyze(self, dataset: object, notes: dict, savefig: bool, savepath: str):
+ time.sleep(2)
+ if savefig:
+ for qubit_name in notes.keys():
+ generate_dummy_figure(
+ f"{savepath}/{qubit_name}_{self.__class__.experiment_name}.png",
+ self.__class__.experiment_name,
+ )
+ pass
+
+
+class Example2(IExperiment):
+ experiment_name = "Example2"
+ input_parameters = ["param1", "param2"]
+ output_parameters = ["output1", "output2"]
+
+ def take_data(self, tdm: TDM, notes: dict, save: bool) -> object:
+ time.sleep(2)
+ return object
+
+ def analyze(self, dataset: object, notes: dict, savefig: bool, savepath: str):
+ time.sleep(2)
+ if savefig:
+ for qubit_name in notes.keys():
+ generate_dummy_figure(
+ f"{savepath}/{qubit_name}_{self.__class__.experiment_name}.png",
+ self.__class__.experiment_name,
+ )
+ pass
+
+
+class Example3(IExperiment):
+ experiment_name = "Example3"
+ input_parameters = ["param1", "param2"]
+ output_parameters = ["output1", "output2"]
+
+ def take_data(self, tdm: TDM, notes: dict, save: bool) -> object:
+ time.sleep(2)
+ return object
+
+ def analyze(self, dataset: object, notes: dict, savefig: bool, savepath: str):
+ time.sleep(2)
+ if savefig:
+ for qubit_name in notes.keys():
+ generate_dummy_figure(
+ f"{savepath}/{qubit_name}_{self.__class__.experiment_name}.png",
+ self.__class__.experiment_name,
+ )
+ pass
+
+
+class Example4(IExperiment):
+ experiment_name = "Example4"
+ input_parameters = ["param1", "param2"]
+ output_parameters = ["output1", "output2"]
+
+ def take_data(self, tdm: TDM, notes: dict, save: bool) -> object:
+ time.sleep(2)
+ return object
+
+ def analyze(self, dataset: object, notes: dict, savefig: bool, savepath: str):
+ time.sleep(2)
+ if savefig:
+ for qubit_name in notes.keys():
+ generate_dummy_figure(
+ f"{savepath}/{qubit_name}_{self.__class__.experiment_name}.png",
+ self.__class__.experiment_name,
+ )
+ pass
+
+
+experiment_map = {
+ "Example1": Example1(),
+ "Example2": Example2(),
+ "Example3": Example3(),
+ "Example4": Example4(),
+}
diff --git a/backend/qcflow/subflow/one_qubit_calibration/flow.py b/backend/qcflow/subflow/one_qubit_calibration/flow.py
new file mode 100644
index 0000000..53374dd
--- /dev/null
+++ b/backend/qcflow/subflow/one_qubit_calibration/flow.py
@@ -0,0 +1,235 @@
+# import json
+import time
+from datetime import datetime
+from typing import Union
+
+from db.experiment_history import (
+ insert_experiment_history,
+ update_experiment_history,
+)
+from dbmodel.one_qubit_calib import Status as NodeStatus
+from prefect import flow, get_run_logger, task
+from prefect.runner import submit_to_runner, wait_for_submitted_runs
+from prefect.runtime import flow_run
+from prefect.task_runners import SequentialTaskRunner
+from qcflow.db.experiment import put_experiment
+from qcflow.db.mongo import update_node_status
+from qcflow.schema.menu import Menu, Mode
+from qcflow.session.labrad import labrad_session
+from qcflow.subflow.one_qubit_calibration.task import (
+ check_sideband_all,
+ create_instrument_manager,
+ execute_experiment,
+)
+
+from .experiment import (
+ experiment_map,
+)
+from .util import (
+ handle_calibration_result,
+ initialize_notes,
+ input_params_to_dict,
+ send_slack_notification,
+ update_slack_failure_notification,
+ update_slack_success_notification,
+)
+
+
+def select_mode(menu: Menu) -> list[str] | None:
+ exp_list: list[str] | None = menu.exp_list
+
+ if menu.mode not in {
+ Mode.DEFAULT.value,
+ Mode.PRESET1.value,
+ Mode.PRESET2.value,
+ Mode.CUSTOM.value,
+ }:
+ raise ValueError(f"mode: {menu.mode} is not supported")
+
+ if exp_list is None or all(isinstance(item, str) for item in exp_list):
+ return exp_list
+ else:
+ raise ValueError("exp_list must be a list of strings or None")
+
+
+@task
+def start_one_qubit_calibration():
+ return "success"
+
+
+@flow(
+ name="one-qubit-calibration-flow",
+ task_runner=SequentialTaskRunner(),
+ log_prints=True,
+ flow_run_name="{execution_id}",
+)
+def one_qubit_calibration_flow(
+ menu: Menu,
+ calib_dir: str,
+ successMap: dict[str, bool],
+ execution_id: str,
+) -> dict[str, bool]:
+ logger = get_run_logger()
+ logger.info(menu.name)
+
+ for qubit_index_list in menu.one_qubit_calib_plan:
+ for qubit_index in qubit_index_list:
+ update_node_status(qubit_index, NodeStatus.SCHEDULED)
+
+ success = start_one_qubit_calibration()
+ submit_to_runner(
+ series_calibration,
+ [
+ {
+ "menu": menu,
+ "qubit_index_list": series_block,
+ "notes": None,
+ "calib_dir": calib_dir,
+ "depend": success,
+ "execution_id": execution_id,
+ }
+ for series_block in menu.one_qubit_calib_plan
+ ],
+ )
+ wait_for_submitted_runs() # type: ignore
+ successMap["one-qubit-calibration-flow"] = True
+ return successMap
+
+
+def generate_flow_run_name():
+ parameters = flow_run.parameters
+ qubit_index_list = parameters["qubit_index_list"]
+ id = qubit_index_list[0] // 4
+ return f"MUX{id}-Q{qubit_index_list}"
+
+
+@flow(
+ flow_run_name=generate_flow_run_name,
+ task_runner=SequentialTaskRunner(),
+ log_prints=True,
+)
+async def series_calibration(
+ menu: Menu,
+ qubit_index_list: list[int],
+ notes: Union[dict, None] = None,
+ calib_dir: str = "",
+ depend: str = "",
+ execution_id: str = "",
+):
+ logger = get_run_logger()
+ depend = "success"
+ max_retry = 1
+ for qubit_index in qubit_index_list:
+ for retry in range(max_retry):
+ try:
+ depend = single_calibration(
+ menu=menu,
+ qubit_index=qubit_index,
+ notes=notes,
+ calib_dir=calib_dir,
+ depend=depend,
+ execution_id=execution_id,
+ ) # type: ignore
+ except Exception:
+ logger.info(f"Retry {retry} for Q{qubit_index}")
+ time.sleep(10)
+ else:
+ depend = depend
+ break
+
+
+@flow(
+ flow_run_name="Q{qubit_index}",
+ task_runner=SequentialTaskRunner(),
+ log_prints=True,
+)
+def single_calibration(
+ menu: Menu,
+ qubit_index: int,
+ notes: Union[dict, None] = None,
+ calib_dir: str = "",
+ depend: str = "",
+ execution_id: str = "",
+) -> str:
+ fig_path = f"{calib_dir}/fig_tdm"
+ with labrad_session() as session:
+ logger = get_run_logger()
+ save = True
+ savefig = True
+ tdm = create_instrument_manager(menu, session, [qubit_index])
+ if notes is None:
+ notes = initialize_notes(qubit_index)
+ logger.info(f"notes: {notes}")
+ result = {
+ "success": True,
+ "fail_at": "",
+ }
+ contents, ts = send_slack_notification(menu)
+ exp_list = select_mode(menu)
+ logger.info(f"exp_list: {menu.model_dump()}")
+ prev_status = check_sideband_all(session=session)
+ for exp_name in exp_list:
+ try:
+ logger.info(f"exp : {exp_name}")
+ update_node_status(qubit_index, NodeStatus.RUNNING)
+ exp = experiment_map[exp_name]
+ input_params = exp.__dict__
+ input_params = input_params_to_dict(input_params)
+ timestamp = datetime.now()
+ label = f"Q{qubit_index}"
+ insert_experiment_history(
+ label=label,
+ exp_name=exp_name,
+ input_params=input_params,
+ output_params={},
+ fig_path=fig_path,
+ timestamp=timestamp,
+ execution_id=execution_id,
+ )
+ put_experiment(exp_name)
+ status = execute_experiment(
+ exp_name=exp_name,
+ tdm=tdm,
+ exp=experiment_map[exp_name],
+ notes=notes,
+ save=save,
+ savefig=savefig,
+ savepath=fig_path,
+ status=prev_status,
+ ) # type: ignore
+ if status != "success":
+ update_experiment_history(
+ label=label,
+ exp_name=exp_name,
+ status=status,
+ output_params={},
+ timestamp=timestamp,
+ )
+ raise Exception(f"Error: {status}")
+
+ output_params = {} # TODO: implement output_params
+ update_experiment_history(
+ label=label,
+ exp_name=exp_name,
+ status=status,
+ output_params=output_params,
+ timestamp=timestamp,
+ )
+ update_slack_success_notification(
+ contents, ts, exp_name, qubit_index, fig_path
+ )
+ update_node_status(qubit_index, NodeStatus.SUCCESS)
+ if status != "success":
+ result["success"] = False
+ result["fail_at"] = exp_name
+ break
+ prev_status = status
+
+ except Exception as e:
+ update_slack_failure_notification(contents, exp_name, qubit_index)
+ update_node_status(qubit_index, NodeStatus.FAILED)
+ raise Exception(f"Error: {e}")
+ handle_calibration_result(
+ notes, qubit_index, status, calib_dir, menu, execution_id
+ )
+ return "success"
diff --git a/backend/qcflow/subflow/one_qubit_calibration/task.py b/backend/qcflow/subflow/one_qubit_calibration/task.py
new file mode 100644
index 0000000..7a90f25
--- /dev/null
+++ b/backend/qcflow/subflow/one_qubit_calibration/task.py
@@ -0,0 +1,64 @@
+from dbmodel.wiring_info import WiringInfoModel
+from prefect import task
+from qcflow.schema.menu import Menu
+from qcflow.session.labrad import Session
+
+from .util import TDM
+
+
+@task(name="check sideband all")
+def check_sideband_all(session):
+ for key in session.connection.qube_server.list_devices():
+ check_sideband(session, key[1])
+ return "success"
+
+
+def check_sideband(session, device_name):
+ session.connection.qube_server.select_device(device_name)
+ res = session.connection.qube_server.frequency_sideband()
+ if "readout" in device_name or "pump" in device_name:
+ flag = res == "usb"
+ else:
+ flag = res == "lsb"
+ if not flag:
+ import sys
+
+ print(f"check {device_name} {res}", file=sys.stderr)
+
+
+def create_instrument_manager(
+ menu: Menu, session: Session, qubit_index_list: list[int]
+) -> TDM:
+ tdm = TDM(session)
+ num_mux = 4
+ wiring_info = WiringInfoModel.get_active_wiring_dict()
+ for qubit_index in qubit_index_list:
+ qubit_name = f"Q{qubit_index}"
+ resonator_name = f"M{qubit_index//num_mux}"
+ device_id_qubit = wiring_info["control"][qubit_name]["device_id"]
+ device_id_resonator = wiring_info["readout"][resonator_name]["device_id"]
+
+ tdm.add_qube_channel(device_id_resonator, f"Q{qubit_index}_readout")
+ tdm.add_qube_channel(device_id_qubit, f"Q{qubit_index}_control")
+ check_sideband(session, device_id_qubit)
+ check_sideband(session, device_id_resonator)
+ return tdm
+
+
+@task(name="execute-experiment", task_run_name="{exp_name}", persist_result=False)
+def execute_experiment(
+ exp_name: str,
+ tdm: TDM,
+ exp: object,
+ notes: dict,
+ save: bool,
+ savefig: bool,
+ savepath: str,
+ status: str,
+) -> str:
+ try:
+ dataset = exp.take_data(tdm=tdm, notes=notes, save=save) # type: ignore
+ exp.analyze(dataset=dataset, notes=notes, savefig=savefig, savepath=savepath) # type: ignore
+ return "success"
+ except Exception as e:
+ raise e
diff --git a/backend/qcflow/subflow/one_qubit_calibration/util.py b/backend/qcflow/subflow/one_qubit_calibration/util.py
new file mode 100644
index 0000000..bc6ca41
--- /dev/null
+++ b/backend/qcflow/subflow/one_qubit_calibration/util.py
@@ -0,0 +1,216 @@
+import json
+from typing import Any
+
+import numpy as np
+from bunnet.exceptions import RevisionIdWasChanged
+from dbmodel.one_qubit_calib import OneQubitCalibModel
+from labrad.units import Value as LabradValue
+from prefect import get_run_logger
+from qcflow.db.mongo import (
+ update_one_qubit_calibration,
+ upsert_one_qubit_all_history,
+ upsert_one_qubit_history,
+)
+from qcflow.schema.menu import Menu
+from qcflow.session.labrad import Session
+from qcflow.utils.slack import SlackContents, Status
+
+
+class Note:
+ def __init__(self):
+ self.globals = {}
+
+ def keys(self):
+ pass
+
+ def add_experiment_note(self, note_type, qubit_dict, keys, extra_param):
+ pass
+
+ def set_initial_value(self, qubit_dict, keys):
+ pass
+
+ def get_calibration_parameters(self, exp_name, output_parameters):
+ return {}
+
+
+class TDM:
+ def __init__(self, session: Session):
+ pass
+
+ def add_qube_channel(self, device_id_resonator, qubit_name):
+ pass
+
+ pass
+
+
+def input_params_to_dict(input_params: dict[str, Any]) -> dict[str, Any]:
+ mydic = {}
+ for key, value in input_params.items():
+ if isinstance(value, LabradValue):
+ mydic[key] = {
+ "value": value[value.unit],
+ "unit": str(value.unit),
+ "type": "labrad_value",
+ }
+ elif isinstance(value, np.ndarray) and any(np.iscomplex(value)):
+ mydic[key] = {
+ "value": [value.real.tolist(), value.imag.tolist()],
+ "unit": "",
+ "type": "complex_array",
+ }
+ elif isinstance(value, np.ndarray) and (not any(np.iscomplex(value))):
+ mydic[key] = {
+ "value": value.tolist(),
+ "unit": "",
+ "type": "real_array",
+ }
+ elif isinstance(value, float | int):
+ mydic[key] = {
+ "value": value,
+ "unit": "",
+ "type": "float_value",
+ }
+ else:
+ continue
+ return mydic
+
+
+def initialize_notes(qubit_index: int) -> dict:
+ notes = {}
+ qubit_name = f"Q{qubit_index}"
+ json_dict = OneQubitCalibModel.get_qubit_info()[qubit_name]
+ logger = get_run_logger()
+ logger.info(f"json_dict: {json_dict}")
+ qubit_dict = OneQubitCalibModel.convert_from_json_dict(json_dict)
+ logger.info(f"qubit_dict: {qubit_dict}")
+ note = Note()
+ note.add_experiment_note("calibration_load", qubit_dict, qubit_dict.keys(), None)
+ notes[qubit_name] = json_dict
+ return notes
+
+
+def send_slack_notification(menu: Menu):
+ contents = SlackContents(
+ status=Status.RUNNING,
+ title="Start one qubit calibration for Q",
+ msg="",
+ notify=menu.notify_bool,
+ ts="",
+ path="",
+ )
+ ts = contents.send_slack()
+ return contents, ts
+
+
+def update_slack_success_notification(
+ contents: SlackContents, ts: str, exp_name: str, qubit_index: int, fig_path: str
+):
+ contents.status = Status.SUCCESS
+ contents.title = f"Success {exp_name} for Q{qubit_index}"
+ contents.path = f"{fig_path}/Q{qubit_index}_{exp_name}.png"
+ contents.ts = ts
+ contents.send_slack()
+
+
+def update_slack_failure_notification(
+ contents: SlackContents, exp_name: str, qubit_index: int
+):
+ contents.status = Status.FAILED
+ contents.title = f"Failed {exp_name} for Q{qubit_index}"
+ contents.msg = "Experiment failed"
+ contents.notify = True
+ contents.ts = ""
+ contents.path = ""
+ contents.send_slack()
+
+
+def handle_calibration_result(
+ notes: dict,
+ qubit_index: int,
+ status: str,
+ calib_dir: str,
+ menu: Menu,
+ execution_id: str,
+):
+ calib_result = {
+ "calib_target": [qubit_index],
+ "calib_notes": notes,
+ "calib_result": status,
+ }
+ logger = get_run_logger()
+ logger.info(f"calib_result: {calib_result}")
+ calib_path = f"{calib_dir}/calib_full"
+ logger.info(f"calib_result: {calib_result}")
+ if calib_result["calib_result"] == "success":
+ calibration_notes_to_json(notes=notes, path=calib_path)
+ calibration_notes_to_mongo(menu=menu, notes=notes, execution_id=execution_id)
+ else:
+ contents = SlackContents(
+ status=Status.SUCCESS,
+ title=f"Success one qubit calibration for Q{qubit_index} :tada:",
+ msg="",
+ notify=True,
+ ts="",
+ path="",
+ )
+ contents.send_slack()
+
+
+def notes_to_dict(notes: dict):
+ doc = {}
+ for qubit_name, note in notes.items():
+ glob = note.globals
+ mydic = {}
+ for key in glob:
+ value = glob[key].value
+ if isinstance(value, LabradValue):
+ mydic[key] = {
+ "value": value[value.unit],
+ "unit": str(value.unit),
+ "type": "labrad_value",
+ }
+ elif isinstance(value, np.ndarray) and any(np.iscomplex(value)):
+ mydic[key] = {
+ "value": [value.real.tolist(), value.imag.tolist()],
+ "unit": "",
+ "type": "complex_array",
+ }
+ elif isinstance(value, np.ndarray) and (not any(np.iscomplex(value))):
+ mydic[key] = {
+ "value": value.tolist(),
+ "unit": "",
+ "type": "real_array",
+ }
+ elif isinstance(value, float):
+ mydic[key] = {
+ "value": value,
+ "unit": "",
+ "type": "float_value",
+ }
+ else:
+ raise ValueError(f"invalid type {key}")
+ doc[qubit_name] = mydic
+ return doc
+
+
+def calibration_notes_to_json(notes: dict, path: str = "./calib"):
+ # notes = notes_to_dict(notes)
+ for name, mydic in notes.items():
+ jsonname = f"{path}/{name}.json"
+ with open(jsonname, "w") as fout:
+ json.dump(mydic, fout)
+ print(f"output {jsonname}")
+
+
+def calibration_notes_to_mongo(menu: Menu, notes: dict, execution_id: str):
+ # notes = notes_to_dict(notes)
+ for name, mydic in notes.items():
+ update_one_qubit_calibration(name, mydic)
+ try:
+ upsert_one_qubit_history(menu=menu, label=name, data=mydic)
+ upsert_one_qubit_all_history(
+ menu=menu, label=name, data=mydic, execution_id=execution_id
+ )
+ except RevisionIdWasChanged as e:
+ print(f"RevisionIdWasChanged: {e} name={name}")
+ continue
diff --git a/backend/qcflow/subflow/one_qubit_daily_summary/__init__.py b/backend/qcflow/subflow/one_qubit_daily_summary/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/subflow/one_qubit_daily_summary/flow.py b/backend/qcflow/subflow/one_qubit_daily_summary/flow.py
new file mode 100644
index 0000000..9224f71
--- /dev/null
+++ b/backend/qcflow/subflow/one_qubit_daily_summary/flow.py
@@ -0,0 +1,7 @@
+from prefect import flow
+from qcflow.db.mongo import upsert_one_qubit_daily_summary
+
+
+@flow
+def one_qubit_daily_summary_flow():
+ upsert_one_qubit_daily_summary()
diff --git a/backend/qcflow/subflow/scheduler/__init__.py b/backend/qcflow/subflow/scheduler/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/subflow/scheduler/flow.py b/backend/qcflow/subflow/scheduler/flow.py
new file mode 100644
index 0000000..89a0dcd
--- /dev/null
+++ b/backend/qcflow/subflow/scheduler/flow.py
@@ -0,0 +1,25 @@
+import datetime
+from datetime import timedelta
+
+from prefect import flow
+from prefect.deployments import run_deployment
+from qcflow.schema.menu import Menu
+from qcflow.utils.slack import SlackContents, Status
+from zoneinfo import ZoneInfo
+
+
+@flow(name="scheduler", log_prints=True)
+def scheduler_flow(menu: Menu):
+ now = datetime.datetime.now(ZoneInfo("Asia/Tokyo"))
+ calc_min = timedelta(minutes=1)
+ target = now + calc_min
+ contents = SlackContents(
+ status=Status.RUNNING,
+ title="scheduler",
+ msg=f"{target.isoformat()}",
+ notify=True,
+ ts="",
+ path="",
+ )
+ contents.send_slack()
+ run_deployment(name="main/main", parameters={"menu": menu}, scheduled_time=target)
diff --git a/backend/qcflow/subflow/service_close/__init__.py b/backend/qcflow/subflow/service_close/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/subflow/service_close/service_close.py b/backend/qcflow/subflow/service_close/service_close.py
new file mode 100644
index 0000000..ab1f82b
--- /dev/null
+++ b/backend/qcflow/subflow/service_close/service_close.py
@@ -0,0 +1,52 @@
+import requests
+from prefect import flow
+from pydantic import BaseModel
+from qcflow.utils.slack import SlackContents, Status
+
+restart_url = "http://localhost:5715/service"
+url = "http://localhost:5715/service/status"
+
+
+class CloudSetting(BaseModel):
+ status: str
+ mode: str
+ qubit_num: int
+ qubit_index: str
+
+
+@flow(name="qpu-close", log_prints=True)
+def qpu_close_flow():
+ response = requests.get(url)
+ settings = response.json()
+ settings["status"] = "unavailable"
+ settings["mode"] = "qpu"
+ response = requests.patch(url, json=settings)
+ _ = requests.put(restart_url)
+ contents = SlackContents(
+ status=Status.SUCCESS,
+ title="QPU Closing",
+ msg=f"{response.json()}",
+ notify=True,
+ ts="",
+ path="",
+ )
+ contents.send_slack()
+
+
+@flow(name="simulator-close", log_prints=True)
+def simulator_close_flow():
+ response = requests.get(url)
+ settings = response.json()
+ settings["status"] = "unavailable"
+ settings["mode"] = "simulator"
+ response = requests.patch(url, json=settings)
+ _ = requests.put(restart_url)
+ contents = SlackContents(
+ status=Status.SUCCESS,
+ title="Simulator Closing",
+ msg=f"{response.json()}",
+ notify=True,
+ ts="",
+ path="",
+ )
+ contents.send_slack()
diff --git a/backend/qcflow/subflow/service_open/__init__.py b/backend/qcflow/subflow/service_open/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/subflow/service_open/service_open.py b/backend/qcflow/subflow/service_open/service_open.py
new file mode 100644
index 0000000..61acbd9
--- /dev/null
+++ b/backend/qcflow/subflow/service_open/service_open.py
@@ -0,0 +1,52 @@
+import requests
+from prefect import flow
+from pydantic import BaseModel
+from qcflow.utils.slack import SlackContents, Status
+
+restart_url = "http://localhost:5715/service"
+url = "http://localhost:5715/service/status"
+
+
+class CloudSetting(BaseModel):
+ status: str
+ mode: str
+ qubit_num: int
+ qubit_index: str
+
+
+@flow(name="qpu-open", log_prints=True)
+def qpu_open_flow():
+ response = requests.get(url)
+ settings = response.json()
+ settings["status"] = "available"
+ settings["mode"] = "qpu"
+ response = requests.patch(url, json=settings)
+ _ = requests.put(restart_url)
+ contents = SlackContents(
+ status=Status.SUCCESS,
+ title="QPU Open",
+ msg=f"{response.json()}",
+ notify=True,
+ ts="",
+ path="",
+ )
+ contents.send_slack()
+
+
+@flow(name="simulator-open", log_prints=True)
+def simulator_open_flow():
+ response = requests.get(url)
+ settings = response.json()
+ settings["status"] = "available"
+ settings["mode"] = "simulator"
+ response = requests.patch(url, json=settings)
+ _ = requests.put(restart_url)
+ contents = SlackContents(
+ status=Status.SUCCESS,
+ title="Simulator Open",
+ msg=f"{response.json()}",
+ notify=True,
+ ts="",
+ path="",
+ )
+ contents.send_slack()
diff --git a/backend/qcflow/utils/__init__.py b/backend/qcflow/utils/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/utils/slack.py b/backend/qcflow/utils/slack.py
new file mode 100644
index 0000000..36c312d
--- /dev/null
+++ b/backend/qcflow/utils/slack.py
@@ -0,0 +1,91 @@
+from dataclasses import dataclass
+from enum import Enum
+
+from slack_sdk import WebClient
+from slack_sdk.errors import SlackApiError
+
+
+class Status(Enum):
+ SUCCESS = 1
+ RUNNING = 2
+ RETRY = 3
+ FAILED = 4
+
+
+@dataclass
+class SlackContents:
+ status: Status
+ title: str
+ msg: str
+ notify: bool
+ ts: str
+ path: str
+ header: str = ""
+ channel: str = "#slack-bot-test"
+
+ def __init__(
+ self,
+ status: Status,
+ title: str,
+ msg: str,
+ notify: bool,
+ ts: str,
+ path: str,
+ header: str = "",
+ channel: str = "#slack-bot-test",
+ token: str = "",
+ ):
+ self.status = status
+ self.title = title
+ self.msg = msg
+ self.notify = notify
+ self.ts = ts
+ self.path = path
+ self.header = header
+ self.channel = channel
+ self.token = token
+
+ def send_slack(self) -> str:
+ if not self.notify:
+ return ""
+ # token = os.environ.get("SLACK_BOT_TOKEN")
+ if self.token is None:
+ return ""
+ client = WebClient(token=self.token)
+ if self.status == Status.SUCCESS:
+ color = "good"
+ elif self.status == Status.RUNNING:
+ color = "#2E64FE"
+ elif self.status == Status.RETRY:
+ color = "warning"
+ elif self.status == Status.FAILED:
+ color = "danger"
+ else:
+ color = ""
+ try:
+ if self.ts != "":
+ client.files_upload(
+ channels=self.channel,
+ file=self.path,
+ title=self.title,
+ thread_ts=self.ts,
+ )
+ return self.ts
+ resp = client.chat_postMessage(
+ channel=self.channel,
+ text=self.header,
+ attachments=[
+ {
+ "color": color,
+ "title": self.title,
+ "text": self.msg,
+ }
+ ],
+ )
+ return str(resp["ts"])
+ except SlackApiError as e:
+ print(f"Got an error: {e.response['error']}")
+ return ""
+ except Exception as e:
+ print(f"Got an error: {e}")
+ raise e
diff --git a/backend/qcflow/utils/time_estimation.py b/backend/qcflow/utils/time_estimation.py
new file mode 100644
index 0000000..7f6710c
--- /dev/null
+++ b/backend/qcflow/utils/time_estimation.py
@@ -0,0 +1,32 @@
+# from pkg.schemas.menu import Menu
+# import itertools
+# from typing import Final
+# from datetime import timedelta
+# from zoneinfo import ZoneInfo
+# import datetime
+# from qcflow.task.two_qubit_calibration import (
+# condition,
+# create_available_cnot_pair,
+# reduce_bidirection,
+# )
+
+# ONE_QUBIT_CALIBRATION_TIME: Final = 22
+# TWO_QUBIT_CALIBRATION_TIME: Final = 22
+
+
+# # def time_estimation(menu: Menu) -> str:
+# # one_qubit_calibration_sequence = len(menu.qubit_index_list)
+# # estimation_time = ONE_QUBIT_CALIBRATION_TIME * one_qubit_calibration_sequence
+# # qubit_index_list = list(itertools.chain.from_iterable(menu.qubit_index_list))
+# # available_cnot_pair = create_available_cnot_pair(qubit_index_list)
+# # available_cnot_pair_target = reduce_bidirection(available_cnot_pair)
+# # available_cnot_pair_target = [
+# # pair
+# # for pair in available_cnot_pair_target
+# # if condition(menu.mux_index_list, pair)
+# # ]
+# # estimation_time += TWO_QUBIT_CALIBRATION_TIME * len(available_cnot_pair_target)
+# # now = datetime.datetime.now(ZoneInfo("Asia/Tokyo"))
+# # calc_min = timedelta(minutes=estimation_time)
+# # end_time = now + calc_min
+# # return end_time.isoformat()
diff --git a/backend/qcflow/utiltask/__init__.py b/backend/qcflow/utiltask/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/qcflow/utiltask/create_directory.py b/backend/qcflow/utiltask/create_directory.py
new file mode 100644
index 0000000..c7ffd37
--- /dev/null
+++ b/backend/qcflow/utiltask/create_directory.py
@@ -0,0 +1,21 @@
+import os
+
+from prefect import task
+
+
+@task(name="create directory")
+def create_directory_task(calib_dir: str):
+ if not os.path.exists(calib_dir):
+ os.makedirs(calib_dir)
+ path_list = [
+ f"{calib_dir}/calib_full",
+ f"{calib_dir}/fig_tdm",
+ f"{calib_dir}/calib_full_jazz",
+ f"{calib_dir}/calib_full_jazz_half_pi",
+ f"{calib_dir}/fig_jazz",
+ f"{calib_dir}/fig_cr",
+ f"{calib_dir}/calib_cr",
+ ]
+ for path in path_list:
+ if not os.path.exists(path):
+ os.mkdir(path)
diff --git a/backend/qcflow/utiltask/save_wiring_info.py b/backend/qcflow/utiltask/save_wiring_info.py
new file mode 100644
index 0000000..67f1177
--- /dev/null
+++ b/backend/qcflow/utiltask/save_wiring_info.py
@@ -0,0 +1,17 @@
+from dbmodel.wiring_info import WiringInfoModel
+from prefect import task
+
+# from qcflow.db.wiring_info import get_wiring_info
+from qcflow.schema.menu import Menu
+from qcflow.session.labrad import labrad_session
+
+
+@task(name="save wiring info")
+def save_wiring_info(menu: Menu):
+ with labrad_session() as session:
+ wiring_info_name = WiringInfoModel.get_active_wiring_name()
+ wiring_info = WiringInfoModel.get_active_wiring_dict()
+ session.save_wiring_info(
+ wiring_name=wiring_info_name,
+ wiring_dict=wiring_info,
+ )
diff --git a/backend/server/Dockerfile b/backend/server/Dockerfile
new file mode 100644
index 0000000..6691042
--- /dev/null
+++ b/backend/server/Dockerfile
@@ -0,0 +1,26 @@
+FROM python:3.10.14-slim-bookworm AS builder
+
+WORKDIR /app
+
+RUN apt-get update \
+ && apt-get install -y --no-install-recommends \
+ build-essential \
+ pkg-config \
+ libhdf5-dev \
+ curl \
+ wget \
+ && apt-get clean \
+ && rm -rf /var/lib/apt/lists/*
+
+COPY ./backend/server/requirements.txt ./
+
+COPY --from=ghcr.io/astral-sh/uv:latest /uv /uvx /bin/
+RUN uv pip install --system --no-cache-dir -r requirements.txt
+
+FROM python:3.10.14-slim-bookworm
+
+WORKDIR /app
+
+COPY --from=builder /app /app
+COPY --from=builder /usr/local/lib/python3.10/site-packages /usr/local/lib/python3.10/site-packages
+COPY --from=builder /usr/local/bin /usr/local/bin
diff --git a/backend/server/__init__.py b/backend/server/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/server/config.py b/backend/server/config.py
new file mode 100644
index 0000000..4529273
--- /dev/null
+++ b/backend/server/config.py
@@ -0,0 +1,22 @@
+from functools import lru_cache
+
+from pydantic_settings import BaseSettings # , SettingsConfigDict
+
+
+class Settings(BaseSettings):
+ env: str
+ client_url: str
+ prefect_api_url: str
+ slack_bot_token: str
+ postgres_data_path: str
+ mongo_data_path: str
+ calib_data_path: str
+ mongo_host: str
+ prefect_host: str
+ postgres_host: str
+ qpu_data_path: str
+
+
+@lru_cache()
+def get_settings():
+ return Settings() # type: ignore
diff --git a/backend/server/lib/slack.py b/backend/server/lib/slack.py
new file mode 100644
index 0000000..7f59742
--- /dev/null
+++ b/backend/server/lib/slack.py
@@ -0,0 +1,70 @@
+import os
+from dataclasses import dataclass
+from enum import Enum
+
+from server.config import get_settings
+from slack_sdk import WebClient
+from slack_sdk.errors import SlackApiError
+
+
+class Status(Enum):
+ SUCCESS = 1
+ RUNNING = 2
+ RETRY = 3
+ FAILED = 4
+
+
+@dataclass
+class SlackContents:
+ status: Status
+ title: str
+ msg: str
+ notify: bool
+ ts: str
+ path: str
+ header: str = ""
+
+ def send_slack(self) -> str:
+ if not self.notify:
+ return ""
+ token = get_settings().slack_bot_token
+ if token is None:
+ return ""
+ client = WebClient(token=token)
+ if self.status == Status.SUCCESS:
+ color = "good"
+ elif self.status == Status.RUNNING:
+ color = "#2E64FE"
+ elif self.status == Status.RETRY:
+ color = "warning"
+ elif self.status == Status.FAILED:
+ color = "danger"
+ else:
+ color = ""
+ try:
+ if self.ts != "":
+ client.files_upload(
+ channels="#slack-bot-test",
+ file=self.path,
+ title=self.title,
+ thread_ts=self.ts,
+ )
+ return self.ts
+ resp = client.chat_postMessage(
+ channel="#slack-bot-test",
+ text=self.header,
+ attachments=[
+ {
+ "color": color,
+ "title": self.title,
+ "text": self.msg,
+ }
+ ],
+ )
+ return str(resp["ts"])
+ except SlackApiError as e:
+ print(f"Got an error: {e.response['error']}")
+ return ""
+ except Exception as e:
+ print(f"Got an error: {e}")
+ raise e
diff --git a/backend/server/main.py b/backend/server/main.py
new file mode 100644
index 0000000..91a3562
--- /dev/null
+++ b/backend/server/main.py
@@ -0,0 +1,115 @@
+import os
+from contextlib import asynccontextmanager
+
+from bunnet import init_bunnet
+from dbmodel.bluefors import BlueforsModel
+from dbmodel.cooling_down import CoolingDownModel
+from dbmodel.execution_lock import ExecutionLockModel
+from dbmodel.execution_run_history import ExecutionRunHistoryModel
+from dbmodel.experiment import ExperimentModel
+from dbmodel.experiment_history import ExperimentHistoryModel
+from dbmodel.instrument import InstrumentModel
+from dbmodel.menu import MenuModel
+from dbmodel.one_qubit_calib import OneQubitCalibModel
+from dbmodel.one_qubit_calib_all_history import OneQubitCalibAllHistoryModel
+from dbmodel.one_qubit_calib_daily_summary import OneQubitCalibDailySummaryModel
+from dbmodel.one_qubit_calib_history import OneQubitCalibHistoryModel
+from dbmodel.qpu import QPUModel
+from dbmodel.qube import QubeModel
+from dbmodel.session_info import SessionInfoModel
+from dbmodel.two_qubit_calib import TwoQubitCalibModel
+from dbmodel.two_qubit_calib_daily_summary import TwoQubitCalibDailySummaryModel
+from dbmodel.two_qubit_calib_history import TwoQubitCalibHistoryModel
+from dbmodel.wiring_info import WiringInfoModel
+from fastapi import FastAPI
+from fastapi.middleware.cors import CORSMiddleware
+from fastapi.routing import APIRoute
+from pymongo import MongoClient
+from server.routers import (
+ calibration,
+ execution,
+ experiment,
+ fridges,
+ menu,
+ qpu,
+ settings,
+)
+
+
+def custom_generate_unique_id(route: APIRoute):
+ return f"{route.tags[0]}-{route.name}"
+
+
+mongo_host = os.getenv("MONGO_HOST")
+
+
+@asynccontextmanager
+async def lifespan(app: FastAPI):
+ client: MongoClient = MongoClient(
+ mongo_host, 27017, username="root", password="example"
+ )
+ init_bunnet(
+ database=client.cloud,
+ document_models=[
+ OneQubitCalibModel,
+ TwoQubitCalibModel,
+ OneQubitCalibHistoryModel,
+ TwoQubitCalibHistoryModel,
+ OneQubitCalibDailySummaryModel,
+ TwoQubitCalibDailySummaryModel,
+ MenuModel,
+ QubeModel,
+ QPUModel,
+ SessionInfoModel,
+ WiringInfoModel,
+ CoolingDownModel,
+ InstrumentModel,
+ BlueforsModel,
+ ExecutionLockModel,
+ ExperimentHistoryModel,
+ ExperimentModel,
+ ExecutionRunHistoryModel,
+ OneQubitCalibAllHistoryModel,
+ CoolingDownModel,
+ ], # type: ignore
+ )
+ yield
+ client.close()
+
+
+app = FastAPI(
+ title="QDash Server",
+ description="API for QDash",
+ summary="QDash API",
+ version="0.0.1",
+ contact={
+ "name": "QDash",
+ "email": "oqtopus-team[at]googlegroups.com",
+ },
+ license_info={
+ "name": "Apache 2.0",
+ "url": "https://www.apache.org/licenses/LICENSE-2.0.html",
+ },
+ # openapi_url="/openapi.json",
+ generate_unique_id_function=custom_generate_unique_id,
+ separate_input_output_schemas=False,
+ lifespan=lifespan,
+)
+
+
+origins = ["*"]
+
+app.add_middleware(
+ CORSMiddleware,
+ allow_origins=origins,
+ allow_credentials=True,
+ allow_methods=["*"],
+ allow_headers=["*"],
+)
+app.include_router(calibration.router, tags=["calibration"])
+app.include_router(menu.router, tags=["menu"])
+app.include_router(qpu.router, tags=["qpu"])
+app.include_router(settings.router, tags=["settings"])
+app.include_router(fridges.router, tags=["fridges"])
+app.include_router(execution.router, tags=["execution"])
+app.include_router(experiment.router, tags=["experiment"])
diff --git a/backend/server/requirements.txt b/backend/server/requirements.txt
new file mode 100644
index 0000000..78e46c4
--- /dev/null
+++ b/backend/server/requirements.txt
@@ -0,0 +1,141 @@
+annotated-types==0.7.0 ; python_full_version >= "3.10.14" and python_version < "4.0"
+anyio==4.4.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+asgi-lifespan==2.1.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+asttokens==2.4.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+attrs==24.2.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+automat==24.8.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+bcrypt==4.2.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+bunnet==1.3.0 ; python_full_version >= "3.10.14" and python_version < "4.0"
+cachetools==5.5.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+certifi==2024.8.30 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+cffi==1.17.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+charset-normalizer==3.3.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+click==8.1.7 ; python_full_version >= "3.10.14" and python_version < "4.0"
+cloudpickle==3.0.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+colorama==0.4.6 ; python_full_version >= "3.10.14" and python_version < "4.0"
+constantly==23.10.4 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+contourpy==1.3.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+coolname==2.2.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+coverage[toml]==7.6.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+croniter==2.0.7 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+cryptography==43.0.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+cycler==0.12.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+decorator==5.1.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+dnspython==2.6.1 ; python_full_version >= "3.10.14" and python_version < "4.0"
+email-validator==2.2.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+exceptiongroup==1.2.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+executing==2.1.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+fastapi-cli==0.0.5 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+fastapi==0.111.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+filelock==3.16.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+fonttools==4.53.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+fsspec==2024.9.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+graphviz==0.20.3 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+griffe==1.2.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+gunicorn==22.0.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+h11==0.14.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+h2==4.1.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+hpack==4.0.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+httpcore==1.0.5 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+httptools==0.6.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+httpx==0.27.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+httpx[http2]==0.27.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+hyperframe==6.0.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+hyperlink==21.0.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+idna==3.8 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+importlib-resources==6.4.5 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+incremental==24.7.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+iniconfig==2.0.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+ipython==8.27.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+itsdangerous==2.2.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+jedi==0.19.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+jinja2==3.1.4 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+jsonpatch==1.33 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+jsonpointer==3.0.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+jsonschema-specifications==2023.12.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+jsonschema==4.23.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+kiwisolver==1.4.7 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+lazy-model==0.2.0 ; python_full_version >= "3.10.14" and python_version < "4.0"
+markdown-it-py==3.0.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+markupsafe==2.1.5 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+matplotlib-inline==0.1.7 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+matplotlib==3.9.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+mdurl==0.1.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+mypy-extensions==1.0.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+mypy==1.11.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+networkx==2.8.8 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+numpy==1.23.5 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+orjson==3.10.7 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+packaging==24.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+paramiko==3.4.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+parso==0.8.4 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pathspec==0.12.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pendulum==2.1.2 ; python_full_version >= "3.10.14" and python_version < "3.12"
+pendulum==3.0.0 ; python_version >= "3.12" and python_full_version < "4.0.0"
+pexpect==4.9.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0" and (sys_platform != "win32" and sys_platform != "emscripten")
+pillow==10.4.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pluggy==1.5.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+prefect-client==2.20.6 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+prompt-toolkit==3.0.47 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+ptyprocess==0.7.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0" and (sys_platform != "win32" and sys_platform != "emscripten")
+pure-eval==0.2.3 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pyasn1-modules==0.4.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pyasn1==0.6.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pycparser==2.22 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pydantic-core==2.23.3 ; python_full_version >= "3.10.14" and python_version < "4.0"
+pydantic-settings==2.4.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pydantic==2.9.1 ; python_full_version >= "3.10.14" and python_version < "4.0"
+pydantic[email]==2.9.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pygments==2.18.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pylabrad==0.98.3 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pymongo==4.8.0 ; python_full_version >= "3.10.14" and python_version < "4.0"
+pynacl==1.5.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pyopenssl==24.2.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pyparsing==3.1.4 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pytest-cov==5.0.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pytest-env==1.1.4 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pytest-mypy==0.10.3 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pytest==8.3.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+python-dateutil==2.9.0.post0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+python-dotenv==1.0.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+python-multipart==0.0.9 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+python-slugify==8.0.4 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pytz==2024.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+pytzdata==2020.1 ; python_full_version >= "3.10.14" and python_version < "3.12"
+pyyaml==6.0.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+referencing==0.35.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+requests==2.32.3 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+rfc3339-validator==0.1.4 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+rich==13.8.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+rpds-py==0.20.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+ruamel-yaml-clib==0.2.8 ; platform_python_implementation == "CPython" and python_version < "3.13" and python_full_version >= "3.10.14"
+ruamel-yaml==0.18.6 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+ruff==0.5.7 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+service-identity==24.1.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+setuptools==74.1.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+shellingham==1.5.4 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+six==1.16.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+slack-sdk==3.32.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+sniffio==1.3.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+stack-data==0.6.3 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+starlette==0.37.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+text-unidecode==1.3 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+toml==0.10.2 ; python_full_version >= "3.10.14" and python_version < "4.0"
+tomli==2.0.1 ; python_full_version >= "3.10.14" and python_full_version <= "3.11.0a6"
+tqdm==4.66.5 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+traitlets==5.14.3 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+twisted==24.7.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+typer==0.12.5 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+types-paramiko==3.4.0.20240423 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+types-python-dateutil==2.9.0.20240906 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+typing-extensions==4.12.2 ; python_full_version >= "3.10.14" and python_version < "4.0"
+tzdata==2024.1 ; python_version >= "3.12" and python_full_version < "4.0.0"
+ujson==5.10.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+urllib3==2.2.2 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+uvicorn==0.30.6 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+uvicorn[standard]==0.30.6 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+uvloop==0.20.0 ; (sys_platform != "win32" and sys_platform != "cygwin") and platform_python_implementation != "PyPy" and python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+watchfiles==0.24.0 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+wcwidth==0.2.13 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+websockets==13.0.1 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
+zope-interface==7.0.3 ; python_full_version >= "3.10.14" and python_full_version < "4.0.0"
diff --git a/backend/server/routers/__init__.py b/backend/server/routers/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/backend/server/routers/calibration.py b/backend/server/routers/calibration.py
new file mode 100644
index 0000000..faac558
--- /dev/null
+++ b/backend/server/routers/calibration.py
@@ -0,0 +1,732 @@
+import os
+import uuid
+from datetime import datetime
+from io import BytesIO
+from logging import getLogger
+from typing import Annotated, Optional
+
+import dateutil.tz
+from dbmodel.menu import MenuModel
+from dbmodel.one_qubit_calib import OneQubitCalibModel
+from dbmodel.one_qubit_calib_daily_summary import OneQubitCalibDailySummaryModel
+from dbmodel.one_qubit_calib_history import OneQubitCalibHistoryModel
+from dbmodel.qpu import QPUModel
+from dbmodel.two_qubit_calib import TwoQubitCalibModel
+from dbmodel.two_qubit_calib_daily_summary import TwoQubitCalibDailySummaryModel
+from dbmodel.two_qubit_calib_history import TwoQubitCalibHistoryModel
+from fastapi import APIRouter, Depends, HTTPException
+from fastapi.responses import StreamingResponse
+from prefect.client.orchestration import PrefectClient
+from prefect.client.schemas.filters import (
+ FlowFilter,
+ FlowFilterId,
+ FlowRunFilter,
+ FlowRunFilterState,
+ FlowRunFilterStateType,
+ StateType,
+)
+from prefect.states import Scheduled
+from server.config import Settings, get_settings
+from server.schemas.calibration import (
+ ExecuteCalibRequest,
+ ExecuteCalibResponse,
+ OneQubitCalibCWInfo,
+ OneQubitCalibDailySummaryRequest,
+ OneQubitCalibDailySummaryResponse,
+ OneQubitCalibHistoryResponse,
+ OneQubitCalibResponse,
+ OneQubitCalibStatsRequest,
+ OneQubitCalibStatsResponse,
+ ScheduleCalibRequest,
+ ScheduleCalibResponse,
+ TwoQubitCalibDailySummaryRequest,
+ TwoQubitCalibDailySummaryResponse,
+ TwoQubitCalibHistoryResponse,
+ TwoQubitCalibResponse,
+ TwoQubitCalibStatsRequest,
+ TwoQubitCalibStatsResponse,
+)
+
+# TwoQubitCalibStatsResponse,
+from server.schemas.error import (
+ Detail,
+ NotFoundErrorResponse,
+)
+from server.schemas.exception import InternalSeverError
+from server.schemas.success import SuccessResponse
+
+router = APIRouter()
+logger = getLogger("uvicorn.app")
+prefect_host = os.getenv("PREFECT_HOST")
+
+
+@router.post(
+ "/calibrations",
+ response_model=ExecuteCalibResponse,
+ summary="Executes a calibration by creating a flow run from a deployment.",
+ operation_id="execute_calib",
+)
+async def execute_calib(
+ request: ExecuteCalibRequest,
+ settings: Annotated[Settings, Depends] = Depends(get_settings),
+) -> ExecuteCalibResponse:
+ """
+ Executes a calibration by creating a flow run from a deployment.
+
+ Args:
+ request (ExecuteCalibRequest): The request object containing the calibration data.
+ settings (Settings): The application settings.
+
+ Returns:
+ FLOW_RUN_URL: The URL of the created flow run.
+
+ Raises:
+ HTTPException: If the execution of the calibration fails.
+ """
+ client = PrefectClient(api=settings.prefect_api_url)
+ env = settings.env
+ target_deployment = await client.read_deployment_by_name(f"main/{env}-main")
+ try:
+ resp = await client.create_flow_run_from_deployment(
+ deployment_id=target_deployment.id,
+ parameters={"menu": request.dict()},
+ )
+ except Exception as e:
+ logger.warn(e)
+ raise InternalSeverError(detail=f"Failed to execute calibration {str(e)}")
+ logger.warn(resp)
+ return ExecuteCalibResponse(
+ flow_run_url=f"http://{prefect_host}:4200/flow-runs/flow-run/{resp.id}"
+ )
+
+
+ja = dateutil.tz.gettz("Asia/Tokyo")
+local_date = datetime.now(tz=ja)
+
+
+@router.post(
+ "/calibrations/schedule",
+ summary="Schedules a calibration.",
+ operation_id="schedule_calib",
+)
+async def schedule_calib(
+ request: ScheduleCalibRequest,
+ settings: Annotated[Settings, Depends] = Depends(get_settings),
+):
+ logger.warn(f"create menu name: {request.menu_name}")
+ menu = MenuModel.find_one(MenuModel.name == request.menu_name).run()
+ if menu is None:
+ raise HTTPException(status_code=404, detail="menu not found")
+ execute_calib_request = ExecuteCalibRequest(
+ name=menu.name,
+ description=menu.description,
+ one_qubit_calib_plan=menu.one_qubit_calib_plan,
+ two_qubit_calib_plan=menu.two_qubit_calib_plan,
+ mode=menu.mode,
+ notify_bool=menu.notify_bool,
+ flow=menu.flow,
+ exp_list=menu.exp_list,
+ tags=menu.tags,
+ )
+ client = PrefectClient(api=settings.prefect_api_url)
+ datetime_str = request.scheduled
+ scheduled_time = datetime.fromisoformat(datetime_str)
+ env = settings.env
+ print(env)
+ try:
+ target_deployment = await client.read_deployment_by_name(f"main/{env}-main")
+ except Exception as e:
+ logger.warn(e)
+ raise HTTPException(status_code=404, detail="deployment not found")
+ print(scheduled_time)
+ try:
+ _ = await client.create_flow_run_from_deployment(
+ deployment_id=target_deployment.id,
+ state=Scheduled(scheduled_time=scheduled_time),
+ parameters={"menu": execute_calib_request.model_dump()},
+ )
+ except Exception as e:
+ logger.warn(e)
+ raise InternalSeverError(detail=f"Failed to schedule calibration {str(e)}")
+
+
+@router.get(
+ "/calibrations/schedule",
+ response_model=list[ScheduleCalibResponse],
+ summary="Fetches all the calibration schedules.",
+ operation_id="fetch_all_calib_schedule",
+)
+async def fetch_all_calib_schedule(
+ settings: Annotated[Settings, Depends] = Depends(get_settings),
+) -> list[ScheduleCalibResponse]:
+ client = PrefectClient(api=settings.prefect_api_url)
+ env = settings.env
+ target_deployment = await client.read_deployment_by_name(f"main/{env}-main")
+ flow_id = target_deployment.flow_id
+ flowFilterId = FlowFilterId()
+ flowFilterId.any_ = [flow_id]
+ state = FlowRunFilterStateType()
+ state.any_ = [StateType.SCHEDULED]
+ flow_run_filter_state = FlowRunFilterState(type=state, name=None)
+
+ try:
+ flows = await client.read_flow_runs(
+ flow_filter=FlowFilter(id=flowFilterId),
+ flow_run_filter=FlowRunFilter(state=flow_run_filter_state),
+ )
+ except Exception as e:
+ logger.warn(e)
+ raise InternalSeverError(
+ detail=f"Failed to fetch calibration schedules {str(e)}"
+ )
+ calib_schedules = []
+ for flow in flows:
+ time = flow.next_scheduled_start_time
+ if time is not None:
+ next_scheduled_start_time = time.in_timezone("Asia/Tokyo").strftime(
+ "%Y-%m-%d %H:%M:%S%z"
+ )
+ calib_schedules.append(
+ ScheduleCalibResponse(
+ menu_name=flow.parameters["menu"]["name"],
+ description=flow.parameters["menu"]["description"],
+ note="foo bar",
+ menu=ExecuteCalibRequest(**flow.parameters["menu"]),
+ timezone="Asia/Tokyo",
+ scheduled_time=next_scheduled_start_time,
+ flow_run_id=str(flow.id),
+ )
+ )
+ calib_schedules = sorted(calib_schedules, key=lambda x: x.scheduled_time)
+ return calib_schedules
+
+
+@router.delete(
+ "/calibrations/schedule/{flow_run_id}",
+ summary="Deletes a calibration schedule.",
+ operation_id="delete_calib_schedule",
+)
+async def delete_calib_schedule(
+ flow_run_id: str, settings: Annotated[Settings, Depends] = Depends(get_settings)
+):
+ client = PrefectClient(api=settings.prefect_api_url)
+ id = uuid.UUID(flow_run_id)
+ try:
+ await client.delete_flow_run(flow_run_id=id)
+ except Exception as e:
+ logger.warn(e)
+ raise InternalSeverError(f"Failed to delete calibration schedule {str(e)}")
+
+
+@router.get(
+ "/calibrations/latest/one_qubit",
+ response_model=list[OneQubitCalibResponse],
+ summary="Fetches all the latest one qubit calibrations.",
+ operation_id="fetch_all_latest_one_qubit_calib",
+)
+def fetch_all_latest_one_qubit_calib() -> list[OneQubitCalibResponse]:
+ """
+ Fetches all the latest one qubit calibrations.
+
+ Returns:
+ A list of OneQubitCalibResponse objects representing the latest one qubit calibrations.
+ """
+ qpu_name = QPUModel.get_active_qpu_name()
+ one_qubit_calib_list = OneQubitCalibModel.find(
+ OneQubitCalibModel.qpu_name == qpu_name
+ ).run()
+ if one_qubit_calib_list is None:
+ return list[OneQubitCalibResponse]
+ one_qubit_calib_resp = []
+ for one_qubit_calib in one_qubit_calib_list:
+ one_qubit_calib_resp.append(
+ OneQubitCalibResponse(
+ qpu_name=one_qubit_calib.qpu_name,
+ cooling_down_id=one_qubit_calib.cooling_down_id,
+ label=one_qubit_calib.label,
+ status=one_qubit_calib.status,
+ node_info=one_qubit_calib.node_info,
+ one_qubit_calib_data=one_qubit_calib.one_qubit_calib_data,
+ created_at=one_qubit_calib.created_at,
+ updated_at=one_qubit_calib.updated_at,
+ )
+ )
+ return one_qubit_calib_resp
+
+
+# @router.put(
+# "/calibrations/latest/one_qubit",
+# summary="Updates a one qubit calibration.",
+# operation_id="update_all_latest_one_qubit_calib",
+# )
+# def update_all_latest_one_qubit_calib(request: OneQubitCalibCWInfo):
+# logger.info(request.model_dump())
+
+
+@router.put(
+ "/calibrations/latest/one_qubit/cw_info",
+ response_model=SuccessResponse,
+ summary="Updates a one qubit calibration CW info.",
+ operation_id="update_all_latest_one_qubit_calib_cw_info",
+)
+def update_all_latest_one_qubit_calib_cw_info(
+ request: OneQubitCalibCWInfo,
+) -> SuccessResponse:
+ logger.info(request.model_dump())
+ qpu_name = QPUModel.get_active_qpu_name()
+ cw_info_dict = request.cw_info.model_dump()
+ for label, cw_info in cw_info_dict.items():
+ one_qubit_calib = OneQubitCalibModel.find_one(
+ OneQubitCalibModel.qpu_name == qpu_name, OneQubitCalibModel.label == label
+ ).run()
+ if one_qubit_calib is None:
+ raise
+ one_qubit_calib.one_qubit_calib_data.cavity_dressed_frequency_cw = cw_info[
+ "cavity_dressed_frequency_cw"
+ ]
+ one_qubit_calib.one_qubit_calib_data.qubit_frequency_cw = cw_info[
+ "qubit_frequency_cw"
+ ]
+ one_qubit_calib.save()
+ return SuccessResponse(message="Successfully updated CW info")
+
+
+@router.get(
+ "/calibrations/latest/two_qubit",
+ response_model=list[TwoQubitCalibResponse],
+ summary="Fetches all the latest two qubit calibrations.",
+ operation_id="fetch_all_latest_two_qubit_calib",
+)
+def fetch_all_latest_two_qubit_calib() -> list[TwoQubitCalibResponse]:
+ """
+ Fetches all the latest two qubit calibrations.
+
+ Returns:
+ list: A list of TwoQubitCalibResponse objects representing the latest two qubit calibrations.
+ """
+ qpu_name = QPUModel.get_active_qpu_name()
+ # two_qubit_calib_list = TwoQubitCalibModel.find_all().to_list()
+ two_qubit_calib_list = TwoQubitCalibModel.find(
+ TwoQubitCalibModel.qpu_name == qpu_name
+ ).run()
+ if two_qubit_calib_list is None:
+ return list[TwoQubitCalibResponse]
+ two_qubit_calib_resp = []
+ for two_qubit_calib in two_qubit_calib_list:
+ two_qubit_calib_resp.append(
+ TwoQubitCalibResponse(
+ qpu_name=two_qubit_calib.qpu_name,
+ cooling_down_id=two_qubit_calib.cooling_down_id,
+ label=two_qubit_calib.label,
+ status=two_qubit_calib.status,
+ edge_info=two_qubit_calib.edge_info,
+ two_qubit_calib_data=two_qubit_calib.two_qubit_calib_data,
+ created_at=two_qubit_calib.created_at,
+ updated_at=two_qubit_calib.updated_at,
+ )
+ )
+ return two_qubit_calib_resp
+
+
+@router.get(
+ "/calibrations/history/one_qubit/{label}",
+ response_model=list[OneQubitCalibHistoryResponse],
+ summary="Fetches the calibration history for a specific one-qubit calibration by its label.",
+ operation_id="fetch_one_qubit_calib_history_by_label",
+)
+def fetch_one_qubit_calib_history_by_label(label: str):
+ """
+ Fetches the calibration history for a specific one-qubit calibration by its ID.
+
+ Args:
+ id (str): The ID of the one-qubit calibration.
+
+ Returns:
+ list[OneQubitCalibHistoryResponse]: A list of OneQubitCalibHistoryResponse objects representing the calibration history.
+ """
+ one_qubit_calib_histories = (
+ OneQubitCalibHistoryModel.find(OneQubitCalibHistoryModel.label == label)
+ .sort("date")
+ .to_list()
+ )
+ if one_qubit_calib_histories is None:
+ return list[OneQubitCalibHistoryResponse]
+ one_qubit_calib_histories_resp = []
+ for one_qubit_calib_history in one_qubit_calib_histories:
+ one_qubit_calib_histories_resp.append(
+ OneQubitCalibHistoryResponse(
+ qpu_name=one_qubit_calib_history.qpu_name,
+ cooling_down_id=one_qubit_calib_history.cooling_down_id,
+ label=one_qubit_calib_history.label,
+ date=one_qubit_calib_history.date,
+ one_qubit_calib_data=one_qubit_calib_history.one_qubit_calib_data,
+ created_at=one_qubit_calib_history.created_at,
+ updated_at=one_qubit_calib_history.updated_at,
+ )
+ )
+ return one_qubit_calib_histories_resp
+
+
+@router.get(
+ "/calibrations/history/two_qubit/{label}",
+ response_model=list[TwoQubitCalibHistoryResponse],
+ summary="Fetches the calibration history for a specific two-qubit calibration by its label.",
+ operation_id="fetch_two_qubit_calib_history_by_label",
+)
+def fetch_two_qubit_calib_history_by_label(
+ label: str,
+) -> list[TwoQubitCalibHistoryResponse]:
+ two_qubit_calib_histories = (
+ TwoQubitCalibHistoryModel.find(TwoQubitCalibHistoryModel.label == label)
+ .sort("date")
+ .to_list()
+ )
+ if two_qubit_calib_histories is None:
+ return list[TwoQubitCalibHistoryResponse]
+ two_qubit_calib_histories_resp = []
+ for two_qubit_calib_history in two_qubit_calib_histories:
+ two_qubit_calib_histories_resp.append(
+ TwoQubitCalibHistoryResponse(
+ qpu_name=two_qubit_calib_history.qpu_name,
+ cooling_down_id=two_qubit_calib_history.cooling_down_id,
+ label=two_qubit_calib_history.label,
+ date=two_qubit_calib_history.date,
+ two_qubit_calib_data=two_qubit_calib_history.two_qubit_calib_data,
+ created_at=two_qubit_calib_history.created_at,
+ updated_at=two_qubit_calib_history.updated_at,
+ )
+ )
+ return two_qubit_calib_histories_resp
+
+
+@router.get(
+ "/calibrations/one_qubit/summary",
+ response_model=list[OneQubitCalibDailySummaryResponse],
+ summary="Fetches all the one qubit calibration summaries.",
+ operation_id="fetch_all_one_qubit_calib_summary",
+)
+def fetch_all_one_qubit_calib_summary() -> list[OneQubitCalibDailySummaryResponse]:
+ one_qubit_daily_summaries = (
+ OneQubitCalibDailySummaryModel.find_all()
+ .sort(-OneQubitCalibDailySummaryModel.date)
+ .to_list()
+ )
+ if one_qubit_daily_summaries is None:
+ return list[OneQubitCalibDailySummaryResponse]
+ one_qubit_daily_summaries_resp = []
+ for one_qubit_daily_summary in one_qubit_daily_summaries:
+ one_qubit_daily_summaries_resp.append(
+ OneQubitCalibDailySummaryResponse(
+ date=one_qubit_daily_summary.date,
+ labels=one_qubit_daily_summary.labels,
+ qpu_name=one_qubit_daily_summary.qpu_name,
+ cooling_down_id=one_qubit_daily_summary.cooling_down_id,
+ summary=one_qubit_daily_summary.summary,
+ note=one_qubit_daily_summary.note,
+ )
+ )
+ return one_qubit_daily_summaries_resp
+
+
+@router.get(
+ "/calibrations/two_qubit/summary",
+ response_model=list[TwoQubitCalibDailySummaryResponse],
+ summary="Fetches all the two qubit calibration summaries.",
+ operation_id="fetch_all_two_qubit_calib_summary",
+)
+def fetch_all_two_qubit_calib_summary_by_date() -> (
+ list[TwoQubitCalibDailySummaryResponse]
+):
+ two_qubit_daily_summaries = (
+ TwoQubitCalibDailySummaryModel.find_all()
+ .sort(-TwoQubitCalibDailySummaryModel.date)
+ .to_list()
+ )
+ if two_qubit_daily_summaries is None:
+ return list[TwoQubitCalibDailySummaryResponse]
+ two_qubit_daily_summaries_resp = []
+ for two_qubit_daily_summary in two_qubit_daily_summaries:
+ two_qubit_daily_summaries_resp.append(
+ TwoQubitCalibDailySummaryResponse(
+ date=two_qubit_daily_summary.date,
+ labels=two_qubit_daily_summary.labels,
+ qpu_name=two_qubit_daily_summary.qpu_name,
+ cooling_down_id=two_qubit_daily_summary.cooling_down_id,
+ summary=two_qubit_daily_summary.summary,
+ note=two_qubit_daily_summary.note,
+ )
+ )
+ return two_qubit_daily_summaries_resp
+
+
+@router.get(
+ "/calibrations/one_qubit/summary/{date}",
+ response_model=OneQubitCalibDailySummaryResponse,
+ responses={404: {"model": Detail}},
+ summary="Fetches a one qubit calibration summary by its date.",
+ operation_id="fetch_one_qubit_calib_summary_by_date",
+)
+def fetch_one_qubit_calib_summary_by_date(
+ date: str,
+ field: Optional[str] = None,
+) -> OneQubitCalibDailySummaryResponse | NotFoundErrorResponse:
+ one_qubit_daily_summary = OneQubitCalibDailySummaryModel.find_one(
+ OneQubitCalibDailySummaryModel.date == date
+ ).run()
+ if one_qubit_daily_summary is None:
+ return NotFoundErrorResponse(
+ detail=f"one qubit calibration summary for date {date} not found"
+ )
+ if field == "value":
+ one_qubit_daily_summary.simplify()
+ return OneQubitCalibDailySummaryResponse(
+ date=one_qubit_daily_summary.date,
+ labels=one_qubit_daily_summary.labels,
+ qpu_name=one_qubit_daily_summary.qpu_name,
+ cooling_down_id=one_qubit_daily_summary.cooling_down_id,
+ summary=one_qubit_daily_summary.summary,
+ note=one_qubit_daily_summary.note,
+ )
+
+
+@router.get(
+ "/calibrations/two_qubit/summary/{date}",
+ response_model=TwoQubitCalibDailySummaryResponse,
+ responses={404: {"model": Detail}},
+ summary="Fetches a two qubit calibration summary by its date.",
+ operation_id="fetch_two_qubit_calib_summary_by_date",
+)
+def fetch_two_qubit_calib_summary_by_date(
+ date: str,
+) -> TwoQubitCalibDailySummaryResponse | NotFoundErrorResponse:
+ two_qubit_daily_summary = TwoQubitCalibDailySummaryModel.find_one(
+ TwoQubitCalibDailySummaryModel.date == date
+ ).run()
+ if two_qubit_daily_summary is None:
+ return NotFoundErrorResponse(
+ detail=f"two qubit calibration summary for date {date} not found"
+ )
+ return TwoQubitCalibDailySummaryResponse(
+ date=two_qubit_daily_summary.date,
+ labels=two_qubit_daily_summary.labels,
+ qpu_name=two_qubit_daily_summary.qpu_name,
+ cooling_down_id=two_qubit_daily_summary.cooling_down_id,
+ summary=two_qubit_daily_summary.summary,
+ note=two_qubit_daily_summary.note,
+ )
+
+
+@router.patch(
+ "/calibrations/one_qubit/summary/{date}",
+ response_model=OneQubitCalibDailySummaryResponse,
+ summary="Updates a one qubit calibration summary by its date.",
+ operation_id="update_one_qubit_calib_summary_by_date",
+)
+def update_one_qubit_calib_summary_by_date(
+ date: str, request: OneQubitCalibDailySummaryRequest
+) -> OneQubitCalibDailySummaryResponse | NotFoundErrorResponse:
+ one_qubit_daily_summary = OneQubitCalibDailySummaryModel.find_one(
+ OneQubitCalibDailySummaryModel.date == date
+ ).run()
+ if one_qubit_daily_summary is None:
+ return NotFoundErrorResponse(
+ detail=f"one qubit calibration summary for date {date} not found"
+ )
+ one_qubit_daily_summary.note = request.note
+ one_qubit_daily_summary.save()
+ return OneQubitCalibDailySummaryResponse(
+ date=one_qubit_daily_summary.date,
+ labels=one_qubit_daily_summary.labels,
+ qpu_name=one_qubit_daily_summary.qpu_name,
+ cooling_down_id=one_qubit_daily_summary.cooling_down_id,
+ summary=one_qubit_daily_summary.summary,
+ note=one_qubit_daily_summary.note,
+ )
+
+
+@router.patch(
+ "/calibrations/two_qubit/summary/{date}",
+ response_model=TwoQubitCalibDailySummaryModel,
+ responses={404: {"model": Detail}},
+ summary="Updates a two qubit calibration summary by its date.",
+ operation_id="update_two_qubit_calib_summary_by_date",
+)
+def update_two_qubit_calib_summary_by_date(
+ date: str, request: TwoQubitCalibDailySummaryRequest
+) -> TwoQubitCalibDailySummaryResponse | NotFoundErrorResponse:
+ two_qubit_daily_summary = TwoQubitCalibDailySummaryModel.find_one(
+ TwoQubitCalibDailySummaryModel.date == date
+ ).run()
+ if two_qubit_daily_summary is None:
+ return NotFoundErrorResponse(
+ detail=f"two qubit calibration summary for date {date} not found"
+ )
+ two_qubit_daily_summary.note = request.note
+ two_qubit_daily_summary.save()
+ return TwoQubitCalibDailySummaryResponse(
+ date=two_qubit_daily_summary.date,
+ labels=two_qubit_daily_summary.labels,
+ qpu_name=two_qubit_daily_summary.qpu_name,
+ cooling_down_id=two_qubit_daily_summary.cooling_down_id,
+ summary=two_qubit_daily_summary.summary,
+ note=two_qubit_daily_summary.note,
+ )
+
+
+@router.get(
+ "/calibrations/figure/{date}/{qubit}/{path}/{exp}",
+ responses={404: {"model": Detail}},
+ summary="Fetches a calibration figure by its date, qubit, and experiment.",
+ operation_id="fetch_calib_figure_by_date",
+)
+def fetch_calib_figure_by_date(date: str, qubit: str, path: str, exp: str):
+ def construct_file_paths(date: str, qubit: str, path: str, exp: str) -> list:
+ import os
+
+ calib_data_path = os.getenv("CALIB_DATA_PATH")
+ base_path = f"{calib_data_path}/{date}/{path}"
+ file_paths = [f"{base_path}/{qubit}_{exp}.png"]
+
+ # If qubit is composed of multiple parts, generate reversed order path
+ if "_" in qubit:
+ qubit_parts = qubit.split("_")
+ qubit_reversed = "_".join(sorted(qubit_parts, reverse=True))
+ file_paths.append(f"{base_path}/{qubit_reversed}_{exp}.png")
+
+ return file_paths
+
+ def find_existing_file(file_paths: list[str]) -> str:
+ for file_path in file_paths:
+ if os.path.exists(file_path):
+ return file_path
+ return ""
+
+ # Construct potential file paths
+ file_paths = construct_file_paths(date, qubit, path, exp)
+ # Find the first existing file
+ file_path = find_existing_file(file_paths)
+
+ if not file_path:
+ # If no file is found, raise a 404 error
+ raise HTTPException(
+ status_code=404,
+ detail=f"Figure for date {date}, qubit {qubit}, and experiment {exp} not found",
+ )
+
+ # Read and return the file
+ with open(file_path, "rb") as file:
+ image_data = file.read()
+
+ return StreamingResponse(BytesIO(image_data), media_type="image/png")
+
+
+@router.post(
+ "/calibrations/stats/one_qubit",
+ summary="Fetches one qubit calibration stats for dashboard plots.",
+ response_model=list[OneQubitCalibStatsResponse],
+ operation_id="fetch_one_qubit_calib_stats",
+)
+def fetch_one_qubit_calib_stats(
+ request: OneQubitCalibStatsRequest,
+) -> list[OneQubitCalibStatsResponse]:
+ """
+ Fetches one qubit calibration statistics for generating dashboard plots.
+
+ Args:
+ request (OneQubitCalibStatsRequest): The request object containing the labels.
+
+ Returns:
+ list: A list of dictionaries representing the calibration statistics for each date.
+ """
+ # from typing import Any
+
+ # result_dict: dict[str, dict[str, Any]] = {}
+ res: dict[str, OneQubitCalibStatsResponse] = {}
+ for label in request.labels:
+ one_qubit_calib_histories = (
+ OneQubitCalibHistoryModel.find(OneQubitCalibHistoryModel.label == label)
+ .sort("date")
+ .to_list()
+ )
+
+ if one_qubit_calib_histories is None:
+ return []
+
+ for one_qubit_calib in one_qubit_calib_histories:
+ if one_qubit_calib.one_qubit_calib_data:
+ one_qubit_calib.one_qubit_calib_data.simplify()
+ if one_qubit_calib.date not in res:
+ res[one_qubit_calib.date] = OneQubitCalibStatsResponse(
+ date=one_qubit_calib.date
+ )
+
+ res[one_qubit_calib.date].add_stats(
+ one_qubit_calib.label, one_qubit_calib.one_qubit_calib_data
+ )
+
+ response_list = list(res.values())
+
+ # Simplify the response list
+ for response in response_list:
+ response.simplify()
+
+ return response_list
+
+ # result = list(result_dict.values())
+
+ # for r in result:
+ # # print(r)
+ # # print(r["date"])
+ # print(r.
+ # return res
+
+
+@router.post(
+ "/calibrations/stats/two_qubit",
+ summary="Fetches two qubit calibration stats for dashboard plots.",
+ response_model=list[TwoQubitCalibStatsResponse],
+ operation_id="fetch_two_qubit_calib_stats",
+)
+def fetch_two_qubit_calib_stats(
+ request: TwoQubitCalibStatsRequest,
+) -> list[TwoQubitCalibStatsResponse]:
+ """
+ Fetches two qubit calibration statistics for generating dashboard plots.
+
+ Args:
+ request (TwoQubitCalibStatsRequest): The request object containing the labels.
+
+ Returns:
+ list: A list of dictionaries representing the calibration statistics for each date.
+ """
+
+ res: dict[str, TwoQubitCalibStatsResponse] = {}
+ for label in request.labels:
+ two_qubit_calib_histories = (
+ TwoQubitCalibHistoryModel.find(TwoQubitCalibHistoryModel.label == label)
+ .sort("date")
+ .to_list()
+ )
+
+ if two_qubit_calib_histories is None:
+ return []
+
+ for two_qubit_calib in two_qubit_calib_histories:
+ if two_qubit_calib.two_qubit_calib_data:
+ two_qubit_calib.two_qubit_calib_data.simplify()
+ if two_qubit_calib.date not in res:
+ res[two_qubit_calib.date] = TwoQubitCalibStatsResponse(
+ date=two_qubit_calib.date
+ )
+
+ res[two_qubit_calib.date].add_stats(
+ two_qubit_calib.label, two_qubit_calib.two_qubit_calib_data
+ )
+
+ response_list = list(res.values())
+
+ # Simplify the response list
+ for response in response_list:
+ response.simplify()
+
+ return response_list
diff --git a/backend/server/routers/execution.py b/backend/server/routers/execution.py
new file mode 100644
index 0000000..a9eb477
--- /dev/null
+++ b/backend/server/routers/execution.py
@@ -0,0 +1,188 @@
+import logging
+from io import BytesIO
+from typing import Optional
+
+from dbmodel.execution_lock import ExecutionLockModel
+from dbmodel.execution_run_history import ExecutionRunHistoryModel
+from dbmodel.experiment_history import ExperimentHistoryModel
+from fastapi import APIRouter, Query
+from fastapi.logger import logger
+from fastapi.responses import StreamingResponse
+from pydantic import BaseModel, Field
+from pymongo import DESCENDING
+from server.schemas.error import (
+ Detail,
+)
+
+router = APIRouter()
+gunicorn_logger = logging.getLogger("gunicorn.error")
+logger.handlers = gunicorn_logger.handlers
+if __name__ != "main":
+ logger.setLevel(gunicorn_logger.level)
+else:
+ logger.setLevel(logging.DEBUG)
+
+
+class ResponseModel(BaseModel):
+ message: str
+
+
+class ExecutionResponse(BaseModel):
+ experiment_name: str
+ label: str
+ status: Optional[str] = Field(None)
+ timestamp: str
+ input_parameter: Optional[dict] = Field(None)
+ output_parameter: Optional[dict] = Field(None)
+ fig_path: Optional[str] = Field(None)
+
+
+class ExecutionRunResponse(BaseModel):
+ timestamp: str
+ date: str
+ status: Optional[str] = Field(None)
+ execution_id: str
+ menu: dict
+ tags: Optional[list[str]] = Field(None)
+ qpu_name: Optional[str] = Field(None)
+ fridge_temperature: Optional[float] = Field(None)
+ flow_url: Optional[str] = Field(None)
+
+
+@router.get(
+ "/executions",
+ response_model=list[ExecutionRunResponse],
+ summary="Fetch all executions",
+ operation_id="fetch_all_executions",
+)
+def fetch_all_executions():
+ execution_runs = ExecutionRunHistoryModel.find(sort=[("timestamp", DESCENDING)])
+ return [
+ ExecutionRunResponse(
+ timestamp=execution_run.timestamp.strftime("%Y-%m-%d %H:%M:%S"),
+ date=execution_run.date,
+ status=execution_run.status,
+ execution_id=execution_run.execution_id,
+ tags=execution_run.tags,
+ menu=execution_run.menu,
+ qpu_name=execution_run.qpu_name,
+ fridge_temperature=execution_run.fridge_temperature,
+ flow_url=execution_run.flow_url,
+ )
+ for execution_run in execution_runs
+ ]
+
+
+@router.get(
+ "/executions/{execution_id}/experiments",
+ response_model=list[ExecutionResponse],
+ summary="Fetch an execution by its ID",
+ operation_id="fetch_experiments_by_id",
+)
+def fetch_experiments_by_id(execution_id: str):
+ executions = ExperimentHistoryModel.find({"execution_id": execution_id})
+ return [
+ ExecutionResponse(
+ experiment_name=execution.experiment_name,
+ label=execution.label,
+ status=execution.status,
+ input_parameter=execution.input_parameter,
+ output_parameter=execution.output_parameter,
+ timestamp=execution.timestamp.strftime("%Y-%m-%d %H:%M:%S"),
+ fig_path=execution.fig_path,
+ )
+ for execution in executions
+ ]
+
+
+@router.post(
+ "/executions/{execution_id}/tags",
+ summary="Add tags to an execution",
+ operation_id="add_execution_tags",
+)
+def add_execution_tags(execution_id: str, tags: list[str]):
+ execution_run_history = ExecutionRunHistoryModel.get_by_execution_id(execution_id)
+ execution_run_history.add_tags(tags)
+
+
+@router.delete(
+ "/executions/{execution_id}/tags",
+ summary="Remove tags from an execution",
+ operation_id="remove_execution_tags",
+)
+def remove_execution_tags(execution_id: str, tags: list[str]):
+ execution_run_history = ExecutionRunHistoryModel.get_by_execution_id(execution_id)
+ execution_run_history.remove_tags(tags)
+
+
+@router.get(
+ "/executions/experiments",
+ response_model=list[ExecutionResponse],
+ summary="Fetch all executions",
+ operation_id="fetch_all_executions_experiments",
+)
+def fetch_all_executions_experiments(
+ label: Optional[list[str]] = Query(None, alias="label[]"),
+ experiment_name: Optional[list[str]] = Query(None, alias="experiment_name[]"),
+ execution_id: Optional[list[str]] = Query(None, alias="execution_id[]"),
+):
+ query = {"$and": []}
+ if label:
+ query["$and"].append({"$or": [{"label": la} for la in label]})
+ if experiment_name:
+ query["$and"].append(
+ {"$or": [{"experiment_name": en} for en in experiment_name]}
+ )
+ if execution_id:
+ query["$and"].append({"$or": [{"execution_id": eid} for eid in execution_id]})
+ logger.info(f"Query: {query}")
+ logger.info(f"label: {label}")
+ logger.info(f"experiment_name: {experiment_name}")
+ logger.info(f"execution_id: {execution_id}")
+
+ if not query["$and"]:
+ query = {}
+
+ executions = ExperimentHistoryModel.find(query, sort=[("timestamp", DESCENDING)])
+ return [
+ ExecutionResponse(
+ experiment_name=execution.experiment_name,
+ label=execution.label,
+ status=execution.status,
+ timestamp=execution.timestamp.strftime("%Y-%m-%d %H:%M:%S"),
+ input_parameter=execution.input_parameter,
+ output_parameter=execution.output_parameter,
+ fig_path=execution.fig_path,
+ )
+ for execution in executions
+ ]
+
+
+@router.get(
+ "/executions/figure",
+ responses={404: {"model": Detail}},
+ response_class=StreamingResponse,
+ summary="Fetches a calibration figure by its path",
+ operation_id="fetch_figure_by_path",
+)
+def fetch_figure_by_path(path: str):
+ with open(path, "rb") as file:
+ image_data = file.read()
+ return StreamingResponse(BytesIO(image_data), media_type="image/png")
+
+
+class ExecutionLockStatusResponse(BaseModel):
+ lock: bool
+
+
+@router.get(
+ "/executions/lock_status",
+ summary="Fetches the status of a calibration.",
+ operation_id="fetch_execution_lock_status",
+ response_model=ExecutionLockStatusResponse,
+)
+def fetch_execution_lock_status():
+ status = ExecutionLockModel.find_one().run()
+ if status is None:
+ return ExecutionLockStatusResponse(lock=False)
+ return ExecutionLockStatusResponse(lock=status.lock)
diff --git a/backend/server/routers/experiment.py b/backend/server/routers/experiment.py
new file mode 100644
index 0000000..48dfff5
--- /dev/null
+++ b/backend/server/routers/experiment.py
@@ -0,0 +1,27 @@
+from dbmodel.experiment import ExperimentModel
+from fastapi import APIRouter
+from pydantic import BaseModel
+
+router = APIRouter()
+
+
+class ExperimentResponse(BaseModel):
+ experiment_name: str
+ updated_at: str
+
+
+@router.get(
+ "/experiments",
+ response_model=list[ExperimentResponse],
+ summary="Fetch all experiments",
+ operation_id="fetch_all_experiment",
+)
+def fetch_all_experiment():
+ experiments = ExperimentModel.find_all()
+ return [
+ ExperimentResponse(
+ experiment_name=exp.experiment_name,
+ updated_at=exp.updated_at.strftime("%Y-%m-%d %H:%M:%S"),
+ )
+ for exp in experiments
+ ]
diff --git a/backend/server/routers/fridges.py b/backend/server/routers/fridges.py
new file mode 100644
index 0000000..2e2bd83
--- /dev/null
+++ b/backend/server/routers/fridges.py
@@ -0,0 +1,57 @@
+import logging
+from datetime import datetime, timedelta
+
+import pytz
+from dbmodel.bluefors import BlueforsModel
+from fastapi import APIRouter
+from fastapi.logger import logger
+from pydantic import BaseModel
+
+router = APIRouter()
+
+
+# class ResponseModel(BaseModel):
+# message: str
+
+
+gunicorn_logger = logging.getLogger("gunicorn.error")
+logger.handlers = gunicorn_logger.handlers
+
+
+# @router.get("/fridges/", response_model=ResponseModel)
+# def health():
+# return {"message": "Hello World"}
+
+
+class ListAllFridgeResponse(BaseModel):
+ device_id: str
+
+
+@router.get("/fridges/", response_model=ListAllFridgeResponse)
+def list_all_fridges():
+ return {"device_id": "XLD"}
+
+
+class ListFridgeResponse(BaseModel):
+ timestamp: datetime
+ temperature: float
+
+
+@router.get("/fridges/XLD/channels/{channel}", response_model=list[ListFridgeResponse])
+def get_fridge_temperature(channel: int, h: float = 12.0):
+ time = datetime.now() - timedelta(hours=h)
+ jst = pytz.timezone("Asia/Tokyo")
+ history = (
+ BlueforsModel.find(
+ BlueforsModel.channel_nr == channel, BlueforsModel.timestamp > time
+ )
+ .sort([BlueforsModel.timestamp])
+ .project(ListFridgeResponse)
+ .to_list()
+ )
+ # 温度を小数点4桁にフォーマット
+ for record in history:
+ record.timestamp = record.timestamp.astimezone(jst)
+ record.temperature = round(record.temperature, 4)
+
+ return history
diff --git a/backend/server/routers/menu.py b/backend/server/routers/menu.py
new file mode 100644
index 0000000..55c382e
--- /dev/null
+++ b/backend/server/routers/menu.py
@@ -0,0 +1,193 @@
+from logging import getLogger
+
+from dbmodel.menu import MenuModel
+from fastapi import APIRouter
+from server.schemas.error import (
+ Detail,
+ NotFoundErrorResponse,
+)
+from server.schemas.exception import InternalSeverError
+from server.schemas.menu import (
+ CreateMenuRequest,
+ CreateMenuResponse,
+ DeleteMenuResponse,
+ GetMenuResponse,
+ ListMenuResponse,
+ UpdateMenuRequest,
+ UpdateMenuResponse,
+)
+
+router = APIRouter()
+logger = getLogger("uvicorn.app")
+
+
+@router.get(
+ "/menu",
+ response_model=list[ListMenuResponse],
+ summary="Retrieve a list of menu items.",
+ operation_id="list_menu",
+)
+def list_menu() -> list[ListMenuResponse]:
+ """
+ Retrieve a list of menu items.
+
+ Returns:
+ ListMenuResponse: A response containing the list of menu items.
+ """
+ try:
+ menu_list = MenuModel.find_all().to_list()
+ except Exception as e:
+ logger.error(f"Failed to list menu: {e}")
+ raise InternalSeverError(detail=f"Failed to list menu: {str(e)}")
+ if menu_list is None:
+ return list[ListMenuResponse]
+ menu_list_response = []
+ for menu in menu_list:
+ menu_list_response.append(
+ ListMenuResponse(
+ name=menu.name,
+ description=menu.description,
+ one_qubit_calib_plan=menu.one_qubit_calib_plan,
+ two_qubit_calib_plan=menu.two_qubit_calib_plan,
+ mode=menu.mode,
+ notify_bool=menu.notify_bool,
+ flow=menu.flow,
+ exp_list=menu.exp_list,
+ tags=menu.tags,
+ )
+ )
+ return menu_list_response
+
+
+@router.post(
+ "/menu",
+ response_model=CreateMenuResponse,
+ summary="Create a new menu item.",
+ operation_id="create_menu",
+)
+def create_menu(request: CreateMenuRequest) -> CreateMenuResponse:
+ """
+ Create a new menu item.
+
+ Args:
+ request (CreateMenuRequest): The request object containing the menu item details.
+
+ Returns:
+ CreateMenuResponse: The response object containing the ID of the created menu item.
+ """
+ menu_model = MenuModel(**request.model_dump())
+ try:
+ menu_model.save()
+ except Exception as e:
+ logger.error(f"Failed to save menu: {e}")
+ raise InternalSeverError(detail=f"Failed to save menu: {str(e)}")
+ return CreateMenuResponse(name=menu_model.name)
+
+
+@router.delete(
+ "/menu/{name}",
+ response_model=DeleteMenuResponse,
+ responses={404: {"model": Detail}},
+ summary="Delete a menu by its name.",
+ operation_id="delete_menu",
+)
+def deleteMenu(name: str) -> DeleteMenuResponse | NotFoundErrorResponse:
+ """
+ Delete a menu by its name.
+
+ Args:
+ name (str): The name of the menu to be deleted.
+
+ Returns:
+ DeleteMenuResponse | NotFoundErrorResponse: The response indicating the success or failure of the deletion.
+
+ Raises:
+ None
+
+ """
+ existing_menu = MenuModel.find_one(MenuModel.name == name).run()
+ if existing_menu is not None:
+ existing_menu.delete()
+ return DeleteMenuResponse(name=existing_menu.name)
+ else:
+ logger.warn(f"menu not found: {name}")
+ return NotFoundErrorResponse(detail=f"menu not found: {name}")
+
+
+@router.put(
+ "/menu/{name}",
+ response_model=UpdateMenuResponse,
+ responses={404: {"model": Detail}},
+ summary="Update a menu with the given name.",
+ operation_id="update_menu",
+)
+def updateMenu(
+ name: str, req: UpdateMenuRequest
+) -> UpdateMenuResponse | NotFoundErrorResponse:
+ """
+ Update a menu with the given name.
+
+ Args:
+ id (str): The name of the menu to update.
+ req (UpdateMenuRequest): The request object containing the updated menu data.
+
+ Returns:
+ Union[UpdateMenuResponse, NotFoundErrorResponse]: The response object indicating the success of the update or an error if the menu is not found.
+ """
+ existing_menu = MenuModel.find_one(MenuModel.name == name).run()
+ if existing_menu:
+ existing_menu.name = req.name
+ existing_menu.description = req.description
+ existing_menu.one_qubit_calib_plan = req.one_qubit_calib_plan
+ existing_menu.two_qubit_calib_plan = req.two_qubit_calib_plan
+ existing_menu.mode = req.mode
+ existing_menu.notify_bool = req.notify_bool
+ existing_menu.flow = req.flow
+ existing_menu.tags = req.tags
+ existing_menu.exp_list = req.exp_list
+ existing_menu.save()
+ return UpdateMenuResponse(name=existing_menu.name)
+ else:
+ logger.warn(f"menu not found: {name}")
+ return NotFoundErrorResponse(detail=f"menu not found: {name}")
+
+
+@router.get(
+ "/menu/{name}",
+ response_model=GetMenuResponse,
+ summary="Retrieve a menu by its name.",
+ responses={404: {"model": Detail}},
+ operation_id="get_menu_by_name",
+)
+def get_menu_by_name(name: str) -> GetMenuResponse | NotFoundErrorResponse:
+ """
+ Retrieve a menu by its name.
+
+ Args:
+ name (str): The name of the menu.
+
+ Returns:
+ GetMenuResponse: The response containing the menu details.
+
+ Raises:
+ InternalServerError: If there is an error retrieving the menu.
+ NotFoundErrorResponse: If the menu is not found.
+ """
+ try:
+ menu = MenuModel.find_one(MenuModel.name == name).run()
+ except Exception as e:
+ logger.error(f"Failed to get menu: {e}")
+ raise InternalSeverError(detail=f"Failed to get menu: {str(e)}")
+ if menu is None:
+ return NotFoundErrorResponse(detail=f"menu not found: {name}")
+ return GetMenuResponse(
+ name=menu.name,
+ description=menu.description,
+ one_qubit_calib_plan=menu.one_qubit_calib_plan,
+ two_qubit_calib_plan=menu.two_qubit_calib_plan,
+ mode=menu.mode,
+ notify_bool=menu.notify_bool,
+ flow=menu.flow,
+ exp_list=menu.exp_list,
+ tags=menu.tags,
+ )
diff --git a/backend/server/routers/qpu.py b/backend/server/routers/qpu.py
new file mode 100644
index 0000000..51e6953
--- /dev/null
+++ b/backend/server/routers/qpu.py
@@ -0,0 +1,601 @@
+import os
+from collections import defaultdict
+from io import BytesIO
+from logging import getLogger
+from typing import Annotated, Any, List, Optional
+
+import matplotlib as mpl
+import numpy as np
+from dbmodel.execution_run_history import ExecutionRunHistoryModel
+from dbmodel.one_qubit_calib import OneQubitCalibData, OneQubitCalibModel
+from dbmodel.one_qubit_calib_all_history import OneQubitCalibAllHistoryModel
+from dbmodel.qpu import QPUModel
+from dbmodel.two_qubit_calib import TwoQubitCalibModel
+from fastapi import APIRouter, Depends, Query
+from fastapi.responses import StreamingResponse
+from matplotlib import pyplot as plt
+from pydantic import BaseModel, Field
+from pymongo import DESCENDING
+from server.config import Settings, get_settings
+from server.routers.execution import ExecutionRunResponse
+from server.schemas.calibration import OneQubitCalibResponse, TwoQubitCalibResponse
+from server.schemas.error import (
+ Detail,
+)
+
+router = APIRouter()
+logger = getLogger("uvicorn.app")
+
+
+class QPUInfoResponse(BaseModel):
+ name: str
+ nodes: list[str]
+ edges: list[str]
+ active: bool
+
+
+@router.get(
+ "/qpu/figure",
+ responses={404: {"model": Detail}},
+ response_class=StreamingResponse,
+ summary="Fetches a calibration figure by its path",
+ operation_id="fetch_qpu_figure_by_path",
+)
+def fetch_qpu_figure_by_path(path: str):
+ with open(path, "rb") as file:
+ image_data = file.read()
+ return StreamingResponse(BytesIO(image_data), media_type="image/png")
+
+
+@router.get(
+ "/qpu/info/{name}",
+ response_model=QPUInfoResponse,
+ operation_id="fetch_qpu_info",
+)
+def fetchQPUInfo(name: str):
+ name = "AIST13th#14(1,0)"
+ logger.warn(name)
+ resp = QPUModel.find_one(QPUModel.name == name).run()
+ logger.warn(resp)
+ if resp is not None:
+ return QPUInfoResponse(
+ name=resp.name, nodes=resp.nodes, edges=resp.edges, active=resp.active
+ )
+
+
+@router.get(
+ "/qpu",
+ response_model=list[QPUInfoResponse],
+ operation_id="list_qpu",
+)
+def list_qpu():
+ resp = QPUModel.find_all(sort=[("installed_at", DESCENDING)]).run()
+ return [
+ QPUInfoResponse(
+ name=resp.name, nodes=resp.nodes, edges=resp.edges, active=resp.active
+ )
+ for resp in resp
+ ]
+
+
+@router.get(
+ "/qpu/active",
+ response_model=QPUInfoResponse,
+ operation_id="fetch_active_qpu",
+)
+def fetch_active_qpu():
+ resp = QPUModel.find_one(QPUModel.active == True).run()
+ return QPUInfoResponse(
+ name=resp.name, nodes=resp.nodes, edges=resp.edges, active=resp.active
+ )
+
+
+@router.get(
+ "/qpu/{name}",
+ response_model=QPUInfoResponse,
+ operation_id="fetch_qpu",
+)
+def fetch_qpu_by_name(name: str):
+ resp = QPUModel.find_one(QPUModel.name == name).run()
+ if resp is not None:
+ return QPUInfoResponse(
+ name=resp.name, nodes=resp.nodes, edges=resp.edges, active=resp.active
+ )
+
+
+@router.get(
+ "/qpu/{name}/executions",
+ response_model=list[ExecutionRunResponse],
+ summary="Fetch all executions",
+ operation_id="fetch_all_executions_by_qpu_name",
+)
+def fetch_all_executions_by_qpu_name(name: str):
+ execution_runs = ExecutionRunHistoryModel.find(
+ ExecutionRunHistoryModel.qpu_name == name, sort=[("timestamp", DESCENDING)]
+ )
+ return [
+ ExecutionRunResponse(
+ timestamp=execution_run.timestamp.strftime("%Y-%m-%d %H:%M:%S"),
+ date=execution_run.date,
+ status=execution_run.status,
+ execution_id=execution_run.execution_id,
+ tags=execution_run.tags,
+ menu=execution_run.menu,
+ qpu_name=execution_run.qpu_name,
+ fridge_temperature=execution_run.fridge_temperature,
+ flow_url=execution_run.flow_url,
+ )
+ for execution_run in execution_runs
+ ]
+
+
+@router.get(
+ "/qpu/{name}/one_qubit_calib/nodes",
+ response_model=list[OneQubitCalibResponse],
+ operation_id="fetch_one_qubit_calib_by_qpu_name",
+)
+def fetch_one_qubit_calib_by_qpu_name(
+ name: str,
+ param_list: Optional[List[str]] = Query(None, alias="param_list[]"),
+):
+ one_qubit_calib_list = OneQubitCalibModel.find(
+ OneQubitCalibModel.qpu_name == name
+ ).run()
+ if one_qubit_calib_list is None:
+ return list[OneQubitCalibResponse]
+
+ one_qubit_calib_resp = []
+ for one_qubit_calib in one_qubit_calib_list:
+ one_qubit_calib_data = one_qubit_calib.one_qubit_calib_data
+ if param_list:
+ filtered_data = {
+ param: getattr(one_qubit_calib_data, param, None)
+ for param in param_list
+ }
+ one_qubit_calib_data = OneQubitCalibData(**filtered_data)
+ one_qubit_calib_resp.append(
+ OneQubitCalibResponse(
+ id=str(one_qubit_calib.id),
+ qpu_name=one_qubit_calib.qpu_name,
+ cooling_down_id=one_qubit_calib.cooling_down_id,
+ label=one_qubit_calib.label,
+ status=one_qubit_calib.status,
+ node_info=one_qubit_calib.node_info,
+ one_qubit_calib_data=one_qubit_calib_data,
+ created_at=one_qubit_calib.created_at,
+ updated_at=one_qubit_calib.updated_at,
+ )
+ )
+ return one_qubit_calib_resp
+
+
+@router.get(
+ "/qpu/{name}/one_qubit_calib/nodes/{label}",
+ response_model=OneQubitCalibResponse,
+ operation_id="fetch_one_qubit_calib_by_label",
+)
+def fetch_one_qubit_calib_by_label(
+ name: str,
+ label: str,
+ param_list: Optional[List[str]] = Query(None, alias="param_list[]"),
+):
+ one_qubit_calib = OneQubitCalibModel.find_one(
+ OneQubitCalibModel.qpu_name == name, OneQubitCalibModel.label == label
+ ).run()
+ if one_qubit_calib is None:
+ return OneQubitCalibResponse
+
+ one_qubit_calib_data = one_qubit_calib.one_qubit_calib_data
+ if param_list:
+ filtered_data = {
+ param: getattr(one_qubit_calib_data, param, None) for param in param_list
+ }
+ one_qubit_calib_data = OneQubitCalibData(**filtered_data)
+
+ return OneQubitCalibResponse(
+ id=str(one_qubit_calib.id),
+ qpu_name=one_qubit_calib.qpu_name,
+ cooling_down_id=one_qubit_calib.cooling_down_id,
+ label=one_qubit_calib.label,
+ status=one_qubit_calib.status,
+ node_info=one_qubit_calib.node_info,
+ one_qubit_calib_data=one_qubit_calib_data,
+ created_at=one_qubit_calib.created_at,
+ updated_at=one_qubit_calib.updated_at,
+ )
+
+
+class ParamData(BaseModel):
+ label: str
+ value: float
+ unit: Optional[str] = Field(None)
+
+
+class ParamResponse(BaseModel):
+ param_name: str
+ data: list[ParamData]
+
+
+@router.get(
+ "/qpu/{name}/one_qubit_calib/params/{param_name}",
+ response_model=ParamResponse,
+ operation_id="fetch_one_qubit_calib_by_param_name",
+)
+def fetch_one_qubit_calib_by_param_name(name: str, param_name: str):
+ one_qubit_calib = OneQubitCalibModel.find(OneQubitCalibModel.qpu_name == name).run()
+ if one_qubit_calib is None:
+ return ParamResponse
+ data = []
+ for one_qubit_calib in one_qubit_calib:
+ param = getattr(one_qubit_calib.one_qubit_calib_data, param_name, None)
+ if param is None:
+ continue
+ data.append(
+ ParamData(
+ label=one_qubit_calib.label,
+ value=param.value,
+ unit=param.unit,
+ )
+ )
+ return ParamResponse(param_name=param_name, data=data)
+
+
+# class MetricsData(BaseModel):
+
+
+class MetricsResponse(BaseModel):
+ name: str
+ # metrics: list[MetricsData]
+ data: list[dict[str, Any]]
+
+
+@router.get(
+ "/qpu/{name}/history/one_qubit_calib/{param_name}",
+ response_model=MetricsResponse,
+ operation_id="fetch_one_qubit_calib_history_by_param_name",
+)
+def fetch_one_qubit_calib_history_by_param_name(
+ name: str,
+ param_name: str,
+ tags: Optional[List[str]] = Query(None, alias="tags[]"),
+):
+ one_qubit_calibs = OneQubitCalibAllHistoryModel.find(
+ OneQubitCalibAllHistoryModel.qpu_name == name
+ ).run()
+ if one_qubit_calibs is None:
+ return MetricsResponse(name=param_name, data=[])
+
+ execution_id_map: defaultdict[str, dict[str, Any]] = defaultdict(dict)
+ for one_qubit_calib in one_qubit_calibs:
+ if (
+ tags
+ and one_qubit_calib.tags
+ and not any(tag in one_qubit_calib.tags for tag in tags)
+ ):
+ continue
+ param = getattr(one_qubit_calib.one_qubit_calib_data, param_name, None)
+ if param is None:
+ continue
+ execution_id_map[one_qubit_calib.execution_id]["event"] = (
+ one_qubit_calib.execution_id
+ )
+ execution_id_map[one_qubit_calib.execution_id][one_qubit_calib.label] = (
+ param.value
+ )
+ data = list(execution_id_map.values())
+
+ return MetricsResponse(name=param_name, data=data)
+
+
+@router.get(
+ "/qpu/{name}/two_qubit_calib/edges",
+ response_model=list[TwoQubitCalibResponse],
+ operation_id="fetch_two_qubit_calib_by_qpu_name",
+)
+def fetch_two_qubit_calib_by_qpu_name(name: str):
+ two_qubit_calib_list = TwoQubitCalibModel.find(
+ TwoQubitCalibModel.qpu_name == name
+ ).run()
+ if two_qubit_calib_list is None:
+ return list[TwoQubitCalibResponse]
+ two_qubit_calib_resp = []
+ for two_qubit_calib in two_qubit_calib_list:
+ two_qubit_calib_resp.append(
+ TwoQubitCalibResponse(
+ id=str(two_qubit_calib.id),
+ qpu_name=two_qubit_calib.qpu_name,
+ cooling_down_id=two_qubit_calib.cooling_down_id,
+ label=two_qubit_calib.label,
+ status=two_qubit_calib.status,
+ edge_info=two_qubit_calib.edge_info,
+ two_qubit_calib_data=two_qubit_calib.two_qubit_calib_data,
+ created_at=two_qubit_calib.created_at,
+ updated_at=two_qubit_calib.updated_at,
+ )
+ )
+ return two_qubit_calib_resp
+
+
+@router.get(
+ "/qpu/{name}/two_qubit_calib/edges/{label}",
+ response_model=TwoQubitCalibResponse,
+ operation_id="fetch_two_qubit_calib_by_label",
+)
+def fetch_two_qubit_calib_by_label(name: str, label: str):
+ two_qubit_calib = TwoQubitCalibModel.find_one(
+ TwoQubitCalibModel.qpu_name == name, TwoQubitCalibModel.label == label
+ ).run()
+ if two_qubit_calib is None:
+ return TwoQubitCalibResponse
+ return TwoQubitCalibResponse(
+ id=str(two_qubit_calib.id),
+ qpu_name=two_qubit_calib.qpu_name,
+ cooling_down_id=two_qubit_calib.cooling_down_id,
+ label=two_qubit_calib.label,
+ status=two_qubit_calib.status,
+ edge_info=two_qubit_calib.edge_info,
+ two_qubit_calib_data=two_qubit_calib.two_qubit_calib_data,
+ created_at=two_qubit_calib.created_at,
+ updated_at=two_qubit_calib.updated_at,
+ )
+
+
+@router.get(
+ "/qpu/{name}/two_qubit_calib/params/{param_name}",
+ response_model=ParamResponse,
+ operation_id="fetch_two_qubit_calib_by_param_name",
+)
+def fetch_two_qubit_calib_by_param_name(name: str, param_name: str):
+ two_qubit_calib = TwoQubitCalibModel.find(TwoQubitCalibModel.qpu_name == name).run()
+ if two_qubit_calib is None:
+ return ParamResponse
+ data = []
+ for two_qubit_calib in two_qubit_calib:
+ param = getattr(two_qubit_calib.two_qubit_calib_data, param_name, None)
+ if param is None:
+ continue
+ data.append(
+ ParamData(
+ label=two_qubit_calib.label,
+ value=param.value,
+ unit=param.unit,
+ )
+ )
+ return ParamResponse(param_name=param_name, data=data)
+
+
+class Stats(BaseModel):
+ average_value: float | None
+ max_value: float | None
+ min_value: float | None
+ fig_path: str
+
+
+class QPUStatsResponse(BaseModel):
+ average_gate_fidelity: Stats
+ resonator_frequency: Stats
+ qubit_frequency: Stats
+ t1: Stats
+ t2_echo: Stats
+ t2_star: Stats
+
+
+@router.get(
+ "/qpu/{name}/stats",
+ response_model=QPUStatsResponse,
+ operation_id="fetch_qpu_stats_by_name",
+ summary="Fetch QPU stats by name",
+)
+def fetch_qpu_stats_by_name(
+ name: str, settings: Annotated[Settings, Depends] = Depends(get_settings)
+):
+ def text(array: np.ndarray, ax):
+ """
+ dataの値をその配列のインデックスの位置で示す
+ Parameters
+ ----------
+ array : np.ndarray
+ テキストとして示す値の配列
+ ax : matplotlib.axes._subplots.AxesSubplot
+ 値を追加したい2次元マップのaxes
+ """
+
+ for num_r, row in enumerate(array):
+ for num_c, value in enumerate(array[num_r]):
+ ax.text(
+ num_c,
+ num_r,
+ value,
+ color="white"
+ if (value - np.nanmin(array))
+ / (np.nanmax(array) - np.nanmin(array))
+ < 0.5
+ else "black",
+ ha="center",
+ va="center",
+ fontsize=10,
+ )
+
+ def riken_chip_sort(data_list, one_side_size):
+ """
+ one_side_size: チップの1辺のqubit数.
+ one_side_size**2個の要素を持つ1行のリスト(data_list)を, 理研チップのqubit番号に合わせて
+ [[0, 1, 4, 5, ..., ],
+ [2, 3, 6, 7, ..., ],
+ [...,],
+ [...,],]
+ の形に並べ直す.
+ """
+
+ sorted_list: list = []
+
+ for q, data in enumerate(data_list):
+ mux = q // 4
+ q_res = q % 4
+
+ if mux % (int(one_side_size / 2)) == 0 and q_res % 2 == 0:
+ sorted_list.append([])
+
+ row = (mux // (int(one_side_size / 2))) * 2 + q_res // 2
+
+ sorted_list[row].append(data_list[q])
+
+ return sorted_list
+
+ path = f"{settings.qpu_data_path}/{name}"
+ if not os.path.exists(path):
+ os.makedirs(path)
+ one_side_size = 8
+ one_qubit_calibs = OneQubitCalibModel.find(
+ OneQubitCalibModel.qpu_name == name
+ ).run()
+ # value_list = []
+ value_dict: dict = {
+ key: []
+ for key in [
+ "average_gate_fidelity",
+ "resonator_frequency",
+ "qubit_frequency",
+ "t1",
+ "t2_echo",
+ "t2_star",
+ ]
+ }
+ for one_qubit_calib in one_qubit_calibs:
+ # print(r.one_qubit_calib_data.qubit_frequency_cw.value * 0.001)
+ for key in value_dict.keys():
+ try:
+ if key == "resonator_frequency":
+ if (
+ one_qubit_calib.one_qubit_calib_data.resonator_frequency.value
+ == 0
+ ):
+ value_dict[key].append(np.nan)
+ continue
+ value_dict[key].append(
+ one_qubit_calib.one_qubit_calib_data.resonator_frequency.value
+ * 0.001
+ )
+ elif key == "qubit_frequency":
+ if one_qubit_calib.one_qubit_calib_data.qubit_frequency.value == 0:
+ value_dict[key].append(np.nan)
+ continue
+ value_dict[key].append(
+ one_qubit_calib.one_qubit_calib_data.qubit_frequency.value
+ * 0.001
+ )
+ elif key == "t1":
+ if one_qubit_calib.one_qubit_calib_data.t1.value == 0:
+ value_dict[key].append(np.nan)
+ continue
+ value_dict[key].append(
+ one_qubit_calib.one_qubit_calib_data.t1.value * 0.001
+ )
+ elif key == "t2_echo":
+ if one_qubit_calib.one_qubit_calib_data.t2_echo.value == 0:
+ value_dict[key].append(np.nan)
+ continue
+ value_dict[key].append(
+ one_qubit_calib.one_qubit_calib_data.t2_echo.value * 0.001
+ )
+ elif key == "t2_star":
+ if one_qubit_calib.one_qubit_calib_data.t2_star.value == 0:
+ value_dict[key].append(np.nan)
+ continue
+ value_dict[key].append(
+ one_qubit_calib.one_qubit_calib_data.t2_star.value * 0.001
+ )
+ elif key == "average_gate_fidelity":
+ if (
+ one_qubit_calib.one_qubit_calib_data.average_gate_fidelity.value
+ == 0
+ ):
+ value_dict[key].append(np.nan)
+ continue
+ value_dict[key].append(
+ one_qubit_calib.one_qubit_calib_data.average_gate_fidelity.value
+ )
+ except AttributeError as e:
+ logger.error(f"Failed to get {key}: {e}")
+ value_dict[key].append(np.nan)
+ continue
+ for key, value_list in value_dict.items():
+ value_list = riken_chip_sort(value_list, one_side_size)
+ plt.rcParams["figure.figsize"] = (one_side_size * 0.8, one_side_size * 0.8)
+ fig, ax = plt.subplots()
+ plt.tick_params(
+ labelbottom=False,
+ labelleft=False,
+ labelright=False,
+ labeltop=False,
+ bottom=False,
+ left=False,
+ right=False,
+ top=False,
+ )
+ ax.set_title(key)
+ cmap = mpl.colormaps.get_cmap(
+ "viridis"
+ ) # viridis is the default colormap for imshow
+ cmap.set_bad(color="white")
+ im = ax.imshow(value_list, cmap=cmap)
+ text(np.round(value_list, 4), ax)
+
+ if key == "resonator_frequency":
+ plt.title("Resonator frequency [GHz]")
+ elif key == "qubit_frequency":
+ plt.title("Qubit frequency [GHz]")
+ elif key == "anharmonicity":
+ plt.title("Anharmonicity [GHz]")
+
+ # グラフ画像の保存
+ plt.savefig(f"{path}/{key}.png", format="png", dpi=300)
+
+ def safe_nanmean(array):
+ return np.round(np.nanmean(array), 5) if np.any(~np.isnan(array)) else None
+
+ def safe_nanmax(array):
+ return np.round(np.nanmax(array), 5) if np.any(~np.isnan(array)) else None
+
+ def safe_nanmin(array):
+ return np.round(np.nanmin(array), 5) if np.any(~np.isnan(array)) else None
+
+ # plt.show()
+ return QPUStatsResponse(
+ average_gate_fidelity=Stats(
+ average_value=safe_nanmean(value_dict["average_gate_fidelity"]),
+ max_value=safe_nanmax(value_dict["average_gate_fidelity"]),
+ min_value=safe_nanmin(value_dict["average_gate_fidelity"]),
+ fig_path=f"{path}/average_gate_fidelity.png",
+ ),
+ resonator_frequency=Stats(
+ average_value=safe_nanmean(value_dict["resonator_frequency"]),
+ max_value=safe_nanmax(value_dict["resonator_frequency"]),
+ min_value=safe_nanmin(value_dict["resonator_frequency"]),
+ fig_path=f"{path}/resonator_frequency.png",
+ ),
+ qubit_frequency=Stats(
+ average_value=safe_nanmean(value_dict["qubit_frequency"]),
+ max_value=safe_nanmax(value_dict["qubit_frequency"]),
+ min_value=safe_nanmin(value_dict["qubit_frequency"]),
+ fig_path=f"{path}/qubit_frequency.png",
+ ),
+ t1=Stats(
+ average_value=safe_nanmean(value_dict["t1"]),
+ max_value=safe_nanmax(value_dict["t1"]),
+ min_value=safe_nanmin(value_dict["t1"]),
+ fig_path=f"{path}/t1.png",
+ ),
+ t2_echo=Stats(
+ average_value=safe_nanmean(value_dict["t2_echo"]),
+ max_value=safe_nanmax(value_dict["t2_echo"]),
+ min_value=safe_nanmin(value_dict["t2_echo"]),
+ fig_path=f"{path}/t2_echo.png",
+ ),
+ t2_star=Stats(
+ average_value=safe_nanmean(value_dict["t2_star"]),
+ max_value=safe_nanmax(value_dict["t2_star"]),
+ min_value=safe_nanmin(value_dict["t2_star"]),
+ fig_path=f"{path}/t2_star.png",
+ ),
+ )
diff --git a/backend/server/routers/settings.py b/backend/server/routers/settings.py
new file mode 100644
index 0000000..91a11d3
--- /dev/null
+++ b/backend/server/routers/settings.py
@@ -0,0 +1,20 @@
+from logging import getLogger
+from typing import Annotated
+
+from fastapi import APIRouter, Depends
+
+from server.config import Settings, get_settings
+
+router = APIRouter()
+logger = getLogger("uvicorn.app")
+
+
+@router.get(
+ "/settings",
+ response_model=Settings,
+ summary="Get settings",
+ description="Get settings from the server",
+ operation_id="fetch_config",
+)
+def fetchConfig(settings: Annotated[Settings, Depends(get_settings)]):
+ return settings
diff --git a/backend/server/schemas/calibration.py b/backend/server/schemas/calibration.py
new file mode 100644
index 0000000..d2dcf7b
--- /dev/null
+++ b/backend/server/schemas/calibration.py
@@ -0,0 +1,172 @@
+from datetime import datetime
+from typing import Generic, Optional, TypeVar
+
+from dbmodel.one_qubit_calib import NodeInfo, OneQubitCalibData
+from dbmodel.one_qubit_calib_daily_summary import OneQubitCalibSummary
+from dbmodel.two_qubit_calib import EdgeInfo, TwoQubitCalibData
+from dbmodel.two_qubit_calib_daily_summary import TwoQubitCalibSummary
+from pydantic import BaseModel, Field
+
+T = TypeVar("T")
+
+
+class OneQubitCalibResponse(BaseModel):
+ qpu_name: str
+ cooling_down_id: int
+ label: str
+ status: str
+ node_info: NodeInfo
+ one_qubit_calib_data: Optional[OneQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+
+class TwoQubitCalibResponse(BaseModel):
+ qpu_name: str
+ cooling_down_id: int
+ label: str
+ status: str
+ edge_info: EdgeInfo
+ two_qubit_calib_data: Optional[TwoQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+
+class OneQubitCalibHistoryResponse(BaseModel):
+ qpu_name: str
+ cooling_down_id: int
+ label: str
+ date: str
+ one_qubit_calib_data: Optional[OneQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+
+class TwoQubitCalibHistoryResponse(BaseModel):
+ qpu_name: str
+ cooling_down_id: int
+ label: str
+ date: str
+ two_qubit_calib_data: Optional[TwoQubitCalibData]
+ created_at: datetime = Field(default_factory=datetime.now)
+ updated_at: datetime = Field(default_factory=datetime.now)
+
+
+class ExecuteCalibRequest(BaseModel):
+ name: str
+ description: str
+ one_qubit_calib_plan: list[list[int]]
+ two_qubit_calib_plan: list[list[tuple[int, int]]]
+ mode: str
+ notify_bool: bool = True
+ flow: list[str]
+ exp_list: Optional[list[str]] = Field(default=[])
+ tags: Optional[list[str]] = Field(default=None)
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "name": "1Q-MOCK-DEMO",
+ "description": "one qubit calibration for mock demo",
+ "one_qubit_calib_plan": [[0, 1, 2], [4, 5, 6], [7, 8, 9]],
+ "two_qubit_calib_plan": [
+ [[0, 1], [0, 2], [3, 4]],
+ [[5, 6], [7, 8]],
+ ],
+ "mode": "calib",
+ "notify_bool": False,
+ "flow": ["one-qubit-calibration-flow"],
+ "tags": ["tag1", "tag2"],
+ },
+ ]
+ }
+ }
+
+
+class ExecuteCalibResponse(BaseModel):
+ flow_run_url: str
+
+
+class ScheduleCalibRequest(BaseModel):
+ menu_name: str
+ scheduled: str
+
+
+class ScheduleCalibResponse(BaseModel):
+ menu_name: str
+ menu: ExecuteCalibRequest
+ description: str
+ note: str
+ timezone: str
+ scheduled_time: str
+ flow_run_id: str
+
+
+class BaseCalibDailySummary(BaseModel, Generic[T]):
+ date: str
+ labels: list[str]
+ qpu_name: str
+ cooling_down_id: int
+ summary: list[T]
+ note: str = ""
+
+
+class OneQubitCalibDailySummaryRequest(BaseCalibDailySummary[OneQubitCalibSummary]):
+ pass
+
+
+class OneQubitCalibDailySummaryResponse(BaseCalibDailySummary[OneQubitCalibSummary]):
+ pass
+
+
+class TwoQubitCalibDailySummaryRequest(BaseCalibDailySummary[TwoQubitCalibSummary]):
+ pass
+
+
+class TwoQubitCalibDailySummaryResponse(BaseCalibDailySummary[TwoQubitCalibSummary]):
+ pass
+
+
+class OneQubitCalibStatsRequest(BaseModel):
+ labels: list[str]
+
+
+class TwoQubitCalibStatsRequest(BaseModel):
+ labels: list[str]
+
+
+class OneQubitCalibStatsResponse(BaseModel):
+ date: str
+
+ class Config:
+ arbitrary_types_allowed = True
+ extra = "allow"
+
+ def simplify(self):
+ for key, value in self.__dict__.items():
+ if isinstance(value, OneQubitCalibData):
+ value.simplify()
+
+ def add_stats(self, label: str, stats: OneQubitCalibData):
+ setattr(self, label, stats)
+
+
+class TwoQubitCalibStatsResponse(BaseModel):
+ date: str
+
+ class Config:
+ arbitrary_types_allowed = True
+ extra = "allow"
+
+ def simplify(self):
+ for key, value in self.__dict__.items():
+ if isinstance(value, TwoQubitCalibData):
+ value.simplify()
+
+ def add_stats(self, label: str, stats: TwoQubitCalibData):
+ setattr(self, label, stats)
+
+
+class OneQubitCalibCWInfo(BaseModel):
+ cw_info: dict[str, OneQubitCalibData]
diff --git a/backend/server/schemas/error.py b/backend/server/schemas/error.py
new file mode 100644
index 0000000..1ba4ad6
--- /dev/null
+++ b/backend/server/schemas/error.py
@@ -0,0 +1,116 @@
+from __future__ import (
+ annotations,
+)
+
+from fastapi.responses import JSONResponse
+from pydantic import BaseModel
+
+
+class ErrorResponse(JSONResponse):
+ pass
+
+
+class Detail(BaseModel):
+ """A simple message response.
+
+ Args:
+ BaseModel: The base class for Pydantic models.
+
+ Attributes:
+ message (str): The message to return.
+
+ """
+
+ detail: str
+
+
+class BadRequestResponse(ErrorResponse):
+ """
+ Represents a response for a bad request.
+
+ Args:
+ detail (str): The detailed error message.
+
+ Attributes:
+ status_code (int): The HTTP status code for the response.
+ content (dict): The content of the response.
+
+ """
+
+ def __init__(
+ self,
+ detail: str,
+ ):
+ super().__init__(
+ status_code=400,
+ content={"detail": detail},
+ )
+
+
+class InternalServerErrorResponse(ErrorResponse):
+ """
+ Represents an internal server error response.
+
+ Args:
+ detail (str): The error message or details of the internal server error.
+
+ Attributes:
+ status_code (int): The HTTP status code for the internal server error response.
+ content (dict): The content of the internal server error response, containing the error detail.
+
+ """
+
+ def __init__(
+ self,
+ detail: str,
+ ):
+ super().__init__(
+ status_code=500,
+ content={"detail": detail},
+ )
+
+
+class NotFoundErrorResponse(ErrorResponse):
+ """
+ Represents an error response for a resource not found.
+
+ Args:
+ detail (str): The detailed error message.
+
+ Attributes:
+ status_code (int): The HTTP status code of the error response.
+ content (dict): The content of the error response.
+
+ """
+
+ def __init__(
+ self,
+ detail: str,
+ ):
+ super().__init__(
+ status_code=404,
+ content={"detail": detail},
+ )
+
+
+class ConflictErrorResponse(ErrorResponse):
+ """
+ Represents an error response for a conflict (HTTP status code 409).
+
+ Args:
+ detail (str): The detailed error message.
+
+ Attributes:
+ status_code (int): The HTTP status code for the error response (409).
+ content (dict): The content of the error response, containing the detail message.
+
+ """
+
+ def __init__(
+ self,
+ detail: str,
+ ):
+ super().__init__(
+ status_code=409,
+ content={"detail": detail},
+ )
diff --git a/backend/server/schemas/exception.py b/backend/server/schemas/exception.py
new file mode 100644
index 0000000..bf1b900
--- /dev/null
+++ b/backend/server/schemas/exception.py
@@ -0,0 +1,6 @@
+from fastapi import HTTPException
+
+
+class InternalSeverError(HTTPException):
+ def __init__(self, detail: str):
+ super().__init__(status_code=500, detail=detail)
diff --git a/backend/server/schemas/instruments.py b/backend/server/schemas/instruments.py
new file mode 100644
index 0000000..c87b155
--- /dev/null
+++ b/backend/server/schemas/instruments.py
@@ -0,0 +1,52 @@
+from typing import Optional
+
+from pydantic import BaseModel, Field
+
+
+class BoxStatus(BaseModel):
+ label: str
+ name: str
+ type: str
+ status: str
+ address: str
+ adapter: str
+
+
+class BoxStatusResponse(BoxStatus):
+ pass
+
+
+class PortConfig(BaseModel):
+ port: Optional[int] = Field(default=0)
+ direction: Optional[str] = Field(default="")
+ lo_freq: Optional[float] = Field(default=0)
+ cnco_freq: Optional[float] = Field(default=0)
+ fullscale_current: Optional[int] = Field(default=0)
+ sideband: Optional[str] = Field(default="")
+
+
+class BoxDetailResponse(BoxStatus):
+ detail: Optional[list[PortConfig]] = Field(default=[])
+
+
+class IQData(BaseModel):
+ i: list[float]
+ q: list[float]
+
+
+class CaptureData(BaseModel):
+ ports: dict[str, IQData]
+
+
+class CaptureDataResponse(IQData):
+ pass
+
+
+class InitLSIResponse(BaseModel):
+ message: str
+
+
+class UpdatePortConfig(BaseModel):
+ port: int
+ sideband: str
+ vatt: int
diff --git a/backend/server/schemas/menu.py b/backend/server/schemas/menu.py
new file mode 100644
index 0000000..65741ad
--- /dev/null
+++ b/backend/server/schemas/menu.py
@@ -0,0 +1,85 @@
+from enum import Enum
+from typing import Optional
+
+from pydantic import BaseModel, Field
+
+
+class Mode(Enum):
+ DEFAULT: str = "default"
+ DRAG: str = "drag"
+ FILTER: str = "filter"
+ CUSTOM: str = "custom"
+
+
+class BaseMenu(BaseModel):
+ """
+ Represents a base menu.
+
+ Attributes:
+ name (str): The name of the menu.
+ description (str): The description of the menu.
+ plan (list[list[int]]): The plan for the menu.
+ mux_index_list (list[int]): The mux index list for the menu.
+ mode (str): The mode of the menu.
+ notify_bool (bool, optional): Whether to notify or not. Defaults to True.
+ flow (list[str]): The flow of the menu.
+ exp_list (list[str], optional): The list of experiments. Defaults to None.
+ """
+
+ name: str
+ description: str
+ one_qubit_calib_plan: list[list[int]]
+ two_qubit_calib_plan: list[list[tuple[int, int]]]
+ mode: str
+ notify_bool: bool = True
+ flow: list[str]
+ exp_list: Optional[list[str]] = Field(default=[])
+ tags: Optional[list[str]] = Field(default=[])
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "name": "sample-menu",
+ "description": "menu description",
+ "one_qubit_calib_plan": [[0, 1, 2], [4, 5, 6], [7, 8, 9]],
+ "two_qubit_calib_plan": [
+ [[0, 1], [0, 2], [3, 4]],
+ [[5, 6], [7, 8]],
+ ],
+ "mode": "calib",
+ "notify_bool": False,
+ "flow": ["one-qubit-calibration-flow"],
+ "tags": ["tag1", "tag2"],
+ },
+ ]
+ }
+ }
+
+
+class CreateMenuRequest(BaseMenu):
+ pass
+
+
+class CreateMenuResponse(BaseModel):
+ name: str
+
+
+class DeleteMenuResponse(BaseModel):
+ name: str
+
+
+class UpdateMenuResponse(BaseModel):
+ name: str
+
+
+class UpdateMenuRequest(BaseMenu):
+ pass
+
+
+class ListMenuResponse(BaseMenu):
+ pass
+
+
+class GetMenuResponse(BaseMenu):
+ pass
diff --git a/backend/server/schemas/service.py b/backend/server/schemas/service.py
new file mode 100644
index 0000000..71e048d
--- /dev/null
+++ b/backend/server/schemas/service.py
@@ -0,0 +1,168 @@
+from pydantic import BaseModel
+
+
+class ServiceStatusResponse(BaseModel):
+ """
+ Represents the response for the service status.
+
+ Attributes:
+ status (str): The status of the service.
+ backend (str): The backend used by the service.
+ qubit_num (int): The number of qubits.
+ qubit_index (str): The index of the qubit.
+ """
+
+ status: str
+ backend: str
+ qubit_num: int
+ qubit_index: str
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "status": "available",
+ "backend": "Simulator",
+ "qubit_num": 4,
+ "qubit_index": "1,2,3,5",
+ }
+ ]
+ }
+ }
+
+
+class ServiceStatusRequest(BaseModel):
+ """
+ Represents a request to get the status of a service.
+
+ Attributes:
+ status (str): The status of the service.
+ backend (str): The backend of the service.
+ qubit_num (int): The number of qubits in the service.
+ qubit_index (str): The index of the qubit in the service.
+ """
+
+ status: str
+ backend: str
+ qubit_num: int
+ qubit_index: str
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "status": "available",
+ "backend": "Simulator",
+ "qubit_num": 4,
+ "qubit_index": "1,2,3,5",
+ }
+ ]
+ }
+ }
+
+
+class RestartServiceResponse(BaseModel):
+ """
+ Represents the response for restarting a service.
+
+ Attributes:
+ message (str): The message indicating the success of the restart.
+ """
+
+ message: str = "QMT server restarted"
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "message": "QMT server restarted",
+ }
+ ]
+ }
+ }
+
+
+class UpdateTopologyInfoResponse(BaseModel):
+ """
+ Represents the response for updating the topology information.
+
+ Attributes:
+ message (str): The message indicating the success of the update.
+ """
+
+ message: str = "Topology information updated"
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "message": "Topology information updated",
+ }
+ ]
+ }
+ }
+
+
+class UpdateWiringInfoResponse(BaseModel):
+ """
+ Represents the response for updating the wiring information.
+
+ Attributes:
+ message (str): The message indicating the success of the update.
+ """
+
+ message: str = "Wiring information updated"
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "message": "Wiring information updated",
+ }
+ ]
+ }
+ }
+
+
+class ScheduleResponse(BaseModel):
+ idx: int
+ name: str
+ description: str
+ cron: str
+ timezone: str
+ active: bool
+ scheduled: str
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "idx": 1,
+ "name": "schedule",
+ "description": "schedule description",
+ "cron": "0 0 * * *",
+ "timezone": "UTC",
+ "active": True,
+ "scheduled": "2022-01-01 00:00:00",
+ }
+ ]
+ }
+ }
+
+
+class ScheduleRequest(BaseModel):
+ idx: int
+ cron: str
+ active: bool
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "idx": 1,
+ "cron": "0 0 * * *",
+ "active": True,
+ }
+ ]
+ }
+ }
diff --git a/backend/server/schemas/session_info.py b/backend/server/schemas/session_info.py
new file mode 100644
index 0000000..10a6476
--- /dev/null
+++ b/backend/server/schemas/session_info.py
@@ -0,0 +1,10 @@
+from pydantic import BaseModel
+
+
+class SessionInfo(BaseModel):
+ labrad_hostname: str
+ labrad_username: str
+ labrad_password: str
+ cooling_down_id: str
+ experiment_username: str
+ package_name: str
diff --git a/backend/server/schemas/success.py b/backend/server/schemas/success.py
new file mode 100644
index 0000000..f61ef46
--- /dev/null
+++ b/backend/server/schemas/success.py
@@ -0,0 +1,15 @@
+from pydantic import BaseModel
+
+
+class SuccessResponse(BaseModel):
+ message: str
+
+ model_config = {
+ "json_schema_extra": {
+ "examples": [
+ {
+ "message": "Successfuly {message}",
+ }
+ ]
+ }
+ }
diff --git a/backend/tests/__init__.py b/backend/tests/__init__.py
new file mode 100644
index 0000000..e69de29
diff --git a/client/.eslintrc.cjs b/client/.eslintrc.cjs
new file mode 100644
index 0000000..1a2c1f1
--- /dev/null
+++ b/client/.eslintrc.cjs
@@ -0,0 +1,55 @@
+module.exports = {
+ root: true,
+ env: { browser: true, es2020: true, node: true },
+ extends: [
+ "eslint:recommended",
+ "plugin:@typescript-eslint/recommended",
+ "plugin:react-hooks/recommended",
+ ],
+ ignorePatterns: ["dist", ".eslintrc.cjs"],
+ parser: "@typescript-eslint/parser",
+ plugins: ["react-refresh", "import"],
+ rules: {
+ "react-refresh/only-export-components": [
+ "warn",
+ { allowConstantExport: true },
+ ],
+ "import/order": [
+ "error",
+ {
+ groups: [
+ "builtin",
+ "external",
+ "parent",
+ "sibling",
+ "index",
+ "object",
+ "type",
+ ],
+ pathGroups: [
+ {
+ pattern: "{react,react-dom/**,react-router-dom}",
+ group: "builtin",
+ position: "before",
+ },
+ {
+ pattern: "@src/**",
+ group: "parent",
+ position: "before",
+ },
+ ],
+ pathGroupsExcludedImportTypes: ["builtin"],
+ alphabetize: {
+ order: "asc",
+ },
+ "newlines-between": "always",
+ },
+ ],
+ "@typescript-eslint/no-unused-vars": "off", // 追加
+ "@typescript-eslint/no-explicit-any": "off", // 追加
+ "@typescript-eslint/consistent-type-imports": [
+ "error",
+ { prefer: "type-imports" },
+ ],
+ },
+};
diff --git a/client/.gitignore b/client/.gitignore
new file mode 100644
index 0000000..54f07af
--- /dev/null
+++ b/client/.gitignore
@@ -0,0 +1,24 @@
+# Logs
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
\ No newline at end of file
diff --git a/client/Dockerfile b/client/Dockerfile
new file mode 100644
index 0000000..618b4b4
--- /dev/null
+++ b/client/Dockerfile
@@ -0,0 +1,11 @@
+FROM node:18-alpine
+
+WORKDIR /app
+
+COPY ./client/package*.json ./
+# pnpm をインストール
+#RUN npm install -g pnpm
+# RUN pnpm install
+RUN npm install
+ENV HOST 0.0.0.0
+CMD ["npm", "run", "dev"]
diff --git a/client/index.html b/client/index.html
new file mode 100644
index 0000000..01793a9
--- /dev/null
+++ b/client/index.html
@@ -0,0 +1,15 @@
+
+
+
+
+
+
+
+ QDash
+
+
+
+
+
+
+
diff --git a/client/orval.config.cjs b/client/orval.config.cjs
new file mode 100644
index 0000000..ccbf588
--- /dev/null
+++ b/client/orval.config.cjs
@@ -0,0 +1,19 @@
+module.exports = {
+ "qdash-file-transfomer": {
+ output: {
+ client: "react-query",
+ mode: "tags-split",
+ target: "./src/client",
+ schemas: "./src/schemas",
+ baseUrl: "http://localhost:5715",
+ clean: true,
+ mock: false,
+ },
+ input: {
+ target: "../docs/oas/openapi.json",
+ },
+ // hooks: {
+ // afterAllFilesWrite: "npx eslint . --fix",
+ // },
+ },
+};
diff --git a/client/package-lock.json b/client/package-lock.json
new file mode 100644
index 0000000..4736568
--- /dev/null
+++ b/client/package-lock.json
@@ -0,0 +1,8468 @@
+{
+ "name": "client",
+ "version": "0.0.0",
+ "lockfileVersion": 3,
+ "requires": true,
+ "packages": {
+ "": {
+ "name": "client",
+ "version": "0.0.0",
+ "dependencies": {
+ "@lit/react": "^1.0.6",
+ "@monaco-editor/react": "4.6.0",
+ "@nivo/line": "^0.87.0",
+ "@tanstack/react-query": "^5.59.20",
+ "@tanstack/react-table": "^8.20.5",
+ "axios": "^1.7.7",
+ "chart.js": "^4.4.6",
+ "color-legend-element": "^1.3.0",
+ "create-vite": "^5.5.5",
+ "date-fns": "4.1.0",
+ "js-yaml": "^4.1.0",
+ "lit": "^3.2.1",
+ "node-fetch": "^3.3.2",
+ "openapi-fetch": "^0.13.0",
+ "openapi-typescript-codegen": "^0.29.0",
+ "react": "^18.3.1",
+ "react-chartjs-2": "^5.2.0",
+ "react-colorscales": "^0.7.3",
+ "react-datepicker": "^7.5.0",
+ "react-dom": "^18.3.1",
+ "react-grid-gallery": "^1.0.1",
+ "react-icons": "^5.3.0",
+ "react-json-editor-ajrm": "^2.5.14",
+ "react-json-editor-viewer": "^1.0.7",
+ "react-loader-spinner": "^6.1.6",
+ "react-router-dom": "^6.28.0",
+ "react-select": "^5.8.2",
+ "react-spinners": "^0.14.1",
+ "react-toastify": "^10.0.6",
+ "react-tooltip": "^5.28.0",
+ "react-transition-group": "^4.4.5",
+ "react18-json-view": "0.2.9-canary.8",
+ "reagraph": "^4.19.5",
+ "recharts": "^2.13.3",
+ "yet-another-react-lightbox": "^3.21.6",
+ "zod": "^3.23.8"
+ },
+ "devDependencies": {
+ "@tailwindcss/typography": "^0.5.15",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@types/react-json-editor-ajrm": "^2.5.6",
+ "@typescript-eslint/eslint-plugin": "^8.13.0",
+ "@typescript-eslint/parser": "^8.13.0",
+ "@vitejs/plugin-react": "^4.3.3",
+ "autoprefixer": "^10.4.20",
+ "daisyui": "^4.12.14",
+ "eslint": "^9.14.0",
+ "eslint-plugin-import": "^2.31.0",
+ "eslint-plugin-react-hooks": "^5.0.0",
+ "eslint-plugin-react-refresh": "^0.4.14",
+ "openapi-typescript": "^7.4.2",
+ "postcss": "^8.4.47",
+ "tailwindcss": "^3.4.14",
+ "typescript": "^5.6.3",
+ "vite": "^5.4.10"
+ }
+ },
+ "node_modules/@alloc/quick-lru": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz",
+ "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@ampproject/remapping": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.3.0.tgz",
+ "integrity": "sha512-30iZtAPgz+LTIYoeivqYo853f02jBYSd5uGnGpkFV0M3xOt9aN73erkgYAmZU43x4VfqcnLxW9Kpg3R5LC4YYw==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@apidevtools/json-schema-ref-parser": {
+ "version": "11.7.2",
+ "resolved": "https://registry.npmjs.org/@apidevtools/json-schema-ref-parser/-/json-schema-ref-parser-11.7.2.tgz",
+ "integrity": "sha512-4gY54eEGEstClvEkGnwVkTkrx0sqwemEFG5OSRRn3tD91XH0+Q8XIkYIfo7IwEWPpJZwILb9GUXeShtplRc/eA==",
+ "dependencies": {
+ "@jsdevtools/ono": "^7.1.3",
+ "@types/json-schema": "^7.0.15",
+ "js-yaml": "^4.1.0"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/philsturgeon"
+ }
+ },
+ "node_modules/@babel/code-frame": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.26.2.tgz",
+ "integrity": "sha512-RJlIHRueQgwWitWgF8OdFYGZX328Ax5BCemNGlqHfplnRT9ESi8JkFlvaVYbS+UubVY6dpv87Fs2u5M29iNFVQ==",
+ "dependencies": {
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.0.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/compat-data": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.26.2.tgz",
+ "integrity": "sha512-Z0WgzSEa+aUcdiJuCIqgujCshpMWgUpgOxXotrYPSA53hA3qopNaqcJpyr0hVb1FeWdnqFA35/fUtXgBK8srQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/core": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.26.0.tgz",
+ "integrity": "sha512-i1SLeK+DzNnQ3LL/CswPCa/E5u4lh1k6IAEphON8F+cXt0t9euTshDru0q7/IqMa1PMPz5RnHuHscF8/ZJsStg==",
+ "dev": true,
+ "dependencies": {
+ "@ampproject/remapping": "^2.2.0",
+ "@babel/code-frame": "^7.26.0",
+ "@babel/generator": "^7.26.0",
+ "@babel/helper-compilation-targets": "^7.25.9",
+ "@babel/helper-module-transforms": "^7.26.0",
+ "@babel/helpers": "^7.26.0",
+ "@babel/parser": "^7.26.0",
+ "@babel/template": "^7.25.9",
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.26.0",
+ "convert-source-map": "^2.0.0",
+ "debug": "^4.1.0",
+ "gensync": "^1.0.0-beta.2",
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/babel"
+ }
+ },
+ "node_modules/@babel/core/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/generator": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.26.2.tgz",
+ "integrity": "sha512-zevQbhbau95nkoxSq3f/DC/SC+EEOUZd3DYqfSkMhY2/wfSeaHV1Ew4vk8e+x8lja31IbyuUa2uQ3JONqKbysw==",
+ "dependencies": {
+ "@babel/parser": "^7.26.2",
+ "@babel/types": "^7.26.0",
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jsesc": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.25.9.tgz",
+ "integrity": "sha512-j9Db8Suy6yV/VHa4qzrj9yZfZxhLWQdVnRlXxmKLYlhWUVB1sB2G5sxuWYXk/whHD9iW76PmNzxZ4UCnTQTVEQ==",
+ "dev": true,
+ "dependencies": {
+ "@babel/compat-data": "^7.25.9",
+ "@babel/helper-validator-option": "^7.25.9",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-compilation-targets/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/@babel/helper-module-imports": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.25.9.tgz",
+ "integrity": "sha512-tnUA4RsrmflIM6W6RFTLFSXITtl0wKjgpnLgXyowocVPrbYrLUXSBXDgTs8BlbmIzIdlBySRQjINYs2BAkiLtw==",
+ "dependencies": {
+ "@babel/traverse": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-module-transforms": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.26.0.tgz",
+ "integrity": "sha512-xO+xu6B5K2czEnQye6BHA7DolFFmS3LB7stHZFaOLb1pAwO1HWLS8fXA+eh0A2yIvltPVmx3eNNDBJA2SLHXFw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9",
+ "@babel/traverse": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
+ }
+ },
+ "node_modules/@babel/helper-plugin-utils": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.25.9.tgz",
+ "integrity": "sha512-kSMlyUVdWe25rEsRGviIgOWnoT/nfABVWlqt9N19/dIPWViAOW2s9wznP5tURbs/IDuNk4gPy3YdYRgH3uxhBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-string-parser": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.25.9.tgz",
+ "integrity": "sha512-4A/SCr/2KLd5jrtOMFzaKjVtAei3+2r/NChoBNoZ3EyP/+GlhoaEGoWOZUmFmoITP7zOJyHIMm+DYRd8o3PvHA==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-identifier": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.25.9.tgz",
+ "integrity": "sha512-Ed61U6XJc3CVRfkERJWDz4dJwKe7iLmmJsbOGu9wSloNSFttHV0I8g6UAgb7qnK5ly5bGLPd4oXZlxCdANBOWQ==",
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helper-validator-option": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.25.9.tgz",
+ "integrity": "sha512-e/zv1co8pp55dNdEcCynfj9X7nyUKUXoUEwfXqaZt0omVOmDe9oOTdKStH4GmAw6zxMFs50ZayuMfHDKlO7Tfw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/helpers": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.26.0.tgz",
+ "integrity": "sha512-tbhNuIxNcVb21pInl3ZSjksLCvgdZy9KwJ8brv993QtIVKJBBkYXz4q4ZbAv31GdnC+R90np23L5FbEBlthAEw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.26.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/parser": {
+ "version": "7.26.2",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.2.tgz",
+ "integrity": "sha512-DWMCZH9WA4Maitz2q21SRKHo9QXZxkDsbNZoVD62gusNtNBBqDg9i7uOhASfTfIGNzW+O+r7+jAlM8dwphcJKQ==",
+ "dependencies": {
+ "@babel/types": "^7.26.0"
+ },
+ "bin": {
+ "parser": "bin/babel-parser.js"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-self": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.25.9.tgz",
+ "integrity": "sha512-y8quW6p0WHkEhmErnfe58r7x0A70uKphQm8Sp8cV7tjNQwK56sNVK0M73LK3WuYmsuyrftut4xAkjjgU0twaMg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/plugin-transform-react-jsx-source": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-source/-/plugin-transform-react-jsx-source-7.25.9.tgz",
+ "integrity": "sha512-+iqjT8xmXhhYv4/uiYd8FNQsraMFZIfxVSqxxVSZP0WbbSAWvBXAul0m/zu+7Vv4O/3WtApy9pmaTMiumEZgfg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/helper-plugin-utils": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ }
+ },
+ "node_modules/@babel/runtime": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.26.0.tgz",
+ "integrity": "sha512-FDSOghenHTiToteC/QRlv2q3DhPZ/oOXTBoirfWNx1Cx3TMVcGWQtMMmQcSvb/JjpNeGzx8Pq/b4fKEJuWm1sw==",
+ "dependencies": {
+ "regenerator-runtime": "^0.14.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/runtime/node_modules/regenerator-runtime": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.14.1.tgz",
+ "integrity": "sha512-dYnhHh0nJoMfnkZs6GmmhFknAGRrLznOu5nc9ML+EJxGvrx6H7teuevqVqCuPcPK//3eDrrjQhehXVx9cnkGdw=="
+ },
+ "node_modules/@babel/template": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.25.9.tgz",
+ "integrity": "sha512-9DGttpmPvIxBb/2uwpVo3dqJ+O6RooAFOS+lB+xDqoE2PVCE8nfoHMdZLpfCQRLwvohzXISPZcgxt80xLfsuwg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/types": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/traverse": {
+ "version": "7.25.9",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.25.9.tgz",
+ "integrity": "sha512-ZCuvfwOwlz/bawvAuvcj8rrithP2/N55Tzz342AkTvq4qaWbGfmCk/tKhNaV2cthijKrPAA8SRJV5WWe7IBMJw==",
+ "dependencies": {
+ "@babel/code-frame": "^7.25.9",
+ "@babel/generator": "^7.25.9",
+ "@babel/parser": "^7.25.9",
+ "@babel/template": "^7.25.9",
+ "@babel/types": "^7.25.9",
+ "debug": "^4.3.1",
+ "globals": "^11.1.0"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@babel/types": {
+ "version": "7.26.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.0.tgz",
+ "integrity": "sha512-Z/yiTPj+lDVnF7lWeKCIJzaIkI0vYO87dMpZ4bg4TDrFe4XXLFWL1TbXU27gBP3QccxV9mZICCrnjnYlJjXHOA==",
+ "dependencies": {
+ "@babel/helper-string-parser": "^7.25.9",
+ "@babel/helper-validator-identifier": "^7.25.9"
+ },
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/@emotion/babel-plugin": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/@emotion/babel-plugin/-/babel-plugin-11.12.0.tgz",
+ "integrity": "sha512-y2WQb+oP8Jqvvclh8Q55gLUyb7UFvgv7eJfsj7td5TToBrIUtPay2kMrZi4xjq9qw2vD0ZR5fSho0yqoFgX7Rw==",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.16.7",
+ "@babel/runtime": "^7.18.3",
+ "@emotion/hash": "^0.9.2",
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/serialize": "^1.2.0",
+ "babel-plugin-macros": "^3.1.0",
+ "convert-source-map": "^1.5.0",
+ "escape-string-regexp": "^4.0.0",
+ "find-root": "^1.1.0",
+ "source-map": "^0.5.7",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/babel-plugin/node_modules/convert-source-map": {
+ "version": "1.9.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.9.0.tgz",
+ "integrity": "sha512-ASFBup0Mz1uyiIjANan1jzLQami9z1PoYSZCiiYW2FczPbenXc45FZdBZLzOT+r6+iciuEModtmCti+hjaAk0A=="
+ },
+ "node_modules/@emotion/babel-plugin/node_modules/source-map": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
+ "integrity": "sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/@emotion/cache": {
+ "version": "11.13.1",
+ "resolved": "https://registry.npmjs.org/@emotion/cache/-/cache-11.13.1.tgz",
+ "integrity": "sha512-iqouYkuEblRcXmylXIwwOodiEK5Ifl7JcX7o6V4jI3iW4mLXX3dmt5xwBtIkJiQEXFAI+pC8X0i67yiPkH9Ucw==",
+ "dependencies": {
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/sheet": "^1.4.0",
+ "@emotion/utils": "^1.4.0",
+ "@emotion/weak-memoize": "^0.4.0",
+ "stylis": "4.2.0"
+ }
+ },
+ "node_modules/@emotion/hash": {
+ "version": "0.9.2",
+ "resolved": "https://registry.npmjs.org/@emotion/hash/-/hash-0.9.2.tgz",
+ "integrity": "sha512-MyqliTZGuOm3+5ZRSaaBGP3USLw6+EGykkwZns2EPC5g8jJ4z9OrdZY9apkl3+UP9+sdz76YYkwCKP5gh8iY3g=="
+ },
+ "node_modules/@emotion/is-prop-valid": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/@emotion/is-prop-valid/-/is-prop-valid-1.2.2.tgz",
+ "integrity": "sha512-uNsoYd37AFmaCdXlg6EYD1KaPOaRWRByMCYzbKUX4+hhMfrxdVSelShywL4JVaAeM/eHUOSprYBQls+/neX3pw==",
+ "dependencies": {
+ "@emotion/memoize": "^0.8.1"
+ }
+ },
+ "node_modules/@emotion/is-prop-valid/node_modules/@emotion/memoize": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.8.1.tgz",
+ "integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
+ },
+ "node_modules/@emotion/memoize": {
+ "version": "0.9.0",
+ "resolved": "https://registry.npmjs.org/@emotion/memoize/-/memoize-0.9.0.tgz",
+ "integrity": "sha512-30FAj7/EoJ5mwVPOWhAyCX+FPfMDrVecJAM+Iw9NRoSl4BBAQeqj4cApHHUXOVvIPgLVDsCFoz/hGD+5QQD1GQ=="
+ },
+ "node_modules/@emotion/react": {
+ "version": "11.13.3",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.13.3.tgz",
+ "integrity": "sha512-lIsdU6JNrmYfJ5EbUCf4xW1ovy5wKQ2CkPRM4xogziOxH1nXxBSjpC9YqbFAP7circxMfYp+6x676BqWcEiixg==",
+ "dependencies": {
+ "@babel/runtime": "^7.18.3",
+ "@emotion/babel-plugin": "^11.12.0",
+ "@emotion/cache": "^11.13.0",
+ "@emotion/serialize": "^1.3.1",
+ "@emotion/use-insertion-effect-with-fallbacks": "^1.1.0",
+ "@emotion/utils": "^1.4.0",
+ "@emotion/weak-memoize": "^0.4.0",
+ "hoist-non-react-statics": "^3.3.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@emotion/serialize": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.3.2.tgz",
+ "integrity": "sha512-grVnMvVPK9yUVE6rkKfAJlYZgo0cu3l9iMC77V7DW6E1DUIrU68pSEXRmFZFOFB1QFo57TncmOcvcbMDWsL4yA==",
+ "dependencies": {
+ "@emotion/hash": "^0.9.2",
+ "@emotion/memoize": "^0.9.0",
+ "@emotion/unitless": "^0.10.0",
+ "@emotion/utils": "^1.4.1",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@emotion/sheet": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/sheet/-/sheet-1.4.0.tgz",
+ "integrity": "sha512-fTBW9/8r2w3dXWYM4HCB1Rdp8NLibOw2+XELH5m5+AkWiL/KqYX6dc0kKYlaYyKjrQ6ds33MCdMPEwgs2z1rqg=="
+ },
+ "node_modules/@emotion/unitless": {
+ "version": "0.10.0",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.10.0.tgz",
+ "integrity": "sha512-dFoMUuQA20zvtVTuxZww6OHoJYgrzfKM1t52mVySDJnMSEa08ruEvdYQbhvyu6soU+NeLVd3yKfTfT0NeV6qGg=="
+ },
+ "node_modules/@emotion/use-insertion-effect-with-fallbacks": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@emotion/use-insertion-effect-with-fallbacks/-/use-insertion-effect-with-fallbacks-1.1.0.tgz",
+ "integrity": "sha512-+wBOcIV5snwGgI2ya3u99D7/FJquOIniQT1IKyDsBmEgwvpxMNeS65Oib7OnE2d2aY+3BU4OiH+0Wchf8yk3Hw==",
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/@emotion/utils": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/@emotion/utils/-/utils-1.4.1.tgz",
+ "integrity": "sha512-BymCXzCG3r72VKJxaYVwOXATqXIZ85cuvg0YOUDxMGNrKc1DJRZk8MgV5wyXRyEayIMd4FuXJIUgTBXvDNW5cA=="
+ },
+ "node_modules/@emotion/weak-memoize": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/@emotion/weak-memoize/-/weak-memoize-0.4.0.tgz",
+ "integrity": "sha512-snKqtPW01tN0ui7yu9rGv69aJXr/a/Ywvl11sUjNtEcRc+ng/mQriFL0wLXMef74iHa/EkftbDzU9F8iFbH+zg=="
+ },
+ "node_modules/@esbuild/aix-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/aix-ppc64/-/aix-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1SDgH6ZSPTlggy1yI6+Dbkiz8xzpHJEVAlF/AM1tHPLsf5STom9rwtjE4hKAF20FfXXNTFqEYXyJNWh1GiZedQ==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "aix"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm/-/android-arm-0.21.5.tgz",
+ "integrity": "sha512-vCPvzSjpPHEi1siZdlvAlsPxXl7WbOVUBBAowWug4rJHb68Ox8KualB+1ocNvT5fjv6wpkX6o/iEpbDrf68zcg==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-arm64/-/android-arm64-0.21.5.tgz",
+ "integrity": "sha512-c0uX9VAUBQ7dTDCjq+wdyGLowMdtR/GoC2U5IYk/7D1H1JYC0qseD7+11iMP2mRLN9RcCMRcjC4YMclCzGwS/A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/android-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/android-x64/-/android-x64-0.21.5.tgz",
+ "integrity": "sha512-D7aPRUUNHRBwHxzxRvp856rjUHRFW1SdQATKXH2hqA0kAZb1hKmi02OpYRacl0TxIGz/ZmXWlbZgjwWYaCakTA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-arm64/-/darwin-arm64-0.21.5.tgz",
+ "integrity": "sha512-DwqXqZyuk5AiWWf3UfLiRDJ5EDd49zg6O9wclZ7kUMv2WRFr4HKjXp/5t8JZ11QbQfUS6/cRCKGwYhtNAY88kQ==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/darwin-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/darwin-x64/-/darwin-x64-0.21.5.tgz",
+ "integrity": "sha512-se/JjF8NlmKVG4kNIuyWMV/22ZaerB+qaSi5MdrXtd6R08kvs2qCN4C09miupktDitvh8jRFflwGFBQcxZRjbw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-arm64/-/freebsd-arm64-0.21.5.tgz",
+ "integrity": "sha512-5JcRxxRDUJLX8JXp/wcBCy3pENnCgBR9bN6JsY4OmhfUtIHe3ZW0mawA7+RDAcMLrMIZaf03NlQiX9DGyB8h4g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/freebsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/freebsd-x64/-/freebsd-x64-0.21.5.tgz",
+ "integrity": "sha512-J95kNBj1zkbMXtHVH29bBriQygMXqoVQOQYA+ISs0/2l3T9/kj42ow2mpqerRBxDJnmkUDCaQT/dfNXWX/ZZCQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm/-/linux-arm-0.21.5.tgz",
+ "integrity": "sha512-bPb5AHZtbeNGjCKVZ9UGqGwo8EUu4cLq68E95A53KlxAPRmUyYv2D6F0uUI65XisGOL1hBP5mTronbgo+0bFcA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-arm64/-/linux-arm64-0.21.5.tgz",
+ "integrity": "sha512-ibKvmyYzKsBeX8d8I7MH/TMfWDXBF3db4qM6sy+7re0YXya+K1cem3on9XgdT2EQGMu4hQyZhan7TeQ8XkGp4Q==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ia32/-/linux-ia32-0.21.5.tgz",
+ "integrity": "sha512-YvjXDqLRqPDl2dvRODYmmhz4rPeVKYvppfGYKSNGdyZkA01046pLWyRKKI3ax8fbJoK5QbxblURkwK/MWY18Tg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-loong64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-loong64/-/linux-loong64-0.21.5.tgz",
+ "integrity": "sha512-uHf1BmMG8qEvzdrzAqg2SIG/02+4/DHB6a9Kbya0XDvwDEKCoC8ZRWI5JJvNdUjtciBGFQ5PuBlpEOXQj+JQSg==",
+ "cpu": [
+ "loong64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-mips64el": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-mips64el/-/linux-mips64el-0.21.5.tgz",
+ "integrity": "sha512-IajOmO+KJK23bj52dFSNCMsz1QP1DqM6cwLUv3W1QwyxkyIWecfafnI555fvSGqEKwjMXVLokcV5ygHW5b3Jbg==",
+ "cpu": [
+ "mips64el"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-ppc64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-ppc64/-/linux-ppc64-0.21.5.tgz",
+ "integrity": "sha512-1hHV/Z4OEfMwpLO8rp7CvlhBDnjsC3CttJXIhBi+5Aj5r+MBvy4egg7wCbe//hSsT+RvDAG7s81tAvpL2XAE4w==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-riscv64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-riscv64/-/linux-riscv64-0.21.5.tgz",
+ "integrity": "sha512-2HdXDMd9GMgTGrPWnJzP2ALSokE/0O5HhTUvWIbD3YdjME8JwvSCnNGBnTThKGEB91OZhzrJ4qIIxk/SBmyDDA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-s390x": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-s390x/-/linux-s390x-0.21.5.tgz",
+ "integrity": "sha512-zus5sxzqBJD3eXxwvjN1yQkRepANgxE9lgOW2qLnmr8ikMTphkjgXu1HR01K4FJg8h1kEEDAqDcZQtbrRnB41A==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/linux-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/linux-x64/-/linux-x64-0.21.5.tgz",
+ "integrity": "sha512-1rYdTpyv03iycF1+BhzrzQJCdOuAOtaqHTWJZCWvijKD2N5Xu0TtVC8/+1faWqcP9iBCWOmjmhoH94dH82BxPQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/netbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/netbsd-x64/-/netbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-Woi2MXzXjMULccIwMnLciyZH4nCIMpWQAs049KEeMvOcNADVxo0UBIQPfSmxB3CWKedngg7sWZdLvLczpe0tLg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "netbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/openbsd-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/openbsd-x64/-/openbsd-x64-0.21.5.tgz",
+ "integrity": "sha512-HLNNw99xsvx12lFBUwoT8EVCsSvRNDVxNpjZ7bPn947b8gJPzeHWyNVhFsaerc0n3TsbOINvRP2byTZ5LKezow==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "openbsd"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/sunos-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/sunos-x64/-/sunos-x64-0.21.5.tgz",
+ "integrity": "sha512-6+gjmFpfy0BHU5Tpptkuh8+uw3mnrvgs+dSPQXQOv3ekbordwnzTVEb4qnIvQcYXq6gzkyTnoZ9dZG+D4garKg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "sunos"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-arm64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-arm64/-/win32-arm64-0.21.5.tgz",
+ "integrity": "sha512-Z0gOTd75VvXqyq7nsl93zwahcTROgqvuAcYDUr+vOv8uHhNSKROyU961kgtCD1e95IqPKSQKH7tBTslnS3tA8A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-ia32": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-ia32/-/win32-ia32-0.21.5.tgz",
+ "integrity": "sha512-SWXFF1CL2RVNMaVs+BBClwtfZSvDgtL//G/smwAc5oVK/UPu2Gu9tIaRgFmYFFKrmg3SyAjSrElf0TiJ1v8fYA==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@esbuild/win32-x64": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/@esbuild/win32-x64/-/win32-x64-0.21.5.tgz",
+ "integrity": "sha512-tQd/1efJuzPC6rCFwEvLtci/xNFcTZknmXs98FYDfGE4wP9ClFV98nyKrzJKVPMhdDnjzLhdUyMX4PsQAPjwIw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ],
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.4.1.tgz",
+ "integrity": "sha512-s3O3waFUrMV8P/XaF/+ZTp1X9XBZW1a4B97ZnjQF2KYWaFD2A8KyFBsrsfSjEmjn3RGWAIuvlneuZm3CUK3jbA==",
+ "dev": true,
+ "dependencies": {
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
+ }
+ },
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.1.tgz",
+ "integrity": "sha512-CCZCDJuduB9OUkFkY2IgppNZMi2lBQgD2qzwXkEia16cge2pijY/aXi96CJMquDMn3nJdlPV1A5KrJEXwfLNzQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
+ },
+ "node_modules/@eslint/config-array": {
+ "version": "0.18.0",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.18.0.tgz",
+ "integrity": "sha512-fTxvnS1sRMu3+JjXwJG0j/i4RT9u4qJ+lqS/yCGap4lH4zZGzQ7tu+xZqQmcMZq5OBZDL4QRxQzRjkWcGt8IVw==",
+ "dev": true,
+ "dependencies": {
+ "@eslint/object-schema": "^2.1.4",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.2"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/config-array/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/config-array/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/core": {
+ "version": "0.7.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.7.0.tgz",
+ "integrity": "sha512-xp5Jirz5DyPYlPiKat8jaq0EmYvDXKKpzTbxXMpT9eqlRJkRKIz9AGMdlvYjih+im+QlhWrpvVjl8IPC/lHlUw==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.1.0.tgz",
+ "integrity": "sha512-4Bfj15dVJdoy3RfZmmo86RK1Fwzn6SstsvK9JS+BaVKqC6QQQQyXekNaC+g+LKNgkQ+2VhGAzm6hO40AhMR3zQ==",
+ "dev": true,
+ "dependencies": {
+ "ajv": "^6.12.4",
+ "debug": "^4.3.2",
+ "espree": "^10.0.1",
+ "globals": "^14.0.0",
+ "ignore": "^5.2.0",
+ "import-fresh": "^3.2.1",
+ "js-yaml": "^4.1.0",
+ "minimatch": "^3.1.2",
+ "strip-json-comments": "^3.1.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/@eslint/eslintrc/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/@eslint/js": {
+ "version": "9.14.0",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.14.0.tgz",
+ "integrity": "sha512-pFoEtFWCPyDOl+C6Ift+wC7Ro89otjigCf5vcuWqWgqNSQbRrpjSvdeE6ofLz4dHmyxD5f7gIdGT4+p36L6Twg==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.4.tgz",
+ "integrity": "sha512-BsWiH1yFGjXXS2yvrf5LyuoSIIbPrGUWob917o+BTKuZ7qJdxX8aJLRxs1fS9n6r7vESrq1OUqb68dANcFXuQQ==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.2.2",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.2.2.tgz",
+ "integrity": "sha512-CXtq5nR4Su+2I47WPOlWud98Y5Lv8Kyxp2ukhgFx/eW6Blm18VXJO5WuQylPugRo8nbluoi6GvvxBLqHcvqUUw==",
+ "dev": true,
+ "dependencies": {
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
+ },
+ "node_modules/@floating-ui/core": {
+ "version": "1.6.8",
+ "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.8.tgz",
+ "integrity": "sha512-7XJ9cPU+yI2QeLS+FCSlqNFZJq8arvswefkZrYI1yQBbftw6FyrZOxYSh+9S7z7TpeWlRt9zJ5IhM1WIL334jA==",
+ "dependencies": {
+ "@floating-ui/utils": "^0.2.8"
+ }
+ },
+ "node_modules/@floating-ui/dom": {
+ "version": "1.6.12",
+ "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.12.tgz",
+ "integrity": "sha512-NP83c0HjokcGVEMeoStg317VD9W7eDlGK7457dMBANbKA6GJZdc7rjujdgqzTaz93jkGgc5P/jeWbaCHnMNc+w==",
+ "dependencies": {
+ "@floating-ui/core": "^1.6.0",
+ "@floating-ui/utils": "^0.2.8"
+ }
+ },
+ "node_modules/@floating-ui/react": {
+ "version": "0.26.27",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.27.tgz",
+ "integrity": "sha512-jLP72x0Kr2CgY6eTYi/ra3VA9LOkTo4C+DUTrbFgFOExKy3omYVmwMjNKqxAHdsnyLS96BIDLcO2SlnsNf8KUQ==",
+ "dependencies": {
+ "@floating-ui/react-dom": "^2.1.2",
+ "@floating-ui/utils": "^0.2.8",
+ "tabbable": "^6.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/react-dom": {
+ "version": "2.1.2",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz",
+ "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==",
+ "dependencies": {
+ "@floating-ui/dom": "^1.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/@floating-ui/utils": {
+ "version": "0.2.8",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz",
+ "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig=="
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.1",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.1.tgz",
+ "integrity": "sha512-5DyQ4+1JEUzejeK1JGICcideyfUbGixgS9jNgex5nqkW+cY7WZhxBigmieN5Qnw9ZosSNVC9KQKyb+GUaGyKUA==",
+ "dev": true,
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.6",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.6.tgz",
+ "integrity": "sha512-YuI2ZHQL78Q5HbhDiBA1X4LmYdXCKCMQIfw0pw7piHJwyREFebJUvrQN4cMssyES6x+vfUbx1CIpaQUKYdQZOw==",
+ "dev": true,
+ "dependencies": {
+ "@humanfs/core": "^0.19.1",
+ "@humanwhocodes/retry": "^0.3.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node/node_modules/@humanwhocodes/retry": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.3.1.tgz",
+ "integrity": "sha512-JBxkERygn7Bv/GbN5Rv8Ul6LVknS+5Bp6RgDC/O8gEBU/yeH5Ui5C/OlWrTb6qct7LjjfT6Re2NxB0ln0yYybA==",
+ "dev": true,
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/module-importer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/module-importer/-/module-importer-1.0.1.tgz",
+ "integrity": "sha512-bxveV4V8v5Yb4ncFTT3rPSgZBOpCkjfK0y4oVVVJwIuDVBRMDXrPyXRL988i5ap9m9bnyEEjWfm5WkBmtffLfA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.1.tgz",
+ "integrity": "sha512-c7hNEllBlenFTHBky65mhq8WD2kbN9Q6gk0bTk8lSBvc554jpXSkST1iePudpt7+A/AQvuHs9EMqjHDXMY1lrA==",
+ "dev": true,
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@isaacs/cliui": {
+ "version": "8.0.2",
+ "resolved": "https://registry.npmjs.org/@isaacs/cliui/-/cliui-8.0.2.tgz",
+ "integrity": "sha512-O8jcjabXaleOG9DQ0+ARXWZBTfnP4WNAqzuiJK7ll44AmxGKv/J2M4TPjxjY3znBCfvBXFzucm1twdyFybFqEA==",
+ "dev": true,
+ "dependencies": {
+ "string-width": "^5.1.2",
+ "string-width-cjs": "npm:string-width@^4.2.0",
+ "strip-ansi": "^7.0.1",
+ "strip-ansi-cjs": "npm:strip-ansi@^6.0.1",
+ "wrap-ansi": "^8.1.0",
+ "wrap-ansi-cjs": "npm:wrap-ansi@^7.0.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
+ "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "dependencies": {
+ "@jridgewell/set-array": "^1.2.1",
+ "@jridgewell/sourcemap-codec": "^1.4.10",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/resolve-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.2.tgz",
+ "integrity": "sha512-bRISgCIjP20/tbWSPWMEi54QVPRZExkuD9lJL+UIxUKtwVJA8wW1Trb1jMs1RFXo1CBTNZ/5hpC9QvmKWdopKw==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/set-array": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.2.1.tgz",
+ "integrity": "sha512-R8gLRTZeyp03ymzP/6Lil/28tGeGEzhx1q2k703KGWRAI1VdvPIXdG70VJc2pAMw3NA6JKL5hhFu1sJX0Mnn/A==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
+ "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ=="
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.25",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.25.tgz",
+ "integrity": "sha512-vNk6aEwybGtawWmy/PzwnGDOjCkLWSD2wqvjGGAgOAwCGWySYXfYoxt00IJkTF+8Lb57DwOb3Aa0o9CApepiYQ==",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@jsdevtools/ono": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz",
+ "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg=="
+ },
+ "node_modules/@kurkle/color": {
+ "version": "0.3.2",
+ "resolved": "https://registry.npmjs.org/@kurkle/color/-/color-0.3.2.tgz",
+ "integrity": "sha512-fuscdXJ9G1qb7W8VdHi+IwRqij3lBkosAm4ydQtEmbY58OzHXqQhvlxqEkoz0yssNVn38bcpRWgA9PP+OGoisw=="
+ },
+ "node_modules/@lit-labs/ssr-dom-shim": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@lit-labs/ssr-dom-shim/-/ssr-dom-shim-1.2.1.tgz",
+ "integrity": "sha512-wx4aBmgeGvFmOKucFKY+8VFJSYZxs9poN3SDNQFF6lT6NrQUnHiPB2PWz2sc4ieEcAaYYzN+1uWahEeTq2aRIQ=="
+ },
+ "node_modules/@lit/react": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@lit/react/-/react-1.0.6.tgz",
+ "integrity": "sha512-QIss8MPh6qUoFJmuaF4dSHts3qCsA36S3HcOLiNPShxhgYPr4XJRnCBKPipk85sR9xr6TQrOcDMfexwbNdJHYA==",
+ "peerDependencies": {
+ "@types/react": "17 || 18"
+ }
+ },
+ "node_modules/@lit/reactive-element": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/@lit/reactive-element/-/reactive-element-2.0.4.tgz",
+ "integrity": "sha512-GFn91inaUa2oHLak8awSIigYz0cU0Payr1rcFsrkf5OJ5eSPxElyZfKh0f2p9FsTiZWXQdWGJeXZICEfXXYSXQ==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0"
+ }
+ },
+ "node_modules/@mediapipe/tasks-vision": {
+ "version": "0.10.8",
+ "resolved": "https://registry.npmjs.org/@mediapipe/tasks-vision/-/tasks-vision-0.10.8.tgz",
+ "integrity": "sha512-Rp7ll8BHrKB3wXaRFKhrltwZl1CiXGdibPxuWXvqGnKTnv8fqa/nvftYNuSbf+pbJWKYCXdBtYTITdAUTGGh0Q=="
+ },
+ "node_modules/@monaco-editor/loader": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.4.0.tgz",
+ "integrity": "sha512-00ioBig0x642hytVspPl7DbQyaSWRaolYie/UFNjoTdvoKPzo6xrXLhTk9ixgIKcLH5b5vDOjVNiGyY+uDCUlg==",
+ "dependencies": {
+ "state-local": "^1.0.6"
+ },
+ "peerDependencies": {
+ "monaco-editor": ">= 0.21.0 < 1"
+ }
+ },
+ "node_modules/@monaco-editor/react": {
+ "version": "4.6.0",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.6.0.tgz",
+ "integrity": "sha512-RFkU9/i7cN2bsq/iTkurMWOEErmYcY6JiQI3Jn+WeR/FGISH8JbHERjpS9oRuSOPvDMJI0Z8nJeKkbOs9sBYQw==",
+ "dependencies": {
+ "@monaco-editor/loader": "^1.4.0"
+ },
+ "peerDependencies": {
+ "monaco-editor": ">= 0.25.0 < 1",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@nivo/annotations": {
+ "version": "0.87.0",
+ "resolved": "https://registry.npmjs.org/@nivo/annotations/-/annotations-0.87.0.tgz",
+ "integrity": "sha512-4Xk/soEmi706iOKszjX1EcGLBNIvhMifCYXOuLIFlMAXqhw1x2YS7PxickVSskdSzJCwJX4NgQ/R/9u6nxc5OA==",
+ "dependencies": {
+ "@nivo/colors": "0.87.0",
+ "@nivo/core": "0.87.0",
+ "@react-spring/web": "9.4.5 || ^9.7.2",
+ "lodash": "^4.17.21"
+ },
+ "peerDependencies": {
+ "react": ">= 16.14.0 < 19.0.0"
+ }
+ },
+ "node_modules/@nivo/axes": {
+ "version": "0.87.0",
+ "resolved": "https://registry.npmjs.org/@nivo/axes/-/axes-0.87.0.tgz",
+ "integrity": "sha512-zCRBfiRKJi+xOxwxH5Pxq/8+yv3fAYDl4a1F2Ssnp5gMIobwzVsdearvsm5B04e9bfy3ZXTL7KgbkEkSAwu6SA==",
+ "dependencies": {
+ "@nivo/core": "0.87.0",
+ "@nivo/scales": "0.87.0",
+ "@react-spring/web": "9.4.5 || ^9.7.2",
+ "@types/d3-format": "^1.4.1",
+ "@types/d3-time-format": "^2.3.1",
+ "d3-format": "^1.4.4",
+ "d3-time-format": "^3.0.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.14.0 < 19.0.0"
+ }
+ },
+ "node_modules/@nivo/axes/node_modules/d3-format": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz",
+ "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ=="
+ },
+ "node_modules/@nivo/colors": {
+ "version": "0.87.0",
+ "resolved": "https://registry.npmjs.org/@nivo/colors/-/colors-0.87.0.tgz",
+ "integrity": "sha512-S4pZzRGKK23t8XAjQMhML6wwsfKO9nH03xuyN4SvCodNA/Dmdys9xV+9Dg/VILTzvzsBTBGTX0dFBg65WoKfVg==",
+ "dependencies": {
+ "@nivo/core": "0.87.0",
+ "@types/d3-color": "^3.0.0",
+ "@types/d3-scale": "^4.0.8",
+ "@types/d3-scale-chromatic": "^3.0.0",
+ "@types/prop-types": "^15.7.2",
+ "d3-color": "^3.1.0",
+ "d3-scale": "^4.0.2",
+ "d3-scale-chromatic": "^3.0.0",
+ "lodash": "^4.17.21",
+ "prop-types": "^15.7.2"
+ },
+ "peerDependencies": {
+ "react": ">= 16.14.0 < 19.0.0"
+ }
+ },
+ "node_modules/@nivo/core": {
+ "version": "0.87.0",
+ "resolved": "https://registry.npmjs.org/@nivo/core/-/core-0.87.0.tgz",
+ "integrity": "sha512-yEQWJn7QjWnbmCZccBCo4dligNyNyz3kgyV9vEtcaB1iGeKhg55RJEAlCOul+IDgSCSPFci2SxTmipE6LZEZCg==",
+ "dependencies": {
+ "@nivo/tooltip": "0.87.0",
+ "@react-spring/web": "9.4.5 || ^9.7.2",
+ "@types/d3-shape": "^3.1.6",
+ "d3-color": "^3.1.0",
+ "d3-format": "^1.4.4",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-scale-chromatic": "^3.0.0",
+ "d3-shape": "^3.2.0",
+ "d3-time-format": "^3.0.0",
+ "lodash": "^4.17.21",
+ "prop-types": "^15.7.2"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/nivo/donate"
+ },
+ "peerDependencies": {
+ "react": ">= 16.14.0 < 19.0.0"
+ }
+ },
+ "node_modules/@nivo/core/node_modules/d3-format": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-1.4.5.tgz",
+ "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ=="
+ },
+ "node_modules/@nivo/legends": {
+ "version": "0.87.0",
+ "resolved": "https://registry.npmjs.org/@nivo/legends/-/legends-0.87.0.tgz",
+ "integrity": "sha512-bVJCeqEmK4qHrxNaPU/+hXUd/yaKlcQ0yrsR18ewoknVX+pgvbe/+tRKJ+835JXlvRijYIuqwK1sUJQIxyB7oA==",
+ "dependencies": {
+ "@nivo/colors": "0.87.0",
+ "@nivo/core": "0.87.0",
+ "@types/d3-scale": "^4.0.8",
+ "d3-scale": "^4.0.2"
+ },
+ "peerDependencies": {
+ "react": ">= 16.14.0 < 19.0.0"
+ }
+ },
+ "node_modules/@nivo/line": {
+ "version": "0.87.0",
+ "resolved": "https://registry.npmjs.org/@nivo/line/-/line-0.87.0.tgz",
+ "integrity": "sha512-Ki/WDd8ZU8VWScW4ZeKUFCXRdAEg8nrS+F+jdfJDPxyxUMHZJCAbrXrnsExcEQLOaDQ2aU/bijEMiDS8/dJzuA==",
+ "dependencies": {
+ "@nivo/annotations": "0.87.0",
+ "@nivo/axes": "0.87.0",
+ "@nivo/colors": "0.87.0",
+ "@nivo/core": "0.87.0",
+ "@nivo/legends": "0.87.0",
+ "@nivo/scales": "0.87.0",
+ "@nivo/tooltip": "0.87.0",
+ "@nivo/voronoi": "0.87.0",
+ "@react-spring/web": "9.4.5 || ^9.7.2",
+ "d3-shape": "^3.2.0"
+ },
+ "peerDependencies": {
+ "react": ">= 16.14.0 < 19.0.0"
+ }
+ },
+ "node_modules/@nivo/scales": {
+ "version": "0.87.0",
+ "resolved": "https://registry.npmjs.org/@nivo/scales/-/scales-0.87.0.tgz",
+ "integrity": "sha512-IHdY9w2em/xpWurcbhUR3cUA1dgbY06rU8gmA/skFCwf3C4Da3Rqwr0XqvxmkDC+EdT/iFljMbLst7VYiCnSdw==",
+ "dependencies": {
+ "@types/d3-scale": "^4.0.8",
+ "@types/d3-time": "^1.1.1",
+ "@types/d3-time-format": "^3.0.0",
+ "d3-scale": "^4.0.2",
+ "d3-time": "^1.0.11",
+ "d3-time-format": "^3.0.0",
+ "lodash": "^4.17.21"
+ }
+ },
+ "node_modules/@nivo/scales/node_modules/@types/d3-time-format": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-3.0.4.tgz",
+ "integrity": "sha512-or9DiDnYI1h38J9hxKEsw513+KVuFbEVhl7qdxcaudoiqWWepapUen+2vAriFGexr6W5+P4l9+HJrB39GG+oRg=="
+ },
+ "node_modules/@nivo/tooltip": {
+ "version": "0.87.0",
+ "resolved": "https://registry.npmjs.org/@nivo/tooltip/-/tooltip-0.87.0.tgz",
+ "integrity": "sha512-nZJWyRIt/45V/JBdJ9ksmNm1LFfj59G1Dy9wB63Icf2YwyBT+J+zCzOGXaY7gxCxgF1mnSL3dC7fttcEdXyN/g==",
+ "dependencies": {
+ "@nivo/core": "0.87.0",
+ "@react-spring/web": "9.4.5 || ^9.7.2"
+ },
+ "peerDependencies": {
+ "react": ">= 16.14.0 < 19.0.0"
+ }
+ },
+ "node_modules/@nivo/voronoi": {
+ "version": "0.87.0",
+ "resolved": "https://registry.npmjs.org/@nivo/voronoi/-/voronoi-0.87.0.tgz",
+ "integrity": "sha512-Tg+9YnCX8LKsEwZMY1Q83mWiVFiyU2smxrO3JaC9vzjIh/2A/bkNPwC6BdmRaQMvY1jngKs+WKDnNxSQWFSOEg==",
+ "dependencies": {
+ "@nivo/core": "0.87.0",
+ "@nivo/tooltip": "0.87.0",
+ "@types/d3-delaunay": "^6.0.4",
+ "@types/d3-scale": "^4.0.8",
+ "d3-delaunay": "^6.0.4",
+ "d3-scale": "^4.0.2"
+ },
+ "peerDependencies": {
+ "react": ">= 16.14.0 < 19.0.0"
+ }
+ },
+ "node_modules/@nodelib/fs.scandir": {
+ "version": "2.1.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.scandir/-/fs.scandir-2.1.5.tgz",
+ "integrity": "sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "2.0.5",
+ "run-parallel": "^1.1.9"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.stat": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
+ "integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@nodelib/fs.walk": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
+ "integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.scandir": "2.1.5",
+ "fastq": "^1.6.0"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/@pkgjs/parseargs": {
+ "version": "0.11.0",
+ "resolved": "https://registry.npmjs.org/@pkgjs/parseargs/-/parseargs-0.11.0.tgz",
+ "integrity": "sha512-+1VkjdD0QBLPodGrJUeqarH8VAIvQODIbwh9XpP5Syisf7YoQgsJKPNFoqqLQlu+VQ/tVSshMR6loPMn8U+dPg==",
+ "dev": true,
+ "optional": true,
+ "engines": {
+ "node": ">=14"
+ }
+ },
+ "node_modules/@react-spring/animated": {
+ "version": "9.7.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.7.5.tgz",
+ "integrity": "sha512-Tqrwz7pIlsSDITzxoLS3n/v/YCUHQdOIKtOJf4yL6kYVSDTSmVK1LI1Q3M/uu2Sx4X3pIWF3xLUhlsA6SPNTNg==",
+ "dependencies": {
+ "@react-spring/shared": "~9.7.5",
+ "@react-spring/types": "~9.7.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-spring/core": {
+ "version": "9.7.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.7.5.tgz",
+ "integrity": "sha512-rmEqcxRcu7dWh7MnCcMXLvrf6/SDlSokLaLTxiPlAYi11nN3B5oiCUAblO72o+9z/87j2uzxa2Inm8UbLjXA+w==",
+ "dependencies": {
+ "@react-spring/animated": "~9.7.5",
+ "@react-spring/shared": "~9.7.5",
+ "@react-spring/types": "~9.7.5"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-spring/donate"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-spring/rafz": {
+ "version": "9.7.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.7.5.tgz",
+ "integrity": "sha512-5ZenDQMC48wjUzPAm1EtwQ5Ot3bLIAwwqP2w2owG5KoNdNHpEJV263nGhCeKKmuA3vG2zLLOdu3or6kuDjA6Aw=="
+ },
+ "node_modules/@react-spring/shared": {
+ "version": "9.7.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.7.5.tgz",
+ "integrity": "sha512-wdtoJrhUeeyD/PP/zo+np2s1Z820Ohr/BbuVYv+3dVLW7WctoiN7std8rISoYoHpUXtbkpesSKuPIw/6U1w1Pw==",
+ "dependencies": {
+ "@react-spring/rafz": "~9.7.5",
+ "@react-spring/types": "~9.7.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-spring/three": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/three/-/three-9.6.1.tgz",
+ "integrity": "sha512-Tyw2YhZPKJAX3t2FcqvpLRb71CyTe1GvT3V+i+xJzfALgpk10uPGdGaQQ5Xrzmok1340DAeg2pR/MCfaW7b8AA==",
+ "dependencies": {
+ "@react-spring/animated": "~9.6.1",
+ "@react-spring/core": "~9.6.1",
+ "@react-spring/shared": "~9.6.1",
+ "@react-spring/types": "~9.6.1"
+ },
+ "peerDependencies": {
+ "@react-three/fiber": ">=6.0",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "three": ">=0.126"
+ }
+ },
+ "node_modules/@react-spring/three/node_modules/@react-spring/animated": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/animated/-/animated-9.6.1.tgz",
+ "integrity": "sha512-ls/rJBrAqiAYozjLo5EPPLLOb1LM0lNVQcXODTC1SMtS6DbuBCPaKco5svFUQFMP2dso3O+qcC4k9FsKc0KxMQ==",
+ "dependencies": {
+ "@react-spring/shared": "~9.6.1",
+ "@react-spring/types": "~9.6.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-spring/three/node_modules/@react-spring/core": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/core/-/core-9.6.1.tgz",
+ "integrity": "sha512-3HAAinAyCPessyQNNXe5W0OHzRfa8Yo5P748paPcmMowZ/4sMfaZ2ZB6e5x5khQI8NusOHj8nquoutd6FRY5WQ==",
+ "dependencies": {
+ "@react-spring/animated": "~9.6.1",
+ "@react-spring/rafz": "~9.6.1",
+ "@react-spring/shared": "~9.6.1",
+ "@react-spring/types": "~9.6.1"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/react-spring/donate"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-spring/three/node_modules/@react-spring/rafz": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/rafz/-/rafz-9.6.1.tgz",
+ "integrity": "sha512-v6qbgNRpztJFFfSE3e2W1Uz+g8KnIBs6SmzCzcVVF61GdGfGOuBrbjIcp+nUz301awVmREKi4eMQb2Ab2gGgyQ=="
+ },
+ "node_modules/@react-spring/three/node_modules/@react-spring/shared": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/shared/-/shared-9.6.1.tgz",
+ "integrity": "sha512-PBFBXabxFEuF8enNLkVqMC9h5uLRBo6GQhRMQT/nRTnemVENimgRd+0ZT4yFnAQ0AxWNiJfX3qux+bW2LbG6Bw==",
+ "dependencies": {
+ "@react-spring/rafz": "~9.6.1",
+ "@react-spring/types": "~9.6.1"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-spring/three/node_modules/@react-spring/types": {
+ "version": "9.6.1",
+ "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.6.1.tgz",
+ "integrity": "sha512-POu8Mk0hIU3lRXB3bGIGe4VHIwwDsQyoD1F394OK7STTiX9w4dG3cTLljjYswkQN+hDSHRrj4O36kuVa7KPU8Q=="
+ },
+ "node_modules/@react-spring/types": {
+ "version": "9.7.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/types/-/types-9.7.5.tgz",
+ "integrity": "sha512-HVj7LrZ4ReHWBimBvu2SKND3cDVUPWKLqRTmWe/fNY6o1owGOX0cAHbdPDTMelgBlVbrTKrre6lFkhqGZErK/g=="
+ },
+ "node_modules/@react-spring/web": {
+ "version": "9.7.5",
+ "resolved": "https://registry.npmjs.org/@react-spring/web/-/web-9.7.5.tgz",
+ "integrity": "sha512-lmvqGwpe+CSttsWNZVr+Dg62adtKhauGwLyGE/RRyZ8AAMLgb9x3NDMA5RMElXo+IMyTkPp7nxTB8ZQlmhb6JQ==",
+ "dependencies": {
+ "@react-spring/animated": "~9.7.5",
+ "@react-spring/core": "~9.7.5",
+ "@react-spring/shared": "~9.7.5",
+ "@react-spring/types": "~9.7.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/@react-three/fiber": {
+ "version": "8.13.5",
+ "resolved": "https://registry.npmjs.org/@react-three/fiber/-/fiber-8.13.5.tgz",
+ "integrity": "sha512-x9QdsaB/Wm/6NGvRXQahPPWfn2dQce7Fg3C2r00NNzyDdqRKw32YavL+WEqjZOOd0nvFpzv7FtaKc+VCOTR59w==",
+ "dependencies": {
+ "@babel/runtime": "^7.17.8",
+ "@types/react-reconciler": "^0.26.7",
+ "its-fine": "^1.0.6",
+ "react-reconciler": "^0.27.0",
+ "react-use-measure": "^2.1.1",
+ "scheduler": "^0.21.0",
+ "suspend-react": "^0.1.3",
+ "zustand": "^3.7.1"
+ },
+ "peerDependencies": {
+ "expo": ">=43.0",
+ "expo-asset": ">=8.4",
+ "expo-gl": ">=11.0",
+ "react": ">=18.0",
+ "react-dom": ">=18.0",
+ "react-native": ">=0.64",
+ "three": ">=0.133"
+ },
+ "peerDependenciesMeta": {
+ "expo": {
+ "optional": true
+ },
+ "expo-asset": {
+ "optional": true
+ },
+ "expo-gl": {
+ "optional": true
+ },
+ "react-dom": {
+ "optional": true
+ },
+ "react-native": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@react-three/fiber/node_modules/scheduler": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz",
+ "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/@react-three/fiber/node_modules/zustand": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
+ "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
+ "engines": {
+ "node": ">=12.7.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@redocly/ajv": {
+ "version": "8.11.2",
+ "resolved": "https://registry.npmjs.org/@redocly/ajv/-/ajv-8.11.2.tgz",
+ "integrity": "sha512-io1JpnwtIcvojV7QKDUSIuMN/ikdOUd1ReEnUnMKGfDVridQZ31J0MmIuqwuRjWDZfmvr+Q0MqCcfHM2gTivOg==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js-replace": "^1.0.1"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@redocly/ajv/node_modules/json-schema-traverse": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true
+ },
+ "node_modules/@redocly/config": {
+ "version": "0.16.0",
+ "resolved": "https://registry.npmjs.org/@redocly/config/-/config-0.16.0.tgz",
+ "integrity": "sha512-t9jnODbUcuANRSl/K4L9nb12V+U5acIHnVSl26NWrtSdDZVtoqUXk2yGFPZzohYf62cCfEQUT8ouJ3bhPfpnJg==",
+ "dev": true
+ },
+ "node_modules/@redocly/openapi-core": {
+ "version": "1.25.11",
+ "resolved": "https://registry.npmjs.org/@redocly/openapi-core/-/openapi-core-1.25.11.tgz",
+ "integrity": "sha512-bH+a8izQz4fnKROKoX3bEU8sQ9rjvEIZOqU6qTmxlhOJ0NsKa5e+LmU18SV0oFeg5YhWQhhEDihXkvKJ1wMMNQ==",
+ "dev": true,
+ "dependencies": {
+ "@redocly/ajv": "^8.11.2",
+ "@redocly/config": "^0.16.0",
+ "colorette": "^1.2.0",
+ "https-proxy-agent": "^7.0.4",
+ "js-levenshtein": "^1.1.6",
+ "js-yaml": "^4.1.0",
+ "lodash.isequal": "^4.5.0",
+ "minimatch": "^5.0.1",
+ "node-fetch": "^2.6.1",
+ "pluralize": "^8.0.0",
+ "yaml-ast-parser": "0.0.43"
+ },
+ "engines": {
+ "node": ">=14.19.0",
+ "npm": ">=7.0.0"
+ }
+ },
+ "node_modules/@redocly/openapi-core/node_modules/minimatch": {
+ "version": "5.1.6",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz",
+ "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/@redocly/openapi-core/node_modules/node-fetch": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz",
+ "integrity": "sha512-c4FRfUm/dbcWZ7U+1Wq0AwCyFL+3nt2bEw05wfxSz+DWpWsitgmSgYmy2dQdWyKC1694ELPqMs/YzUSNozLt8A==",
+ "dev": true,
+ "dependencies": {
+ "whatwg-url": "^5.0.0"
+ },
+ "engines": {
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@remix-run/router": {
+ "version": "1.21.0",
+ "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.21.0.tgz",
+ "integrity": "sha512-xfSkCAchbdG5PnbrKqFWwia4Bi61nH+wm8wLEqfHDyp7Y3dZzgqS2itV8i4gAq9pC2HsTpwyBC6Ds8VHZ96JlA==",
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/@rollup/rollup-android-arm-eabi": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm-eabi/-/rollup-android-arm-eabi-4.25.0.tgz",
+ "integrity": "sha512-CC/ZqFZwlAIbU1wUPisHyV/XRc5RydFrNLtgl3dGYskdwPZdt4HERtKm50a/+DtTlKeCq9IXFEWR+P6blwjqBA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-android-arm64": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-android-arm64/-/rollup-android-arm64-4.25.0.tgz",
+ "integrity": "sha512-/Y76tmLGUJqVBXXCfVS8Q8FJqYGhgH4wl4qTA24E9v/IJM0XvJCGQVSW1QZ4J+VURO9h8YCa28sTFacZXwK7Rg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "android"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-arm64": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-arm64/-/rollup-darwin-arm64-4.25.0.tgz",
+ "integrity": "sha512-YVT6L3UrKTlC0FpCZd0MGA7NVdp7YNaEqkENbWQ7AOVOqd/7VzyHpgIpc1mIaxRAo1ZsJRH45fq8j4N63I/vvg==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-darwin-x64": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-darwin-x64/-/rollup-darwin-x64-4.25.0.tgz",
+ "integrity": "sha512-ZRL+gexs3+ZmmWmGKEU43Bdn67kWnMeWXLFhcVv5Un8FQcx38yulHBA7XR2+KQdYIOtD0yZDWBCudmfj6lQJoA==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-arm64": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-arm64/-/rollup-freebsd-arm64-4.25.0.tgz",
+ "integrity": "sha512-xpEIXhiP27EAylEpreCozozsxWQ2TJbOLSivGfXhU4G1TBVEYtUPi2pOZBnvGXHyOdLAUUhPnJzH3ah5cqF01g==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-freebsd-x64": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-freebsd-x64/-/rollup-freebsd-x64-4.25.0.tgz",
+ "integrity": "sha512-sC5FsmZGlJv5dOcURrsnIK7ngc3Kirnx3as2XU9uER+zjfyqIjdcMVgzy4cOawhsssqzoAX19qmxgJ8a14Qrqw==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "freebsd"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-gnueabihf": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-gnueabihf/-/rollup-linux-arm-gnueabihf-4.25.0.tgz",
+ "integrity": "sha512-uD/dbLSs1BEPzg564TpRAQ/YvTnCds2XxyOndAO8nJhaQcqQGFgv/DAVko/ZHap3boCvxnzYMa3mTkV/B/3SWA==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm-musleabihf": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm-musleabihf/-/rollup-linux-arm-musleabihf-4.25.0.tgz",
+ "integrity": "sha512-ZVt/XkrDlQWegDWrwyC3l0OfAF7yeJUF4fq5RMS07YM72BlSfn2fQQ6lPyBNjt+YbczMguPiJoCfaQC2dnflpQ==",
+ "cpu": [
+ "arm"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-gnu": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-gnu/-/rollup-linux-arm64-gnu-4.25.0.tgz",
+ "integrity": "sha512-qboZ+T0gHAW2kkSDPHxu7quaFaaBlynODXpBVnPxUgvWYaE84xgCKAPEYE+fSMd3Zv5PyFZR+L0tCdYCMAtG0A==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-arm64-musl": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-arm64-musl/-/rollup-linux-arm64-musl-4.25.0.tgz",
+ "integrity": "sha512-ndWTSEmAaKr88dBuogGH2NZaxe7u2rDoArsejNslugHZ+r44NfWiwjzizVS1nUOHo+n1Z6qV3X60rqE/HlISgw==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-powerpc64le-gnu": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-powerpc64le-gnu/-/rollup-linux-powerpc64le-gnu-4.25.0.tgz",
+ "integrity": "sha512-BVSQvVa2v5hKwJSy6X7W1fjDex6yZnNKy3Kx1JGimccHft6HV0THTwNtC2zawtNXKUu+S5CjXslilYdKBAadzA==",
+ "cpu": [
+ "ppc64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-riscv64-gnu": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-riscv64-gnu/-/rollup-linux-riscv64-gnu-4.25.0.tgz",
+ "integrity": "sha512-G4hTREQrIdeV0PE2JruzI+vXdRnaK1pg64hemHq2v5fhv8C7WjVaeXc9P5i4Q5UC06d/L+zA0mszYIKl+wY8oA==",
+ "cpu": [
+ "riscv64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-s390x-gnu": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-s390x-gnu/-/rollup-linux-s390x-gnu-4.25.0.tgz",
+ "integrity": "sha512-9T/w0kQ+upxdkFL9zPVB6zy9vWW1deA3g8IauJxojN4bnz5FwSsUAD034KpXIVX5j5p/rn6XqumBMxfRkcHapQ==",
+ "cpu": [
+ "s390x"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-gnu": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-gnu/-/rollup-linux-x64-gnu-4.25.0.tgz",
+ "integrity": "sha512-ThcnU0EcMDn+J4B9LD++OgBYxZusuA7iemIIiz5yzEcFg04VZFzdFjuwPdlURmYPZw+fgVrFzj4CA64jSTG4Ig==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-linux-x64-musl": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-linux-x64-musl/-/rollup-linux-x64-musl-4.25.0.tgz",
+ "integrity": "sha512-zx71aY2oQxGxAT1JShfhNG79PnjYhMC6voAjzpu/xmMjDnKNf6Nl/xv7YaB/9SIa9jDYf8RBPWEnjcdlhlv1rQ==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "linux"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-arm64-msvc": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-arm64-msvc/-/rollup-win32-arm64-msvc-4.25.0.tgz",
+ "integrity": "sha512-JT8tcjNocMs4CylWY/CxVLnv8e1lE7ff1fi6kbGocWwxDq9pj30IJ28Peb+Y8yiPNSF28oad42ApJB8oUkwGww==",
+ "cpu": [
+ "arm64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-ia32-msvc": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-ia32-msvc/-/rollup-win32-ia32-msvc-4.25.0.tgz",
+ "integrity": "sha512-dRLjLsO3dNOfSN6tjyVlG+Msm4IiZnGkuZ7G5NmpzwF9oOc582FZG05+UdfTbz5Jd4buK/wMb6UeHFhG18+OEg==",
+ "cpu": [
+ "ia32"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rollup/rollup-win32-x64-msvc": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/@rollup/rollup-win32-x64-msvc/-/rollup-win32-x64-msvc-4.25.0.tgz",
+ "integrity": "sha512-/RqrIFtLB926frMhZD0a5oDa4eFIbyNEwLLloMTEjmqfwZWXywwVVOVmwTsuyhC9HKkVEZcOOi+KV4U9wmOdlg==",
+ "cpu": [
+ "x64"
+ ],
+ "dev": true,
+ "optional": true,
+ "os": [
+ "win32"
+ ]
+ },
+ "node_modules/@rtsao/scc": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/@rtsao/scc/-/scc-1.1.0.tgz",
+ "integrity": "sha512-zt6OdqaDoOnJ1ZYsCYGt9YmWzDXl4vQdKTyJev62gFhRGKdx7mcT54V9KIjg+d2wi9EXsPvAPKe7i7WjfVWB8g==",
+ "dev": true
+ },
+ "node_modules/@tailwindcss/typography": {
+ "version": "0.5.15",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/typography/-/typography-0.5.15.tgz",
+ "integrity": "sha512-AqhlCXl+8grUz8uqExv5OTtgpjuVIwFTSXTrh8y9/pw6q2ek7fJ+Y8ZEVw7EB2DCcuCOtEjf9w3+J3rzts01uA==",
+ "dev": true,
+ "dependencies": {
+ "lodash.castarray": "^4.4.0",
+ "lodash.isplainobject": "^4.0.6",
+ "lodash.merge": "^4.6.2",
+ "postcss-selector-parser": "6.0.10"
+ },
+ "peerDependencies": {
+ "tailwindcss": ">=3.0.0 || insiders || >=4.0.0-alpha.20"
+ }
+ },
+ "node_modules/@tanstack/query-core": {
+ "version": "5.59.20",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.59.20.tgz",
+ "integrity": "sha512-e8vw0lf7KwfGe1if4uPFhvZRWULqHjFcz3K8AebtieXvnMOz5FSzlZe3mTLlPuUBcydCnBRqYs2YJ5ys68wwLg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tanstack/react-query": {
+ "version": "5.59.20",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.59.20.tgz",
+ "integrity": "sha512-Zly0egsK0tFdfSbh5/mapSa+Zfc3Et0Zkar7Wo5sQkFzWyB3p3uZWOHR2wrlAEEV2L953eLuDBtbgFvMYiLvUw==",
+ "dependencies": {
+ "@tanstack/query-core": "5.59.20"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": "^18 || ^19"
+ }
+ },
+ "node_modules/@tanstack/react-table": {
+ "version": "8.20.5",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-table/-/react-table-8.20.5.tgz",
+ "integrity": "sha512-WEHopKw3znbUZ61s9i0+i9g8drmDo6asTWbrQh8Us63DAk/M0FkmIqERew6P71HI75ksZ2Pxyuf4vvKh9rAkiA==",
+ "dependencies": {
+ "@tanstack/table-core": "8.20.5"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/@tanstack/table-core": {
+ "version": "8.20.5",
+ "resolved": "https://registry.npmjs.org/@tanstack/table-core/-/table-core-8.20.5.tgz",
+ "integrity": "sha512-P9dF7XbibHph2PFRz8gfBKEXEY/HJPOhym8CHmjF8y3q5mWpKx9xtZapXQUWCgkqvsK0R46Azuz+VaxD4Xl+Tg==",
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
+ "node_modules/@tweenjs/tween.js": {
+ "version": "23.1.3",
+ "resolved": "https://registry.npmjs.org/@tweenjs/tween.js/-/tween.js-23.1.3.tgz",
+ "integrity": "sha512-vJmvvwFxYuGnF2axRtPYocag6Clbb5YS7kLL+SO/TeVFzHqDIWrNKYtcsPMibjDx9O+bu+psAy9NKfWklassUA=="
+ },
+ "node_modules/@types/babel__core": {
+ "version": "7.20.5",
+ "resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
+ "integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.20.7",
+ "@babel/types": "^7.20.7",
+ "@types/babel__generator": "*",
+ "@types/babel__template": "*",
+ "@types/babel__traverse": "*"
+ }
+ },
+ "node_modules/@types/babel__generator": {
+ "version": "7.6.8",
+ "resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.8.tgz",
+ "integrity": "sha512-ASsj+tpEDsEiFr1arWrlN6V3mdfjRMZt6LtK/Vp/kreFLnr5QH5+DhvD5nINYZXzwJvXeGq+05iUXcAzVrqWtw==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__template": {
+ "version": "7.4.4",
+ "resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.4.tgz",
+ "integrity": "sha512-h/NUaSyG5EyxBIp8YRxo4RMe2/qQgvyowRwVMzhYhBCONbW8PUsg4lkFMrhgZhUe5z3L3MiLDuvyJ/CaPa2A8A==",
+ "dev": true,
+ "dependencies": {
+ "@babel/parser": "^7.1.0",
+ "@babel/types": "^7.0.0"
+ }
+ },
+ "node_modules/@types/babel__traverse": {
+ "version": "7.20.6",
+ "resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.6.tgz",
+ "integrity": "sha512-r1bzfrm0tomOI8g1SzvCaQHo6Lcv6zu0EA+W2kHrt8dyrHQxGzBBL4kdkzIS+jBMV+EYcMAEAqXqYaLJq5rOZg==",
+ "dev": true,
+ "dependencies": {
+ "@babel/types": "^7.20.7"
+ }
+ },
+ "node_modules/@types/d3-array": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz",
+ "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg=="
+ },
+ "node_modules/@types/d3-color": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz",
+ "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A=="
+ },
+ "node_modules/@types/d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw=="
+ },
+ "node_modules/@types/d3-ease": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz",
+ "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA=="
+ },
+ "node_modules/@types/d3-format": {
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-1.4.5.tgz",
+ "integrity": "sha512-mLxrC1MSWupOSncXN/HOlWUAAIffAEBaI4+PKy2uMPsKe4FNZlk7qrbTjmzJXITQQqBHivaks4Td18azgqnotA=="
+ },
+ "node_modules/@types/d3-interpolate": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz",
+ "integrity": "sha512-mgLPETlrpVV1YRJIglr4Ez47g7Yxjl1lj7YKsiMCb27VJH9W8NVM6Bb9d8kkpG/uAQS5AmbA48q2IAolKKo1MA==",
+ "dependencies": {
+ "@types/d3-color": "*"
+ }
+ },
+ "node_modules/@types/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ=="
+ },
+ "node_modules/@types/d3-scale": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz",
+ "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==",
+ "dependencies": {
+ "@types/d3-time": "*"
+ }
+ },
+ "node_modules/@types/d3-scale-chromatic": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz",
+ "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw=="
+ },
+ "node_modules/@types/d3-shape": {
+ "version": "3.1.6",
+ "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz",
+ "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==",
+ "dependencies": {
+ "@types/d3-path": "*"
+ }
+ },
+ "node_modules/@types/d3-time": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-1.1.4.tgz",
+ "integrity": "sha512-JIvy2HjRInE+TXOmIGN5LCmeO0hkFZx5f9FZ7kiN+D+YTcc8pptsiLiuHsvwxwC7VVKmJ2ExHUgNlAiV7vQM9g=="
+ },
+ "node_modules/@types/d3-time-format": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-2.3.4.tgz",
+ "integrity": "sha512-xdDXbpVO74EvadI3UDxjxTdR6QIxm1FKzEA/+F8tL4GWWUg/hgvBqf6chql64U5A9ZUGWo7pEu4eNlyLwbKdhg=="
+ },
+ "node_modules/@types/d3-timer": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz",
+ "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw=="
+ },
+ "node_modules/@types/draco3d": {
+ "version": "1.4.10",
+ "resolved": "https://registry.npmjs.org/@types/draco3d/-/draco3d-1.4.10.tgz",
+ "integrity": "sha512-AX22jp8Y7wwaBgAixaSvkoG4M/+PlAcm3Qs4OW8yT9DM4xUpWKeFhLueTAyZF39pviAdcDdeJoACapiAceqNcw=="
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.6.tgz",
+ "integrity": "sha512-AYnb1nQyY49te+VRAVgmzfcgjYS91mY5P0TKUDCLEM+gNnA+3T6rWITXRLYCpahpqSQbN5cE+gHpnPyXjHWxcw==",
+ "dev": true
+ },
+ "node_modules/@types/json-schema": {
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA=="
+ },
+ "node_modules/@types/json5": {
+ "version": "0.0.29",
+ "resolved": "https://registry.npmjs.org/@types/json5/-/json5-0.0.29.tgz",
+ "integrity": "sha512-dRLjCWHYg4oaA77cxO64oO+7JwCwnIzkZPdrrC71jQmQtlhM556pwKo5bUzqvZndkVbeFLIIi+9TC40JNF5hNQ==",
+ "dev": true
+ },
+ "node_modules/@types/offscreencanvas": {
+ "version": "2019.7.3",
+ "resolved": "https://registry.npmjs.org/@types/offscreencanvas/-/offscreencanvas-2019.7.3.tgz",
+ "integrity": "sha512-ieXiYmgSRXUDeOntE1InxjWyvEelZGP63M+cGuquuRLuIKKT1osnkXjxev9B7d1nXSug5vpunx+gNlbVxMlC9A=="
+ },
+ "node_modules/@types/parse-json": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
+ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw=="
+ },
+ "node_modules/@types/prop-types": {
+ "version": "15.7.13",
+ "resolved": "https://registry.npmjs.org/@types/prop-types/-/prop-types-15.7.13.tgz",
+ "integrity": "sha512-hCZTSvwbzWGvhqxp/RqVqwU999pBf2vp7hzIjiYOsl8wqOmUxkQ6ddw1cV3l8811+kdUFus/q4d1Y3E3SyEifA=="
+ },
+ "node_modules/@types/react": {
+ "version": "18.3.12",
+ "resolved": "https://registry.npmjs.org/@types/react/-/react-18.3.12.tgz",
+ "integrity": "sha512-D2wOSq/d6Agt28q7rSI3jhU7G6aiuzljDGZ2hTZHIkrTLUI+AF3WMeKkEZ9nN2fkBAlcktT6vcZjDFiIhMYEQw==",
+ "dependencies": {
+ "@types/prop-types": "*",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/@types/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/@types/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-qW1Mfv8taImTthu4KoXgDfLuk4bydU6Q/TkADnDWWHwi4NX4BR+LWfTp2sVmTqRrsHvyDDTelgelxJ+SsejKKQ==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-json-editor-ajrm": {
+ "version": "2.5.6",
+ "resolved": "https://registry.npmjs.org/@types/react-json-editor-ajrm/-/react-json-editor-ajrm-2.5.6.tgz",
+ "integrity": "sha512-Dk8WUF0UPzHCnDfgNQ7EBtjZRsHLZPfjm/fFZOrHVO4TbD1EQpKS/i8p3EpVEnvgE5LJack35eAxFjxN1UWMnA==",
+ "dev": true,
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-reconciler": {
+ "version": "0.26.7",
+ "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.26.7.tgz",
+ "integrity": "sha512-mBDYl8x+oyPX/VBb3E638N0B7xG+SPk/EAMcVPeexqus/5aTpTphQi0curhhshOqRrc9t6OPoJfEUkbymse/lQ==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/react-transition-group": {
+ "version": "4.4.11",
+ "resolved": "https://registry.npmjs.org/@types/react-transition-group/-/react-transition-group-4.4.11.tgz",
+ "integrity": "sha512-RM05tAniPZ5DZPzzNFP+DmrcOdD0efDUxMy3145oljWSl3x9ZV5vhme98gTxFrj2lhXvmGNnUiuDyJgY9IKkNA==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/@types/stats.js": {
+ "version": "0.17.3",
+ "resolved": "https://registry.npmjs.org/@types/stats.js/-/stats.js-0.17.3.tgz",
+ "integrity": "sha512-pXNfAD3KHOdif9EQXZ9deK82HVNaXP5ZIF5RP2QG6OQFNTaY2YIetfrE9t528vEreGQvEPRDDc8muaoYeK0SxQ=="
+ },
+ "node_modules/@types/stylis": {
+ "version": "4.2.5",
+ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.5.tgz",
+ "integrity": "sha512-1Xve+NMN7FWjY14vLoY5tL3BVEQ/n42YLwaqJIPYhotZ9uBHt87VceMwWQpzmdEt2TNXIorIFG+YeCUUW7RInw=="
+ },
+ "node_modules/@types/three": {
+ "version": "0.169.0",
+ "resolved": "https://registry.npmjs.org/@types/three/-/three-0.169.0.tgz",
+ "integrity": "sha512-oan7qCgJBt03wIaK+4xPWclYRPG9wzcg7Z2f5T8xYTNEF95kh0t0lklxLLYBDo7gQiGLYzE6iF4ta7nXF2bcsw==",
+ "dependencies": {
+ "@tweenjs/tween.js": "~23.1.3",
+ "@types/stats.js": "*",
+ "@types/webxr": "*",
+ "@webgpu/types": "*",
+ "fflate": "~0.8.2",
+ "meshoptimizer": "~0.18.1"
+ }
+ },
+ "node_modules/@types/trusted-types": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz",
+ "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw=="
+ },
+ "node_modules/@types/webxr": {
+ "version": "0.5.20",
+ "resolved": "https://registry.npmjs.org/@types/webxr/-/webxr-0.5.20.tgz",
+ "integrity": "sha512-JGpU6qiIJQKUuVSKx1GtQnHJGxRjtfGIhzO2ilq43VZZS//f1h1Sgexbdk+Lq+7569a6EYhOWrUpIruR/1Enmg=="
+ },
+ "node_modules/@typescript-eslint/eslint-plugin": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-8.13.0.tgz",
+ "integrity": "sha512-nQtBLiZYMUPkclSeC3id+x4uVd1SGtHuElTxL++SfP47jR0zfkZBJHc+gL4qPsgTuypz0k8Y2GheaDYn6Gy3rg==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/regexpp": "^4.10.0",
+ "@typescript-eslint/scope-manager": "8.13.0",
+ "@typescript-eslint/type-utils": "8.13.0",
+ "@typescript-eslint/utils": "8.13.0",
+ "@typescript-eslint/visitor-keys": "8.13.0",
+ "graphemer": "^1.4.0",
+ "ignore": "^5.3.1",
+ "natural-compare": "^1.4.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "@typescript-eslint/parser": "^8.0.0 || ^8.0.0-alpha.0",
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/parser": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/parser/-/parser-8.13.0.tgz",
+ "integrity": "sha512-w0xp+xGg8u/nONcGw1UXAr6cjCPU1w0XVyBs6Zqaj5eLmxkKQAByTdV/uGgNN5tVvN/kKpoQlP2cL7R+ajZZIQ==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/scope-manager": "8.13.0",
+ "@typescript-eslint/types": "8.13.0",
+ "@typescript-eslint/typescript-estree": "8.13.0",
+ "@typescript-eslint/visitor-keys": "8.13.0",
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/scope-manager": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/scope-manager/-/scope-manager-8.13.0.tgz",
+ "integrity": "sha512-XsGWww0odcUT0gJoBZ1DeulY1+jkaHUciUq4jKNv4cpInbvvrtDoyBH9rE/n2V29wQJPk8iCH1wipra9BhmiMA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "8.13.0",
+ "@typescript-eslint/visitor-keys": "8.13.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/type-utils": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/type-utils/-/type-utils-8.13.0.tgz",
+ "integrity": "sha512-Rqnn6xXTR316fP4D2pohZenJnp+NwQ1mo7/JM+J1LWZENSLkJI8ID8QNtlvFeb0HnFSK94D6q0cnMX6SbE5/vA==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/typescript-estree": "8.13.0",
+ "@typescript-eslint/utils": "8.13.0",
+ "debug": "^4.3.4",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/types": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/types/-/types-8.13.0.tgz",
+ "integrity": "sha512-4cyFErJetFLckcThRUFdReWJjVsPCqyBlJTi6IDEpc1GWCIIZRFxVppjWLIMcQhNGhdWJJRYFHpHoDWvMlDzng==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@typescript-eslint/typescript-estree": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/typescript-estree/-/typescript-estree-8.13.0.tgz",
+ "integrity": "sha512-v7SCIGmVsRK2Cy/LTLGN22uea6SaUIlpBcO/gnMGT/7zPtxp90bphcGf4fyrCQl3ZtiBKqVTG32hb668oIYy1g==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "8.13.0",
+ "@typescript-eslint/visitor-keys": "8.13.0",
+ "debug": "^4.3.4",
+ "fast-glob": "^3.3.2",
+ "is-glob": "^4.0.3",
+ "minimatch": "^9.0.4",
+ "semver": "^7.6.0",
+ "ts-api-utils": "^1.3.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependenciesMeta": {
+ "typescript": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@typescript-eslint/utils": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/utils/-/utils-8.13.0.tgz",
+ "integrity": "sha512-A1EeYOND6Uv250nybnLZapeXpYMl8tkzYUxqmoKAWnI4sei3ihf2XdZVd+vVOmHGcp3t+P7yRrNsyyiXTvShFQ==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
+ "@typescript-eslint/scope-manager": "8.13.0",
+ "@typescript-eslint/types": "8.13.0",
+ "@typescript-eslint/typescript-estree": "8.13.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0"
+ }
+ },
+ "node_modules/@typescript-eslint/visitor-keys": {
+ "version": "8.13.0",
+ "resolved": "https://registry.npmjs.org/@typescript-eslint/visitor-keys/-/visitor-keys-8.13.0.tgz",
+ "integrity": "sha512-7N/+lztJqH4Mrf0lb10R/CbI1EaAMMGyF5y0oJvFoAhafwgiRA7TXyd8TFn8FC8k5y2dTsYogg238qavRGNnlw==",
+ "dev": true,
+ "dependencies": {
+ "@typescript-eslint/types": "8.13.0",
+ "eslint-visitor-keys": "^3.4.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/typescript-eslint"
+ }
+ },
+ "node_modules/@use-gesture/core": {
+ "version": "10.3.1",
+ "resolved": "https://registry.npmjs.org/@use-gesture/core/-/core-10.3.1.tgz",
+ "integrity": "sha512-WcINiDt8WjqBdUXye25anHiNxPc0VOrlT8F6LLkU6cycrOGUDyY/yyFmsg3k8i5OLvv25llc0QC45GhR/C8llw=="
+ },
+ "node_modules/@use-gesture/react": {
+ "version": "10.3.1",
+ "resolved": "https://registry.npmjs.org/@use-gesture/react/-/react-10.3.1.tgz",
+ "integrity": "sha512-Yy19y6O2GJq8f7CHf7L0nxL8bf4PZCPaVOCgJrusOeFHY1LvHgYXnmnXg6N5iwAnbgbZCDjo60SiM6IPJi9C5g==",
+ "dependencies": {
+ "@use-gesture/core": "10.3.1"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0"
+ }
+ },
+ "node_modules/@vitejs/plugin-react": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-4.3.3.tgz",
+ "integrity": "sha512-NooDe9GpHGqNns1i8XDERg0Vsg5SSYRhRxxyTGogUdkdNt47jal+fbuYi+Yfq6pzRCKXyoPcWisfxE6RIM3GKA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/core": "^7.25.2",
+ "@babel/plugin-transform-react-jsx-self": "^7.24.7",
+ "@babel/plugin-transform-react-jsx-source": "^7.24.7",
+ "@types/babel__core": "^7.20.5",
+ "react-refresh": "^0.14.2"
+ },
+ "engines": {
+ "node": "^14.18.0 || >=16.0.0"
+ },
+ "peerDependencies": {
+ "vite": "^4.2.0 || ^5.0.0"
+ }
+ },
+ "node_modules/@webgpu/types": {
+ "version": "0.1.51",
+ "resolved": "https://registry.npmjs.org/@webgpu/types/-/types-0.1.51.tgz",
+ "integrity": "sha512-ktR3u64NPjwIViNCck+z9QeyN0iPkQCUOQ07ZCV1RzlkfP+olLTeEZ95O1QHS+v4w9vJeY9xj/uJuSphsHy5rQ=="
+ },
+ "node_modules/@yomguithereal/helpers": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/@yomguithereal/helpers/-/helpers-1.1.1.tgz",
+ "integrity": "sha512-UYvAq/XCA7xoh1juWDYsq3W0WywOB+pz8cgVnE1b45ZfdMhBvHDrgmSFG3jXeZSr2tMTYLGHFHON+ekG05Jebg=="
+ },
+ "node_modules/acorn": {
+ "version": "8.14.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.14.0.tgz",
+ "integrity": "sha512-cl669nCJTZBsL97OF4kUQm5g5hC2uihk0NxY3WENAC0TYdILVkAyHymAntgxGkl7K+t0cXIrH5siy5S4XkFycA==",
+ "dev": true,
+ "bin": {
+ "acorn": "bin/acorn"
+ },
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/acorn-jsx": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
+ "integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
+ "dev": true,
+ "peerDependencies": {
+ "acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
+ }
+ },
+ "node_modules/add-dom-event-listener": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/add-dom-event-listener/-/add-dom-event-listener-1.1.0.tgz",
+ "integrity": "sha512-WCxx1ixHT0GQU9hb0KI/mhgRQhnU+U3GvwY6ZvVjYq8rsihIGoaIOUbY0yMPBxLH5MDtr0kz3fisWGNcbWW7Jw==",
+ "dependencies": {
+ "object-assign": "4.x"
+ }
+ },
+ "node_modules/agent-base": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/agent-base/-/agent-base-7.1.1.tgz",
+ "integrity": "sha512-H0TSyFNDMomMNJQBn8wFV5YC/2eJ+VXECwOadZJT554xP6cODZHPX3H9QMQECxvrgiSOP1pHjy1sMWQVYJOUOA==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^4.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/ajv": {
+ "version": "6.12.6",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
+ "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "dev": true,
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "fast-json-stable-stringify": "^2.0.0",
+ "json-schema-traverse": "^0.4.1",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ansi-colors": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz",
+ "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/ansi-regex": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.1.0.tgz",
+ "integrity": "sha512-7HSX4QQb4CspciLpVFwyRe79O3xsIZDDLER21kERQ71oaPodF8jL725AgJMFAYbooIqolJoRLuM81SpeUkpkvA==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-regex?sponsor=1"
+ }
+ },
+ "node_modules/ansi-styles": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
+ "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
+ "dev": true,
+ "dependencies": {
+ "color-convert": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/any-promise": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "dev": true
+ },
+ "node_modules/anymatch": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
+ "dependencies": {
+ "normalize-path": "^3.0.0",
+ "picomatch": "^2.0.4"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/arg": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "dev": true
+ },
+ "node_modules/argparse": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q=="
+ },
+ "node_modules/array-buffer-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/array-buffer-byte-length/-/array-buffer-byte-length-1.0.1.tgz",
+ "integrity": "sha512-ahC5W1xgou+KTXix4sAO8Ki12Q+jf4i0+tmk3sC+zgcynshkHxzpXdImBehiUYKKKDwvfFiJl1tZt6ewscS1Mg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "is-array-buffer": "^3.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array-includes": {
+ "version": "3.1.8",
+ "resolved": "https://registry.npmjs.org/array-includes/-/array-includes-3.1.8.tgz",
+ "integrity": "sha512-itaWrbYbqpGXkGhZPGUulwnhVf5Hpy1xiCFsGqyIGglbBxmG5vSjxQen3/WGOjPpNEv1RtBLKxbmVXm8HpJStQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0",
+ "get-intrinsic": "^1.2.4",
+ "is-string": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.findlastindex": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/array.prototype.findlastindex/-/array.prototype.findlastindex-1.2.5.tgz",
+ "integrity": "sha512-zfETvRFA8o7EiNn++N5f/kaCw221hrpGsDmcpndVupkPzEc1Wuf3VgC0qby1BbHs7f5DVYjgtEU2LLh5bqeGfQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-shim-unscopables": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flat": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flat/-/array.prototype.flat-1.3.2.tgz",
+ "integrity": "sha512-djYB+Zx2vLewY8RWlNCUdHjDXs2XOgm602S9E7P/UpHgfeHL00cRiIF+IN/G/aUJ7kGPb6yO/ErDI5V2s8iycA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/array.prototype.flatmap": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/array.prototype.flatmap/-/array.prototype.flatmap-1.3.2.tgz",
+ "integrity": "sha512-Ewyx0c9PmpcsByhSW4r+9zDU7sGjFc86qf/kKtuSCRdhfbk0SNLLkaT5qvcHnRGgc5NP/ly/y+qkXkqONX54CQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "es-shim-unscopables": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/arraybuffer.prototype.slice": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/arraybuffer.prototype.slice/-/arraybuffer.prototype.slice-1.0.3.tgz",
+ "integrity": "sha512-bMxMKAjg13EBSVscxTaYA4mRc5t1UAXa2kXiGTNfZ079HIWXEkKmkgFrh/nJqamaLSrXO5H4WFFkPEaLJWbs3A==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.22.3",
+ "es-errors": "^1.2.1",
+ "get-intrinsic": "^1.2.3",
+ "is-array-buffer": "^3.0.4",
+ "is-shared-array-buffer": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.20",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.20.tgz",
+ "integrity": "sha512-XY25y5xSv/wEoqzDyXXME4AFfkZI0P23z6Fs3YgymDnKJkCGOnkL0iTxCa85UTqaSgfcqyf3UA6+c7wUvx/16g==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "browserslist": "^4.23.3",
+ "caniuse-lite": "^1.0.30001646",
+ "fraction.js": "^4.3.7",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
+ }
+ },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.7.tgz",
+ "integrity": "sha512-wvUjBtSGN7+7SjNpq/9M2Tg350UZD3q62IFZLbRAR1bSMlCo1ZaeW+BJ+D090e4hIIZLBcTDWe4Mh4jvUDajzQ==",
+ "dev": true,
+ "dependencies": {
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/axios": {
+ "version": "1.7.7",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.7.7.tgz",
+ "integrity": "sha512-S4kL7XrjgBmvdGut0sN3yJxqYzrDOnivkBiN0OFs6hLiUam3UPvswUo0kqGyhqUZGEOytHyumEdXsAkgCOUf3Q==",
+ "dependencies": {
+ "follow-redirects": "^1.15.6",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
+ }
+ },
+ "node_modules/babel-plugin-macros": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-macros/-/babel-plugin-macros-3.1.0.tgz",
+ "integrity": "sha512-Cg7TFGpIr01vOQNODXOOaGz2NpCU5gl8x1qJFbb6hbZxR7XrcE2vtbAsTAbJ7/xwJtUuJEw8K8Zr/AE0LHlesg==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.5",
+ "cosmiconfig": "^7.0.0",
+ "resolve": "^1.19.0"
+ },
+ "engines": {
+ "node": ">=10",
+ "npm": ">=6"
+ }
+ },
+ "node_modules/babel-runtime": {
+ "version": "6.26.0",
+ "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz",
+ "integrity": "sha512-ITKNuq2wKlW1fJg9sSW52eepoYgZBggvOAHC0u/CYu/qxQ9EVzThCgR69BnSXLHjy2f7SY5zaQ4yt7H9ZVxY2g==",
+ "dependencies": {
+ "core-js": "^2.4.0",
+ "regenerator-runtime": "^0.11.0"
+ }
+ },
+ "node_modules/balanced-match": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
+ },
+ "node_modules/bidi-js": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/bidi-js/-/bidi-js-1.0.3.tgz",
+ "integrity": "sha512-RKshQI1R3YQ+n9YJz2QQ147P66ELpa1FQEg20Dk8oW9t2KgLbpDLLp9aGZ7y8WHSshDknG0bknqGw5/tyCs5tw==",
+ "dependencies": {
+ "require-from-string": "^2.0.2"
+ }
+ },
+ "node_modules/binary-extensions": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/brace-expansion": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz",
+ "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0"
+ }
+ },
+ "node_modules/braces": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "dev": true,
+ "dependencies": {
+ "fill-range": "^7.1.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/browserslist": {
+ "version": "4.24.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.24.2.tgz",
+ "integrity": "sha512-ZIc+Q62revdMcqC6aChtW4jz3My3klmCO1fEmINZY/8J3EpBg5/A/D0AKmBveUh6pgoeycoMkVMko84tuYS+Gg==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "caniuse-lite": "^1.0.30001669",
+ "electron-to-chromium": "^1.5.41",
+ "node-releases": "^2.0.18",
+ "update-browserslist-db": "^1.1.1"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
+ }
+ },
+ "node_modules/call-bind": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.7.tgz",
+ "integrity": "sha512-GHTSNSYICQ7scH7sZ+M2rFopRoLh8t2bLSW6BbgrtLsahOIB5iyAVJf9GjWK3cYTDaMj4XdBpM1cA6pIS0Kv2w==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "set-function-length": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/callsites": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
+ "integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/camelcase": {
+ "version": "6.3.0",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
+ "integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/camelcase-css": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
+ "integrity": "sha512-QOSvevhslijgYwRx6Rv7zKdMF8lbRmx+uQGx2+vDc+KI/eBnsy9kit5aj23AgGu3pa4t9AgwbnXWqS+iOY+2aA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/camelize": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.1.tgz",
+ "integrity": "sha512-dU+Tx2fsypxTgtLoE36npi3UqcjSSMNYfkqgmoEhtZrraP5VWq0K7FkWVTYa8eMPtnU/G2txVsfdCJTn9uzpuQ==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/camera-controls": {
+ "version": "2.9.0",
+ "resolved": "https://registry.npmjs.org/camera-controls/-/camera-controls-2.9.0.tgz",
+ "integrity": "sha512-TpCujnP0vqPppTXXJRYpvIy0xq9Tro6jQf2iYUxlDpPCNxkvE/XGaTuwIxnhINOkVP/ob2CRYXtY3iVYXeMEzA==",
+ "peerDependencies": {
+ "three": ">=0.126.1"
+ }
+ },
+ "node_modules/caniuse-lite": {
+ "version": "1.0.30001679",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001679.tgz",
+ "integrity": "sha512-j2YqID/YwpLnKzCmBOS4tlZdWprXm3ZmQLBH9ZBXFOhoxLA46fwyBvx6toCBWBmnuwUY/qB3kEU6gFx8qgCroA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/caniuse-lite"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ]
+ },
+ "node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/change-case": {
+ "version": "5.4.4",
+ "resolved": "https://registry.npmjs.org/change-case/-/change-case-5.4.4.tgz",
+ "integrity": "sha512-HRQyTk2/YPEkt9TnUPbOpr64Uw3KOicFWPVBb+xiHvd6eBx/qPr9xqfBFDT8P2vWsvvz4jbEkfDe71W3VyNu2w==",
+ "dev": true
+ },
+ "node_modules/chart.js": {
+ "version": "4.4.6",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-4.4.6.tgz",
+ "integrity": "sha512-8Y406zevUPbbIBA/HRk33khEmQPk5+cxeflWE/2rx1NJsjVWMPw/9mSP9rxHP5eqi6LNoPBVMfZHxbwLSgldYA==",
+ "dependencies": {
+ "@kurkle/color": "^0.3.0"
+ },
+ "engines": {
+ "pnpm": ">=8"
+ }
+ },
+ "node_modules/chokidar": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "dev": true,
+ "dependencies": {
+ "anymatch": "~3.1.2",
+ "braces": "~3.0.2",
+ "glob-parent": "~5.1.2",
+ "is-binary-path": "~2.1.0",
+ "is-glob": "~4.0.1",
+ "normalize-path": "~3.0.0",
+ "readdirp": "~3.6.0"
+ },
+ "engines": {
+ "node": ">= 8.10.0"
+ },
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/chokidar/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/chroma-js": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/chroma-js/-/chroma-js-1.4.1.tgz",
+ "integrity": "sha512-jTwQiT859RTFN/vIf7s+Vl/Z2LcMrvMv3WUFmd/4u76AdlFC0NTNgqEEFPcRiHmAswPsMiQEDZLM8vX8qXpZNQ=="
+ },
+ "node_modules/classnames": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/classnames/-/classnames-2.5.1.tgz",
+ "integrity": "sha512-saHYOzhIQs6wy2sVxTM6bUDsQO4F50V9RQ22qBpEdCW+I+/Wmke2HOl6lS6dTpdxVhb88/I6+Hs+438c3lfUow=="
+ },
+ "node_modules/clsx": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz",
+ "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==",
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/color-convert": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
+ "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
+ "dependencies": {
+ "color-name": "~1.1.4"
+ },
+ "engines": {
+ "node": ">=7.0.0"
+ }
+ },
+ "node_modules/color-legend-element": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/color-legend-element/-/color-legend-element-1.3.0.tgz",
+ "integrity": "sha512-EkQxQGF0yWp1yd65fw7G26vfzcxbSjTtP9swv/WSKTaYAI08WpzjpJ4BnWO5r6QM8yNxpR0zqlB/f6yr2RL6zA==",
+ "dependencies": {
+ "lit": "^2.8.0 || ^3.1.0"
+ },
+ "engines": {
+ "node": ">=16.13.0"
+ },
+ "peerDependencies": {
+ "d3-array": "^3.1.1",
+ "d3-format": "^3.1.0",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-scale-chromatic": "^3.0.0"
+ }
+ },
+ "node_modules/color-name": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "dev": true
+ },
+ "node_modules/colorette": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-1.4.0.tgz",
+ "integrity": "sha512-Y2oEozpomLn7Q3HFP7dpww7AtMJplbM9lGZP6RDfHqmbeRjiwRg4n6VM6j4KLmRke85uWEI7JqF17f3pqdRA0g==",
+ "dev": true
+ },
+ "node_modules/combined-stream": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
+ "integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "dependencies": {
+ "delayed-stream": "~1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.8"
+ }
+ },
+ "node_modules/commander": {
+ "version": "12.1.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-12.1.0.tgz",
+ "integrity": "sha512-Vw8qHK3bZM9y/P10u3Vib8o/DdkvA2OtPtZvD871QKjy74Wj1WSKFILMPRPSdUSx5RFK1arlJzEtA4PkFgnbuA==",
+ "engines": {
+ "node": ">=18"
+ }
+ },
+ "node_modules/component-classes": {
+ "version": "1.2.6",
+ "resolved": "https://registry.npmjs.org/component-classes/-/component-classes-1.2.6.tgz",
+ "integrity": "sha512-hPFGULxdwugu1QWW3SvVOCUHLzO34+a2J6Wqy0c5ASQkfi9/8nZcBB0ZohaEbXOQlCflMAEMmEWk7u7BVs4koA==",
+ "dependencies": {
+ "component-indexof": "0.0.3"
+ }
+ },
+ "node_modules/component-indexof": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/component-indexof/-/component-indexof-0.0.3.tgz",
+ "integrity": "sha512-puDQKvx/64HZXb4hBwIcvQLaLgux8o1CbWl39s41hrIIZDl1lJiD5jc22gj3RBeGK0ovxALDYpIbyjqDUUl0rw=="
+ },
+ "node_modules/concat-map": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
+ },
+ "node_modules/convert-source-map": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true
+ },
+ "node_modules/copy-to-clipboard": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/copy-to-clipboard/-/copy-to-clipboard-3.3.3.tgz",
+ "integrity": "sha512-2KV8NhB5JqC3ky0r9PMCAZKbUHSwtEo4CwCs0KXgruG43gX5PMqDEBbVU4OUzw2MuAWUfsuFmWvEKG5QRfSnJA==",
+ "dependencies": {
+ "toggle-selection": "^1.0.6"
+ }
+ },
+ "node_modules/core-js": {
+ "version": "2.6.12",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.6.12.tgz",
+ "integrity": "sha512-Kb2wC0fvsWfQrgk8HU5lW6U/Lcs8+9aaYcy4ZFc6DDlo4nZ7n70dEgE5rtR0oG6ufKDUnrwfWL1mXR5ljDatrQ==",
+ "deprecated": "core-js@<3.23.3 is no longer maintained and not recommended for usage due to the number of issues. Because of the V8 engine whims, feature detection in old core-js versions could cause a slowdown up to 100x even if nothing is polyfilled. Some versions have web compatibility issues. Please, upgrade your dependencies to the actual version of core-js.",
+ "hasInstallScript": true
+ },
+ "node_modules/cosmiconfig": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
+ "dependencies": {
+ "@types/parse-json": "^4.0.0",
+ "import-fresh": "^3.2.1",
+ "parse-json": "^5.0.0",
+ "path-type": "^4.0.0",
+ "yaml": "^1.10.0"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/cosmiconfig/node_modules/parse-json": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
+ "integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
+ "dependencies": {
+ "@babel/code-frame": "^7.0.0",
+ "error-ex": "^1.3.1",
+ "json-parse-even-better-errors": "^2.3.0",
+ "lines-and-columns": "^1.1.6"
+ },
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/create-vite": {
+ "version": "5.5.5",
+ "resolved": "https://registry.npmjs.org/create-vite/-/create-vite-5.5.5.tgz",
+ "integrity": "sha512-xQaaMBBP7iTs9GrWj48y6WIMqn1l+83ao/BW1T32KkEzzi6kTEEAp0UI9EW/waCy7R4dGN6bRR86YQfPHmUsuQ==",
+ "bin": {
+ "create-vite": "index.js",
+ "cva": "index.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ }
+ },
+ "node_modules/cross-env": {
+ "version": "7.0.3",
+ "resolved": "https://registry.npmjs.org/cross-env/-/cross-env-7.0.3.tgz",
+ "integrity": "sha512-+/HKd6EgcQCJGh2PSjZuUitQBQynKor4wrFbRg4DtAgS1aWO+gU52xpH7M9ScGgXSYmAVS9bIJ8EzuaGw0oNAw==",
+ "dependencies": {
+ "cross-spawn": "^7.0.1"
+ },
+ "bin": {
+ "cross-env": "src/bin/cross-env.js",
+ "cross-env-shell": "src/bin/cross-env-shell.js"
+ },
+ "engines": {
+ "node": ">=10.14",
+ "npm": ">=6",
+ "yarn": ">=1"
+ }
+ },
+ "node_modules/cross-spawn": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.5.tgz",
+ "integrity": "sha512-ZVJrKKYunU38/76t0RMOulHOnUcbU9GbpWKAOZ0mhjr7CX6FVrH+4FrAapSOekrgFQ3f/8gwMEuIft0aKq6Hug==",
+ "dependencies": {
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/css-animation": {
+ "version": "1.6.1",
+ "resolved": "https://registry.npmjs.org/css-animation/-/css-animation-1.6.1.tgz",
+ "integrity": "sha512-/48+/BaEaHRY6kNQ2OIPzKf9A6g8WjZYjhiNDNuIVbsm5tXCGIAsHDjB4Xu1C4vXJtUWZo26O68OQkDpNBaPog==",
+ "dependencies": {
+ "babel-runtime": "6.x",
+ "component-classes": "^1.2.5"
+ }
+ },
+ "node_modules/css-color-keywords": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/css-color-keywords/-/css-color-keywords-1.0.0.tgz",
+ "integrity": "sha512-FyyrDHZKEjXDpNJYvVsV960FiqQyXc/LlYmsxl2BcdMb2WPx0OGRVgTg55rPSyLSNMqP52R9r8geSp7apN3Ofg==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/css-selector-tokenizer": {
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/css-selector-tokenizer/-/css-selector-tokenizer-0.8.0.tgz",
+ "integrity": "sha512-Jd6Ig3/pe62/qe5SBPTN8h8LeUg/pT4lLgtavPf7updwwHpvFzxvOQBHYj2LZDMjUnBzgvIUSjRcf6oT5HzHFg==",
+ "dev": true,
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "fastparse": "^1.1.2"
+ }
+ },
+ "node_modules/css-to-react-native": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/css-to-react-native/-/css-to-react-native-3.2.0.tgz",
+ "integrity": "sha512-e8RKaLXMOFii+02mOlqwjbD00KSEKqblnpO9e++1aXS1fPQOpS1YoqdVHBqPjHNoxeF2mimzVqawm2KCbEdtHQ==",
+ "dependencies": {
+ "camelize": "^1.0.0",
+ "css-color-keywords": "^1.0.0",
+ "postcss-value-parser": "^4.0.2"
+ }
+ },
+ "node_modules/cssesc": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz",
+ "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==",
+ "dev": true,
+ "bin": {
+ "cssesc": "bin/cssesc"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/csstype": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
+ "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw=="
+ },
+ "node_modules/ctrl-keys": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/ctrl-keys/-/ctrl-keys-1.0.3.tgz",
+ "integrity": "sha512-Kcb05/xUNra57fxpsLOflECWYbjQEQ9ZuQEthB3cgESN5zMLJ364twA9h2kqz8n06RnTY/+rKWM3UbkOWKeEJg==",
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/culori": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/culori/-/culori-3.3.0.tgz",
+ "integrity": "sha512-pHJg+jbuFsCjz9iclQBqyL3B2HLCBF71BwVNujUYEvCeQMvV97R59MNK3R2+jgJ3a1fcZgI9B3vYgz8lzr/BFQ==",
+ "dev": true,
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ }
+ },
+ "node_modules/d3-array": {
+ "version": "3.2.4",
+ "resolved": "https://registry.npmjs.org/d3-array/-/d3-array-3.2.4.tgz",
+ "integrity": "sha512-tdQAmyA18i4J7wprpYq8ClcxZy3SC31QMeByyCFyRt7BVHdREQZ5lpzoe5mFEYZUWe+oq8HBvk9JjpibyEV4Jg==",
+ "dependencies": {
+ "internmap": "1 - 2"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-binarytree": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/d3-binarytree/-/d3-binarytree-1.0.2.tgz",
+ "integrity": "sha512-cElUNH+sHu95L04m92pG73t2MEJXKu+GeKUN1TJkFsu93E5W8E9Sc3kHEGJKgenGvj19m6upSn2EunvMgMD2Yw=="
+ },
+ "node_modules/d3-color": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-color/-/d3-color-3.1.0.tgz",
+ "integrity": "sha512-zg/chbXyeBtMQ1LbD/WSoW2DpC3I0mpmPdW+ynRTj/x2DAWYrIY7qeZIHidozwV24m4iavr15lNwIwLxRmOxhA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-delaunay": {
+ "version": "6.0.4",
+ "resolved": "https://registry.npmjs.org/d3-delaunay/-/d3-delaunay-6.0.4.tgz",
+ "integrity": "sha512-mdjtIZ1XLAM8bm/hx3WwjfHt6Sggek7qH043O8KEjDXN40xi3vx/6pYSVTwLjEgiXQTbvaouWKynLBiUZ6SK6A==",
+ "dependencies": {
+ "delaunator": "5"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-dispatch": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-3.0.1.tgz",
+ "integrity": "sha512-rzUyPU/S7rwUflMyLc1ETDeBj0NRuHKKAcvukozwhshr6g6c5d8zh4c2gQjY2bZ0dXeGLWc1PF174P2tVvKhfg==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-ease": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-ease/-/d3-ease-3.0.1.tgz",
+ "integrity": "sha512-wR/XK3D3XcLIZwpbvQwQ5fK+8Ykds1ip7A2Txe0yxncXSdq1L9skcG7blcedkOX+ZcgxGAmLX1FrRGbADwzi0w==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-force-3d": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/d3-force-3d/-/d3-force-3d-3.0.5.tgz",
+ "integrity": "sha512-tdwhAhoTYZY/a6eo9nR7HP3xSW/C6XvJTbeRpR92nlPzH6OiE+4MliN9feuSFd0tPtEUo+191qOhCTWx3NYifg==",
+ "dependencies": {
+ "d3-binarytree": "1",
+ "d3-dispatch": "1 - 3",
+ "d3-octree": "1",
+ "d3-quadtree": "1 - 3",
+ "d3-timer": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-hierarchy": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-3.1.2.tgz",
+ "integrity": "sha512-FX/9frcub54beBdugHjDCdikxThEqjnR93Qt7PvQTOHxyiNCAlvMrHhclk3cD5VeAaq9fxmfRp+CnWw9rEMBuA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-interpolate": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-interpolate/-/d3-interpolate-3.0.1.tgz",
+ "integrity": "sha512-3bYs1rOD33uo8aqJfKP3JWPAibgw8Zm2+L9vBKEHJ2Rg+viTR7o5Mmv5mZcieN+FRYaAOWX5SJATX6k1PWz72g==",
+ "dependencies": {
+ "d3-color": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-octree": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/d3-octree/-/d3-octree-1.0.2.tgz",
+ "integrity": "sha512-Qxg4oirJrNXauiuC94uKMbgxwnhdda9xRLl9ihq45srlJ4Ga3CSgqGcAL8iW7N5CIv4Oz8x3E734ulxyvHPvwA=="
+ },
+ "node_modules/d3-path": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-path/-/d3-path-3.1.0.tgz",
+ "integrity": "sha512-p3KP5HCf/bvjBSSKuXid6Zqijx7wIfNW+J/maPs+iwR35at5JCbLUT0LzF1cnjbCHWhqzQTIN2Jpe8pRebIEFQ==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-quadtree": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-3.0.1.tgz",
+ "integrity": "sha512-04xDrxQTDTCFwP5H6hRhsRcb9xxv2RzkcsygFzmkSIOJy3PeRJP7sNk3VRIbKXcog561P9oU0/rVH6vDROAgUw==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/d3-scale/-/d3-scale-4.0.2.tgz",
+ "integrity": "sha512-GZW464g1SH7ag3Y7hXjf8RoUuAFIqklOAq3MRl4OaWabTFJY9PN/E1YklhXLh+OQ3fM9yS2nOkCoS+WLZ6kvxQ==",
+ "dependencies": {
+ "d3-array": "2.10.0 - 3",
+ "d3-format": "1 - 3",
+ "d3-interpolate": "1.2.0 - 3",
+ "d3-time": "2.1.1 - 3",
+ "d3-time-format": "2 - 4"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale-chromatic": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+ "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
+ "dependencies": {
+ "d3-color": "1 - 3",
+ "d3-interpolate": "1 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-scale/node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-shape": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-3.2.0.tgz",
+ "integrity": "sha512-SaLBuwGm3MOViRq2ABk3eLoxwZELpH6zhl3FbAoJ7Vm1gofKx6El1Ib5z23NUEhF9AsGl7y+dzLe5Cw2AArGTA==",
+ "dependencies": {
+ "d3-path": "^3.1.0"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/d3-time": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-1.1.0.tgz",
+ "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA=="
+ },
+ "node_modules/d3-time-format": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-3.0.0.tgz",
+ "integrity": "sha512-UXJh6EKsHBTjopVqZBhFysQcoXSv/5yLONZvkQ5Kk3qbwiUYkdX17Xa1PT6U1ZWXGGfB1ey5L8dKMlFq2DO0Ag==",
+ "dependencies": {
+ "d3-time": "1 - 2"
+ }
+ },
+ "node_modules/d3-timer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-3.0.1.tgz",
+ "integrity": "sha512-ndfJ/JxxMd3nw31uyKoY2naivF+r29V+Lc0svZxe1JvvIRmi8hUsrMvdOwgS1o6uBHmiz91geQ0ylPP0aj1VUA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/daisyui": {
+ "version": "4.12.14",
+ "resolved": "https://registry.npmjs.org/daisyui/-/daisyui-4.12.14.tgz",
+ "integrity": "sha512-hA27cdBasdwd4/iEjn+aidoCrRroDuo3G5W9NDKaVCJI437Mm/3eSL/2u7MkZ0pt8a+TrYF3aT2pFVemTS3how==",
+ "dev": true,
+ "dependencies": {
+ "css-selector-tokenizer": "^0.8",
+ "culori": "^3",
+ "picocolors": "^1",
+ "postcss-js": "^4"
+ },
+ "engines": {
+ "node": ">=16.9.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/daisyui"
+ }
+ },
+ "node_modules/data-uri-to-buffer": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/data-uri-to-buffer/-/data-uri-to-buffer-4.0.1.tgz",
+ "integrity": "sha512-0R9ikRb668HB7QDxT1vkpuUBtqc53YyAwMwGeUFKRojY/NWKvdZ+9UYtRfGmhqNbRkTSVpMbmyhXipFFv2cb/A==",
+ "engines": {
+ "node": ">= 12"
+ }
+ },
+ "node_modules/data-view-buffer": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-buffer/-/data-view-buffer-1.0.1.tgz",
+ "integrity": "sha512-0lht7OugA5x3iJLOWFhWK/5ehONdprk0ISXqVFn/NFrDu+cuc8iADFrGQz5BnRK7LLU3JmkbXSxaqX+/mXYtUA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/data-view-byte-length/-/data-view-byte-length-1.0.1.tgz",
+ "integrity": "sha512-4J7wRJD3ABAzr8wP+OcIcqq2dlUKp4DVflx++hs5h5ZKydWMI6/D/fAot+yh6g2tHh8fLFTvNOaVN357NvSrOQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/data-view-byte-offset": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/data-view-byte-offset/-/data-view-byte-offset-1.0.0.tgz",
+ "integrity": "sha512-t/Ygsytq+R995EJ5PZlD4Cu56sWa8InXySaViRzw9apusqsOO2bQP+SbYzAhR0pFKoB+43lYy8rWban9JSuXnA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-data-view": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/date-fns": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-4.1.0.tgz",
+ "integrity": "sha512-Ukq0owbQXxa/U3EGtsdVBkR1w7KOQ5gIBqdH2hkvknzZPYvBxb/aa6E8L7tmjFtkwZBu3UXBbjIgPo/Ez4xaNg==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/debounce": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
+ "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug=="
+ },
+ "node_modules/debug": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.7.tgz",
+ "integrity": "sha512-Er2nc/H7RrMXZBFCEim6TCmMk02Z8vLC2Rbi1KEBggpo0fS6l0S1nnapwmIi3yW/+GOJap1Krg4w0Hg80oCqgQ==",
+ "dependencies": {
+ "ms": "^2.1.3"
+ },
+ "engines": {
+ "node": ">=6.0"
+ },
+ "peerDependenciesMeta": {
+ "supports-color": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/decimal.js-light": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/decimal.js-light/-/decimal.js-light-2.5.1.tgz",
+ "integrity": "sha512-qIMFpTMZmny+MMIitAB6D7iVPEorVw6YQRWkvarTkT4tBeSLLiHzcwj6q0MmYSFCiVpiqPJTJEYIrpcPzVEIvg=="
+ },
+ "node_modules/deep-is": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.4.tgz",
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true
+ },
+ "node_modules/define-data-property": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/define-data-property/-/define-data-property-1.1.4.tgz",
+ "integrity": "sha512-rBMvIzlpA8v6E+SJZoo++HAYqsLrkg7MSfIinMPFhmkorw7X+dOXVJQs+QT69zGkzMyfDnIMN2Wid1+NbL3T+A==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/delaunator": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz",
+ "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==",
+ "dependencies": {
+ "robust-predicates": "^3.0.2"
+ }
+ },
+ "node_modules/delayed-stream": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "engines": {
+ "node": ">=0.4.0"
+ }
+ },
+ "node_modules/detect-gpu": {
+ "version": "5.0.55",
+ "resolved": "https://registry.npmjs.org/detect-gpu/-/detect-gpu-5.0.55.tgz",
+ "integrity": "sha512-muXhz2twvGiyatqK3VTy//Jb/MmHXExEaOPEMyLpVb9BSzTUgimFwbHKPBIfjEyQV0P+Y1mEjVSyPrlqPzUPQQ==",
+ "dependencies": {
+ "webgl-constants": "^1.1.1"
+ }
+ },
+ "node_modules/didyoumean": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/didyoumean/-/didyoumean-1.2.2.tgz",
+ "integrity": "sha512-gxtyfqMg7GKyhQmb056K7M3xszy/myH8w+B4RT+QXBQsvAOdc3XymqDDPHx1BgPgsdAA5SIifona89YtRATDzw==",
+ "dev": true
+ },
+ "node_modules/dlv": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/dlv/-/dlv-1.1.3.tgz",
+ "integrity": "sha512-+HlytyjlPKnIG8XuRG8WvmBP8xs8P71y+SKKS6ZXWoEgLuePxtDoUEiH7WkdePWrQ5JBpE6aoVqfZfJUQkjXwA==",
+ "dev": true
+ },
+ "node_modules/doctrine": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz",
+ "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==",
+ "dev": true,
+ "dependencies": {
+ "esutils": "^2.0.2"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/dom-align": {
+ "version": "1.12.4",
+ "resolved": "https://registry.npmjs.org/dom-align/-/dom-align-1.12.4.tgz",
+ "integrity": "sha512-R8LUSEay/68zE5c8/3BDxiTEvgb4xZTF0RKmAHfiEVN3klfIpXfi2/QCoiWPccVQ0J/ZGdz9OjzL4uJEP/MRAw=="
+ },
+ "node_modules/dom-helpers": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/dom-helpers/-/dom-helpers-5.2.1.tgz",
+ "integrity": "sha512-nRCa7CK3VTrM2NmGkIy4cbK7IZlgBE/PYMn55rrXefr5xXDP0LdtfPnblFDoVdcAfslJ7or6iqAUnx0CCGIWQA==",
+ "dependencies": {
+ "@babel/runtime": "^7.8.7",
+ "csstype": "^3.0.2"
+ }
+ },
+ "node_modules/draco3d": {
+ "version": "1.5.7",
+ "resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.7.tgz",
+ "integrity": "sha512-m6WCKt/erDXcw+70IJXnG7M3awwQPAsZvJGX5zY7beBqpELw6RDGkYVU0W43AFxye4pDZ5i2Lbyc/NNGqwjUVQ=="
+ },
+ "node_modules/eastasianwidth": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/eastasianwidth/-/eastasianwidth-0.2.0.tgz",
+ "integrity": "sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==",
+ "dev": true
+ },
+ "node_modules/electron-to-chromium": {
+ "version": "1.5.55",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.55.tgz",
+ "integrity": "sha512-6maZ2ASDOTBtjt9FhqYPRnbvKU5tjG0IN9SztUOWYw2AzNDNpKJYLJmlK0/En4Hs/aiWnB+JZ+gW19PIGszgKg==",
+ "dev": true
+ },
+ "node_modules/ellipsize": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/ellipsize/-/ellipsize-0.5.1.tgz",
+ "integrity": "sha512-0jEAyuIRU6U8MN0S5yUqIrkK/AQWkChh642N3zQuGV57s9bsUWYLc0jJOoDIUkZ2sbEL3ySq8xfq71BvG4q3hw=="
+ },
+ "node_modules/emoji-regex": {
+ "version": "9.2.2",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-9.2.2.tgz",
+ "integrity": "sha512-L18DaJsXSUk2+42pv8mLs5jJT2hqFkFE4j21wOmgbUqsZ2hL72NsUU785g9RXgo3s0ZNgVl42TiHp3ZtOv/Vyg==",
+ "dev": true
+ },
+ "node_modules/error-ex": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz",
+ "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==",
+ "dependencies": {
+ "is-arrayish": "^0.2.1"
+ }
+ },
+ "node_modules/es-abstract": {
+ "version": "1.23.3",
+ "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.23.3.tgz",
+ "integrity": "sha512-e+HfNH61Bj1X9/jLc5v1owaLYuHdeHHSQlkhCBiTK8rBvKaULl/beGMxwrMXjpYrv4pz22BlY570vVePA2ho4A==",
+ "dev": true,
+ "dependencies": {
+ "array-buffer-byte-length": "^1.0.1",
+ "arraybuffer.prototype.slice": "^1.0.3",
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "data-view-buffer": "^1.0.1",
+ "data-view-byte-length": "^1.0.1",
+ "data-view-byte-offset": "^1.0.0",
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "es-object-atoms": "^1.0.0",
+ "es-set-tostringtag": "^2.0.3",
+ "es-to-primitive": "^1.2.1",
+ "function.prototype.name": "^1.1.6",
+ "get-intrinsic": "^1.2.4",
+ "get-symbol-description": "^1.0.2",
+ "globalthis": "^1.0.3",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2",
+ "has-proto": "^1.0.3",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.2",
+ "internal-slot": "^1.0.7",
+ "is-array-buffer": "^3.0.4",
+ "is-callable": "^1.2.7",
+ "is-data-view": "^1.0.1",
+ "is-negative-zero": "^2.0.3",
+ "is-regex": "^1.1.4",
+ "is-shared-array-buffer": "^1.0.3",
+ "is-string": "^1.0.7",
+ "is-typed-array": "^1.1.13",
+ "is-weakref": "^1.0.2",
+ "object-inspect": "^1.13.1",
+ "object-keys": "^1.1.1",
+ "object.assign": "^4.1.5",
+ "regexp.prototype.flags": "^1.5.2",
+ "safe-array-concat": "^1.1.2",
+ "safe-regex-test": "^1.0.3",
+ "string.prototype.trim": "^1.2.9",
+ "string.prototype.trimend": "^1.0.8",
+ "string.prototype.trimstart": "^1.0.8",
+ "typed-array-buffer": "^1.0.2",
+ "typed-array-byte-length": "^1.0.1",
+ "typed-array-byte-offset": "^1.0.2",
+ "typed-array-length": "^1.0.6",
+ "unbox-primitive": "^1.0.2",
+ "which-typed-array": "^1.1.15"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/es-define-property": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.0.tgz",
+ "integrity": "sha512-jxayLKShrEqqzJ0eumQbVhTYQM27CfT1T35+gCgDFoL82JLsXqTJ76zv6A0YLOgEnLUMvLzsDsGIrl8NFpT2gQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-errors": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz",
+ "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-object-atoms": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.0.0.tgz",
+ "integrity": "sha512-MZ4iQ6JwHOBQjahnjwaC1ZtIBH+2ohjamzAO3oaHcXYup7qxjF2fixyH+Q71voWHeOkI2q/TnJao/KfXYIZWbw==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-set-tostringtag": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/es-set-tostringtag/-/es-set-tostringtag-2.0.3.tgz",
+ "integrity": "sha512-3T8uNMC3OQTHkFUsFq8r/BwAXLHvU/9O9mE0fBc/MY5iq/8H7ncvO947LmYA6ldWw9Uh8Yhf25zu6n7nML5QWQ==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.2.4",
+ "has-tostringtag": "^1.0.2",
+ "hasown": "^2.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/es-shim-unscopables": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/es-shim-unscopables/-/es-shim-unscopables-1.0.2.tgz",
+ "integrity": "sha512-J3yBRXCzDu4ULnQwxyToo/OjdMx6akgVC7K6few0a7F/0wLtmKKN7I73AH5T2836UuXRqN7Qg+IIUw/+YJksRw==",
+ "dev": true,
+ "dependencies": {
+ "hasown": "^2.0.0"
+ }
+ },
+ "node_modules/es-to-primitive": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/es-to-primitive/-/es-to-primitive-1.2.1.tgz",
+ "integrity": "sha512-QCOllgZJtaUo9miYBcLChTUaHNjJF3PYs1VidD7AwiEj1kYxKeQTctLAezAOH5ZKRH0g2IgPn6KwB4IT8iRpvA==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.4",
+ "is-date-object": "^1.0.1",
+ "is-symbol": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/esbuild": {
+ "version": "0.21.5",
+ "resolved": "https://registry.npmjs.org/esbuild/-/esbuild-0.21.5.tgz",
+ "integrity": "sha512-mg3OPMV4hXywwpoDxu3Qda5xCKQi+vCTZq8S9J/EpkhB2HzKXq4SNFZE3+NK93JYxc8VMSep+lOUSC/RVKaBqw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "bin": {
+ "esbuild": "bin/esbuild"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "optionalDependencies": {
+ "@esbuild/aix-ppc64": "0.21.5",
+ "@esbuild/android-arm": "0.21.5",
+ "@esbuild/android-arm64": "0.21.5",
+ "@esbuild/android-x64": "0.21.5",
+ "@esbuild/darwin-arm64": "0.21.5",
+ "@esbuild/darwin-x64": "0.21.5",
+ "@esbuild/freebsd-arm64": "0.21.5",
+ "@esbuild/freebsd-x64": "0.21.5",
+ "@esbuild/linux-arm": "0.21.5",
+ "@esbuild/linux-arm64": "0.21.5",
+ "@esbuild/linux-ia32": "0.21.5",
+ "@esbuild/linux-loong64": "0.21.5",
+ "@esbuild/linux-mips64el": "0.21.5",
+ "@esbuild/linux-ppc64": "0.21.5",
+ "@esbuild/linux-riscv64": "0.21.5",
+ "@esbuild/linux-s390x": "0.21.5",
+ "@esbuild/linux-x64": "0.21.5",
+ "@esbuild/netbsd-x64": "0.21.5",
+ "@esbuild/openbsd-x64": "0.21.5",
+ "@esbuild/sunos-x64": "0.21.5",
+ "@esbuild/win32-arm64": "0.21.5",
+ "@esbuild/win32-ia32": "0.21.5",
+ "@esbuild/win32-x64": "0.21.5"
+ }
+ },
+ "node_modules/escalade": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/escape-string-regexp": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/eslint": {
+ "version": "9.14.0",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.14.0.tgz",
+ "integrity": "sha512-c2FHsVBr87lnUtjP4Yhvk4yEhKrQavGafRA/Se1ouse8PfbfC/Qh9Mxa00yWsZRlqeUB9raXip0aiiUZkgnr9g==",
+ "dev": true,
+ "dependencies": {
+ "@eslint-community/eslint-utils": "^4.2.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.18.0",
+ "@eslint/core": "^0.7.0",
+ "@eslint/eslintrc": "^3.1.0",
+ "@eslint/js": "9.14.0",
+ "@eslint/plugin-kit": "^0.2.0",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.0",
+ "@types/estree": "^1.0.6",
+ "@types/json-schema": "^7.0.15",
+ "ajv": "^6.12.4",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.2",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.2.0",
+ "eslint-visitor-keys": "^4.2.0",
+ "espree": "^10.3.0",
+ "esquery": "^1.5.0",
+ "esutils": "^2.0.2",
+ "fast-deep-equal": "^3.1.3",
+ "file-entry-cache": "^8.0.0",
+ "find-up": "^5.0.0",
+ "glob-parent": "^6.0.2",
+ "ignore": "^5.2.0",
+ "imurmurhash": "^0.1.4",
+ "is-glob": "^4.0.0",
+ "json-stable-stringify-without-jsonify": "^1.0.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.2",
+ "natural-compare": "^1.4.0",
+ "optionator": "^0.9.3",
+ "text-table": "^0.2.0"
+ },
+ "bin": {
+ "eslint": "bin/eslint.js"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
+ },
+ "peerDependencies": {
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-import-resolver-node": {
+ "version": "0.3.9",
+ "resolved": "https://registry.npmjs.org/eslint-import-resolver-node/-/eslint-import-resolver-node-0.3.9.tgz",
+ "integrity": "sha512-WFj2isz22JahUv+B788TlO3N6zL3nNJGU8CcZbPZvVEkBPaJdCV4vy5wyghty5ROFbCRnm132v8BScu5/1BQ8g==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7",
+ "is-core-module": "^2.13.0",
+ "resolve": "^1.22.4"
+ }
+ },
+ "node_modules/eslint-import-resolver-node/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-module-utils": {
+ "version": "2.12.0",
+ "resolved": "https://registry.npmjs.org/eslint-module-utils/-/eslint-module-utils-2.12.0.tgz",
+ "integrity": "sha512-wALZ0HFoytlyh/1+4wuZ9FJCD/leWHQzzrxJ8+rebyReSLk7LApMyd3WJaLVoN+D5+WIdJyDK1c6JnE65V4Zyg==",
+ "dev": true,
+ "dependencies": {
+ "debug": "^3.2.7"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependenciesMeta": {
+ "eslint": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/eslint-module-utils/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import": {
+ "version": "2.31.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-import/-/eslint-plugin-import-2.31.0.tgz",
+ "integrity": "sha512-ixmkI62Rbc2/w8Vfxyh1jQRTdRTF52VxwRVHl/ykPAmqG+Nb7/kNn+byLP0LxPgI7zWA16Jt82SybJInmMia3A==",
+ "dev": true,
+ "dependencies": {
+ "@rtsao/scc": "^1.1.0",
+ "array-includes": "^3.1.8",
+ "array.prototype.findlastindex": "^1.2.5",
+ "array.prototype.flat": "^1.3.2",
+ "array.prototype.flatmap": "^1.3.2",
+ "debug": "^3.2.7",
+ "doctrine": "^2.1.0",
+ "eslint-import-resolver-node": "^0.3.9",
+ "eslint-module-utils": "^2.12.0",
+ "hasown": "^2.0.2",
+ "is-core-module": "^2.15.1",
+ "is-glob": "^4.0.3",
+ "minimatch": "^3.1.2",
+ "object.fromentries": "^2.0.8",
+ "object.groupby": "^1.0.3",
+ "object.values": "^1.2.0",
+ "semver": "^6.3.1",
+ "string.prototype.trimend": "^1.0.8",
+ "tsconfig-paths": "^3.15.0"
+ },
+ "engines": {
+ "node": ">=4"
+ },
+ "peerDependencies": {
+ "eslint": "^2 || ^3 || ^4 || ^5 || ^6 || ^7.2.0 || ^8 || ^9"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/debug": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
+ "integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "dev": true,
+ "dependencies": {
+ "ms": "^2.1.1"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/eslint-plugin-import/node_modules/semver": {
+ "version": "6.3.1",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
+ "integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ }
+ },
+ "node_modules/eslint-plugin-react-hooks": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-hooks/-/eslint-plugin-react-hooks-5.0.0.tgz",
+ "integrity": "sha512-hIOwI+5hYGpJEc4uPRmz2ulCjAGD/N13Lukkh8cLV0i2IRk/bdZDYjgLVHj+U9Z704kLIdIO6iueGvxNur0sgw==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "peerDependencies": {
+ "eslint": "^3.0.0 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0-0 || ^9.0.0"
+ }
+ },
+ "node_modules/eslint-plugin-react-refresh": {
+ "version": "0.4.14",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-react-refresh/-/eslint-plugin-react-refresh-0.4.14.tgz",
+ "integrity": "sha512-aXvzCTK7ZBv1e7fahFuR3Z/fyQQSIQ711yPgYRj+Oj64tyTgO4iQIDmYXDBqvSWQ/FA4OSCsXOStlF+noU0/NA==",
+ "dev": true,
+ "peerDependencies": {
+ "eslint": ">=7"
+ }
+ },
+ "node_modules/eslint-scope": {
+ "version": "8.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.2.0.tgz",
+ "integrity": "sha512-PHlWUfG6lvPc3yvP5A4PNyBL1W8fkDUccmI21JUu/+GKZBoH/W5u6usENXUrWFRsyoW5ACUjFGgAFQp5gUlb/A==",
+ "dev": true,
+ "dependencies": {
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/brace-expansion": {
+ "version": "1.1.11",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
+ "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
+ "dependencies": {
+ "balanced-match": "^1.0.0",
+ "concat-map": "0.0.1"
+ }
+ },
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+ "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/minimatch": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
+ "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^1.1.7"
+ },
+ "engines": {
+ "node": "*"
+ }
+ },
+ "node_modules/espree": {
+ "version": "10.3.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.3.0.tgz",
+ "integrity": "sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==",
+ "dev": true,
+ "dependencies": {
+ "acorn": "^8.14.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.0.tgz",
+ "integrity": "sha512-UyLnSehNt62FFhSwjZlHmeokpRK59rcz29j+F1/aDgbkbRTk7wIc9XzdoasMUbRNKDM0qQt/+BJ4BrpFeABemw==",
+ "dev": true,
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/esquery": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.6.0.tgz",
+ "integrity": "sha512-ca9pw9fomFcKPvFLXhBKUK90ZvGibiGOvRJNbjljY7s7uq/5YO4BOzcYtJqExdx99rF6aAcnRxHmcUHcz6sQsg==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.1.0"
+ },
+ "engines": {
+ "node": ">=0.10"
+ }
+ },
+ "node_modules/esrecurse": {
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
+ "integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
+ "dev": true,
+ "dependencies": {
+ "estraverse": "^5.2.0"
+ },
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esutils": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
+ "integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/eventemitter3": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
+ "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw=="
+ },
+ "node_modules/events": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
+ "integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "engines": {
+ "node": ">=0.8.x"
+ }
+ },
+ "node_modules/fast-deep-equal": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-3.1.3.tgz",
+ "integrity": "sha512-f3qQ9oQy9j2AhBe/H9VC91wLmKBCCU/gDOnKNAYG5hswO7BLKj09Hc5HYNz9cGI++xlpDCIgDaitVs03ATR84Q==",
+ "dev": true
+ },
+ "node_modules/fast-equals": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/fast-equals/-/fast-equals-5.0.1.tgz",
+ "integrity": "sha512-WF1Wi8PwwSY7/6Kx0vKXtw8RwuSGoM1bvDaJbu7MxDlR1vovZjIAKrnzyrThgAjm6JDTu0fVgWXDlMGspodfoQ==",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.2.tgz",
+ "integrity": "sha512-oX2ruAFQwf/Orj8m737Y5adxDQO0LAB7/S5MnxCdTNDd4p6BsyIVsv9JQsATbTSq8KHRpLwIHbVlUNatxd+1Ow==",
+ "dev": true,
+ "dependencies": {
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.4"
+ },
+ "engines": {
+ "node": ">=8.6.0"
+ }
+ },
+ "node_modules/fast-glob/node_modules/glob-parent": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
+ "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.1"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
+ "dev": true
+ },
+ "node_modules/fastparse": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/fastparse/-/fastparse-1.1.2.tgz",
+ "integrity": "sha512-483XLLxTVIwWK3QTrMGRqUfUpoOs/0hbQrl2oz4J0pAcm3A3bu84wxTFqGqkJzewCLdME38xJLJAxBABfQT8sQ==",
+ "dev": true
+ },
+ "node_modules/fastq": {
+ "version": "1.17.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.17.1.tgz",
+ "integrity": "sha512-sRVD3lWVIXWg6By68ZN7vho9a1pQcN/WBFaAAsDDFzlJjvoGx0P8z7V1t72grFJfJhu3YPZBuu25f7Kaw2jN1w==",
+ "dev": true,
+ "dependencies": {
+ "reusify": "^1.0.4"
+ }
+ },
+ "node_modules/fetch-blob": {
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/fetch-blob/-/fetch-blob-3.2.0.tgz",
+ "integrity": "sha512-7yAQpD2UMJzLi1Dqv7qFYnPbaPx7ZfFK6PiIxQ4PfkGPyNyl2Ugx+a/umUonmKqjhM4DnfbMvdX6otXq83soQQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "dependencies": {
+ "node-domexception": "^1.0.0",
+ "web-streams-polyfill": "^3.0.3"
+ },
+ "engines": {
+ "node": "^12.20 || >= 14.13"
+ }
+ },
+ "node_modules/fflate": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.8.2.tgz",
+ "integrity": "sha512-cPJU47OaAoCbg0pBvzsgpTPhmhqI5eJjh/JIu8tPj5q+T7iLvW/JAYUqmE7KOB4R1ZyEhzBaIQpQpardBF5z8A=="
+ },
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
+ "dev": true,
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=16.0.0"
+ }
+ },
+ "node_modules/fill-range": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz",
+ "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==",
+ "dev": true,
+ "dependencies": {
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/find-root": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/find-root/-/find-root-1.1.0.tgz",
+ "integrity": "sha512-NKfW6bec6GfKc0SGx1e07QZY9PE99u0Bft/0rzSD5k3sO/vwkVUpDUKVm5Gpp5Ue3YfShPFTX2070tDs5kB9Ng=="
+ },
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
+ "dev": true,
+ "dependencies": {
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
+ "dev": true,
+ "dependencies": {
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
+ },
+ "engines": {
+ "node": ">=16"
+ }
+ },
+ "node_modules/flatted": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.3.1.tgz",
+ "integrity": "sha512-X8cqMLLie7KsNUDSdzeN8FYK9rEt4Dt67OsG/DNGnYTSDBG4uFAJFBnUeiV+zCVAvwFy56IjM9sH51jVaEhNxw==",
+ "dev": true
+ },
+ "node_modules/follow-redirects": {
+ "version": "1.15.9",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.9.tgz",
+ "integrity": "sha512-gew4GsXizNgdoRyqmyfMHyAmXsZDk6mHkSxZFCzW9gwlbtOW44CDtYavM+y+72qD/Vq2l550kMF52DT8fOLJqQ==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "engines": {
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/for-each": {
+ "version": "0.3.3",
+ "resolved": "https://registry.npmjs.org/for-each/-/for-each-0.3.3.tgz",
+ "integrity": "sha512-jqYfLp7mo9vIyQf8ykW2v7A+2N4QjeCeI5+Dz9XraiO1ign81wjiH7Fb9vSOWvQfNtmSa4H2RoQTrrXivdUZmw==",
+ "dev": true,
+ "dependencies": {
+ "is-callable": "^1.1.3"
+ }
+ },
+ "node_modules/foreground-child": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/foreground-child/-/foreground-child-3.3.0.tgz",
+ "integrity": "sha512-Ld2g8rrAyMYFXBhEqMz8ZAHBi4J4uS1i/CxGMDnjyFWddMXLVcDp051DZfu+t7+ab7Wv6SMqpWmyFIj5UbfFvg==",
+ "dev": true,
+ "dependencies": {
+ "cross-spawn": "^7.0.0",
+ "signal-exit": "^4.0.1"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/form-data": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.1.tgz",
+ "integrity": "sha512-tzN8e4TX8+kkxGPK8D5u0FNmjPUjw3lwC9lSLxxoB/+GtsJG91CO8bSWy73APlgAZzZbXEYZJuxjkHH2w+Ezhw==",
+ "dependencies": {
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "mime-types": "^2.1.12"
+ },
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/formdata-polyfill": {
+ "version": "4.0.10",
+ "resolved": "https://registry.npmjs.org/formdata-polyfill/-/formdata-polyfill-4.0.10.tgz",
+ "integrity": "sha512-buewHzMvYL29jdeQTVILecSaZKnt/RJWjoZCF5OW60Z67/GmSLBkOFM7qh1PI3zFNtJbaZL5eQu1vLfazOwj4g==",
+ "dependencies": {
+ "fetch-blob": "^3.1.2"
+ },
+ "engines": {
+ "node": ">=12.20.0"
+ }
+ },
+ "node_modules/fraction.js": {
+ "version": "4.3.7",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.7.tgz",
+ "integrity": "sha512-ZsDfxO51wGAXREY55a7la9LScWpwv9RxIrYABrlvOFBlH/ShPnrtsXeuUIfXKKOVicNxQ+o8JTbJvjS4M89yew==",
+ "dev": true,
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
+ }
+ },
+ "node_modules/fs-extra": {
+ "version": "11.2.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-11.2.0.tgz",
+ "integrity": "sha512-PmDi3uwK5nFuXh7XDTlVnS17xJS7vW36is2+w3xcv8SVxiB4NyATf4ctkVY5bkSjX0Y4nbvZCq1/EjtEyr9ktw==",
+ "dependencies": {
+ "graceful-fs": "^4.2.0",
+ "jsonfile": "^6.0.1",
+ "universalify": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=14.14"
+ }
+ },
+ "node_modules/fsevents": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
+ "dev": true,
+ "hasInstallScript": true,
+ "optional": true,
+ "os": [
+ "darwin"
+ ],
+ "engines": {
+ "node": "^8.16.0 || ^10.6.0 || >=11.0.0"
+ }
+ },
+ "node_modules/function-bind": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz",
+ "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/function.prototype.name": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/function.prototype.name/-/function.prototype.name-1.1.6.tgz",
+ "integrity": "sha512-Z5kx79swU5P27WEayXM1tBi5Ze/lbIyiNgU3qyXUOf9b2rgXYyF9Dy9Cx+IQv/Lc8WCG6L82zwUPpSS9hGehIg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "define-properties": "^1.2.0",
+ "es-abstract": "^1.22.1",
+ "functions-have-names": "^1.2.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/functions-have-names": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/functions-have-names/-/functions-have-names-1.2.3.tgz",
+ "integrity": "sha512-xckBUXyTIqT97tq2x2AMb+g163b5JFysYk0x4qxNFwbfQkmNZoiRHb6sPzI9/QV33WeuvVYBUIiD4NzNIyqaRQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/gensync": {
+ "version": "1.0.0-beta.2",
+ "resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
+ "integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6.9.0"
+ }
+ },
+ "node_modules/get-intrinsic": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.2.4.tgz",
+ "integrity": "sha512-5uYhsJH8VJBTv7oslg4BznJYhDoRI6waYCxMmCdnTrcCrHA/fCFKoTFz2JKKE0HdDFUF7/oQuhzumXJK7paBRQ==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "has-proto": "^1.0.1",
+ "has-symbols": "^1.0.3",
+ "hasown": "^2.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/get-symbol-description": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.2.tgz",
+ "integrity": "sha512-g0QYk1dZBxGwk+Ngc+ltRH2IBp2f7zBkBMBJZCDerh6EhlhSR6+9irMCuT/09zD6qkarHUSn529sK/yL4S27mg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glob": {
+ "version": "10.4.5",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-10.4.5.tgz",
+ "integrity": "sha512-7Bv8RF0k6xjo7d4A/PxYLbUCfb6c+Vpd2/mB2yRDlew7Jb5hEXiCD9ibfO7wpk8i4sevK6DFny9h7EYbM3/sHg==",
+ "dev": true,
+ "dependencies": {
+ "foreground-child": "^3.1.0",
+ "jackspeak": "^3.1.2",
+ "minimatch": "^9.0.4",
+ "minipass": "^7.1.2",
+ "package-json-from-dist": "^1.0.0",
+ "path-scurry": "^1.11.1"
+ },
+ "bin": {
+ "glob": "dist/esm/bin.mjs"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/glob-parent": {
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
+ "integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
+ "dev": true,
+ "dependencies": {
+ "is-glob": "^4.0.3"
+ },
+ "engines": {
+ "node": ">=10.13.0"
+ }
+ },
+ "node_modules/globals": {
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
+ "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/globalthis": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/globalthis/-/globalthis-1.0.4.tgz",
+ "integrity": "sha512-DpLKbNU4WylpxJykQujfCcwYWiV/Jhm50Goo0wrVILAv5jOr9d+H+UR3PhSCD2rCCEIg0uc+G+muBTwD54JhDQ==",
+ "dev": true,
+ "dependencies": {
+ "define-properties": "^1.2.1",
+ "gopd": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/glodrei": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/glodrei/-/glodrei-0.0.1.tgz",
+ "integrity": "sha512-DMx6ElCSwh1pR4IyDS3LvyFwZHSCCKCqdqo8P1G7klQtqH6PcOjleduCDsHehDtyYQ1E4dzVeoEzHIL1DIxjag==",
+ "dependencies": {
+ "@babel/runtime": "^7.11.2",
+ "@mediapipe/tasks-vision": "0.10.8",
+ "@react-spring/three": "~9.6.1",
+ "@use-gesture/react": "^10.2.24",
+ "camera-controls": "^2.4.2",
+ "cross-env": "^7.0.3",
+ "detect-gpu": "^5.0.28",
+ "glsl-noise": "^0.0.0",
+ "maath": "^0.10.7",
+ "meshline": "^3.1.6",
+ "react-composer": "^5.0.3",
+ "react-merge-refs": "^1.1.0",
+ "stats-gl": "^2.0.0",
+ "stats.js": "^0.17.0",
+ "suspend-react": "^0.1.3",
+ "three-mesh-bvh": "^0.7.0",
+ "three-stdlib": "^2.29.4",
+ "troika-three-text": "^0.47.2",
+ "tunnel-rat": "^0.1.2",
+ "utility-types": "^3.10.0",
+ "uuid": "^9.0.1",
+ "zustand": "^3.7.1"
+ },
+ "peerDependencies": {
+ "@react-three/fiber": ">=8.0",
+ "react": ">=18.0",
+ "react-dom": ">=18.0",
+ "three": ">=0.137"
+ },
+ "peerDependenciesMeta": {
+ "react-dom": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/glodrei/node_modules/zustand": {
+ "version": "3.7.2",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-3.7.2.tgz",
+ "integrity": "sha512-PIJDIZKtokhof+9+60cpockVOq05sJzHCriyvaLBmEJixseQ1a5Kdov6fWZfWOu5SK9c+FhH1jU0tntLxRJYMA==",
+ "engines": {
+ "node": ">=12.7.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ },
+ "peerDependenciesMeta": {
+ "react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/glsl-noise": {
+ "version": "0.0.0",
+ "resolved": "https://registry.npmjs.org/glsl-noise/-/glsl-noise-0.0.0.tgz",
+ "integrity": "sha512-b/ZCF6amfAUb7dJM/MxRs7AetQEahYzJ8PtgfrmEdtw6uyGOr+ZSGtgjFm6mfsBkxJ4d2W7kg+Nlqzqvn3Bc0w=="
+ },
+ "node_modules/gopd": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.0.1.tgz",
+ "integrity": "sha512-d65bNlIadxvpb/A2abVdlqKqV563juRnZ1Wtk6s1sIR8uNsXR70xqIzVqxVf1eTqDunwT2MkczEeaezCKTZhwA==",
+ "dev": true,
+ "dependencies": {
+ "get-intrinsic": "^1.1.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/graceful-fs": {
+ "version": "4.2.11",
+ "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz",
+ "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ=="
+ },
+ "node_modules/graphemer": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/graphemer/-/graphemer-1.4.0.tgz",
+ "integrity": "sha512-EtKwoO6kxCL9WO5xipiHTZlSzBm7WLT627TqC/uVRd0HKmq8NXyebnNYxDoBi7wt8eTWrUrKXCOVaFq9x1kgag==",
+ "dev": true
+ },
+ "node_modules/graphology": {
+ "version": "0.25.4",
+ "resolved": "https://registry.npmjs.org/graphology/-/graphology-0.25.4.tgz",
+ "integrity": "sha512-33g0Ol9nkWdD6ulw687viS8YJQBxqG5LWII6FI6nul0pq6iM2t5EKquOTFDbyTblRB3O9I+7KX4xI8u5ffekAQ==",
+ "dependencies": {
+ "events": "^3.3.0",
+ "obliterator": "^2.0.2"
+ },
+ "peerDependencies": {
+ "graphology-types": ">=0.24.0"
+ }
+ },
+ "node_modules/graphology-indices": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/graphology-indices/-/graphology-indices-0.17.0.tgz",
+ "integrity": "sha512-A7RXuKQvdqSWOpn7ZVQo4S33O0vCfPBnUSf7FwE0zNCasqwZVUaCXePuWo5HBpWw68KJcwObZDHpFk6HKH6MYQ==",
+ "dependencies": {
+ "graphology-utils": "^2.4.2",
+ "mnemonist": "^0.39.0"
+ },
+ "peerDependencies": {
+ "graphology-types": ">=0.20.0"
+ }
+ },
+ "node_modules/graphology-layout": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/graphology-layout/-/graphology-layout-0.6.1.tgz",
+ "integrity": "sha512-m9aMvbd0uDPffUCFPng5ibRkb2pmfNvdKjQWeZrf71RS1aOoat5874+DcyNfMeCT4aQguKC7Lj9eCbqZj/h8Ag==",
+ "dependencies": {
+ "graphology-utils": "^2.3.0",
+ "pandemonium": "^2.4.0"
+ },
+ "peerDependencies": {
+ "graphology-types": ">=0.19.0"
+ }
+ },
+ "node_modules/graphology-layout-forceatlas2": {
+ "version": "0.10.1",
+ "resolved": "https://registry.npmjs.org/graphology-layout-forceatlas2/-/graphology-layout-forceatlas2-0.10.1.tgz",
+ "integrity": "sha512-ogzBeF1FvWzjkikrIFwxhlZXvD2+wlY54lqhsrWprcdPjopM2J9HoMweUmIgwaTvY4bUYVimpSsOdvDv1gPRFQ==",
+ "dependencies": {
+ "graphology-utils": "^2.1.0"
+ },
+ "peerDependencies": {
+ "graphology-types": ">=0.19.0"
+ }
+ },
+ "node_modules/graphology-layout-noverlap": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/graphology-layout-noverlap/-/graphology-layout-noverlap-0.4.2.tgz",
+ "integrity": "sha512-13WwZSx96zim6l1dfZONcqLh3oqyRcjIBsqz2c2iJ3ohgs3605IDWjldH41Gnhh462xGB1j6VGmuGhZ2FKISXA==",
+ "dependencies": {
+ "graphology-utils": "^2.3.0"
+ },
+ "peerDependencies": {
+ "graphology-types": ">=0.19.0"
+ }
+ },
+ "node_modules/graphology-metrics": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/graphology-metrics/-/graphology-metrics-2.3.1.tgz",
+ "integrity": "sha512-131GRSKUR8DrGkLZSYKM3cwxEg+jqXvv1yLh/KgO0My7BOiuo80r0Qrsnv2N3ZjcOlh8namUS4sSk+cCVnTgKA==",
+ "dependencies": {
+ "graphology-indices": "^0.17.0",
+ "graphology-shortest-path": "^2.0.0",
+ "graphology-utils": "^2.4.4",
+ "mnemonist": "^0.39.0"
+ },
+ "peerDependencies": {
+ "graphology-types": ">=0.20.0"
+ }
+ },
+ "node_modules/graphology-shortest-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/graphology-shortest-path/-/graphology-shortest-path-2.1.0.tgz",
+ "integrity": "sha512-KbT9CTkP/u72vGEJzyRr24xFC7usI9Es3LMmCPHGwQ1KTsoZjxwA9lMKxfU0syvT/w+7fZUdB/Hu2wWYcJBm6Q==",
+ "dependencies": {
+ "@yomguithereal/helpers": "^1.1.1",
+ "graphology-indices": "^0.17.0",
+ "graphology-utils": "^2.4.3",
+ "mnemonist": "^0.39.0"
+ },
+ "peerDependencies": {
+ "graphology-types": ">=0.20.0"
+ }
+ },
+ "node_modules/graphology-types": {
+ "version": "0.24.7",
+ "resolved": "https://registry.npmjs.org/graphology-types/-/graphology-types-0.24.7.tgz",
+ "integrity": "sha512-tdcqOOpwArNjEr0gNQKCXwaNCWnQJrog14nJNQPeemcLnXQUUGrsCWpWkVKt46zLjcS6/KGoayeJfHHyPDlvwA==",
+ "peer": true
+ },
+ "node_modules/graphology-utils": {
+ "version": "2.5.2",
+ "resolved": "https://registry.npmjs.org/graphology-utils/-/graphology-utils-2.5.2.tgz",
+ "integrity": "sha512-ckHg8MXrXJkOARk56ZaSCM1g1Wihe2d6iTmz1enGOz4W/l831MBCKSayeFQfowgF8wd+PQ4rlch/56Vs/VZLDQ==",
+ "peerDependencies": {
+ "graphology-types": ">=0.23.0"
+ }
+ },
+ "node_modules/handlebars": {
+ "version": "4.7.8",
+ "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz",
+ "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==",
+ "dependencies": {
+ "minimist": "^1.2.5",
+ "neo-async": "^2.6.2",
+ "source-map": "^0.6.1",
+ "wordwrap": "^1.0.0"
+ },
+ "bin": {
+ "handlebars": "bin/handlebars"
+ },
+ "engines": {
+ "node": ">=0.4.7"
+ },
+ "optionalDependencies": {
+ "uglify-js": "^3.1.4"
+ }
+ },
+ "node_modules/has-bigints": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.2.tgz",
+ "integrity": "sha512-tSvCKtBr9lkF0Ex0aQiP9N+OpV4zi2r/Nee5VkRDbaqv35RLYMzbwQfFSZZH0kR+Rd6302UJZ2p/bJCEoR3VoQ==",
+ "dev": true,
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-flag": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
+ "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/has-property-descriptors": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-property-descriptors/-/has-property-descriptors-1.0.2.tgz",
+ "integrity": "sha512-55JNKuIW+vq4Ke1BjOTjM2YctQIvCT7GFzHwmfZPGo5wnrgkid0YQtnAleFSqumZm4az3n2BS+erby5ipJdgrg==",
+ "dev": true,
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-proto": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-proto/-/has-proto-1.0.3.tgz",
+ "integrity": "sha512-SJ1amZAJUiZS+PhsVLf5tGydlaVB8EdFpaSO4gmiUKUOxk8qzn5AIy4ZeJUmh22znIdk/uMAUT2pl3FxzVUH+Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-symbols": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.0.3.tgz",
+ "integrity": "sha512-l3LCuF6MgDNwTDKkdYGEihYjt5pRPbEg46rtlmnSPlUbgmB8LOIrKJbYYFBSbnPaJexMKtiPO8hmeRjRz2Td+A==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/has-tostringtag": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/has-tostringtag/-/has-tostringtag-1.0.2.tgz",
+ "integrity": "sha512-NqADB8VjPFLM2V0VvHUewwwsw0ZWBaIdgo+ieHtK3hasLz4qeCRjYcqfB6AQrBggRKppKF8L52/VqdVsO47Dlw==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.3"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/hasown": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
+ "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
+ "dependencies": {
+ "function-bind": "^1.1.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/hoist-non-react-statics": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-3.3.2.tgz",
+ "integrity": "sha512-/gGivxi8JPKWNm/W0jSmzcMPpfpPLc3dY/6GxhX2hQ9iGj3aDfklV4ET7NjKpSinLpJ5vafa9iiGIEZg10SfBw==",
+ "dependencies": {
+ "react-is": "^16.7.0"
+ }
+ },
+ "node_modules/hold-event": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/hold-event/-/hold-event-0.2.0.tgz",
+ "integrity": "sha512-rko5P1XgHzy4B0NR0xVHEpWPgj0i23f8Mf8qsOugd1CHvfLR0PyIyy+8TAQQA9v8qAa1OZ4XuCKk04rxmPGHNQ=="
+ },
+ "node_modules/https-proxy-agent": {
+ "version": "7.0.5",
+ "resolved": "https://registry.npmjs.org/https-proxy-agent/-/https-proxy-agent-7.0.5.tgz",
+ "integrity": "sha512-1e4Wqeblerz+tMKPIq2EMGiiWW1dIjZOksyHWSUm1rmuvw/how9hBHZ38lAGj5ID4Ik6EdkOw7NmWPy6LAwalw==",
+ "dev": true,
+ "dependencies": {
+ "agent-base": "^7.0.2",
+ "debug": "4"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/ignore": {
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/import-fresh": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.0.tgz",
+ "integrity": "sha512-veYYhQa+D1QBKznvhUHxb8faxlrwUnxseDAbAp457E0wLNio2bOSKnjYDhMj+YiAq61xrMGhQk9iXVk5FzgQMw==",
+ "dependencies": {
+ "parent-module": "^1.0.0",
+ "resolve-from": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/imurmurhash": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.8.19"
+ }
+ },
+ "node_modules/index-to-position": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/index-to-position/-/index-to-position-0.1.2.tgz",
+ "integrity": "sha512-MWDKS3AS1bGCHLBA2VLImJz42f7bJh8wQsTGCzI3j519/CASStoDONUBVz2I/VID0MpiX3SGSnbOD2xUalbE5g==",
+ "dev": true,
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/internal-slot": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.7.tgz",
+ "integrity": "sha512-NGnrKwXzSms2qUUih/ILZ5JBqNTSa1+ZmP6flaIp6KmSElgE9qdndzS3cqjrDovwFdmwsGsLdeFgB6suw+1e9g==",
+ "dev": true,
+ "dependencies": {
+ "es-errors": "^1.3.0",
+ "hasown": "^2.0.0",
+ "side-channel": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/internmap": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/internmap/-/internmap-2.0.3.tgz",
+ "integrity": "sha512-5Hh7Y1wQbvY5ooGgPbDaL5iYLAPzMTUrjMulskHLH6wnv/A+1q5rgEaiuqEjB+oxGXIVZs1FF+R/KPN3ZSQYYg==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/is-array-buffer": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/is-array-buffer/-/is-array-buffer-3.0.4.tgz",
+ "integrity": "sha512-wcjaerHw0ydZwfhiKbXJWLDY8A7yV7KhjQOpb83hGgGfId/aQa4TOvwyzn2PuswW2gPCYEL/nEAiSVpdOj1lXw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "get-intrinsic": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-arrayish": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg=="
+ },
+ "node_modules/is-bigint": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
+ "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "dev": true,
+ "dependencies": {
+ "has-bigints": "^1.0.1"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-binary-path": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
+ "integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
+ "dev": true,
+ "dependencies": {
+ "binary-extensions": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-boolean-object": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/is-boolean-object/-/is-boolean-object-1.1.2.tgz",
+ "integrity": "sha512-gDYaKHJmnj4aWxyj6YHyXVpdQawtVLHU5cb+eztPGczf6cjuTdwve5ZIEfgXqH4e57An1D1AKf8CZ3kYrQRqYA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-callable": {
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.7.tgz",
+ "integrity": "sha512-1BC0BVFhS/p0qtw6enp8e+8OD0UrK0oFLztSjNzhcKA3WDuJxxAPXzPuPtKkjEY9UUoEWlX/8fgKeu2S8i9JTA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-core-module": {
+ "version": "2.15.1",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.15.1.tgz",
+ "integrity": "sha512-z0vtXSwucUJtANQWldhbtbt7BnL0vxiFjIdDLAatwhDYty2bad6s+rijD6Ri4YuYJubLzIJLUidCh09e1djEVQ==",
+ "dependencies": {
+ "hasown": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-data-view": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/is-data-view/-/is-data-view-1.0.1.tgz",
+ "integrity": "sha512-AHkaJrsUVW6wq6JS8y3JnM/GJF/9cf+k20+iDzlSaJrinEo5+7vRiteOSwBhHRiAyQATN1AmY4hwzxJKPmYf+w==",
+ "dev": true,
+ "dependencies": {
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-date-object": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/is-date-object/-/is-date-object-1.0.5.tgz",
+ "integrity": "sha512-9YQaSxsAiSwcvS33MBk3wTCVnWK+HhF8VZR2jRxehM16QcVOdHqPn4VPHmRK4lSr38n9JriurInLcP90xsYNfQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-extglob": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-fullwidth-code-point": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-3.0.0.tgz",
+ "integrity": "sha512-zymm5+u+sCsSWyD9qNaejV3DFvhCKclKdizYaJUuHA83RLjb7nSuGnddCHGv0hk+KY7BMAlsWeK4Ueg6EV6XQg==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/is-glob": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
+ "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
+ "dev": true,
+ "dependencies": {
+ "is-extglob": "^2.1.1"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/is-negative-zero": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.3.tgz",
+ "integrity": "sha512-5KoIu2Ngpyek75jXodFvnafB6DJgr3u8uuK0LEZJjrU19DrMD3EVERaR8sjz8CCGgpZvxPl9SuE1GMVPFHx1mw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-number": {
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
+ "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.12.0"
+ }
+ },
+ "node_modules/is-number-object": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.7.tgz",
+ "integrity": "sha512-k1U0IRzLMo7ZlYIfzRu23Oh6MiIFasgpb9X76eqfFZAqwH44UI4KTBvBYIZ1dSL9ZzChTB9ShHfLkR4pdW5krQ==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-regex": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/is-regex/-/is-regex-1.1.4.tgz",
+ "integrity": "sha512-kvRdxDsxZjhzUX07ZnLydzS1TU/TJlTUHHY4YLL87e37oUA49DfkLqgy+VjFocowy29cKvcSiu+kIv728jTTVg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-shared-array-buffer": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.3.tgz",
+ "integrity": "sha512-nA2hv5XIhLR3uVzDDfCIknerhx8XUKnstuOERPNNIinXG7v9u+ohXF67vxm4TPTEPU6lm61ZkwP3c9PCB97rhg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-string": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/is-string/-/is-string-1.0.7.tgz",
+ "integrity": "sha512-tE2UXzivje6ofPW7l23cjDOMa09gb7xlAqG6jG5ej6uPV32TlWP3NKPigtaGeHNu9fohccRYvIiZMfOOnOYUtg==",
+ "dev": true,
+ "dependencies": {
+ "has-tostringtag": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-symbol": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/is-symbol/-/is-symbol-1.0.4.tgz",
+ "integrity": "sha512-C/CPBqKWnvdcxqIARxyOh4v1UUEOCHpgDa0WYgpKDFMszcrPcffg5uhwSgPCLD2WWxmq6isisz87tzT01tuGhg==",
+ "dev": true,
+ "dependencies": {
+ "has-symbols": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-typed-array": {
+ "version": "1.1.13",
+ "resolved": "https://registry.npmjs.org/is-typed-array/-/is-typed-array-1.1.13.tgz",
+ "integrity": "sha512-uZ25/bUAlUY5fR4OKT4rZQEBrzQWYV9ZJYGGsUmEJ6thodVJ1HX64ePQ6Z0qPWP+m+Uq6e9UugrE38jeYsDSMw==",
+ "dev": true,
+ "dependencies": {
+ "which-typed-array": "^1.1.14"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/is-weakref": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.2.tgz",
+ "integrity": "sha512-qctsuLZmIQ0+vSSMfoVvyFe2+GSEvnmZ2ezTup1SBse9+twCCeial6EEi3Nc2KFcf6+qz2FBPnjXsk8xhKSaPQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/isarray": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "dev": true
+ },
+ "node_modules/isexe": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw=="
+ },
+ "node_modules/its-fine": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/its-fine/-/its-fine-1.2.5.tgz",
+ "integrity": "sha512-fXtDA0X0t0eBYAGLVM5YsgJGsJ5jEmqZEPrGbzdf5awjv0xE7nqv3TVnvtUF060Tkes15DbDAKW/I48vsb6SyA==",
+ "dependencies": {
+ "@types/react-reconciler": "^0.28.0"
+ },
+ "peerDependencies": {
+ "react": ">=18.0"
+ }
+ },
+ "node_modules/its-fine/node_modules/@types/react-reconciler": {
+ "version": "0.28.8",
+ "resolved": "https://registry.npmjs.org/@types/react-reconciler/-/react-reconciler-0.28.8.tgz",
+ "integrity": "sha512-SN9c4kxXZonFhbX4hJrZy37yw9e7EIxcpHCxQv5JUS18wDE5ovkQKlqQEkufdJCCMfuI9BnjUJvhYeJ9x5Ra7g==",
+ "dependencies": {
+ "@types/react": "*"
+ }
+ },
+ "node_modules/jackspeak": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-3.4.3.tgz",
+ "integrity": "sha512-OGlZQpz2yfahA/Rd1Y8Cd9SIEsqvXkLVoSw/cgwhnhFMDbsQFeZYoJJ7bIZBS9BcamUW96asq/npPWugM+RQBw==",
+ "dev": true,
+ "dependencies": {
+ "@isaacs/cliui": "^8.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ },
+ "optionalDependencies": {
+ "@pkgjs/parseargs": "^0.11.0"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.21.6",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.6.tgz",
+ "integrity": "sha512-2yTgeWTWzMWkHu6Jp9NKgePDaYHbntiwvYuuJLbbN9vl7DC9DvXKOB2BC3ZZ92D3cvV/aflH0osDfwpHepQ53w==",
+ "dev": true,
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/js-levenshtein": {
+ "version": "1.1.6",
+ "resolved": "https://registry.npmjs.org/js-levenshtein/-/js-levenshtein-1.1.6.tgz",
+ "integrity": "sha512-X2BB11YZtrRqY4EnQcLX5Rh373zbK4alC1FW7D7MBhL2gtcC17cTnr6DmfHZeS0s2rTHjUTMMHfG7gO8SSdw+g==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/js-tokens": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz",
+ "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ=="
+ },
+ "node_modules/js-yaml": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.0.tgz",
+ "integrity": "sha512-wpxZs9NoxZaJESJGIZTyDEaYpl0FKSA+FB9aJiyemKhMwkxQg63h4T1KJgUGHpTqPDNRcmmYLugrRjJlBtWvRA==",
+ "dependencies": {
+ "argparse": "^2.0.1"
+ },
+ "bin": {
+ "js-yaml": "bin/js-yaml.js"
+ }
+ },
+ "node_modules/jsesc": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.0.2.tgz",
+ "integrity": "sha512-xKqzzWXDttJuOcawBt4KnKHHIf5oQ/Cxax+0PWFG+DFDgHNAdi+TXECADI+RYiFUMmx8792xsMbbgXj4CwnP4g==",
+ "bin": {
+ "jsesc": "bin/jsesc"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true
+ },
+ "node_modules/json-parse-even-better-errors": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
+ "integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w=="
+ },
+ "node_modules/json-schema-traverse": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz",
+ "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==",
+ "dev": true
+ },
+ "node_modules/json-stable-stringify-without-jsonify": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz",
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true
+ },
+ "node_modules/json5": {
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
+ "bin": {
+ "json5": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/jsonfile": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
+ "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "dependencies": {
+ "universalify": "^2.0.0"
+ },
+ "optionalDependencies": {
+ "graceful-fs": "^4.1.6"
+ }
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
+ "dev": true,
+ "dependencies": {
+ "json-buffer": "3.0.1"
+ }
+ },
+ "node_modules/levn": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/levn/-/levn-0.4.1.tgz",
+ "integrity": "sha512-+bT2uH4E5LGE7h/n3evcS/sQlJXCpIp6ym8OWJ5eV6+67Dsql/LaaT7qJBAt2rzfoa/5QBGBhxDix1dMt2kQKQ==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/lilconfig": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
+ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/lines-and-columns": {
+ "version": "1.2.4",
+ "resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
+ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg=="
+ },
+ "node_modules/lit": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/lit/-/lit-3.2.1.tgz",
+ "integrity": "sha512-1BBa1E/z0O9ye5fZprPtdqnc0BFzxIxTTOO/tQFmyC/hj1O3jL4TfmLBw0WEwjAokdLwpclkvGgDJwTIh0/22w==",
+ "dependencies": {
+ "@lit/reactive-element": "^2.0.4",
+ "lit-element": "^4.1.0",
+ "lit-html": "^3.2.0"
+ }
+ },
+ "node_modules/lit-element": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/lit-element/-/lit-element-4.1.1.tgz",
+ "integrity": "sha512-HO9Tkkh34QkTeUmEdNYhMT8hzLid7YlMlATSi1q4q17HE5d9mrrEHJ/o8O2D0cMi182zK1F3v7x0PWFjrhXFew==",
+ "dependencies": {
+ "@lit-labs/ssr-dom-shim": "^1.2.0",
+ "@lit/reactive-element": "^2.0.4",
+ "lit-html": "^3.2.0"
+ }
+ },
+ "node_modules/lit-html": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/lit-html/-/lit-html-3.2.1.tgz",
+ "integrity": "sha512-qI/3lziaPMSKsrwlxH/xMgikhQ0EGOX2ICU73Bi/YHFvz2j/yMCIrw4+puF2IpQ4+upd3EWbvnHM9+PnJn48YA==",
+ "dependencies": {
+ "@types/trusted-types": "^2.0.2"
+ }
+ },
+ "node_modules/locate-path": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
+ "dev": true,
+ "dependencies": {
+ "p-locate": "^5.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/lodash": {
+ "version": "4.17.21",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
+ "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ },
+ "node_modules/lodash.castarray": {
+ "version": "4.4.0",
+ "resolved": "https://registry.npmjs.org/lodash.castarray/-/lodash.castarray-4.4.0.tgz",
+ "integrity": "sha512-aVx8ztPv7/2ULbArGJ2Y42bG1mEQ5mGjpdvrbJcJFU3TbYybe+QlLS4pst9zV52ymy2in1KpFPiZnAOATxD4+Q==",
+ "dev": true
+ },
+ "node_modules/lodash.isequal": {
+ "version": "4.5.0",
+ "resolved": "https://registry.npmjs.org/lodash.isequal/-/lodash.isequal-4.5.0.tgz",
+ "integrity": "sha512-pDo3lu8Jhfjqls6GkMgpahsF9kCyayhgykjyLMNFTKWrpVdAQtYyB4muAMWozBB4ig/dtWAmsMxLEI8wuz+DYQ==",
+ "dev": true
+ },
+ "node_modules/lodash.isplainobject": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/lodash.isplainobject/-/lodash.isplainobject-4.0.6.tgz",
+ "integrity": "sha512-oSXzaWypCMHkPC3NvBEaPHf0KsA5mvPrOPgQWDsbg8n7orZ290M0BmC/jgRZ4vcJ6DTAhjrsSYgdsW/F+MFOBA==",
+ "dev": true
+ },
+ "node_modules/lodash.merge": {
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/lodash.merge/-/lodash.merge-4.6.2.tgz",
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "dev": true
+ },
+ "node_modules/loose-envify": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.4.0.tgz",
+ "integrity": "sha512-lyuxPGr/Wfhrlem2CL/UcnUc1zcqKAImBDzukY7Y5F/yQiNdko6+fRLevlw1HgMySw7f611UIY408EtxRSoK3Q==",
+ "dependencies": {
+ "js-tokens": "^3.0.0 || ^4.0.0"
+ },
+ "bin": {
+ "loose-envify": "cli.js"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/maath": {
+ "version": "0.10.8",
+ "resolved": "https://registry.npmjs.org/maath/-/maath-0.10.8.tgz",
+ "integrity": "sha512-tRvbDF0Pgqz+9XUa4jjfgAQ8/aPKmQdWXilFu2tMy4GWj4NOsx99HlULO4IeREfbO3a0sA145DZYyvXPkybm0g==",
+ "peerDependencies": {
+ "@types/three": ">=0.134.0",
+ "three": ">=0.134.0"
+ }
+ },
+ "node_modules/memoize-one": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/memoize-one/-/memoize-one-6.0.0.tgz",
+ "integrity": "sha512-rkpe71W0N0c0Xz6QD0eJETuWAJGnJ9afsl1srmwPrI+yBCkge5EycXXbYRyvL29zZVUWQCY7InPRCv3GDXuZNw=="
+ },
+ "node_modules/merge2": {
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/merge2/-/merge2-1.4.1.tgz",
+ "integrity": "sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/meshline": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/meshline/-/meshline-3.3.1.tgz",
+ "integrity": "sha512-/TQj+JdZkeSUOl5Mk2J7eLcYTLiQm2IDzmlSvYm7ov15anEcDJ92GHqqazxTSreeNgfnYu24kiEvvv0WlbCdFQ==",
+ "peerDependencies": {
+ "three": ">=0.137"
+ }
+ },
+ "node_modules/meshoptimizer": {
+ "version": "0.18.1",
+ "resolved": "https://registry.npmjs.org/meshoptimizer/-/meshoptimizer-0.18.1.tgz",
+ "integrity": "sha512-ZhoIoL7TNV4s5B6+rx5mC//fw8/POGyNxS/DZyCJeiZ12ScLfVwRE/GfsxwiTkMYYD5DmK2/JXnEVXqL4rF+Sw=="
+ },
+ "node_modules/micromatch": {
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "dev": true,
+ "dependencies": {
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
+ },
+ "engines": {
+ "node": ">=8.6"
+ }
+ },
+ "node_modules/mime-db": {
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/mime-types": {
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "dependencies": {
+ "mime-db": "1.52.0"
+ },
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
+ "node_modules/minimatch": {
+ "version": "9.0.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-9.0.5.tgz",
+ "integrity": "sha512-G6T0ZX48xgozx7587koeX9Ys2NYy6Gmv//P89sEte9V9whIapMNF4idKxnW2QtCcLiTWlb/wfCabAtAFWhhBow==",
+ "dev": true,
+ "dependencies": {
+ "brace-expansion": "^2.0.1"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/minimist": {
+ "version": "1.2.8",
+ "resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
+ "integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/minipass": {
+ "version": "7.1.2",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz",
+ "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==",
+ "dev": true,
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/mnemonist": {
+ "version": "0.39.8",
+ "resolved": "https://registry.npmjs.org/mnemonist/-/mnemonist-0.39.8.tgz",
+ "integrity": "sha512-vyWo2K3fjrUw8YeeZ1zF0fy6Mu59RHokURlld8ymdUPjMlD9EC9ov1/YPqTgqRvUN9nTr3Gqfz29LYAmu0PHPQ==",
+ "dependencies": {
+ "obliterator": "^2.0.1"
+ }
+ },
+ "node_modules/monaco-editor": {
+ "version": "0.52.0",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.52.0.tgz",
+ "integrity": "sha512-OeWhNpABLCeTqubfqLMXGsqf6OmPU6pHM85kF3dhy6kq5hnhuVS1p3VrEW/XhWHc71P2tHyS5JFySD8mgs1crw==",
+ "peer": true
+ },
+ "node_modules/ms": {
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA=="
+ },
+ "node_modules/mz": {
+ "version": "2.7.0",
+ "resolved": "https://registry.npmjs.org/mz/-/mz-2.7.0.tgz",
+ "integrity": "sha512-z81GNO7nnYMEhrGh9LeymoE4+Yr0Wn5McHIZMK5cfQCl+NDX08sCZgUc9/6MHni9IWuFLm1Z3HTCXu2z9fN62Q==",
+ "dev": true,
+ "dependencies": {
+ "any-promise": "^1.0.0",
+ "object-assign": "^4.0.1",
+ "thenify-all": "^1.0.0"
+ }
+ },
+ "node_modules/nanoid": {
+ "version": "3.3.7",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
+ "integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "bin": {
+ "nanoid": "bin/nanoid.cjs"
+ },
+ "engines": {
+ "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
+ }
+ },
+ "node_modules/natural-compare": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true
+ },
+ "node_modules/neo-async": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
+ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw=="
+ },
+ "node_modules/node-domexception": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/node-domexception/-/node-domexception-1.0.0.tgz",
+ "integrity": "sha512-/jKZoMpw0F8GRwl4/eLROPA3cfcXtLApP0QzLmUT/HuPCZWyB7IY9ZrMeKw2O/nFIqPQB3PVM9aYm0F312AXDQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/jimmywarting"
+ },
+ {
+ "type": "github",
+ "url": "https://paypal.me/jimmywarting"
+ }
+ ],
+ "engines": {
+ "node": ">=10.5.0"
+ }
+ },
+ "node_modules/node-fetch": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-3.3.2.tgz",
+ "integrity": "sha512-dRB78srN/l6gqWulah9SrxeYnxeddIG30+GOqK/9OlLVyLg3HPnr6SqOWTWOXKRwC2eGYCkZ59NNuSgvSrpgOA==",
+ "dependencies": {
+ "data-uri-to-buffer": "^4.0.0",
+ "fetch-blob": "^3.1.4",
+ "formdata-polyfill": "^4.0.10"
+ },
+ "engines": {
+ "node": "^12.20.0 || ^14.13.1 || >=16.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/node-fetch"
+ }
+ },
+ "node_modules/node-releases": {
+ "version": "2.0.18",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.18.tgz",
+ "integrity": "sha512-d9VeXT4SJ7ZeOqGX6R5EM022wpL+eWPooLI+5UpWn2jCT1aosUQEhQP214x33Wkwx3JQMvIm+tIoVOdodFS40g==",
+ "dev": true
+ },
+ "node_modules/normalize-path": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
+ "integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/normalize-range": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/normalize-range/-/normalize-range-0.1.2.tgz",
+ "integrity": "sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-assign": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/object-hash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/object-inspect": {
+ "version": "1.13.3",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.3.tgz",
+ "integrity": "sha512-kDCGIbxkDSXE3euJZZXzc6to7fCrKHNI/hSRQnRuQ+BWjFNzZwiFF8fj/6o2t2G9/jTj8PSIYTfCLelLZEeRpA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object-keys": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
+ "integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.assign": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.5.tgz",
+ "integrity": "sha512-byy+U7gp+FVwmyzKPYhW2h5l3crpmGsxl7X2s8y43IgxvG4g3QZ6CffDtsNQy1WsmZpQbO+ybo0AlW7TY6DcBQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.5",
+ "define-properties": "^1.2.1",
+ "has-symbols": "^1.0.3",
+ "object-keys": "^1.1.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.fromentries": {
+ "version": "2.0.8",
+ "resolved": "https://registry.npmjs.org/object.fromentries/-/object.fromentries-2.0.8.tgz",
+ "integrity": "sha512-k6E21FzySsSK5a21KRADBd/NGneRegFO5pLHfdQLpRDETUNJueLXs3WCzyQ3tFRDYgbq3KHGXfTbi2bs8WQ6rQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/object.groupby": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/object.groupby/-/object.groupby-1.0.3.tgz",
+ "integrity": "sha512-+Lhy3TQTuzXI5hevh8sBGqbmurHbbIjAi0Z4S63nthVLmLxfbj4T54a4CfZrXIrt9iP4mVAPYMo/v99taj3wjQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/object.values": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.2.0.tgz",
+ "integrity": "sha512-yBYjY9QX2hnRmZHAjG/f13MzmBzxzYgQhFrke06TTyKY5zSTEqkOeukBzIdVA3j3ulu8Qa3MbVFShV7T2RmGtQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/obliterator": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/obliterator/-/obliterator-2.0.4.tgz",
+ "integrity": "sha512-lgHwxlxV1qIg1Eap7LgIeoBWIMFibOjbrYPIPJZcI1mmGAI2m3lNYpK12Y+GBdPQ0U1hRwSord7GIaawz962qQ=="
+ },
+ "node_modules/openapi-fetch": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/openapi-fetch/-/openapi-fetch-0.13.0.tgz",
+ "integrity": "sha512-6Nlf/BDbtyHwHdNrLPUiyt4CZMzL3ZyAt55yWH8W7+Z+8aYWnvca4uZHQHXViy8KcnCMqAhLM/bifh2Yjjkf6w==",
+ "dependencies": {
+ "openapi-typescript-helpers": "^0.0.15"
+ }
+ },
+ "node_modules/openapi-typescript": {
+ "version": "7.4.3",
+ "resolved": "https://registry.npmjs.org/openapi-typescript/-/openapi-typescript-7.4.3.tgz",
+ "integrity": "sha512-xTIjMIIOv9kNhsr8JxaC00ucbIY/6ZwuJPJBZMSh5FA2dicZN5uM805DWVJojXdom8YI4AQTavPDPHMx/3g0vQ==",
+ "dev": true,
+ "dependencies": {
+ "@redocly/openapi-core": "^1.25.9",
+ "ansi-colors": "^4.1.3",
+ "change-case": "^5.4.4",
+ "parse-json": "^8.1.0",
+ "supports-color": "^9.4.0",
+ "yargs-parser": "^21.1.1"
+ },
+ "bin": {
+ "openapi-typescript": "bin/cli.js"
+ },
+ "peerDependencies": {
+ "typescript": "^5.x"
+ }
+ },
+ "node_modules/openapi-typescript-codegen": {
+ "version": "0.29.0",
+ "resolved": "https://registry.npmjs.org/openapi-typescript-codegen/-/openapi-typescript-codegen-0.29.0.tgz",
+ "integrity": "sha512-/wC42PkD0LGjDTEULa/XiWQbv4E9NwLjwLjsaJ/62yOsoYhwvmBR31kPttn1DzQ2OlGe5stACcF/EIkZk43M6w==",
+ "dependencies": {
+ "@apidevtools/json-schema-ref-parser": "^11.5.4",
+ "camelcase": "^6.3.0",
+ "commander": "^12.0.0",
+ "fs-extra": "^11.2.0",
+ "handlebars": "^4.7.8"
+ },
+ "bin": {
+ "openapi": "bin/index.js"
+ }
+ },
+ "node_modules/openapi-typescript-helpers": {
+ "version": "0.0.15",
+ "resolved": "https://registry.npmjs.org/openapi-typescript-helpers/-/openapi-typescript-helpers-0.0.15.tgz",
+ "integrity": "sha512-opyTPaunsklCBpTK8JGef6mfPhLSnyy5a0IN9vKtx3+4aExf+KxEqYwIy3hqkedXIB97u357uLMJsOnm3GVjsw=="
+ },
+ "node_modules/openapi-typescript/node_modules/supports-color": {
+ "version": "9.4.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-9.4.0.tgz",
+ "integrity": "sha512-VL+lNrEoIXww1coLPOmiEmK/0sGigko5COxI09KzHc2VJXJsQ37UaQ+8quuxjDeA7+KnLGTWRyOXSLLR2Wb4jw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
+ "dev": true,
+ "dependencies": {
+ "deep-is": "^0.1.3",
+ "fast-levenshtein": "^2.0.6",
+ "levn": "^0.4.1",
+ "prelude-ls": "^1.2.1",
+ "type-check": "^0.4.0",
+ "word-wrap": "^1.2.5"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/p-limit": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
+ "dev": true,
+ "dependencies": {
+ "yocto-queue": "^0.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/p-locate": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
+ "dev": true,
+ "dependencies": {
+ "p-limit": "^3.0.2"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/package-json-from-dist": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/package-json-from-dist/-/package-json-from-dist-1.0.1.tgz",
+ "integrity": "sha512-UEZIS3/by4OC8vL3P2dTXRETpebLI2NiI5vIrjaD/5UtrkFX/tNbwjTSRAGC/+7CAo2pIcBaRgWmcBBHcsaCIw==",
+ "dev": true
+ },
+ "node_modules/pandemonium": {
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/pandemonium/-/pandemonium-2.4.1.tgz",
+ "integrity": "sha512-wRqjisUyiUfXowgm7MFH2rwJzKIr20rca5FsHXCMNm1W5YPP1hCtrZfgmQ62kP7OZ7Xt+cR858aB28lu5NX55g==",
+ "dependencies": {
+ "mnemonist": "^0.39.2"
+ }
+ },
+ "node_modules/parent-module": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
+ "integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
+ "dependencies": {
+ "callsites": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/parse-json": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-8.1.0.tgz",
+ "integrity": "sha512-rum1bPifK5SSar35Z6EKZuYPJx85pkNaFrxBK3mwdfSJ1/WKbYrjoW/zTPSjRRamfmVX1ACBIdFAO0VRErW/EA==",
+ "dev": true,
+ "dependencies": {
+ "@babel/code-frame": "^7.22.13",
+ "index-to-position": "^0.1.2",
+ "type-fest": "^4.7.1"
+ },
+ "engines": {
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/path-exists": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
+ "integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-key": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/path-parse": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz",
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw=="
+ },
+ "node_modules/path-scurry": {
+ "version": "1.11.1",
+ "resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-1.11.1.tgz",
+ "integrity": "sha512-Xa4Nw17FS9ApQFJ9umLiJS4orGjm7ZzwUrwamcGQuHSzDyth9boKDaycYdDcZDuqYATXw4HFXgaqWTctW/v1HA==",
+ "dev": true,
+ "dependencies": {
+ "lru-cache": "^10.2.0",
+ "minipass": "^5.0.0 || ^6.0.2 || ^7.0.0"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/path-scurry/node_modules/lru-cache": {
+ "version": "10.4.3",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-10.4.3.tgz",
+ "integrity": "sha512-JNAzZcXrCt42VGLuYz0zfAzDfAvJWW6AfYlDBQyDV5DClI2m5sAmK+OIO7s59XfsRsWHp02jAJrRadPRGTt6SQ==",
+ "dev": true
+ },
+ "node_modules/path-type": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
+ "integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/performance-now": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
+ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
+ },
+ "node_modules/picocolors": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz",
+ "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA=="
+ },
+ "node_modules/picomatch": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
+ "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
+ "engines": {
+ "node": ">=8.6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/jonschlinkert"
+ }
+ },
+ "node_modules/pify": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.6",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
+ "integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pluralize": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-8.0.0.tgz",
+ "integrity": "sha512-Nc3IT5yHzflTfbjgqWcCPpo7DaKy4FnpB0l/zCAW0Tc7jxAiuqSxHasntB3D7887LSrA93kDJ9IXovxJYxyLCA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/possible-typed-array-names": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/possible-typed-array-names/-/possible-typed-array-names-1.0.0.tgz",
+ "integrity": "sha512-d7Uw+eZoloe0EHDIYoe+bQ5WXnGMOpmiZFTuMWCwpjzzkL2nTjcKiAk4hh8TjnGye2TwWOk3UXucZ+3rbmBa8Q==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/postcss": {
+ "version": "8.4.47",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz",
+ "integrity": "sha512-56rxCq7G/XfB4EkXq9Egn5GCqugWvDFjafDOThIdMBsI15iqPqR5r15TfSr1YPYeEI19YeaXMCbY6u88Y76GLQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.1.0",
+ "source-map-js": "^1.2.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/postcss-import": {
+ "version": "15.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-import/-/postcss-import-15.1.0.tgz",
+ "integrity": "sha512-hpr+J05B2FVYUAXHeK1YyI267J/dDDhMU6B6civm8hSY1jYJnBXxzKDKDswzJmtLHryrjhnDjqqp/49t8FALew==",
+ "dev": true,
+ "dependencies": {
+ "postcss-value-parser": "^4.0.0",
+ "read-cache": "^1.0.0",
+ "resolve": "^1.1.7"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.0"
+ }
+ },
+ "node_modules/postcss-js": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.0.1.tgz",
+ "integrity": "sha512-dDLF8pEO191hJMtlHFPRa8xsizHaM82MLfNkUHdUtVEV3tgTp5oj+8qbEqYM57SLfc74KSbw//4SeJma2LRVIw==",
+ "dev": true,
+ "dependencies": {
+ "camelcase-css": "^2.0.1"
+ },
+ "engines": {
+ "node": "^12 || ^14 || >= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
+ }
+ },
+ "node_modules/postcss-load-config": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-4.0.2.tgz",
+ "integrity": "sha512-bSVhyJGL00wMVoPUzAVAnbEoWyqRxkjv64tUl427SKnPrENtq6hJwUojroMz2VB+Q1edmi4IfrAPpami5VVgMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "lilconfig": "^3.0.0",
+ "yaml": "^2.3.4"
+ },
+ "engines": {
+ "node": ">= 14"
+ },
+ "peerDependencies": {
+ "postcss": ">=8.0.9",
+ "ts-node": ">=9.0.0"
+ },
+ "peerDependenciesMeta": {
+ "postcss": {
+ "optional": true
+ },
+ "ts-node": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/postcss-load-config/node_modules/lilconfig": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.2.tgz",
+ "integrity": "sha512-eop+wDAvpItUys0FWkHIKeC9ybYrTGbU41U5K7+bttZZeohvnY7M9dZ5kB21GNWiFT2q1OoPTvncPCgSOVO5ow==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
+ }
+ },
+ "node_modules/postcss-load-config/node_modules/yaml": {
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.6.0.tgz",
+ "integrity": "sha512-a6ae//JvKDEra2kdi1qzCyrJW/WZCgFi8ydDV+eXExl95t+5R+ijnqHJbz9tmMh8FUjx3iv2fCQ4dclAQlO2UQ==",
+ "dev": true,
+ "bin": {
+ "yaml": "bin.mjs"
+ },
+ "engines": {
+ "node": ">= 14"
+ }
+ },
+ "node_modules/postcss-nested": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-6.2.0.tgz",
+ "integrity": "sha512-HQbt28KulC5AJzG+cZtj9kvKB93CFCdLvog1WFLf1D+xmMvPGlBstkpTEZfK5+AN9hfJocyBFCNiqyS48bpgzQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "postcss-selector-parser": "^6.1.1"
+ },
+ "engines": {
+ "node": ">=12.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.14"
+ }
+ },
+ "node_modules/postcss-nested/node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "dev": true,
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-selector-parser": {
+ "version": "6.0.10",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.10.tgz",
+ "integrity": "sha512-IQ7TZdoaqbT+LCpShg46jnZVlhWD2w6iQYAcYXfHARZ7X1t/UGhhceQDs5X0cGqKvYlHNOuv7Oa1xmb0oQuA3w==",
+ "dev": true,
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/postcss-value-parser": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz",
+ "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ=="
+ },
+ "node_modules/potpack": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz",
+ "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ=="
+ },
+ "node_modules/prelude-ls": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.2.1.tgz",
+ "integrity": "sha512-vkcDPrRZo1QZLbn5RLGPpg/WmIQ65qoWWhcGKf/b5eplkkarX0m9z8ppCat4mlOqUsWpyNuYgO3VRyrYHSzX5g==",
+ "dev": true,
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/prop-types": {
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.8.1.tgz",
+ "integrity": "sha512-oj87CgZICdulUohogVAR7AjlC0327U4el4L6eAvOqCeudMDVU0NThNaV+b9Df4dXgSP1gXMTnPdhfe/2qDH5cg==",
+ "dependencies": {
+ "loose-envify": "^1.4.0",
+ "object-assign": "^4.1.1",
+ "react-is": "^16.13.1"
+ }
+ },
+ "node_modules/proxy-from-env": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
+ "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg=="
+ },
+ "node_modules/punycode": {
+ "version": "2.3.1",
+ "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.3.1.tgz",
+ "integrity": "sha512-vYt7UD1U9Wg6138shLtLOvdAu+8DsC/ilFtEVHcH+wydcSpNE20AfSOduf6MkRFahL5FY7X1oU7nKVZFtfq8Fg==",
+ "dev": true,
+ "engines": {
+ "node": ">=6"
+ }
+ },
+ "node_modules/queue-microtask": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
+ "integrity": "sha512-NuaNSa6flKT5JaSYQzJok04JzTL1CA6aGhv5rfLW3PgqA+M2ChpZQnAC8h8i4ZFkBS8X5RqkDBHA7r4hej3K9A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ]
+ },
+ "node_modules/raf": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
+ "integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+ "dependencies": {
+ "performance-now": "^2.1.0"
+ }
+ },
+ "node_modules/rc-align": {
+ "version": "2.4.5",
+ "resolved": "https://registry.npmjs.org/rc-align/-/rc-align-2.4.5.tgz",
+ "integrity": "sha512-nv9wYUYdfyfK+qskThf4BQUSIadeI/dCsfaMZfNEoxm9HwOIioQ+LyqmMK6jWHAZQgOzMLaqawhuBXlF63vgjw==",
+ "dependencies": {
+ "babel-runtime": "^6.26.0",
+ "dom-align": "^1.7.0",
+ "prop-types": "^15.5.8",
+ "rc-util": "^4.0.4"
+ }
+ },
+ "node_modules/rc-animate": {
+ "version": "2.11.1",
+ "resolved": "https://registry.npmjs.org/rc-animate/-/rc-animate-2.11.1.tgz",
+ "integrity": "sha512-1NyuCGFJG/0Y+9RKh5y/i/AalUCA51opyyS/jO2seELpgymZm2u9QV3xwODwEuzkmeQ1BDPxMLmYLcTJedPlkQ==",
+ "dependencies": {
+ "babel-runtime": "6.x",
+ "classnames": "^2.2.6",
+ "css-animation": "^1.3.2",
+ "prop-types": "15.x",
+ "raf": "^3.4.0",
+ "rc-util": "^4.15.3",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
+ "node_modules/rc-slider": {
+ "version": "8.7.1",
+ "resolved": "https://registry.npmjs.org/rc-slider/-/rc-slider-8.7.1.tgz",
+ "integrity": "sha512-WMT5mRFUEcrLWwTxsyS8jYmlaMsTVCZIGENLikHsNv+tE8ThU2lCoPfi/xFNUfJFNFSBFP3MwPez9ZsJmNp13g==",
+ "dependencies": {
+ "babel-runtime": "6.x",
+ "classnames": "^2.2.5",
+ "prop-types": "^15.5.4",
+ "rc-tooltip": "^3.7.0",
+ "rc-util": "^4.0.4",
+ "react-lifecycles-compat": "^3.0.4",
+ "shallowequal": "^1.1.0",
+ "warning": "^4.0.3"
+ }
+ },
+ "node_modules/rc-tooltip": {
+ "version": "3.7.3",
+ "resolved": "https://registry.npmjs.org/rc-tooltip/-/rc-tooltip-3.7.3.tgz",
+ "integrity": "sha512-dE2ibukxxkrde7wH9W8ozHKUO4aQnPZ6qBHtrTH9LoO836PjDdiaWO73fgPB05VfJs9FbZdmGPVEbXCeOP99Ww==",
+ "dependencies": {
+ "babel-runtime": "6.x",
+ "prop-types": "^15.5.8",
+ "rc-trigger": "^2.2.2"
+ }
+ },
+ "node_modules/rc-trigger": {
+ "version": "2.6.5",
+ "resolved": "https://registry.npmjs.org/rc-trigger/-/rc-trigger-2.6.5.tgz",
+ "integrity": "sha512-m6Cts9hLeZWsTvWnuMm7oElhf+03GOjOLfTuU0QmdB9ZrW7jR2IpI5rpNM7i9MvAAlMAmTx5Zr7g3uu/aMvZAw==",
+ "dependencies": {
+ "babel-runtime": "6.x",
+ "classnames": "^2.2.6",
+ "prop-types": "15.x",
+ "rc-align": "^2.4.0",
+ "rc-animate": "2.x",
+ "rc-util": "^4.4.0",
+ "react-lifecycles-compat": "^3.0.4"
+ }
+ },
+ "node_modules/rc-util": {
+ "version": "4.21.1",
+ "resolved": "https://registry.npmjs.org/rc-util/-/rc-util-4.21.1.tgz",
+ "integrity": "sha512-Z+vlkSQVc1l8O2UjR3WQ+XdWlhj5q9BMQNLk2iOBch75CqPfrJyGtcWMcnhRlNuDu0Ndtt4kLVO8JI8BrABobg==",
+ "dependencies": {
+ "add-dom-event-listener": "^1.1.0",
+ "prop-types": "^15.5.10",
+ "react-is": "^16.12.0",
+ "react-lifecycles-compat": "^3.0.4",
+ "shallowequal": "^1.1.0"
+ }
+ },
+ "node_modules/react": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react/-/react-18.3.1.tgz",
+ "integrity": "sha512-wS+hAgJShR0KhEvPJArfuPVN1+Hz1t0Y6n5jLrGQbkb4urgPE/0Rve+1kMB1v/oWgHgm4WIcV+i7F2pTVj+2iQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-chartjs-2": {
+ "version": "5.2.0",
+ "resolved": "https://registry.npmjs.org/react-chartjs-2/-/react-chartjs-2-5.2.0.tgz",
+ "integrity": "sha512-98iN5aguJyVSxp5U3CblRLH67J8gkfyGNbiK3c+l1QI/G4irHMPQw44aEPmjVag+YKTyQ260NcF82GTQ3bdscA==",
+ "peerDependencies": {
+ "chart.js": "^4.1.1",
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-colorscales": {
+ "version": "0.7.3",
+ "resolved": "https://registry.npmjs.org/react-colorscales/-/react-colorscales-0.7.3.tgz",
+ "integrity": "sha512-cekeF6mgATIwG257lu4aan2uF3AaiLmI4XvC1Sf2x+KKfCM6J8Ogl4eoO8ii2Cy/ddb+bL1QNnjN9KSQmbGc2Q==",
+ "dependencies": {
+ "chroma-js": "^1.3.4",
+ "rc-slider": "^8.4.0",
+ "react-select": "^1.2.1"
+ },
+ "peerDependencies": {
+ "react": ">=0.14",
+ "react-dom": ">=0.14"
+ }
+ },
+ "node_modules/react-colorscales/node_modules/react-select": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/react-select/-/react-select-1.3.0.tgz",
+ "integrity": "sha512-g/QAU1HZrzSfxkwMAo/wzi6/ezdWye302RGZevsATec07hI/iSxcpB1hejFIp7V63DJ8mwuign6KmB3VjdlinQ==",
+ "dependencies": {
+ "classnames": "^2.2.4",
+ "prop-types": "^15.5.8",
+ "react-input-autosize": "^2.1.2"
+ },
+ "peerDependencies": {
+ "react": "^0.14.9 || ^15.3.0 || ^16.0.0-rc || ^16.0",
+ "react-dom": "^0.14.9 || ^15.3.0 || ^16.0.0-rc || ^16.0"
+ }
+ },
+ "node_modules/react-colorscales/node_modules/react-select/node_modules/react-input-autosize": {
+ "version": "2.2.2",
+ "resolved": "https://registry.npmjs.org/react-input-autosize/-/react-input-autosize-2.2.2.tgz",
+ "integrity": "sha512-jQJgYCA3S0j+cuOwzuCd1OjmBmnZLdqQdiLKRYrsMMzbjUrVDS5RvJUDwJqA7sKuksDuzFtm6hZGKFu7Mjk5aw==",
+ "dependencies": {
+ "prop-types": "^15.5.8"
+ },
+ "peerDependencies": {
+ "react": "^0.14.9 || ^15.3.0 || ^16.0.0-rc || ^16.0"
+ }
+ },
+ "node_modules/react-composer": {
+ "version": "5.0.3",
+ "resolved": "https://registry.npmjs.org/react-composer/-/react-composer-5.0.3.tgz",
+ "integrity": "sha512-1uWd07EME6XZvMfapwZmc7NgCZqDemcvicRi3wMJzXsQLvZ3L7fTHVyPy1bZdnWXM4iPjYuNE+uJ41MLKeTtnA==",
+ "dependencies": {
+ "prop-types": "^15.6.0"
+ },
+ "peerDependencies": {
+ "react": "^15.0.0 || ^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-datepicker": {
+ "version": "7.5.0",
+ "resolved": "https://registry.npmjs.org/react-datepicker/-/react-datepicker-7.5.0.tgz",
+ "integrity": "sha512-6MzeamV8cWSOcduwePHfGqY40acuGlS1cG//ePHT6bVbLxWyqngaStenfH03n1wbzOibFggF66kWaBTb1SbTtQ==",
+ "dependencies": {
+ "@floating-ui/react": "^0.26.23",
+ "clsx": "^2.1.1",
+ "date-fns": "^3.6.0",
+ "prop-types": "^15.8.1"
+ },
+ "peerDependencies": {
+ "react": "^16.9.0 || ^17 || ^18",
+ "react-dom": "^16.9.0 || ^17 || ^18"
+ }
+ },
+ "node_modules/react-datepicker/node_modules/date-fns": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/date-fns/-/date-fns-3.6.0.tgz",
+ "integrity": "sha512-fRHTG8g/Gif+kSh50gaGEdToemgfj74aRX3swtiouboip5JDLAyDE9F11nHMIcvOaXeOC6D7SpNhi7uFyB7Uww==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/kossnocorp"
+ }
+ },
+ "node_modules/react-dom": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-dom/-/react-dom-18.3.1.tgz",
+ "integrity": "sha512-5m4nQKp+rZRb09LNH59GM4BxTh9251/ylbKIbpe7TpGxfJ+9kv6BLkLBXIjjspbgbnIBNqlI23tRnTWT0snUIw==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.23.2"
+ },
+ "peerDependencies": {
+ "react": "^18.3.1"
+ }
+ },
+ "node_modules/react-grid-gallery": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/react-grid-gallery/-/react-grid-gallery-1.0.1.tgz",
+ "integrity": "sha512-+fVd6fH9tm0W+UMgzRHET/gmzSs2/l2sGOuELLaHXMto6UhuZdscj9ILHOYe7hn0GBRUJiczMllsEs7OJz9uPA==",
+ "peerDependencies": {
+ "react": ">=16.14.0"
+ }
+ },
+ "node_modules/react-icons": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.3.0.tgz",
+ "integrity": "sha512-DnUk8aFbTyQPSkCfF8dbX6kQjXA9DktMeJqfjrg6cK9vwQVMxmcA3BfP4QoiztVmEHtwlTgLFsPuH2NskKT6eg==",
+ "peerDependencies": {
+ "react": "*"
+ }
+ },
+ "node_modules/react-is": {
+ "version": "16.13.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz",
+ "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ=="
+ },
+ "node_modules/react-json-editor-ajrm": {
+ "version": "2.5.14",
+ "resolved": "https://registry.npmjs.org/react-json-editor-ajrm/-/react-json-editor-ajrm-2.5.14.tgz",
+ "integrity": "sha512-z2035l5lnU0Wo73AUonj68d1Eh9vjVcLXEa8YogDEeFPcogzYkfT6R38fvYlLKDhP0oI+LyOO/IBWsFkXs4M0Q==",
+ "dependencies": {
+ "@babel/runtime": "^7.0.0-rc.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.2.0",
+ "react-dom": ">=16.2.0"
+ }
+ },
+ "node_modules/react-json-editor-viewer": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/react-json-editor-viewer/-/react-json-editor-viewer-1.0.7.tgz",
+ "integrity": "sha512-vDgNOyhWhIsTIvmfIW84ZAWtLx0FAiStI+GLvqQ8/Tz05lBsgGCzOfBHduJKYBD40UamhDRMgaa6vYHbO4g4ig==",
+ "peerDependencies": {
+ "react": ">=0.14",
+ "react-dom": ">=0.14"
+ }
+ },
+ "node_modules/react-lifecycles-compat": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/react-lifecycles-compat/-/react-lifecycles-compat-3.0.4.tgz",
+ "integrity": "sha512-fBASbA6LnOU9dOU2eW7aQ8xmYBSXUIWr+UmF9b1efZBazGNO+rcXT/icdKnYm2pTwcRylVUYwW7H1PHfLekVzA=="
+ },
+ "node_modules/react-loader-spinner": {
+ "version": "6.1.6",
+ "resolved": "https://registry.npmjs.org/react-loader-spinner/-/react-loader-spinner-6.1.6.tgz",
+ "integrity": "sha512-x5h1Jcit7Qn03MuKlrWcMG9o12cp9SNDVHVJTNRi9TgtGPKcjKiXkou4NRfLAtXaFB3+Z8yZsVzONmPzhv2ErA==",
+ "dependencies": {
+ "react-is": "^18.2.0",
+ "styled-components": "^6.1.2"
+ },
+ "engines": {
+ "node": ">= 12"
+ },
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-loader-spinner/node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+ },
+ "node_modules/react-merge-refs": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/react-merge-refs/-/react-merge-refs-1.1.0.tgz",
+ "integrity": "sha512-alTKsjEL0dKH/ru1Iyn7vliS2QRcBp9zZPGoWxUOvRGWPUYgjo+V01is7p04It6KhgrzhJGnIj9GgX8W4bZoCQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/gregberge"
+ }
+ },
+ "node_modules/react-reconciler": {
+ "version": "0.27.0",
+ "resolved": "https://registry.npmjs.org/react-reconciler/-/react-reconciler-0.27.0.tgz",
+ "integrity": "sha512-HmMDKciQjYmBRGuuhIaKA1ba/7a+UsM5FzOZsMO2JYHt9Jh8reCb7j1eDC95NOyUlKM9KRyvdx0flBuDvYSBoA==",
+ "dependencies": {
+ "loose-envify": "^1.1.0",
+ "scheduler": "^0.21.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ },
+ "peerDependencies": {
+ "react": "^18.0.0"
+ }
+ },
+ "node_modules/react-reconciler/node_modules/scheduler": {
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.21.0.tgz",
+ "integrity": "sha512-1r87x5fz9MXqswA2ERLo0EbOAU74DpIUO090gIasYTqlVoJeMcl+Z1Rg7WHz+qtPujhS/hGIt9kxZOYBV3faRQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/react-refresh": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.14.2.tgz",
+ "integrity": "sha512-jCvmsr+1IUSMUyzOkRcvnVbX3ZYC6g9TDrDbFuFmRDq7PD4yaGbLKNQL6k2jnArV8hjYxh7hVhAZB6s9HDGpZA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/react-router": {
+ "version": "6.28.0",
+ "resolved": "https://registry.npmjs.org/react-router/-/react-router-6.28.0.tgz",
+ "integrity": "sha512-HrYdIFqdrnhDw0PqG/AKjAqEqM7AvxCz0DQ4h2W8k6nqmc5uRBYDag0SBxx9iYz5G8gnuNVLzUe13wl9eAsXXg==",
+ "dependencies": {
+ "@remix-run/router": "1.21.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8"
+ }
+ },
+ "node_modules/react-router-dom": {
+ "version": "6.28.0",
+ "resolved": "https://registry.npmjs.org/react-router-dom/-/react-router-dom-6.28.0.tgz",
+ "integrity": "sha512-kQ7Unsl5YdyOltsPGl31zOjLrDv+m2VcIEcIHqYYD3Lp0UppLjrzcfJqDJwXxFw3TH/yvapbnUvPlAj7Kx5nbg==",
+ "dependencies": {
+ "@remix-run/router": "1.21.0",
+ "react-router": "6.28.0"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.8",
+ "react-dom": ">=16.8"
+ }
+ },
+ "node_modules/react-select": {
+ "version": "5.8.2",
+ "resolved": "https://registry.npmjs.org/react-select/-/react-select-5.8.2.tgz",
+ "integrity": "sha512-a/LkOckoI62710gGPQSQqUp7A10fGbH/ya3/IR49qaq3XoBvwymgD5mJgtiHxBDsutyEQfdKNycWVh8Cg8UCjw==",
+ "dependencies": {
+ "@babel/runtime": "^7.12.0",
+ "@emotion/cache": "^11.4.0",
+ "@emotion/react": "^11.8.1",
+ "@floating-ui/dom": "^1.0.1",
+ "@types/react-transition-group": "^4.4.0",
+ "memoize-one": "^6.0.0",
+ "prop-types": "^15.6.0",
+ "react-transition-group": "^4.3.0",
+ "use-isomorphic-layout-effect": "^1.1.2"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-smooth": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/react-smooth/-/react-smooth-4.0.1.tgz",
+ "integrity": "sha512-OE4hm7XqR0jNOq3Qmk9mFLyd6p2+j6bvbPJ7qlB7+oo0eNcL2l7WQzG6MBnT3EXY6xzkLMUBec3AfewJdA0J8w==",
+ "dependencies": {
+ "fast-equals": "^5.0.1",
+ "prop-types": "^15.8.1",
+ "react-transition-group": "^4.4.5"
+ },
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-spinners": {
+ "version": "0.14.1",
+ "resolved": "https://registry.npmjs.org/react-spinners/-/react-spinners-0.14.1.tgz",
+ "integrity": "sha512-2Izq+qgQ08HTofCVEdcAQCXFEYfqTDdfeDQJeo/HHQiQJD4imOicNLhkfN2eh1NYEWVOX4D9ok2lhuDB0z3Aag==",
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/react-toastify": {
+ "version": "10.0.6",
+ "resolved": "https://registry.npmjs.org/react-toastify/-/react-toastify-10.0.6.tgz",
+ "integrity": "sha512-yYjp+omCDf9lhZcrZHKbSq7YMuK0zcYkDFTzfRFgTXkTFHZ1ToxwAonzA4JI5CxA91JpjFLmwEsZEgfYfOqI1A==",
+ "dependencies": {
+ "clsx": "^2.1.0"
+ },
+ "peerDependencies": {
+ "react": ">=18",
+ "react-dom": ">=18"
+ }
+ },
+ "node_modules/react-tooltip": {
+ "version": "5.28.0",
+ "resolved": "https://registry.npmjs.org/react-tooltip/-/react-tooltip-5.28.0.tgz",
+ "integrity": "sha512-R5cO3JPPXk6FRbBHMO0rI9nkUG/JKfalBSQfZedZYzmqaZQgq7GLzF8vcCWx6IhUCKg0yPqJhXIzmIO5ff15xg==",
+ "dependencies": {
+ "@floating-ui/dom": "^1.6.1",
+ "classnames": "^2.3.0"
+ },
+ "peerDependencies": {
+ "react": ">=16.14.0",
+ "react-dom": ">=16.14.0"
+ }
+ },
+ "node_modules/react-transition-group": {
+ "version": "4.4.5",
+ "resolved": "https://registry.npmjs.org/react-transition-group/-/react-transition-group-4.4.5.tgz",
+ "integrity": "sha512-pZcd1MCJoiKiBR2NRxeCRg13uCXbydPnmB4EOeRrY7480qNWO8IIgQG6zlDkm6uRMsURXPuKq0GWtiM59a5Q6g==",
+ "dependencies": {
+ "@babel/runtime": "^7.5.5",
+ "dom-helpers": "^5.0.1",
+ "loose-envify": "^1.4.0",
+ "prop-types": "^15.6.2"
+ },
+ "peerDependencies": {
+ "react": ">=16.6.0",
+ "react-dom": ">=16.6.0"
+ }
+ },
+ "node_modules/react-use-measure": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/react-use-measure/-/react-use-measure-2.1.1.tgz",
+ "integrity": "sha512-nocZhN26cproIiIduswYpV5y5lQpSQS1y/4KuvUCjSKmw7ZWIS/+g3aFnX3WdBkyuGUtTLif3UTqnLLhbDoQig==",
+ "dependencies": {
+ "debounce": "^1.2.1"
+ },
+ "peerDependencies": {
+ "react": ">=16.13",
+ "react-dom": ">=16.13"
+ }
+ },
+ "node_modules/react18-json-view": {
+ "version": "0.2.9-canary.8",
+ "resolved": "https://registry.npmjs.org/react18-json-view/-/react18-json-view-0.2.9-canary.8.tgz",
+ "integrity": "sha512-NYCSH1i9RhkIVWedjHcrjBMmnsnFecoYTyEWN9gC8d/STCNjRkiinj8HEitbvf/198iNFrEIFpxGMprUqyRwmg==",
+ "dependencies": {
+ "copy-to-clipboard": "^3.3.3"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0"
+ }
+ },
+ "node_modules/read-cache": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz",
+ "integrity": "sha512-Owdv/Ft7IjOgm/i0xvNDZ1LrRANRfew4b2prF3OWMQLxLfu3bS8FVhCsrSCMK4lR56Y9ya+AThoTpDCTxCmpRA==",
+ "dev": true,
+ "dependencies": {
+ "pify": "^2.3.0"
+ }
+ },
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "dev": true,
+ "dependencies": {
+ "picomatch": "^2.2.1"
+ },
+ "engines": {
+ "node": ">=8.10.0"
+ }
+ },
+ "node_modules/reagraph": {
+ "version": "4.19.5",
+ "resolved": "https://registry.npmjs.org/reagraph/-/reagraph-4.19.5.tgz",
+ "integrity": "sha512-4EzHbF1XHpXV7IHdWUNzA3m1cKTmVJNnjJ7e0IhgdATekSmcB+xhUwCHFb9eVEPa/x+buq2gtP4w4Bj2A5cyjQ==",
+ "dependencies": {
+ "@react-spring/three": "9.6.1",
+ "@react-three/fiber": "8.13.5",
+ "@use-gesture/react": "^10.3.1",
+ "camera-controls": "^2.8.3",
+ "classnames": "^2.5.1",
+ "d3-array": "^3.2.4",
+ "d3-force-3d": "^3.0.3",
+ "d3-hierarchy": "^3.1.2",
+ "d3-scale": "^4.0.2",
+ "ellipsize": "^0.5.1",
+ "glodrei": "^0.0.1",
+ "graphology": "^0.25.4",
+ "graphology-layout": "^0.6.1",
+ "graphology-layout-forceatlas2": "^0.10.1",
+ "graphology-layout-noverlap": "^0.4.2",
+ "graphology-metrics": "^2.1.0",
+ "graphology-shortest-path": "^2.0.2",
+ "hold-event": "^0.2.0",
+ "reakeys": "^2.0.3",
+ "three": "^0.154.0",
+ "three-stdlib": "^2.23.13",
+ "zustand": "4.3.9"
+ },
+ "peerDependencies": {
+ "react": ">=16",
+ "react-dom": ">=16"
+ }
+ },
+ "node_modules/reakeys": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/reakeys/-/reakeys-2.0.3.tgz",
+ "integrity": "sha512-5qeGH9xtvFITi+9AyPeTmPhzjDTEBRZICxAg6RJFuEgWFKMHqr6mnMIaL9fgOKJMBzLWCBorpUhyiB824f0EyA==",
+ "dependencies": {
+ "ctrl-keys": "^1.0.3"
+ },
+ "peerDependencies": {
+ "react": ">=16",
+ "react-dom": ">=16"
+ }
+ },
+ "node_modules/recharts": {
+ "version": "2.13.3",
+ "resolved": "https://registry.npmjs.org/recharts/-/recharts-2.13.3.tgz",
+ "integrity": "sha512-YDZ9dOfK9t3ycwxgKbrnDlRC4BHdjlY73fet3a0C1+qGMjXVZe6+VXmpOIIhzkje5MMEL8AN4hLIe4AMskBzlA==",
+ "dependencies": {
+ "clsx": "^2.0.0",
+ "eventemitter3": "^4.0.1",
+ "lodash": "^4.17.21",
+ "react-is": "^18.3.1",
+ "react-smooth": "^4.0.0",
+ "recharts-scale": "^0.4.4",
+ "tiny-invariant": "^1.3.1",
+ "victory-vendor": "^36.6.8"
+ },
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": "^16.0.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.0.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/recharts-scale": {
+ "version": "0.4.5",
+ "resolved": "https://registry.npmjs.org/recharts-scale/-/recharts-scale-0.4.5.tgz",
+ "integrity": "sha512-kivNFO+0OcUNu7jQquLXAxz1FIwZj8nrj+YkOKc5694NbjCvcT6aSZiIzNzd2Kul4o4rTto8QVR9lMNtxD4G1w==",
+ "dependencies": {
+ "decimal.js-light": "^2.4.1"
+ }
+ },
+ "node_modules/recharts/node_modules/react-is": {
+ "version": "18.3.1",
+ "resolved": "https://registry.npmjs.org/react-is/-/react-is-18.3.1.tgz",
+ "integrity": "sha512-/LLMVyas0ljjAtoYiPqYiL8VWXzUUdThrmU5+n20DZv+a+ClRoevUzw5JxU+Ieh5/c87ytoTBV9G1FiKfNJdmg=="
+ },
+ "node_modules/regenerator-runtime": {
+ "version": "0.11.1",
+ "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz",
+ "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg=="
+ },
+ "node_modules/regexp.prototype.flags": {
+ "version": "1.5.3",
+ "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.5.3.tgz",
+ "integrity": "sha512-vqlC04+RQoFalODCbCumG2xIOvapzVMHwsyIGM/SIE8fRhFFsXeH8/QQ+s0T0kDAhKc4k30s73/0ydkHQz6HlQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-errors": "^1.3.0",
+ "set-function-name": "^2.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/require-from-string": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/require-from-string/-/require-from-string-2.0.2.tgz",
+ "integrity": "sha512-Xf0nWe6RseziFMu+Ap9biiUbmplq6S9/p+7w7YXP/JBHhrUDDUhwa+vANyubuqfZWTveU//DYVGsDG7RKL/vEw==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/resolve": {
+ "version": "1.22.8",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.8.tgz",
+ "integrity": "sha512-oKWePCxqpd6FlLvGV1VU0x7bkPmmCNolxzjMf4NczoDnQcIWrAF+cPtZn5i6n+RfD2d9i0tzpKnG6Yk168yIyw==",
+ "dependencies": {
+ "is-core-module": "^2.13.0",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
+ },
+ "bin": {
+ "resolve": "bin/resolve"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/resolve-from": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
+ "integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/reusify": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.0.4.tgz",
+ "integrity": "sha512-U9nH88a3fc/ekCF1l0/UP1IosiuIjyTh7hBvXVMHYgVcfGvt897Xguj2UOLDeI5BG2m7/uwyaLVT6fbtCwTyzw==",
+ "dev": true,
+ "engines": {
+ "iojs": ">=1.0.0",
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/robust-predicates": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/robust-predicates/-/robust-predicates-3.0.2.tgz",
+ "integrity": "sha512-IXgzBWvWQwE6PrDI05OvmXUIruQTcoMDzRsOd5CDvHCVLcLHMTSYvOK5Cm46kWqlV3yAbuSpBZdJ5oP5OUoStg=="
+ },
+ "node_modules/rollup": {
+ "version": "4.25.0",
+ "resolved": "https://registry.npmjs.org/rollup/-/rollup-4.25.0.tgz",
+ "integrity": "sha512-uVbClXmR6wvx5R1M3Od4utyLUxrmOcEm3pAtMphn73Apq19PDtHpgZoEvqH2YnnaNUuvKmg2DgRd2Sqv+odyqg==",
+ "dev": true,
+ "dependencies": {
+ "@types/estree": "1.0.6"
+ },
+ "bin": {
+ "rollup": "dist/bin/rollup"
+ },
+ "engines": {
+ "node": ">=18.0.0",
+ "npm": ">=8.0.0"
+ },
+ "optionalDependencies": {
+ "@rollup/rollup-android-arm-eabi": "4.25.0",
+ "@rollup/rollup-android-arm64": "4.25.0",
+ "@rollup/rollup-darwin-arm64": "4.25.0",
+ "@rollup/rollup-darwin-x64": "4.25.0",
+ "@rollup/rollup-freebsd-arm64": "4.25.0",
+ "@rollup/rollup-freebsd-x64": "4.25.0",
+ "@rollup/rollup-linux-arm-gnueabihf": "4.25.0",
+ "@rollup/rollup-linux-arm-musleabihf": "4.25.0",
+ "@rollup/rollup-linux-arm64-gnu": "4.25.0",
+ "@rollup/rollup-linux-arm64-musl": "4.25.0",
+ "@rollup/rollup-linux-powerpc64le-gnu": "4.25.0",
+ "@rollup/rollup-linux-riscv64-gnu": "4.25.0",
+ "@rollup/rollup-linux-s390x-gnu": "4.25.0",
+ "@rollup/rollup-linux-x64-gnu": "4.25.0",
+ "@rollup/rollup-linux-x64-musl": "4.25.0",
+ "@rollup/rollup-win32-arm64-msvc": "4.25.0",
+ "@rollup/rollup-win32-ia32-msvc": "4.25.0",
+ "@rollup/rollup-win32-x64-msvc": "4.25.0",
+ "fsevents": "~2.3.2"
+ }
+ },
+ "node_modules/run-parallel": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/run-parallel/-/run-parallel-1.2.0.tgz",
+ "integrity": "sha512-5l4VyZR86LZ/lDxZTR6jqL8AFE2S0IFLMP26AbjsLVADxHdhB/c0GUsH+y39UfCi3dzz8OlQuPmnaJOMoDHQBA==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "dependencies": {
+ "queue-microtask": "^1.2.2"
+ }
+ },
+ "node_modules/safe-array-concat": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/safe-array-concat/-/safe-array-concat-1.1.2.tgz",
+ "integrity": "sha512-vj6RsCsWBCf19jIeHEfkRMw8DPiBb+DMXklQ/1SGDHOMlHdPUkZXFQ2YdplS23zESTijAcurb1aSgJA3AgMu1Q==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "get-intrinsic": "^1.2.4",
+ "has-symbols": "^1.0.3",
+ "isarray": "^2.0.5"
+ },
+ "engines": {
+ "node": ">=0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/safe-regex-test": {
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/safe-regex-test/-/safe-regex-test-1.0.3.tgz",
+ "integrity": "sha512-CdASjNJPvRa7roO6Ra/gLYBTzYzzPyyBXxIMdGW3USQLyjWEls2RgW5UBTXaQVp+OrpeCK3bLem8smtmheoRuw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.6",
+ "es-errors": "^1.3.0",
+ "is-regex": "^1.1.4"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/scheduler": {
+ "version": "0.23.2",
+ "resolved": "https://registry.npmjs.org/scheduler/-/scheduler-0.23.2.tgz",
+ "integrity": "sha512-UOShsPwz7NrMUqhR6t0hWjFduvOzbtv7toDH1/hIrfRNIDBnnBWd0CwJTGvTpngVlmwGCdP9/Zl/tVrDqcuYzQ==",
+ "dependencies": {
+ "loose-envify": "^1.1.0"
+ }
+ },
+ "node_modules/semver": {
+ "version": "7.6.3",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.6.3.tgz",
+ "integrity": "sha512-oVekP1cKtI+CTDvHWYFUcMtsK/00wmAEfyqKfNdARm8u1wNVhSgaX7A8d4UuIlUI5e84iEwOhs7ZPYRmzU9U6A==",
+ "dev": true,
+ "bin": {
+ "semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
+ }
+ },
+ "node_modules/set-function-length": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/set-function-length/-/set-function-length-1.2.2.tgz",
+ "integrity": "sha512-pgRc4hJ4/sNjWCSS9AmnS40x3bNMDTknHgL5UaMBTMyJnU90EgWh1Rz+MC9eFu4BuN/UwZjKQuY/1v3rM7HMfg==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "function-bind": "^1.1.2",
+ "get-intrinsic": "^1.2.4",
+ "gopd": "^1.0.1",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/set-function-name": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/set-function-name/-/set-function-name-2.0.2.tgz",
+ "integrity": "sha512-7PGFlmtwsEADb0WYyvCMa1t+yke6daIG4Wirafur5kcf+MhUnPms1UeR0CKQdTZD81yESwMHbtn+TR+dMviakQ==",
+ "dev": true,
+ "dependencies": {
+ "define-data-property": "^1.1.4",
+ "es-errors": "^1.3.0",
+ "functions-have-names": "^1.2.3",
+ "has-property-descriptors": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/shallowequal": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/shallowequal/-/shallowequal-1.1.0.tgz",
+ "integrity": "sha512-y0m1JoUZSlPAjXVtPPW70aZWfIL/dSP7AFkRnniLCrK/8MDKog3TySTBmckD+RObVxH0v4Tox67+F14PdED2oQ=="
+ },
+ "node_modules/shebang-command": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
+ "dependencies": {
+ "shebang-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/shebang-regex": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/side-channel": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.6.tgz",
+ "integrity": "sha512-fDW/EZ6Q9RiO8eFG8Hj+7u/oW+XrPTIChwCOM2+th2A6OblDtYYIpve9m+KvI9Z4C9qSEXlaGR6bTEYHReuglA==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.4",
+ "object-inspect": "^1.13.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/signal-exit": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz",
+ "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==",
+ "dev": true,
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
+ }
+ },
+ "node_modules/source-map": {
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/source-map-js": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz",
+ "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/state-local": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
+ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
+ },
+ "node_modules/stats-gl": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/stats-gl/-/stats-gl-2.4.2.tgz",
+ "integrity": "sha512-g5O9B0hm9CvnM36+v7SFl39T7hmAlv541tU81ME8YeSb3i1CIP5/QdDeSB3A0la0bKNHpxpwxOVRo2wFTYEosQ==",
+ "dependencies": {
+ "@types/three": "*",
+ "three": "^0.170.0"
+ },
+ "peerDependencies": {
+ "@types/three": "*",
+ "three": "*"
+ }
+ },
+ "node_modules/stats-gl/node_modules/three": {
+ "version": "0.170.0",
+ "resolved": "https://registry.npmjs.org/three/-/three-0.170.0.tgz",
+ "integrity": "sha512-FQK+LEpYc0fBD+J8g6oSEyyNzjp+Q7Ks1C568WWaoMRLW+TkNNWmenWeGgJjV105Gd+p/2ql1ZcjYvNiPZBhuQ=="
+ },
+ "node_modules/stats.js": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/stats.js/-/stats.js-0.17.0.tgz",
+ "integrity": "sha512-hNKz8phvYLPEcRkeG1rsGmV5ChMjKDAWU7/OJJdDErPBNChQXxCo3WZurGpnWc6gZhAzEPFad1aVgyOANH1sMw=="
+ },
+ "node_modules/string-width": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-5.1.2.tgz",
+ "integrity": "sha512-HnLOCR3vjcY8beoNLtcjZ5/nxn2afmME6lhrDrebokqMap+XbeW8n9TXpPDOqdGK5qcI3oT0GKTW6wC7EMiVqA==",
+ "dev": true,
+ "dependencies": {
+ "eastasianwidth": "^0.2.0",
+ "emoji-regex": "^9.2.2",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/string-width-cjs": {
+ "name": "string-width",
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string-width-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/string-width-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/string.prototype.trim": {
+ "version": "1.2.9",
+ "resolved": "https://registry.npmjs.org/string.prototype.trim/-/string.prototype.trim-1.2.9.tgz",
+ "integrity": "sha512-klHuCNxiMZ8MlsOihJhJEBJAiMVqU3Z2nEXWfWnIqjN0gEFS9J9+IxKozWWtQGcgoa1WUZzLjKPTr4ZHNFTFxw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-abstract": "^1.23.0",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimend": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.8.tgz",
+ "integrity": "sha512-p73uL5VCHCO2BZZ6krwwQE3kCzM7NKmis8S//xEC6fQonchbum4eP6kR4DLEjQFO3Wnj3Fuo8NM0kOSjVdHjZQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/string.prototype.trimstart": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.8.tgz",
+ "integrity": "sha512-UXSH262CSZY1tfu3G3Secr6uGLCFVPMhIqHjlgCUtCCcgihYc/xKs9djMTMUOb2j1mVSeU8EU6NWc/iQKU6Gfg==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/strip-ansi": {
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
+ "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
+ }
+ },
+ "node_modules/strip-ansi-cjs": {
+ "name": "strip-ansi",
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/strip-bom": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz",
+ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==",
+ "dev": true,
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/strip-json-comments": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
+ "integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/styled-components": {
+ "version": "6.1.13",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.13.tgz",
+ "integrity": "sha512-M0+N2xSnAtwcVAQeFEsGWFFxXDftHUD7XrKla06QbpUMmbmtFBMMTcKWvFXtWxuD5qQkB8iU5gk6QASlx2ZRMw==",
+ "dependencies": {
+ "@emotion/is-prop-valid": "1.2.2",
+ "@emotion/unitless": "0.8.1",
+ "@types/stylis": "4.2.5",
+ "css-to-react-native": "3.2.0",
+ "csstype": "3.1.3",
+ "postcss": "8.4.38",
+ "shallowequal": "1.1.0",
+ "stylis": "4.3.2",
+ "tslib": "2.6.2"
+ },
+ "engines": {
+ "node": ">= 16"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/styled-components"
+ },
+ "peerDependencies": {
+ "react": ">= 16.8.0",
+ "react-dom": ">= 16.8.0"
+ }
+ },
+ "node_modules/styled-components/node_modules/@emotion/unitless": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
+ "integrity": "sha512-KOEGMu6dmJZtpadb476IsZBclKvILjopjUii3V+7MnXIQCYh8W3NgNcgwo21n9LXZX6EDIKvqfjYxXebDwxKmQ=="
+ },
+ "node_modules/styled-components/node_modules/postcss": {
+ "version": "8.4.38",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.38.tgz",
+ "integrity": "sha512-Wglpdk03BSfXkHoQa3b/oulrotAkwrlLDRSOb9D0bN86FdRyE9lppSp33aHNPgBa0JKCoB+drFLZkQoRRYae5A==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "nanoid": "^3.3.7",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/styled-components/node_modules/stylis": {
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.2.tgz",
+ "integrity": "sha512-bhtUjWd/z6ltJiQwg0dUfxEJ+W+jdqQd8TbWLWyeIJHlnsqmGLRFFd8e5mA0AZi/zx90smXRlN66YMTcaSFifg=="
+ },
+ "node_modules/stylis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.2.0.tgz",
+ "integrity": "sha512-Orov6g6BB1sDfYgzWfTHDOxamtX1bE/zo104Dh9e6fqJ3PooipYyfJ0pUmrZO2wAvO8YbEyeFrkV91XTsGMSrw=="
+ },
+ "node_modules/sucrase": {
+ "version": "3.35.0",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.0.tgz",
+ "integrity": "sha512-8EbVDiu9iN/nESwxeSxDKe0dunta1GOlHufmSSXxMD2z2/tMZpDMpvXQGsc+ajGo8y2uYUmixaSRUc/QPoQ0GA==",
+ "dev": true,
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "glob": "^10.3.10",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
+ },
+ "engines": {
+ "node": ">=16 || 14 >=14.17"
+ }
+ },
+ "node_modules/sucrase/node_modules/commander": {
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-4.1.1.tgz",
+ "integrity": "sha512-NOKm8xhkzAjzFx8B2v5OAHT+u5pRQc2UCa2Vq9jYL/31o2wi9mxBA7LIFs3sV5VSC49z6pEhfbMULvShKj26WA==",
+ "dev": true,
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/supports-color": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
+ "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
+ "dev": true,
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/supports-preserve-symlinks-flag": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz",
+ "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/suspend-react": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/suspend-react/-/suspend-react-0.1.3.tgz",
+ "integrity": "sha512-aqldKgX9aZqpoDp3e8/BZ8Dm7x1pJl+qI3ZKxDN0i/IQTWUwBx/ManmlVJ3wowqbno6c2bmiIfs+Um6LbsjJyQ==",
+ "peerDependencies": {
+ "react": ">=17.0"
+ }
+ },
+ "node_modules/tabbable": {
+ "version": "6.2.0",
+ "resolved": "https://registry.npmjs.org/tabbable/-/tabbable-6.2.0.tgz",
+ "integrity": "sha512-Cat63mxsVJlzYvN51JmVXIgNoUokrIaT2zLclCXjRd8boZ0004U4KCs/sToJ75C6sdlByWxpYnb5Boif1VSFew=="
+ },
+ "node_modules/tailwindcss": {
+ "version": "3.4.14",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.14.tgz",
+ "integrity": "sha512-IcSvOcTRcUtQQ7ILQL5quRDg7Xs93PdJEk1ZLbhhvJc7uj/OAhYOnruEiwnGgBvUtaUAJ8/mhSw1o8L2jCiENA==",
+ "dev": true,
+ "dependencies": {
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.5.3",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.0",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.0",
+ "lilconfig": "^2.1.0",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.0.0",
+ "postcss": "^8.4.23",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.1",
+ "postcss-nested": "^6.0.1",
+ "postcss-selector-parser": "^6.0.11",
+ "resolve": "^1.22.2",
+ "sucrase": "^3.32.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
+ },
+ "engines": {
+ "node": ">=14.0.0"
+ }
+ },
+ "node_modules/tailwindcss/node_modules/postcss-selector-parser": {
+ "version": "6.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz",
+ "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==",
+ "dev": true,
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/text-table": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
+ "integrity": "sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
+ "dev": true
+ },
+ "node_modules/thenify": {
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/thenify/-/thenify-3.3.1.tgz",
+ "integrity": "sha512-RVZSIV5IG10Hk3enotrhvz0T9em6cyHBLkH/YAZuKqd8hRkKhSfCGIcP2KUY0EPxndzANBmNllzWPwak+bheSw==",
+ "dev": true,
+ "dependencies": {
+ "any-promise": "^1.0.0"
+ }
+ },
+ "node_modules/thenify-all": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "dev": true,
+ "dependencies": {
+ "thenify": ">= 3.1.0 < 4"
+ },
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/three": {
+ "version": "0.154.0",
+ "resolved": "https://registry.npmjs.org/three/-/three-0.154.0.tgz",
+ "integrity": "sha512-Uzz8C/5GesJzv8i+Y2prEMYUwodwZySPcNhuJUdsVMH2Yn4Nm8qlbQe6qRN5fOhg55XB0WiLfTPBxVHxpE60ug=="
+ },
+ "node_modules/three-mesh-bvh": {
+ "version": "0.7.6",
+ "resolved": "https://registry.npmjs.org/three-mesh-bvh/-/three-mesh-bvh-0.7.6.tgz",
+ "integrity": "sha512-rCjsnxEqR9r1/C/lCqzGLS67NDty/S/eT6rAJfDvsanrIctTWdNoR4ZOGWewCB13h1QkVo2BpmC0wakj1+0m8A==",
+ "peerDependencies": {
+ "three": ">= 0.151.0"
+ }
+ },
+ "node_modules/three-stdlib": {
+ "version": "2.34.0",
+ "resolved": "https://registry.npmjs.org/three-stdlib/-/three-stdlib-2.34.0.tgz",
+ "integrity": "sha512-U5qJYWgUKBFJqr1coMSbczA964uvouzBjQbtJlaI9LfMwy7hr+kc1Mfh0gqi/2872KmGu9utgff6lj8Oti8+VQ==",
+ "dependencies": {
+ "@types/draco3d": "^1.4.0",
+ "@types/offscreencanvas": "^2019.6.4",
+ "@types/webxr": "^0.5.2",
+ "draco3d": "^1.4.1",
+ "fflate": "^0.6.9",
+ "potpack": "^1.0.1"
+ },
+ "peerDependencies": {
+ "three": ">=0.128.0"
+ }
+ },
+ "node_modules/three-stdlib/node_modules/fflate": {
+ "version": "0.6.10",
+ "resolved": "https://registry.npmjs.org/fflate/-/fflate-0.6.10.tgz",
+ "integrity": "sha512-IQrh3lEPM93wVCEczc9SaAOvkmcoQn/G8Bo1e8ZPlY3X3bnAxWaBdvTdvM1hP62iZp0BXWDy4vTAy4fF0+Dlpg=="
+ },
+ "node_modules/tiny-invariant": {
+ "version": "1.3.3",
+ "resolved": "https://registry.npmjs.org/tiny-invariant/-/tiny-invariant-1.3.3.tgz",
+ "integrity": "sha512-+FbBPE1o9QAYvviau/qC5SE3caw21q3xkvWKBtja5vgqOWIHHJ3ioaq1VPfn/Szqctz2bU/oYeKd9/z5BL+PVg=="
+ },
+ "node_modules/to-regex-range": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
+ "integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
+ "dependencies": {
+ "is-number": "^7.0.0"
+ },
+ "engines": {
+ "node": ">=8.0"
+ }
+ },
+ "node_modules/toggle-selection": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/toggle-selection/-/toggle-selection-1.0.6.tgz",
+ "integrity": "sha512-BiZS+C1OS8g/q2RRbJmy59xpyghNBqrr6k5L/uKBGRsTfxmu3ffiRnd8mlGPUVayg8pvfi5urfnu8TU7DVOkLQ=="
+ },
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
+ "dev": true
+ },
+ "node_modules/troika-three-text": {
+ "version": "0.47.2",
+ "resolved": "https://registry.npmjs.org/troika-three-text/-/troika-three-text-0.47.2.tgz",
+ "integrity": "sha512-qylT0F+U7xGs+/PEf3ujBdJMYWbn0Qci0kLqI5BJG2kW1wdg4T1XSxneypnF05DxFqJhEzuaOR9S2SjiyknMng==",
+ "dependencies": {
+ "bidi-js": "^1.0.2",
+ "troika-three-utils": "^0.47.2",
+ "troika-worker-utils": "^0.47.2",
+ "webgl-sdf-generator": "1.1.1"
+ },
+ "peerDependencies": {
+ "three": ">=0.125.0"
+ }
+ },
+ "node_modules/troika-three-utils": {
+ "version": "0.47.2",
+ "resolved": "https://registry.npmjs.org/troika-three-utils/-/troika-three-utils-0.47.2.tgz",
+ "integrity": "sha512-/28plhCxfKtH7MSxEGx8e3b/OXU5A0xlwl+Sbdp0H8FXUHKZDoksduEKmjQayXYtxAyuUiCRunYIv/8Vi7aiyg==",
+ "peerDependencies": {
+ "three": ">=0.125.0"
+ }
+ },
+ "node_modules/troika-worker-utils": {
+ "version": "0.47.2",
+ "resolved": "https://registry.npmjs.org/troika-worker-utils/-/troika-worker-utils-0.47.2.tgz",
+ "integrity": "sha512-mzss4MeyzUkYBppn4x5cdAqrhBHFEuVmMMgLMTyFV23x6GvQMyo+/R5E5Lsbrt7WSt5RfvewjcwD1DChRTA9lA=="
+ },
+ "node_modules/ts-api-utils": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.4.0.tgz",
+ "integrity": "sha512-032cPxaEKwM+GT3vA5JXNzIaizx388rhsSW79vGRNGXfRRAdEAn2mvk36PvK5HnOchyWZ7afLEXqYCvPCrzuzQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "peerDependencies": {
+ "typescript": ">=4.2.0"
+ }
+ },
+ "node_modules/ts-interface-checker": {
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/ts-interface-checker/-/ts-interface-checker-0.1.13.tgz",
+ "integrity": "sha512-Y/arvbn+rrz3JCKl9C4kVNfTfSm2/mEp5FSz5EsZSANGPSlQrpRI5M4PKF+mJnE52jOO90PnPSc3Ur3bTQw0gA==",
+ "dev": true
+ },
+ "node_modules/tsconfig-paths": {
+ "version": "3.15.0",
+ "resolved": "https://registry.npmjs.org/tsconfig-paths/-/tsconfig-paths-3.15.0.tgz",
+ "integrity": "sha512-2Ac2RgzDe/cn48GvOe3M+o82pEFewD3UPbyoUHHdKasHwJKjds4fLXWf/Ux5kATBKN20oaFGu+jbElp1pos0mg==",
+ "dev": true,
+ "dependencies": {
+ "@types/json5": "^0.0.29",
+ "json5": "^1.0.2",
+ "minimist": "^1.2.6",
+ "strip-bom": "^3.0.0"
+ }
+ },
+ "node_modules/tsconfig-paths/node_modules/json5": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.2.tgz",
+ "integrity": "sha512-g1MWMLBiz8FKi1e4w0UyVL3w+iJceWAFBAaBnnGKOpNa5f8TLktkbre1+s6oICydWAm+HRUGTmI+//xv2hvXYA==",
+ "dev": true,
+ "dependencies": {
+ "minimist": "^1.2.0"
+ },
+ "bin": {
+ "json5": "lib/cli.js"
+ }
+ },
+ "node_modules/tslib": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.6.2.tgz",
+ "integrity": "sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q=="
+ },
+ "node_modules/tunnel-rat": {
+ "version": "0.1.2",
+ "resolved": "https://registry.npmjs.org/tunnel-rat/-/tunnel-rat-0.1.2.tgz",
+ "integrity": "sha512-lR5VHmkPhzdhrM092lI2nACsLO4QubF0/yoOhzX7c+wIpbN1GjHNzCc91QlpxBi+cnx8vVJ+Ur6vL5cEoQPFpQ==",
+ "dependencies": {
+ "zustand": "^4.3.2"
+ }
+ },
+ "node_modules/type-check": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "dependencies": {
+ "prelude-ls": "^1.2.1"
+ },
+ "engines": {
+ "node": ">= 0.8.0"
+ }
+ },
+ "node_modules/type-fest": {
+ "version": "4.26.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.26.1.tgz",
+ "integrity": "sha512-yOGpmOAL7CkKe/91I5O3gPICmJNLJ1G4zFYVAsRHg7M64biSnPtRj0WNQt++bRkjYOqjWXrhnUw1utzmVErAdg==",
+ "dev": true,
+ "engines": {
+ "node": ">=16"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/typed-array-buffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-buffer/-/typed-array-buffer-1.0.2.tgz",
+ "integrity": "sha512-gEymJYKZtKXzzBzM4jqa9w6Q1Jjm7x2d+sh19AdsD4wqnMPDYyvwpsIc2Q/835kHuo3BEQ7CjelGhfTsoBb2MQ==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "es-errors": "^1.3.0",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ }
+ },
+ "node_modules/typed-array-byte-length": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-length/-/typed-array-byte-length-1.0.1.tgz",
+ "integrity": "sha512-3iMJ9q0ao7WE9tWcaYKIptkNBuOIcZCCT0d4MRvuuH88fEoEH62IuQe0OtraD3ebQEoTRk8XCBoknUNc1Y67pw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-byte-offset": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/typed-array-byte-offset/-/typed-array-byte-offset-1.0.2.tgz",
+ "integrity": "sha512-Ous0vodHa56FviZucS2E63zkgtgrACj7omjwd/8lTEMEPFFyjfixMZ1ZXenpgCFBBt4EC1J2XsyVS2gkG0eTFA==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typed-array-length": {
+ "version": "1.0.6",
+ "resolved": "https://registry.npmjs.org/typed-array-length/-/typed-array-length-1.0.6.tgz",
+ "integrity": "sha512-/OxDN6OtAk5KBpGb28T+HZc2M+ADtvRxXrKKbUwtsLgdoxgX13hyy7ek6bFRl5+aBs2yZzB0c4CnQfAtVypW/g==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-proto": "^1.0.3",
+ "is-typed-array": "^1.1.13",
+ "possible-typed-array-names": "^1.0.0"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/typescript": {
+ "version": "5.6.3",
+ "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.6.3.tgz",
+ "integrity": "sha512-hjcS1mhfuyi4WW8IWtjP7brDrG2cuDZukyrYrSauoXGNgx0S7zceP07adYkJycEr56BOUTNPzbInooiN3fn1qw==",
+ "dev": true,
+ "bin": {
+ "tsc": "bin/tsc",
+ "tsserver": "bin/tsserver"
+ },
+ "engines": {
+ "node": ">=14.17"
+ }
+ },
+ "node_modules/uglify-js": {
+ "version": "3.19.3",
+ "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.19.3.tgz",
+ "integrity": "sha512-v3Xu+yuwBXisp6QYTcH4UbH+xYJXqnq2m/LtQVWKWzYc1iehYnLixoQDN9FH6/j9/oybfd6W9Ghwkl8+UMKTKQ==",
+ "optional": true,
+ "bin": {
+ "uglifyjs": "bin/uglifyjs"
+ },
+ "engines": {
+ "node": ">=0.8.0"
+ }
+ },
+ "node_modules/unbox-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.2.tgz",
+ "integrity": "sha512-61pPlCD9h51VoreyJ0BReideM3MDKMKnh6+V9L08331ipq6Q8OFXZYiqP6n/tbHx4s5I9uRhcye6BrbkizkBDw==",
+ "dev": true,
+ "dependencies": {
+ "call-bind": "^1.0.2",
+ "has-bigints": "^1.0.2",
+ "has-symbols": "^1.0.3",
+ "which-boxed-primitive": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/universalify": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
+ "engines": {
+ "node": ">= 10.0.0"
+ }
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.1.1.tgz",
+ "integrity": "sha512-R8UzCaa9Az+38REPiJ1tXlImTJXlVfgHZsglwBD/k6nj76ctsH1E3q4doGrukiLQd3sGQYu56r5+lo5r94l29A==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "dependencies": {
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.0"
+ },
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
+ }
+ },
+ "node_modules/uri-js": {
+ "version": "4.4.1",
+ "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.4.1.tgz",
+ "integrity": "sha512-7rKUyy33Q1yc98pQ1DAmLtwX109F7TIfWlW1Ydo8Wl1ii1SeHieeh0HHfPeL2fMXK6z0s8ecKs9frCuLJvndBg==",
+ "dev": true,
+ "dependencies": {
+ "punycode": "^2.1.0"
+ }
+ },
+ "node_modules/uri-js-replace": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/uri-js-replace/-/uri-js-replace-1.0.1.tgz",
+ "integrity": "sha512-W+C9NWNLFOoBI2QWDp4UT9pv65r2w5Cx+3sTYFvtMdDBxkKt1syCqsUdSFAChbEe1uK5TfS04wt/nGwmaeIQ0g==",
+ "dev": true
+ },
+ "node_modules/use-isomorphic-layout-effect": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/use-isomorphic-layout-effect/-/use-isomorphic-layout-effect-1.1.2.tgz",
+ "integrity": "sha512-49L8yCO3iGT/ZF9QttjwLF/ZD9Iwto5LnH5LmEdk/6cFmXddqi2ulF0edxTwjj+7mqvpVVGQWvbXZdn32wRSHA==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/use-sync-external-store": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/use-sync-external-store/-/use-sync-external-store-1.2.0.tgz",
+ "integrity": "sha512-eEgnFxGQ1Ife9bzYs6VLi8/4X6CObHMw9Qr9tPY43iKwsPw8xE8+EFsf/2cFZ5S3esXgpWgtSCtLNS41F+sKPA==",
+ "peerDependencies": {
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ }
+ },
+ "node_modules/util-deprecate": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
+ "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==",
+ "dev": true
+ },
+ "node_modules/utility-types": {
+ "version": "3.11.0",
+ "resolved": "https://registry.npmjs.org/utility-types/-/utility-types-3.11.0.tgz",
+ "integrity": "sha512-6Z7Ma2aVEWisaL6TvBCy7P8rm2LQoPv6dJ7ecIaIixHcwfbJ0x7mWdbcwlIM5IGQxPZSFYeqRCqlOOeKoJYMkw==",
+ "engines": {
+ "node": ">= 4"
+ }
+ },
+ "node_modules/uuid": {
+ "version": "9.0.1",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-9.0.1.tgz",
+ "integrity": "sha512-b+1eJOlsR9K8HJpow9Ok3fiWOWSIcIzXodvv0rQjVoOVNpWMpxf1wZNpt4y9h10odCNrqnYp1OBzRktckBe3sA==",
+ "funding": [
+ "https://github.com/sponsors/broofa",
+ "https://github.com/sponsors/ctavan"
+ ],
+ "bin": {
+ "uuid": "dist/bin/uuid"
+ }
+ },
+ "node_modules/victory-vendor": {
+ "version": "36.9.2",
+ "resolved": "https://registry.npmjs.org/victory-vendor/-/victory-vendor-36.9.2.tgz",
+ "integrity": "sha512-PnpQQMuxlwYdocC8fIJqVXvkeViHYzotI+NJrCuav0ZYFoq912ZHBk3mCeuj+5/VpodOjPe1z0Fk2ihgzlXqjQ==",
+ "dependencies": {
+ "@types/d3-array": "^3.0.3",
+ "@types/d3-ease": "^3.0.0",
+ "@types/d3-interpolate": "^3.0.1",
+ "@types/d3-scale": "^4.0.2",
+ "@types/d3-shape": "^3.1.0",
+ "@types/d3-time": "^3.0.0",
+ "@types/d3-timer": "^3.0.0",
+ "d3-array": "^3.1.6",
+ "d3-ease": "^3.0.1",
+ "d3-interpolate": "^3.0.1",
+ "d3-scale": "^4.0.2",
+ "d3-shape": "^3.1.0",
+ "d3-time": "^3.0.0",
+ "d3-timer": "^3.0.1"
+ }
+ },
+ "node_modules/victory-vendor/node_modules/@types/d3-time": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz",
+ "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw=="
+ },
+ "node_modules/victory-vendor/node_modules/d3-time": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-time/-/d3-time-3.1.0.tgz",
+ "integrity": "sha512-VqKjzBLejbSMT4IgbmVgDjpkYrNWUYJnbCGo874u7MMKIWsILRX+OpX/gTk8MqjpT1A/c6HY2dCA77ZN0lkQ2Q==",
+ "dependencies": {
+ "d3-array": "2 - 3"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/vite": {
+ "version": "5.4.10",
+ "resolved": "https://registry.npmjs.org/vite/-/vite-5.4.10.tgz",
+ "integrity": "sha512-1hvaPshuPUtxeQ0hsVH3Mud0ZanOLwVTneA1EgbAM5LhaZEqyPWGRQ7BtaMvUrTDeEaC8pxtj6a6jku3x4z6SQ==",
+ "dev": true,
+ "dependencies": {
+ "esbuild": "^0.21.3",
+ "postcss": "^8.4.43",
+ "rollup": "^4.20.0"
+ },
+ "bin": {
+ "vite": "bin/vite.js"
+ },
+ "engines": {
+ "node": "^18.0.0 || >=20.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/vitejs/vite?sponsor=1"
+ },
+ "optionalDependencies": {
+ "fsevents": "~2.3.3"
+ },
+ "peerDependencies": {
+ "@types/node": "^18.0.0 || >=20.0.0",
+ "less": "*",
+ "lightningcss": "^1.21.0",
+ "sass": "*",
+ "sass-embedded": "*",
+ "stylus": "*",
+ "sugarss": "*",
+ "terser": "^5.4.0"
+ },
+ "peerDependenciesMeta": {
+ "@types/node": {
+ "optional": true
+ },
+ "less": {
+ "optional": true
+ },
+ "lightningcss": {
+ "optional": true
+ },
+ "sass": {
+ "optional": true
+ },
+ "sass-embedded": {
+ "optional": true
+ },
+ "stylus": {
+ "optional": true
+ },
+ "sugarss": {
+ "optional": true
+ },
+ "terser": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/warning": {
+ "version": "4.0.3",
+ "resolved": "https://registry.npmjs.org/warning/-/warning-4.0.3.tgz",
+ "integrity": "sha512-rpJyN222KWIvHJ/F53XSZv0Zl/accqHR8et1kpaMTD/fLCRxtV8iX8czMzY7sVZupTI3zcUTg8eycS2kNF9l6w==",
+ "dependencies": {
+ "loose-envify": "^1.0.0"
+ }
+ },
+ "node_modules/web-streams-polyfill": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-3.3.3.tgz",
+ "integrity": "sha512-d2JWLCivmZYTSIoge9MsgFCZrt571BikcWGYkjC1khllbTeDlGqZ2D8vD8E/lJa8WGWbb7Plm8/XJYV7IJHZZw==",
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/webgl-constants": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/webgl-constants/-/webgl-constants-1.1.1.tgz",
+ "integrity": "sha512-LkBXKjU5r9vAW7Gcu3T5u+5cvSvh5WwINdr0C+9jpzVB41cjQAP5ePArDtk/WHYdVj0GefCgM73BA7FlIiNtdg=="
+ },
+ "node_modules/webgl-sdf-generator": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/webgl-sdf-generator/-/webgl-sdf-generator-1.1.1.tgz",
+ "integrity": "sha512-9Z0JcMTFxeE+b2x1LJTdnaT8rT8aEp7MVxkNwoycNmJWwPdzoXzMh0BjJSh/AEFP+KPYZUli814h8bJZFIZ2jA=="
+ },
+ "node_modules/webidl-conversions": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
+ "dev": true
+ },
+ "node_modules/whatwg-url": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/whatwg-url/-/whatwg-url-5.0.0.tgz",
+ "integrity": "sha512-saE57nupxk6v3HY35+jzBwYa0rKSy0XR8JSxZPwgLr7ys0IBzhGviA1/TUGJLmSVqs8pb9AnvICXEuOHLprYTw==",
+ "dev": true,
+ "dependencies": {
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
+ }
+ },
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
+ "dependencies": {
+ "isexe": "^2.0.0"
+ },
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
+ }
+ },
+ "node_modules/which-boxed-primitive": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/which-boxed-primitive/-/which-boxed-primitive-1.0.2.tgz",
+ "integrity": "sha512-bwZdv0AKLpplFY2KZRX6TvyuN7ojjr7lwkg6ml0roIy9YeuSr7JS372qlNW18UQYzgYK9ziGcerWqZOmEn9VNg==",
+ "dev": true,
+ "dependencies": {
+ "is-bigint": "^1.0.1",
+ "is-boolean-object": "^1.1.0",
+ "is-number-object": "^1.0.4",
+ "is-string": "^1.0.5",
+ "is-symbol": "^1.0.3"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/which-typed-array": {
+ "version": "1.1.15",
+ "resolved": "https://registry.npmjs.org/which-typed-array/-/which-typed-array-1.1.15.tgz",
+ "integrity": "sha512-oV0jmFtUky6CXfkqehVvBP/LSWJ2sy4vWMioiENyJLePrBO/yKyV9OyJySfAKosh+RYkIl5zJCNZ8/4JncrpdA==",
+ "dev": true,
+ "dependencies": {
+ "available-typed-arrays": "^1.0.7",
+ "call-bind": "^1.0.7",
+ "for-each": "^0.3.3",
+ "gopd": "^1.0.1",
+ "has-tostringtag": "^1.0.2"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
+ "node_modules/word-wrap": {
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/wordwrap": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz",
+ "integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q=="
+ },
+ "node_modules/wrap-ansi": {
+ "version": "8.1.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-8.1.0.tgz",
+ "integrity": "sha512-si7QWI6zUMq56bESFvagtmzMdGOtoxfR+Sez11Mobfc7tm+VkUckk9bW2UeffTGVUbOksxmSw0AA2gs8g71NCQ==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^6.1.0",
+ "string-width": "^5.0.1",
+ "strip-ansi": "^7.0.1"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs": {
+ "name": "wrap-ansi",
+ "version": "7.0.0",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
+ "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "dev": true,
+ "dependencies": {
+ "ansi-styles": "^4.0.0",
+ "string-width": "^4.1.0",
+ "strip-ansi": "^6.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/ansi-regex": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
+ "integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
+ "dev": true,
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/emoji-regex": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-8.0.0.tgz",
+ "integrity": "sha512-MSjYzcWNOA0ewAHpz0MxpYFvwg6yjy1NG3xteoqz644VCo/RPgnr1/GGt+ic3iJTzQ8Eu3TdM14SawnVUmGE6A==",
+ "dev": true
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/string-width": {
+ "version": "4.2.3",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
+ "integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
+ "dev": true,
+ "dependencies": {
+ "emoji-regex": "^8.0.0",
+ "is-fullwidth-code-point": "^3.0.0",
+ "strip-ansi": "^6.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi-cjs/node_modules/strip-ansi": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
+ "integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
+ "dev": true,
+ "dependencies": {
+ "ansi-regex": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/wrap-ansi/node_modules/ansi-styles": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz",
+ "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/ansi-styles?sponsor=1"
+ }
+ },
+ "node_modules/yallist": {
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
+ },
+ "node_modules/yaml": {
+ "version": "1.10.2",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
+ "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/yaml-ast-parser": {
+ "version": "0.0.43",
+ "resolved": "https://registry.npmjs.org/yaml-ast-parser/-/yaml-ast-parser-0.0.43.tgz",
+ "integrity": "sha512-2PTINUwsRqSd+s8XxKaJWQlUuEMHJQyEuh2edBbW8KNJz0SJPwUSD2zRWqezFEdN7IzAgeuYHFUCF7o8zRdZ0A==",
+ "dev": true
+ },
+ "node_modules/yargs-parser": {
+ "version": "21.1.1",
+ "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-21.1.1.tgz",
+ "integrity": "sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==",
+ "dev": true,
+ "engines": {
+ "node": ">=12"
+ }
+ },
+ "node_modules/yet-another-react-lightbox": {
+ "version": "3.21.6",
+ "resolved": "https://registry.npmjs.org/yet-another-react-lightbox/-/yet-another-react-lightbox-3.21.6.tgz",
+ "integrity": "sha512-uKcRmmezsj1Fbj38B6hFOGwbAu94fPr8d5H6I0+1FmcToX56freEGXXXtdA1oRo6036ug+UgrKZzzvsw/MIM/w==",
+ "engines": {
+ "node": ">=14"
+ },
+ "peerDependencies": {
+ "react": ">=16.8.0",
+ "react-dom": ">=16.8.0"
+ }
+ },
+ "node_modules/yocto-queue": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/yocto-queue/-/yocto-queue-0.1.0.tgz",
+ "integrity": "sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==",
+ "dev": true,
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/zod": {
+ "version": "3.23.8",
+ "resolved": "https://registry.npmjs.org/zod/-/zod-3.23.8.tgz",
+ "integrity": "sha512-XBx9AXhXktjUqnepgTiE5flcKIYWi/rme0Eaj+5Y0lftuGBq+jyRu/md4WnuxqgP1ubdpNCsYEYPxrzVHD8d6g==",
+ "funding": {
+ "url": "https://github.com/sponsors/colinhacks"
+ }
+ },
+ "node_modules/zustand": {
+ "version": "4.3.9",
+ "resolved": "https://registry.npmjs.org/zustand/-/zustand-4.3.9.tgz",
+ "integrity": "sha512-Tat5r8jOMG1Vcsj8uldMyqYKC5IZvQif8zetmLHs9WoZlntTHmIoNM8TpLRY31ExncuUvUOXehd0kvahkuHjDw==",
+ "dependencies": {
+ "use-sync-external-store": "1.2.0"
+ },
+ "engines": {
+ "node": ">=12.7.0"
+ },
+ "peerDependencies": {
+ "immer": ">=9.0",
+ "react": ">=16.8"
+ },
+ "peerDependenciesMeta": {
+ "immer": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ }
+ }
+ }
+ }
+}
diff --git a/client/package.json b/client/package.json
new file mode 100644
index 0000000..526d83a
--- /dev/null
+++ b/client/package.json
@@ -0,0 +1,73 @@
+{
+ "name": "client",
+ "homepage": "/dashboard",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite",
+ "build": "tsc && vite build",
+ "lint": "eslint . --ext ts,tsx --report-unused-disable-directives --max-warnings 0",
+ "preview": "vite preview",
+ "fmt": "eslint . --fix",
+ "generate-qdash": "curl http://localhost:5715/openapi.json | jq > ../docs/openapi/qdash-openapi.json && openapi-typescript ../docs/openapi/qdash-openapi.json -o ./src/qdash.d.ts"
+ },
+ "dependencies": {
+ "@lit/react": "^1.0.6",
+ "@monaco-editor/react": "4.6.0",
+ "@nivo/line": "^0.87.0",
+ "@tanstack/react-query": "^5.59.20",
+ "@tanstack/react-table": "^8.20.5",
+ "axios": "^1.7.7",
+ "chart.js": "^4.4.6",
+ "color-legend-element": "^1.3.0",
+ "create-vite": "^5.5.5",
+ "date-fns": "4.1.0",
+ "js-yaml": "^4.1.0",
+ "lit": "^3.2.1",
+ "node-fetch": "^3.3.2",
+ "openapi-fetch": "^0.13.0",
+ "openapi-typescript-codegen": "^0.29.0",
+ "react": "^18.3.1",
+ "react-chartjs-2": "^5.2.0",
+ "react-colorscales": "^0.7.3",
+ "react-datepicker": "^7.5.0",
+ "react-dom": "^18.3.1",
+ "react-grid-gallery": "^1.0.1",
+ "react-icons": "^5.3.0",
+ "react-json-editor-ajrm": "^2.5.14",
+ "react-json-editor-viewer": "^1.0.7",
+ "react-loader-spinner": "^6.1.6",
+ "react-router-dom": "^6.28.0",
+ "react-select": "^5.8.2",
+ "react-spinners": "^0.14.1",
+ "react-toastify": "^10.0.6",
+ "react-tooltip": "^5.28.0",
+ "react-transition-group": "^4.4.5",
+ "react18-json-view": "0.2.9-canary.8",
+ "reagraph": "^4.19.5",
+ "recharts": "^2.13.3",
+ "yet-another-react-lightbox": "^3.21.6",
+ "zod": "^3.23.8"
+ },
+ "devDependencies": {
+ "@tailwindcss/typography": "^0.5.15",
+ "@types/react": "^18.3.12",
+ "@types/react-dom": "^18.3.1",
+ "@types/react-json-editor-ajrm": "^2.5.6",
+ "@typescript-eslint/eslint-plugin": "^8.13.0",
+ "@typescript-eslint/parser": "^8.13.0",
+ "@vitejs/plugin-react": "^4.3.3",
+ "autoprefixer": "^10.4.20",
+ "daisyui": "^4.12.14",
+ "eslint": "^9.14.0",
+ "eslint-plugin-import": "^2.31.0",
+ "eslint-plugin-react-hooks": "^5.0.0",
+ "eslint-plugin-react-refresh": "^0.4.14",
+ "openapi-typescript": "^7.4.2",
+ "postcss": "^8.4.47",
+ "tailwindcss": "^3.4.14",
+ "typescript": "^5.6.3",
+ "vite": "^5.4.10"
+ }
+}
diff --git a/client/postcss.config.js b/client/postcss.config.js
new file mode 100644
index 0000000..2aa7205
--- /dev/null
+++ b/client/postcss.config.js
@@ -0,0 +1,6 @@
+export default {
+ plugins: {
+ tailwindcss: {},
+ autoprefixer: {},
+ },
+};
diff --git a/client/public/vite.svg b/client/public/vite.svg
new file mode 100644
index 0000000..e7b8dfb
--- /dev/null
+++ b/client/public/vite.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/src/App.css b/client/src/App.css
new file mode 100644
index 0000000..238bdfa
--- /dev/null
+++ b/client/src/App.css
@@ -0,0 +1,58 @@
+#root {
+ /* max-width: 1280px; */
+ margin: 0;
+ padding: 0rem;
+ text-align: center;
+}
+
+.logo {
+ height: 6em;
+ padding: 1.5em;
+ will-change: filter;
+ transition: filter 300ms;
+}
+
+.logo:hover {
+ filter: drop-shadow(0 0 2em #646cffaa);
+}
+
+.logo.react:hover {
+ filter: drop-shadow(0 0 2em #61dafbaa);
+}
+
+@keyframes logo-spin {
+ from {
+ transform: rotate(0deg);
+ }
+
+ to {
+ transform: rotate(360deg);
+ }
+}
+
+@media (prefers-reduced-motion: no-preference) {
+ a:nth-of-type(2) .logo {
+ animation: logo-spin infinite 20s linear;
+ }
+}
+
+.card {
+ padding: 2em;
+}
+
+.read-the-docs {
+ color: #888;
+}
+
+.loader-container {
+ position: fixed;
+ top: 0;
+ left: 0;
+ width: 100%;
+ height: 100%;
+ display: flex;
+ justify-content: center;
+ align-items: center;
+ background-color: rgba(255, 255, 255, 0.8); /* 透け感を出すための背景色 */
+ z-index: 1000; /* 他のコンテンツの上に表示されるようにする */
+}
diff --git a/client/src/App.tsx b/client/src/App.tsx
new file mode 100644
index 0000000..2a328d9
--- /dev/null
+++ b/client/src/App.tsx
@@ -0,0 +1,29 @@
+import "./App.css";
+import { BrowserRouter as Router } from "react-router-dom";
+
+import { QueryClient, QueryClientProvider } from "@tanstack/react-query";
+
+import Navbar from "./components/Navbar";
+import Sidebar from "./components/Sidebar";
+import AppRoutes from "./routes";
+
+function App() {
+ // const { _, textClass, _ } = useTheme();
+ const queryClient = new QueryClient();
+ return (
+
+
+
+
+
+ );
+}
+
+export default App;
diff --git a/client/src/assets/404.png b/client/src/assets/404.png
new file mode 100644
index 0000000..e2d1b29
Binary files /dev/null and b/client/src/assets/404.png differ
diff --git a/client/src/assets/Res_Amazon-Braket_Chandelier_48.svg b/client/src/assets/Res_Amazon-Braket_Chandelier_48.svg
new file mode 100644
index 0000000..fa8e1f8
--- /dev/null
+++ b/client/src/assets/Res_Amazon-Braket_Chandelier_48.svg
@@ -0,0 +1,7 @@
+
+
\ No newline at end of file
diff --git a/client/src/assets/react.svg b/client/src/assets/react.svg
new file mode 100644
index 0000000..6c87de9
--- /dev/null
+++ b/client/src/assets/react.svg
@@ -0,0 +1 @@
+
\ No newline at end of file
diff --git a/client/src/client/calibration/calibration.ts b/client/src/client/calibration/calibration.ts
new file mode 100644
index 0000000..8c047c9
--- /dev/null
+++ b/client/src/client/calibration/calibration.ts
@@ -0,0 +1,2237 @@
+/**
+ * Generated by orval v7.3.0 🍺
+ * Do not edit manually.
+ * QDash Server
+ * API for QDash
+ * OpenAPI spec version: 0.0.1
+ */
+import { useMutation, useQuery } from "@tanstack/react-query";
+import type {
+ DataTag,
+ DefinedInitialDataOptions,
+ DefinedUseQueryResult,
+ MutationFunction,
+ QueryFunction,
+ QueryKey,
+ UndefinedInitialDataOptions,
+ UseMutationOptions,
+ UseMutationResult,
+ UseQueryOptions,
+ UseQueryResult,
+} from "@tanstack/react-query";
+import * as axios from "axios";
+import type { AxiosError, AxiosRequestConfig, AxiosResponse } from "axios";
+import type {
+ Detail,
+ ExecuteCalibRequest,
+ ExecuteCalibResponse,
+ FetchOneQubitCalibSummaryByDateParams,
+ HTTPValidationError,
+ OneQubitCalibCWInfo,
+ OneQubitCalibDailySummaryRequest,
+ OneQubitCalibDailySummaryResponse,
+ OneQubitCalibHistoryResponse,
+ OneQubitCalibResponse,
+ OneQubitCalibStatsRequest,
+ OneQubitCalibStatsResponse,
+ ScheduleCalibRequest,
+ ScheduleCalibResponse,
+ SuccessResponse,
+ TwoQubitCalibDailySummaryModel,
+ TwoQubitCalibDailySummaryRequest,
+ TwoQubitCalibDailySummaryResponse,
+ TwoQubitCalibHistoryResponse,
+ TwoQubitCalibResponse,
+ TwoQubitCalibStatsRequest,
+ TwoQubitCalibStatsResponse,
+} from "../../schemas";
+
+/**
+ * Executes a calibration by creating a flow run from a deployment.
+
+Args:
+ request (ExecuteCalibRequest): The request object containing the calibration data.
+ settings (Settings): The application settings.
+
+Returns:
+ FLOW_RUN_URL: The URL of the created flow run.
+
+Raises:
+ HTTPException: If the execution of the calibration fails.
+ * @summary Executes a calibration by creating a flow run from a deployment.
+ */
+export const executeCalib = (
+ executeCalibRequest: ExecuteCalibRequest,
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.post(
+ `http://localhost:5715/calibrations`,
+ executeCalibRequest,
+ options,
+ );
+};
+
+export const getExecuteCalibMutationOptions = <
+ TError = AxiosError,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: ExecuteCalibRequest },
+ TContext
+ >;
+ axios?: AxiosRequestConfig;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: ExecuteCalibRequest },
+ TContext
+> => {
+ const { mutation: mutationOptions, axios: axiosOptions } = options ?? {};
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: ExecuteCalibRequest }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return executeCalib(data, axiosOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type ExecuteCalibMutationResult = NonNullable<
+ Awaited>
+>;
+export type ExecuteCalibMutationBody = ExecuteCalibRequest;
+export type ExecuteCalibMutationError = AxiosError;
+
+/**
+ * @summary Executes a calibration by creating a flow run from a deployment.
+ */
+export const useExecuteCalib = <
+ TError = AxiosError,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: ExecuteCalibRequest },
+ TContext
+ >;
+ axios?: AxiosRequestConfig;
+}): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: ExecuteCalibRequest },
+ TContext
+> => {
+ const mutationOptions = getExecuteCalibMutationOptions(options);
+
+ return useMutation(mutationOptions);
+};
+/**
+ * @summary Fetches all the calibration schedules.
+ */
+export const fetchAllCalibSchedule = (
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.get(
+ `http://localhost:5715/calibrations/schedule`,
+ options,
+ );
+};
+
+export const getFetchAllCalibScheduleQueryKey = () => {
+ return [`http://localhost:5715/calibrations/schedule`] as const;
+};
+
+export const getFetchAllCalibScheduleQueryOptions = <
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}) => {
+ const { query: queryOptions, axios: axiosOptions } = options ?? {};
+
+ const queryKey = queryOptions?.queryKey ?? getFetchAllCalibScheduleQueryKey();
+
+ const queryFn: QueryFunction<
+ Awaited>
+ > = ({ signal }) => fetchAllCalibSchedule({ signal, ...axiosOptions });
+
+ return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ > & { queryKey: DataTag };
+};
+
+export type FetchAllCalibScheduleQueryResult = NonNullable<
+ Awaited>
+>;
+export type FetchAllCalibScheduleQueryError = AxiosError;
+
+export function useFetchAllCalibSchedule<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options: {
+ query: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ DefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+}): DefinedUseQueryResult & {
+ queryKey: DataTag;
+};
+export function useFetchAllCalibSchedule<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ UndefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag };
+export function useFetchAllCalibSchedule<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag };
+/**
+ * @summary Fetches all the calibration schedules.
+ */
+
+export function useFetchAllCalibSchedule<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag } {
+ const queryOptions = getFetchAllCalibScheduleQueryOptions(options);
+
+ const query = useQuery(queryOptions) as UseQueryResult & {
+ queryKey: DataTag;
+ };
+
+ query.queryKey = queryOptions.queryKey;
+
+ return query;
+}
+
+/**
+ * @summary Schedules a calibration.
+ */
+export const scheduleCalib = (
+ scheduleCalibRequest: ScheduleCalibRequest,
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.post(
+ `http://localhost:5715/calibrations/schedule`,
+ scheduleCalibRequest,
+ options,
+ );
+};
+
+export const getScheduleCalibMutationOptions = <
+ TError = AxiosError,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: ScheduleCalibRequest },
+ TContext
+ >;
+ axios?: AxiosRequestConfig;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: ScheduleCalibRequest },
+ TContext
+> => {
+ const { mutation: mutationOptions, axios: axiosOptions } = options ?? {};
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: ScheduleCalibRequest }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return scheduleCalib(data, axiosOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type ScheduleCalibMutationResult = NonNullable<
+ Awaited>
+>;
+export type ScheduleCalibMutationBody = ScheduleCalibRequest;
+export type ScheduleCalibMutationError = AxiosError;
+
+/**
+ * @summary Schedules a calibration.
+ */
+export const useScheduleCalib = <
+ TError = AxiosError,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: ScheduleCalibRequest },
+ TContext
+ >;
+ axios?: AxiosRequestConfig;
+}): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: ScheduleCalibRequest },
+ TContext
+> => {
+ const mutationOptions = getScheduleCalibMutationOptions(options);
+
+ return useMutation(mutationOptions);
+};
+/**
+ * @summary Deletes a calibration schedule.
+ */
+export const deleteCalibSchedule = (
+ flowRunId: string,
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.delete(
+ `http://localhost:5715/calibrations/schedule/${flowRunId}`,
+ options,
+ );
+};
+
+export const getDeleteCalibScheduleMutationOptions = <
+ TError = AxiosError,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { flowRunId: string },
+ TContext
+ >;
+ axios?: AxiosRequestConfig;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { flowRunId: string },
+ TContext
+> => {
+ const { mutation: mutationOptions, axios: axiosOptions } = options ?? {};
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { flowRunId: string }
+ > = (props) => {
+ const { flowRunId } = props ?? {};
+
+ return deleteCalibSchedule(flowRunId, axiosOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type DeleteCalibScheduleMutationResult = NonNullable<
+ Awaited>
+>;
+
+export type DeleteCalibScheduleMutationError = AxiosError;
+
+/**
+ * @summary Deletes a calibration schedule.
+ */
+export const useDeleteCalibSchedule = <
+ TError = AxiosError,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { flowRunId: string },
+ TContext
+ >;
+ axios?: AxiosRequestConfig;
+}): UseMutationResult<
+ Awaited>,
+ TError,
+ { flowRunId: string },
+ TContext
+> => {
+ const mutationOptions = getDeleteCalibScheduleMutationOptions(options);
+
+ return useMutation(mutationOptions);
+};
+/**
+ * Fetches all the latest one qubit calibrations.
+
+Returns:
+ A list of OneQubitCalibResponse objects representing the latest one qubit calibrations.
+ * @summary Fetches all the latest one qubit calibrations.
+ */
+export const fetchAllLatestOneQubitCalib = (
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.get(
+ `http://localhost:5715/calibrations/latest/one_qubit`,
+ options,
+ );
+};
+
+export const getFetchAllLatestOneQubitCalibQueryKey = () => {
+ return [`http://localhost:5715/calibrations/latest/one_qubit`] as const;
+};
+
+export const getFetchAllLatestOneQubitCalibQueryOptions = <
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}) => {
+ const { query: queryOptions, axios: axiosOptions } = options ?? {};
+
+ const queryKey =
+ queryOptions?.queryKey ?? getFetchAllLatestOneQubitCalibQueryKey();
+
+ const queryFn: QueryFunction<
+ Awaited>
+ > = ({ signal }) => fetchAllLatestOneQubitCalib({ signal, ...axiosOptions });
+
+ return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ > & { queryKey: DataTag };
+};
+
+export type FetchAllLatestOneQubitCalibQueryResult = NonNullable<
+ Awaited>
+>;
+export type FetchAllLatestOneQubitCalibQueryError = AxiosError;
+
+export function useFetchAllLatestOneQubitCalib<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options: {
+ query: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ DefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+}): DefinedUseQueryResult & {
+ queryKey: DataTag;
+};
+export function useFetchAllLatestOneQubitCalib<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ UndefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag };
+export function useFetchAllLatestOneQubitCalib<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag };
+/**
+ * @summary Fetches all the latest one qubit calibrations.
+ */
+
+export function useFetchAllLatestOneQubitCalib<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag } {
+ const queryOptions = getFetchAllLatestOneQubitCalibQueryOptions(options);
+
+ const query = useQuery(queryOptions) as UseQueryResult & {
+ queryKey: DataTag;
+ };
+
+ query.queryKey = queryOptions.queryKey;
+
+ return query;
+}
+
+/**
+ * @summary Updates a one qubit calibration CW info.
+ */
+export const updateAllLatestOneQubitCalibCwInfo = (
+ oneQubitCalibCWInfo: OneQubitCalibCWInfo,
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.put(
+ `http://localhost:5715/calibrations/latest/one_qubit/cw_info`,
+ oneQubitCalibCWInfo,
+ options,
+ );
+};
+
+export const getUpdateAllLatestOneQubitCalibCwInfoMutationOptions = <
+ TError = AxiosError,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: OneQubitCalibCWInfo },
+ TContext
+ >;
+ axios?: AxiosRequestConfig;
+}): UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: OneQubitCalibCWInfo },
+ TContext
+> => {
+ const { mutation: mutationOptions, axios: axiosOptions } = options ?? {};
+
+ const mutationFn: MutationFunction<
+ Awaited>,
+ { data: OneQubitCalibCWInfo }
+ > = (props) => {
+ const { data } = props ?? {};
+
+ return updateAllLatestOneQubitCalibCwInfo(data, axiosOptions);
+ };
+
+ return { mutationFn, ...mutationOptions };
+};
+
+export type UpdateAllLatestOneQubitCalibCwInfoMutationResult = NonNullable<
+ Awaited>
+>;
+export type UpdateAllLatestOneQubitCalibCwInfoMutationBody =
+ OneQubitCalibCWInfo;
+export type UpdateAllLatestOneQubitCalibCwInfoMutationError =
+ AxiosError;
+
+/**
+ * @summary Updates a one qubit calibration CW info.
+ */
+export const useUpdateAllLatestOneQubitCalibCwInfo = <
+ TError = AxiosError,
+ TContext = unknown,
+>(options?: {
+ mutation?: UseMutationOptions<
+ Awaited>,
+ TError,
+ { data: OneQubitCalibCWInfo },
+ TContext
+ >;
+ axios?: AxiosRequestConfig;
+}): UseMutationResult<
+ Awaited>,
+ TError,
+ { data: OneQubitCalibCWInfo },
+ TContext
+> => {
+ const mutationOptions =
+ getUpdateAllLatestOneQubitCalibCwInfoMutationOptions(options);
+
+ return useMutation(mutationOptions);
+};
+/**
+ * Fetches all the latest two qubit calibrations.
+
+Returns:
+ list: A list of TwoQubitCalibResponse objects representing the latest two qubit calibrations.
+ * @summary Fetches all the latest two qubit calibrations.
+ */
+export const fetchAllLatestTwoQubitCalib = (
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.get(
+ `http://localhost:5715/calibrations/latest/two_qubit`,
+ options,
+ );
+};
+
+export const getFetchAllLatestTwoQubitCalibQueryKey = () => {
+ return [`http://localhost:5715/calibrations/latest/two_qubit`] as const;
+};
+
+export const getFetchAllLatestTwoQubitCalibQueryOptions = <
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}) => {
+ const { query: queryOptions, axios: axiosOptions } = options ?? {};
+
+ const queryKey =
+ queryOptions?.queryKey ?? getFetchAllLatestTwoQubitCalibQueryKey();
+
+ const queryFn: QueryFunction<
+ Awaited>
+ > = ({ signal }) => fetchAllLatestTwoQubitCalib({ signal, ...axiosOptions });
+
+ return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ > & { queryKey: DataTag };
+};
+
+export type FetchAllLatestTwoQubitCalibQueryResult = NonNullable<
+ Awaited>
+>;
+export type FetchAllLatestTwoQubitCalibQueryError = AxiosError;
+
+export function useFetchAllLatestTwoQubitCalib<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options: {
+ query: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ DefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+}): DefinedUseQueryResult & {
+ queryKey: DataTag;
+};
+export function useFetchAllLatestTwoQubitCalib<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ UndefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag };
+export function useFetchAllLatestTwoQubitCalib<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag };
+/**
+ * @summary Fetches all the latest two qubit calibrations.
+ */
+
+export function useFetchAllLatestTwoQubitCalib<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag } {
+ const queryOptions = getFetchAllLatestTwoQubitCalibQueryOptions(options);
+
+ const query = useQuery(queryOptions) as UseQueryResult & {
+ queryKey: DataTag;
+ };
+
+ query.queryKey = queryOptions.queryKey;
+
+ return query;
+}
+
+/**
+ * Fetches the calibration history for a specific one-qubit calibration by its ID.
+
+Args:
+ id (str): The ID of the one-qubit calibration.
+
+Returns:
+ list[OneQubitCalibHistoryResponse]: A list of OneQubitCalibHistoryResponse objects representing the calibration history.
+ * @summary Fetches the calibration history for a specific one-qubit calibration by its label.
+ */
+export const fetchOneQubitCalibHistoryByLabel = (
+ label: string,
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.get(
+ `http://localhost:5715/calibrations/history/one_qubit/${label}`,
+ options,
+ );
+};
+
+export const getFetchOneQubitCalibHistoryByLabelQueryKey = (label: string) => {
+ return [
+ `http://localhost:5715/calibrations/history/one_qubit/${label}`,
+ ] as const;
+};
+
+export const getFetchOneQubitCalibHistoryByLabelQueryOptions = <
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+ },
+) => {
+ const { query: queryOptions, axios: axiosOptions } = options ?? {};
+
+ const queryKey =
+ queryOptions?.queryKey ??
+ getFetchOneQubitCalibHistoryByLabelQueryKey(label);
+
+ const queryFn: QueryFunction<
+ Awaited>
+ > = ({ signal }) =>
+ fetchOneQubitCalibHistoryByLabel(label, { signal, ...axiosOptions });
+
+ return {
+ queryKey,
+ queryFn,
+ enabled: !!label,
+ ...queryOptions,
+ } as UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ > & { queryKey: DataTag };
+};
+
+export type FetchOneQubitCalibHistoryByLabelQueryResult = NonNullable<
+ Awaited>
+>;
+export type FetchOneQubitCalibHistoryByLabelQueryError =
+ AxiosError;
+
+export function useFetchOneQubitCalibHistoryByLabel<
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options: {
+ query: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ DefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+ },
+): DefinedUseQueryResult & {
+ queryKey: DataTag;
+};
+export function useFetchOneQubitCalibHistoryByLabel<
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ UndefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+ },
+): UseQueryResult & { queryKey: DataTag };
+export function useFetchOneQubitCalibHistoryByLabel<
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+ },
+): UseQueryResult & { queryKey: DataTag };
+/**
+ * @summary Fetches the calibration history for a specific one-qubit calibration by its label.
+ */
+
+export function useFetchOneQubitCalibHistoryByLabel<
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+ },
+): UseQueryResult & { queryKey: DataTag } {
+ const queryOptions = getFetchOneQubitCalibHistoryByLabelQueryOptions(
+ label,
+ options,
+ );
+
+ const query = useQuery(queryOptions) as UseQueryResult & {
+ queryKey: DataTag;
+ };
+
+ query.queryKey = queryOptions.queryKey;
+
+ return query;
+}
+
+/**
+ * @summary Fetches the calibration history for a specific two-qubit calibration by its label.
+ */
+export const fetchTwoQubitCalibHistoryByLabel = (
+ label: string,
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.get(
+ `http://localhost:5715/calibrations/history/two_qubit/${label}`,
+ options,
+ );
+};
+
+export const getFetchTwoQubitCalibHistoryByLabelQueryKey = (label: string) => {
+ return [
+ `http://localhost:5715/calibrations/history/two_qubit/${label}`,
+ ] as const;
+};
+
+export const getFetchTwoQubitCalibHistoryByLabelQueryOptions = <
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+ },
+) => {
+ const { query: queryOptions, axios: axiosOptions } = options ?? {};
+
+ const queryKey =
+ queryOptions?.queryKey ??
+ getFetchTwoQubitCalibHistoryByLabelQueryKey(label);
+
+ const queryFn: QueryFunction<
+ Awaited>
+ > = ({ signal }) =>
+ fetchTwoQubitCalibHistoryByLabel(label, { signal, ...axiosOptions });
+
+ return {
+ queryKey,
+ queryFn,
+ enabled: !!label,
+ ...queryOptions,
+ } as UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ > & { queryKey: DataTag };
+};
+
+export type FetchTwoQubitCalibHistoryByLabelQueryResult = NonNullable<
+ Awaited>
+>;
+export type FetchTwoQubitCalibHistoryByLabelQueryError =
+ AxiosError;
+
+export function useFetchTwoQubitCalibHistoryByLabel<
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options: {
+ query: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ DefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+ },
+): DefinedUseQueryResult & {
+ queryKey: DataTag;
+};
+export function useFetchTwoQubitCalibHistoryByLabel<
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ UndefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+ },
+): UseQueryResult & { queryKey: DataTag };
+export function useFetchTwoQubitCalibHistoryByLabel<
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+ },
+): UseQueryResult & { queryKey: DataTag };
+/**
+ * @summary Fetches the calibration history for a specific two-qubit calibration by its label.
+ */
+
+export function useFetchTwoQubitCalibHistoryByLabel<
+ TData = Awaited>,
+ TError = AxiosError,
+>(
+ label: string,
+ options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+ },
+): UseQueryResult & { queryKey: DataTag } {
+ const queryOptions = getFetchTwoQubitCalibHistoryByLabelQueryOptions(
+ label,
+ options,
+ );
+
+ const query = useQuery(queryOptions) as UseQueryResult & {
+ queryKey: DataTag;
+ };
+
+ query.queryKey = queryOptions.queryKey;
+
+ return query;
+}
+
+/**
+ * @summary Fetches all the one qubit calibration summaries.
+ */
+export const fetchAllOneQubitCalibSummary = (
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.get(
+ `http://localhost:5715/calibrations/one_qubit/summary`,
+ options,
+ );
+};
+
+export const getFetchAllOneQubitCalibSummaryQueryKey = () => {
+ return [`http://localhost:5715/calibrations/one_qubit/summary`] as const;
+};
+
+export const getFetchAllOneQubitCalibSummaryQueryOptions = <
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}) => {
+ const { query: queryOptions, axios: axiosOptions } = options ?? {};
+
+ const queryKey =
+ queryOptions?.queryKey ?? getFetchAllOneQubitCalibSummaryQueryKey();
+
+ const queryFn: QueryFunction<
+ Awaited>
+ > = ({ signal }) => fetchAllOneQubitCalibSummary({ signal, ...axiosOptions });
+
+ return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ > & { queryKey: DataTag };
+};
+
+export type FetchAllOneQubitCalibSummaryQueryResult = NonNullable<
+ Awaited>
+>;
+export type FetchAllOneQubitCalibSummaryQueryError = AxiosError;
+
+export function useFetchAllOneQubitCalibSummary<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options: {
+ query: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ DefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+}): DefinedUseQueryResult & {
+ queryKey: DataTag;
+};
+export function useFetchAllOneQubitCalibSummary<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ UndefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag };
+export function useFetchAllOneQubitCalibSummary<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag };
+/**
+ * @summary Fetches all the one qubit calibration summaries.
+ */
+
+export function useFetchAllOneQubitCalibSummary<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}): UseQueryResult & { queryKey: DataTag } {
+ const queryOptions = getFetchAllOneQubitCalibSummaryQueryOptions(options);
+
+ const query = useQuery(queryOptions) as UseQueryResult & {
+ queryKey: DataTag;
+ };
+
+ query.queryKey = queryOptions.queryKey;
+
+ return query;
+}
+
+/**
+ * @summary Fetches all the two qubit calibration summaries.
+ */
+export const fetchAllTwoQubitCalibSummary = (
+ options?: AxiosRequestConfig,
+): Promise> => {
+ return axios.default.get(
+ `http://localhost:5715/calibrations/two_qubit/summary`,
+ options,
+ );
+};
+
+export const getFetchAllTwoQubitCalibSummaryQueryKey = () => {
+ return [`http://localhost:5715/calibrations/two_qubit/summary`] as const;
+};
+
+export const getFetchAllTwoQubitCalibSummaryQueryOptions = <
+ TData = Awaited>,
+ TError = AxiosError,
+>(options?: {
+ query?: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ >;
+ axios?: AxiosRequestConfig;
+}) => {
+ const { query: queryOptions, axios: axiosOptions } = options ?? {};
+
+ const queryKey =
+ queryOptions?.queryKey ?? getFetchAllTwoQubitCalibSummaryQueryKey();
+
+ const queryFn: QueryFunction<
+ Awaited>
+ > = ({ signal }) => fetchAllTwoQubitCalibSummary({ signal, ...axiosOptions });
+
+ return { queryKey, queryFn, ...queryOptions } as UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ > & { queryKey: DataTag };
+};
+
+export type FetchAllTwoQubitCalibSummaryQueryResult = NonNullable<
+ Awaited>
+>;
+export type FetchAllTwoQubitCalibSummaryQueryError = AxiosError;
+
+export function useFetchAllTwoQubitCalibSummary<
+ TData = Awaited>,
+ TError = AxiosError,
+>(options: {
+ query: Partial<
+ UseQueryOptions<
+ Awaited>,
+ TError,
+ TData
+ >
+ > &
+ Pick<
+ DefinedInitialDataOptions<
+ Awaited>,
+ TError,
+ TData
+ >,
+ "initialData"
+ >;
+ axios?: AxiosRequestConfig;
+}): DefinedUseQueryResult & {
+ queryKey: DataTag;
+};
+export function useFetchAllTwoQubitCalibSummary<
+ TData = Awaited