diff --git a/.devcontainer/docker-compose-dev-traefik-ssl.yml b/.devcontainer/docker-compose-dev-traefik-ssl.yml
index afed60a..f116edf 100755
--- a/.devcontainer/docker-compose-dev-traefik-ssl.yml
+++ b/.devcontainer/docker-compose-dev-traefik-ssl.yml
@@ -221,7 +221,7 @@ services:
container_name: magnetdb-pgadmin
image: dpage/pgadmin4:8
environment:
- PGADMIN_DEFAULT_EMAIL: christophe.trophime@lncmi.cnrs.fr
+ PGADMIN_DEFAULT_EMAIL: pgadmin@magnetdb-dev.local
PGADMIN_DEFAULT_PASSWORD: admin
# PGADMIN_CONFIG_SERVER_MODE: 'False'
# Environment variables for server auto-configuration
diff --git a/.gitignore b/.gitignore
index 59f5ad7..51c75b8 100755
--- a/.gitignore
+++ b/.gitignore
@@ -96,3 +96,12 @@ tmp/*
*.tar.gz
backups/
+# duckdb
+*.duckdb
+
+*.old
+*log
+
+# direnv
+.envrc*
+*.my
diff --git a/Dockerfile b/Dockerfile
index df15748..da8832e 100755
--- a/Dockerfile
+++ b/Dockerfile
@@ -1,4 +1,4 @@
-FROM trophime/magnettools:bookworm-poetry-2.2.1
+FROM trophime/magnettools:trixie-poetry-2.4.0
ARG USERNAME=feelpp
ARG USER_UID=1000
@@ -35,6 +35,6 @@ RUN echo "create local user $USERNAME (uid=${USER_UID}, gid=${USER_GID})" \
&& ssh-keyscan github.com >> /home/${USERNAME}/.ssh/known_hosts \
&& chown -R $USER_GID:$USER_UID /home/${USERNAME}/.ssh
-ENV LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu/MagnetTools/:$LD_LIBRARY_PATH"
+ENV LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu/MagnetTools/:${LD_LIBRARY_PATH:-}"
USER $USERNAME
diff --git a/Dockerfile-dev b/Dockerfile-dev
index df15748..da8832e 100755
--- a/Dockerfile-dev
+++ b/Dockerfile-dev
@@ -1,4 +1,4 @@
-FROM trophime/magnettools:bookworm-poetry-2.2.1
+FROM trophime/magnettools:trixie-poetry-2.4.0
ARG USERNAME=feelpp
ARG USER_UID=1000
@@ -35,6 +35,6 @@ RUN echo "create local user $USERNAME (uid=${USER_UID}, gid=${USER_GID})" \
&& ssh-keyscan github.com >> /home/${USERNAME}/.ssh/known_hosts \
&& chown -R $USER_GID:$USER_UID /home/${USERNAME}/.ssh
-ENV LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu/MagnetTools/:$LD_LIBRARY_PATH"
+ENV LD_LIBRARY_PATH="/usr/lib/x86_64-linux-gnu/MagnetTools/:${LD_LIBRARY_PATH:-}"
USER $USERNAME
diff --git a/docker-compose-dev-traefik-ssl.yml b/docker-compose-dev-traefik-ssl.yml
index 33e48e6..341f77f 100755
--- a/docker-compose-dev-traefik-ssl.yml
+++ b/docker-compose-dev-traefik-ssl.yml
@@ -132,7 +132,7 @@ services:
- /bin/bash
- -c
- |
- npm install --legacy-peer-deps
+ npm install
npm run serve
working_dir: /app
labels:
diff --git a/docker-compose-traefik-ssl.yml b/docker-compose-traefik-ssl.yml
index ccfac0a..b21aa0e 100755
--- a/docker-compose-traefik-ssl.yml
+++ b/docker-compose-traefik-ssl.yml
@@ -1,7 +1,7 @@
version: '3'
services:
proxy:
- image: traefik:3.3
+ image: traefik:v3.6.7
container_name: magnetdb-traefik
ports:
- "80:80"
diff --git a/network_internal.conf b/network_internal.conf
deleted file mode 100644
index 0ac8b70..0000000
--- a/network_internal.conf
+++ /dev/null
@@ -1,11 +0,0 @@
-# These networks are considered "internal"
-allow 127.0.0.0/8;
-allow 10.0.0.0/8;
-allow 192.168.0.0/16;
-allow 172.16.0.0/12;
-allow 147.173.81.0/24;
-allow 147.173.82.0/24;
-allow 147.173.83.0/24;
-
-# Traffic from all other networks will be rejected
-deny all;
\ No newline at end of file
diff --git a/poetry.lock b/poetry.lock
index 9998596..0cd4a48 100644
--- a/poetry.lock
+++ b/poetry.lock
@@ -41,14 +41,14 @@ files = [
[[package]]
name = "anyio"
-version = "4.12.0"
+version = "4.12.1"
description = "High-level concurrency and networking framework on top of asyncio or Trio"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "anyio-4.12.0-py3-none-any.whl", hash = "sha256:dad2376a628f98eeca4881fc56cd06affd18f659b17a747d3ff0307ced94b1bb"},
- {file = "anyio-4.12.0.tar.gz", hash = "sha256:73c693b567b0c55130c104d0b43a9baf3aa6a31fc6110116509f27bf75e21ec0"},
+ {file = "anyio-4.12.1-py3-none-any.whl", hash = "sha256:d405828884fc140aa80a3c667b8beed277f1dfedec42ba031bd6ac3db606ab6c"},
+ {file = "anyio-4.12.1.tar.gz", hash = "sha256:41cfcc3a4c85d3f05c932da7c26d0201ac36f72abd4435ba90d0464a3ffed703"},
]
[package.dependencies]
@@ -117,14 +117,14 @@ cffi = [
[[package]]
name = "asgiref"
-version = "3.11.0"
+version = "3.11.1"
description = "ASGI specs, helper code, and adapters"
optional = false
python-versions = ">=3.9"
groups = ["main", "dev"]
files = [
- {file = "asgiref-3.11.0-py3-none-any.whl", hash = "sha256:1db9021efadb0d9512ce8ffaf72fcef601c7b73a8807a1bb2ef143dc6b14846d"},
- {file = "asgiref-3.11.0.tar.gz", hash = "sha256:13acff32519542a1736223fb79a715acdebe24286d98e8b164a73085f40da2c4"},
+ {file = "asgiref-3.11.1-py3-none-any.whl", hash = "sha256:e8667a091e69529631969fd45dc268fa79b99c92c5fcdda727757e52146ec133"},
+ {file = "asgiref-3.11.1.tar.gz", hash = "sha256:5f184dc43b7e763efe848065441eac62229c9f7b0475f41f80e207a114eda4ce"},
]
[package.extras]
@@ -234,46 +234,46 @@ files = [
[[package]]
name = "black"
-version = "25.12.0"
+version = "26.1.0"
description = "The uncompromising code formatter."
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "black-25.12.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f85ba1ad15d446756b4ab5f3044731bf68b777f8f9ac9cdabd2425b97cd9c4e8"},
- {file = "black-25.12.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:546eecfe9a3a6b46f9d69d8a642585a6eaf348bcbbc4d87a19635570e02d9f4a"},
- {file = "black-25.12.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:17dcc893da8d73d8f74a596f64b7c98ef5239c2cd2b053c0f25912c4494bf9ea"},
- {file = "black-25.12.0-cp310-cp310-win_amd64.whl", hash = "sha256:09524b0e6af8ba7a3ffabdfc7a9922fb9adef60fed008c7cd2fc01f3048e6e6f"},
- {file = "black-25.12.0-cp310-cp310-win_arm64.whl", hash = "sha256:b162653ed89eb942758efeb29d5e333ca5bb90e5130216f8369857db5955a7da"},
- {file = "black-25.12.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d0cfa263e85caea2cff57d8f917f9f51adae8e20b610e2b23de35b5b11ce691a"},
- {file = "black-25.12.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:1a2f578ae20c19c50a382286ba78bfbeafdf788579b053d8e4980afb079ab9be"},
- {file = "black-25.12.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d3e1b65634b0e471d07ff86ec338819e2ef860689859ef4501ab7ac290431f9b"},
- {file = "black-25.12.0-cp311-cp311-win_amd64.whl", hash = "sha256:a3fa71e3b8dd9f7c6ac4d818345237dfb4175ed3bf37cd5a581dbc4c034f1ec5"},
- {file = "black-25.12.0-cp311-cp311-win_arm64.whl", hash = "sha256:51e267458f7e650afed8445dc7edb3187143003d52a1b710c7321aef22aa9655"},
- {file = "black-25.12.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:31f96b7c98c1ddaeb07dc0f56c652e25bdedaac76d5b68a059d998b57c55594a"},
- {file = "black-25.12.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:05dd459a19e218078a1f98178c13f861fe6a9a5f88fc969ca4d9b49eb1809783"},
- {file = "black-25.12.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c1f68c5eff61f226934be6b5b80296cf6939e5d2f0c2f7d543ea08b204bfaf59"},
- {file = "black-25.12.0-cp312-cp312-win_amd64.whl", hash = "sha256:274f940c147ddab4442d316b27f9e332ca586d39c85ecf59ebdea82cc9ee8892"},
- {file = "black-25.12.0-cp312-cp312-win_arm64.whl", hash = "sha256:169506ba91ef21e2e0591563deda7f00030cb466e747c4b09cb0a9dae5db2f43"},
- {file = "black-25.12.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:a05ddeb656534c3e27a05a29196c962877c83fa5503db89e68857d1161ad08a5"},
- {file = "black-25.12.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9ec77439ef3e34896995503865a85732c94396edcc739f302c5673a2315e1e7f"},
- {file = "black-25.12.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0e509c858adf63aa61d908061b52e580c40eae0dfa72415fa47ac01b12e29baf"},
- {file = "black-25.12.0-cp313-cp313-win_amd64.whl", hash = "sha256:252678f07f5bac4ff0d0e9b261fbb029fa530cfa206d0a636a34ab445ef8ca9d"},
- {file = "black-25.12.0-cp313-cp313-win_arm64.whl", hash = "sha256:bc5b1c09fe3c931ddd20ee548511c64ebf964ada7e6f0763d443947fd1c603ce"},
- {file = "black-25.12.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:0a0953b134f9335c2434864a643c842c44fba562155c738a2a37a4d61f00cad5"},
- {file = "black-25.12.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2355bbb6c3b76062870942d8cc450d4f8ac71f9c93c40122762c8784df49543f"},
- {file = "black-25.12.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9678bd991cc793e81d19aeeae57966ee02909877cb65838ccffef24c3ebac08f"},
- {file = "black-25.12.0-cp314-cp314-win_amd64.whl", hash = "sha256:97596189949a8aad13ad12fcbb4ae89330039b96ad6742e6f6b45e75ad5cfd83"},
- {file = "black-25.12.0-cp314-cp314-win_arm64.whl", hash = "sha256:778285d9ea197f34704e3791ea9404cd6d07595745907dd2ce3da7a13627b29b"},
- {file = "black-25.12.0-py3-none-any.whl", hash = "sha256:48ceb36c16dbc84062740049eef990bb2ce07598272e673c17d1a7720c71c828"},
- {file = "black-25.12.0.tar.gz", hash = "sha256:8d3dd9cea14bff7ddc0eb243c811cdb1a011ebb4800a5f0335a01a68654796a7"},
+ {file = "black-26.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:ca699710dece84e3ebf6e92ee15f5b8f72870ef984bf944a57a777a48357c168"},
+ {file = "black-26.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5e8e75dabb6eb83d064b0db46392b25cabb6e784ea624219736e8985a6b3675d"},
+ {file = "black-26.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:eb07665d9a907a1a645ee41a0df8a25ffac8ad9c26cdb557b7b88eeeeec934e0"},
+ {file = "black-26.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:7ed300200918147c963c87700ccf9966dceaefbbb7277450a8d646fc5646bf24"},
+ {file = "black-26.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:c5b7713daea9bf943f79f8c3b46f361cc5229e0e604dcef6a8bb6d1c37d9df89"},
+ {file = "black-26.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:3cee1487a9e4c640dc7467aaa543d6c0097c391dc8ac74eb313f2fbf9d7a7cb5"},
+ {file = "black-26.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d62d14ca31c92adf561ebb2e5f2741bf8dea28aef6deb400d49cca011d186c68"},
+ {file = "black-26.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fb1dafbbaa3b1ee8b4550a84425aac8874e5f390200f5502cf3aee4a2acb2f14"},
+ {file = "black-26.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:101540cb2a77c680f4f80e628ae98bd2bd8812fb9d72ade4f8995c5ff019e82c"},
+ {file = "black-26.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:6f3977a16e347f1b115662be07daa93137259c711e526402aa444d7a88fdc9d4"},
+ {file = "black-26.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:6eeca41e70b5f5c84f2f913af857cf2ce17410847e1d54642e658e078da6544f"},
+ {file = "black-26.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:dd39eef053e58e60204f2cdf059e2442e2eb08f15989eefe259870f89614c8b6"},
+ {file = "black-26.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9459ad0d6cd483eacad4c6566b0f8e42af5e8b583cee917d90ffaa3778420a0a"},
+ {file = "black-26.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:a19915ec61f3a8746e8b10adbac4a577c6ba9851fa4a9e9fbfbcf319887a5791"},
+ {file = "black-26.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:643d27fb5facc167c0b1b59d0315f2674a6e950341aed0fc05cf307d22bf4954"},
+ {file = "black-26.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:ba1d768fbfb6930fc93b0ecc32a43d8861ded16f47a40f14afa9bb04ab93d304"},
+ {file = "black-26.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:2b807c240b64609cb0e80d2200a35b23c7df82259f80bef1b2c96eb422b4aac9"},
+ {file = "black-26.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1de0f7d01cc894066a1153b738145b194414cc6eeaad8ef4397ac9abacf40f6b"},
+ {file = "black-26.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:91a68ae46bf07868963671e4d05611b179c2313301bd756a89ad4e3b3db2325b"},
+ {file = "black-26.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:be5e2fe860b9bd9edbf676d5b60a9282994c03fbbd40fe8f5e75d194f96064ca"},
+ {file = "black-26.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:9dc8c71656a79ca49b8d3e2ce8103210c9481c57798b48deeb3a8bb02db5f115"},
+ {file = "black-26.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:b22b3810451abe359a964cc88121d57f7bce482b53a066de0f1584988ca36e79"},
+ {file = "black-26.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:53c62883b3f999f14e5d30b5a79bd437236658ad45b2f853906c7cbe79de00af"},
+ {file = "black-26.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:f016baaadc423dc960cdddf9acae679e71ee02c4c341f78f3179d7e4819c095f"},
+ {file = "black-26.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:66912475200b67ef5a0ab665011964bf924745103f51977a78b4fb92a9fc1bf0"},
+ {file = "black-26.1.0-py3-none-any.whl", hash = "sha256:1054e8e47ebd686e078c0bb0eaf31e6ce69c966058d122f2c0c950311f9f3ede"},
+ {file = "black-26.1.0.tar.gz", hash = "sha256:d294ac3340eef9c9eb5d29288e96dc719ff269a88e27b396340459dd85da4c58"},
]
[package.dependencies]
click = ">=8.0.0"
mypy-extensions = ">=0.4.3"
packaging = ">=22.0"
-pathspec = ">=0.9.0"
+pathspec = ">=1.0.0"
platformdirs = ">=2"
pytokens = ">=0.3.0"
@@ -285,14 +285,14 @@ uvloop = ["uvloop (>=0.15.2)"]
[[package]]
name = "celery"
-version = "5.6.0"
+version = "5.6.2"
description = "Distributed Task Queue."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "celery-5.6.0-py3-none-any.whl", hash = "sha256:33cf01477b175017fc8f22c5ee8a65157591043ba8ca78a443fe703aa910f581"},
- {file = "celery-5.6.0.tar.gz", hash = "sha256:641405206042d52ae460e4e9751a2e31b06cf80ab836fcf92e0b9311d7ea8113"},
+ {file = "celery-5.6.2-py3-none-any.whl", hash = "sha256:3ffafacbe056951b629c7abcf9064c4a2366de0bdfc9fdba421b97ebb68619a5"},
+ {file = "celery-5.6.2.tar.gz", hash = "sha256:4a8921c3fcf2ad76317d3b29020772103581ed2454c4c042cc55dcc43585009b"},
]
[package.dependencies]
@@ -301,7 +301,6 @@ click = ">=8.1.2,<9.0"
click-didyoumean = ">=0.3.0"
click-plugins = ">=1.1.1"
click-repl = ">=0.2.0"
-exceptiongroup = ">=1.3.0"
kombu = [
{version = ">=5.6.0"},
{version = "*", extras = ["redis"], optional = true, markers = "extra == \"redis\""},
@@ -324,7 +323,7 @@ django = ["Django (>=2.2.28)"]
dynamodb = ["boto3 (>=1.26.143)"]
elasticsearch = ["elastic-transport (<=9.1.0)", "elasticsearch (<=9.1.2)"]
eventlet = ["eventlet (>=0.32.0) ; python_version < \"3.10\""]
-gcs = ["google-cloud-firestore (==2.21.0)", "google-cloud-storage (>=2.10.0)", "grpcio (==1.75.1)"]
+gcs = ["google-cloud-firestore (==2.22.0)", "google-cloud-storage (>=2.10.0)", "grpcio (==1.75.1)"]
gevent = ["gevent (>=1.5.0)"]
librabbitmq = ["librabbitmq (>=2.0.0) ; python_version < \"3.11\""]
memcache = ["pylibmc (==1.6.3) ; platform_system != \"Windows\""]
@@ -347,14 +346,14 @@ zstd = ["zstandard (==0.23.0)"]
[[package]]
name = "certifi"
-version = "2025.11.12"
+version = "2026.1.4"
description = "Python package for providing Mozilla's CA Bundle."
optional = false
python-versions = ">=3.7"
groups = ["main"]
files = [
- {file = "certifi-2025.11.12-py3-none-any.whl", hash = "sha256:97de8790030bbd5c2d96b7ec782fc2f7820ef8dba6db909ccf95449f2d062d4b"},
- {file = "certifi-2025.11.12.tar.gz", hash = "sha256:d8ab5478f2ecd78af242878415affce761ca6bc54a22a27e026d7c25357c3316"},
+ {file = "certifi-2026.1.4-py3-none-any.whl", hash = "sha256:9943707519e4add1115f44c2bc244f782c0249876bf51b6599fee1ffbedd685c"},
+ {file = "certifi-2026.1.4.tar.gz", hash = "sha256:ac726dd470482006e014ad384921ed6438c457018f4b3d204aea4281258b2120"},
]
[[package]]
@@ -763,104 +762,104 @@ test-no-images = ["pytest", "pytest-cov", "pytest-rerunfailures", "pytest-xdist"
[[package]]
name = "coverage"
-version = "7.13.0"
+version = "7.13.3"
description = "Code coverage measurement for Python"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "coverage-7.13.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:02d9fb9eccd48f6843c98a37bd6817462f130b86da8660461e8f5e54d4c06070"},
- {file = "coverage-7.13.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:367449cf07d33dc216c083f2036bb7d976c6e4903ab31be400ad74ad9f85ce98"},
- {file = "coverage-7.13.0-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cdb3c9f8fef0a954c632f64328a3935988d33a6604ce4bf67ec3e39670f12ae5"},
- {file = "coverage-7.13.0-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d10fd186aac2316f9bbb46ef91977f9d394ded67050ad6d84d94ed6ea2e8e54e"},
- {file = "coverage-7.13.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f88ae3e69df2ab62fb0bc5219a597cb890ba5c438190ffa87490b315190bb33"},
- {file = "coverage-7.13.0-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:c4be718e51e86f553bcf515305a158a1cd180d23b72f07ae76d6017c3cc5d791"},
- {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a00d3a393207ae12f7c49bb1c113190883b500f48979abb118d8b72b8c95c032"},
- {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:3a7b1cd820e1b6116f92c6128f1188e7afe421c7e1b35fa9836b11444e53ebd9"},
- {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:37eee4e552a65866f15dedd917d5e5f3d59805994260720821e2c1b51ac3248f"},
- {file = "coverage-7.13.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:62d7c4f13102148c78d7353c6052af6d899a7f6df66a32bddcc0c0eb7c5326f8"},
- {file = "coverage-7.13.0-cp310-cp310-win32.whl", hash = "sha256:24e4e56304fdb56f96f80eabf840eab043b3afea9348b88be680ec5986780a0f"},
- {file = "coverage-7.13.0-cp310-cp310-win_amd64.whl", hash = "sha256:74c136e4093627cf04b26a35dab8cbfc9b37c647f0502fc313376e11726ba303"},
- {file = "coverage-7.13.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:0dfa3855031070058add1a59fdfda0192fd3e8f97e7c81de0596c145dea51820"},
- {file = "coverage-7.13.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4fdb6f54f38e334db97f72fa0c701e66d8479af0bc3f9bfb5b90f1c30f54500f"},
- {file = "coverage-7.13.0-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7e442c013447d1d8d195be62852270b78b6e255b79b8675bad8479641e21fd96"},
- {file = "coverage-7.13.0-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:1ed5630d946859de835a85e9a43b721123a8a44ec26e2830b296d478c7fd4259"},
- {file = "coverage-7.13.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7f15a931a668e58087bc39d05d2b4bf4b14ff2875b49c994bbdb1c2217a8daeb"},
- {file = "coverage-7.13.0-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:30a3a201a127ea57f7e14ba43c93c9c4be8b7d17a26e03bb49e6966d019eede9"},
- {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a485ff48fbd231efa32d58f479befce52dcb6bfb2a88bb7bf9a0b89b1bc8030"},
- {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:22486cdafba4f9e471c816a2a5745337742a617fef68e890d8baf9f3036d7833"},
- {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:263c3dbccc78e2e331e59e90115941b5f53e85cfcc6b3b2fbff1fd4e3d2c6ea8"},
- {file = "coverage-7.13.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:e5330fa0cc1f5c3c4c3bb8e101b742025933e7848989370a1d4c8c5e401ea753"},
- {file = "coverage-7.13.0-cp311-cp311-win32.whl", hash = "sha256:0f4872f5d6c54419c94c25dd6ae1d015deeb337d06e448cd890a1e89a8ee7f3b"},
- {file = "coverage-7.13.0-cp311-cp311-win_amd64.whl", hash = "sha256:51a202e0f80f241ccb68e3e26e19ab5b3bf0f813314f2c967642f13ebcf1ddfe"},
- {file = "coverage-7.13.0-cp311-cp311-win_arm64.whl", hash = "sha256:d2a9d7f1c11487b1c69367ab3ac2d81b9b3721f097aa409a3191c3e90f8f3dd7"},
- {file = "coverage-7.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0b3d67d31383c4c68e19a88e28fc4c2e29517580f1b0ebec4a069d502ce1e0bf"},
- {file = "coverage-7.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:581f086833d24a22c89ae0fe2142cfaa1c92c930adf637ddf122d55083fb5a0f"},
- {file = "coverage-7.13.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0a3a30f0e257df382f5f9534d4ce3d4cf06eafaf5192beb1a7bd066cb10e78fb"},
- {file = "coverage-7.13.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:583221913fbc8f53b88c42e8dbb8fca1d0f2e597cb190ce45916662b8b9d9621"},
- {file = "coverage-7.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f5d9bd30756fff3e7216491a0d6d520c448d5124d3d8e8f56446d6412499e74"},
- {file = "coverage-7.13.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a23e5a1f8b982d56fa64f8e442e037f6ce29322f1f9e6c2344cd9e9f4407ee57"},
- {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b01c22bc74a7fb44066aaf765224c0d933ddf1f5047d6cdfe4795504a4493f8"},
- {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:898cce66d0836973f48dda4e3514d863d70142bdf6dfab932b9b6a90ea5b222d"},
- {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:3ab483ea0e251b5790c2aac03acde31bff0c736bf8a86829b89382b407cd1c3b"},
- {file = "coverage-7.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d84e91521c5e4cb6602fe11ece3e1de03b2760e14ae4fcf1a4b56fa3c801fcd"},
- {file = "coverage-7.13.0-cp312-cp312-win32.whl", hash = "sha256:193c3887285eec1dbdb3f2bd7fbc351d570ca9c02ca756c3afbc71b3c98af6ef"},
- {file = "coverage-7.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:4f3e223b2b2db5e0db0c2b97286aba0036ca000f06aca9b12112eaa9af3d92ae"},
- {file = "coverage-7.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:086cede306d96202e15a4b77ace8472e39d9f4e5f9fd92dd4fecdfb2313b2080"},
- {file = "coverage-7.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:28ee1c96109974af104028a8ef57cec21447d42d0e937c0275329272e370ebcf"},
- {file = "coverage-7.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e97353dcc5587b85986cda4ff3ec98081d7e84dd95e8b2a6d59820f0545f8a"},
- {file = "coverage-7.13.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:99acd4dfdfeb58e1937629eb1ab6ab0899b131f183ee5f23e0b5da5cba2fec74"},
- {file = "coverage-7.13.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ff45e0cd8451e293b63ced93161e189780baf444119391b3e7d25315060368a6"},
- {file = "coverage-7.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f4f72a85316d8e13234cafe0a9f81b40418ad7a082792fa4165bd7d45d96066b"},
- {file = "coverage-7.13.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11c21557d0e0a5a38632cbbaca5f008723b26a89d70db6315523df6df77d6232"},
- {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76541dc8d53715fb4f7a3a06b34b0dc6846e3c69bc6204c55653a85dd6220971"},
- {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6e9e451dee940a86789134b6b0ffbe31c454ade3b849bb8a9d2cca2541a8e91d"},
- {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5c67dace46f361125e6b9cace8fe0b729ed8479f47e70c89b838d319375c8137"},
- {file = "coverage-7.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f59883c643cb19630500f57016f76cfdcd6845ca8c5b5ea1f6e17f74c8e5f511"},
- {file = "coverage-7.13.0-cp313-cp313-win32.whl", hash = "sha256:58632b187be6f0be500f553be41e277712baa278147ecb7559983c6d9faf7ae1"},
- {file = "coverage-7.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:73419b89f812f498aca53f757dd834919b48ce4799f9d5cad33ca0ae442bdb1a"},
- {file = "coverage-7.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:eb76670874fdd6091eedcc856128ee48c41a9bbbb9c3f1c7c3cf169290e3ffd6"},
- {file = "coverage-7.13.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6e63ccc6e0ad8986386461c3c4b737540f20426e7ec932f42e030320896c311a"},
- {file = "coverage-7.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:494f5459ffa1bd45e18558cd98710c36c0b8fbfa82a5eabcbe671d80ecffbfe8"},
- {file = "coverage-7.13.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:06cac81bf10f74034e055e903f5f946e3e26fc51c09fc9f584e4a1605d977053"},
- {file = "coverage-7.13.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f2ffc92b46ed6e6760f1d47a71e56b5664781bc68986dbd1836b2b70c0ce2071"},
- {file = "coverage-7.13.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0602f701057c6823e5db1b74530ce85f17c3c5be5c85fc042ac939cbd909426e"},
- {file = "coverage-7.13.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:25dc33618d45456ccb1d37bce44bc78cf269909aa14c4db2e03d63146a8a1493"},
- {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:71936a8b3b977ddd0b694c28c6a34f4fff2e9dd201969a4ff5d5fc7742d614b0"},
- {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:936bc20503ce24770c71938d1369461f0c5320830800933bc3956e2a4ded930e"},
- {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:af0a583efaacc52ae2521f8d7910aff65cdb093091d76291ac5820d5e947fc1c"},
- {file = "coverage-7.13.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f1c23e24a7000da892a312fb17e33c5f94f8b001de44b7cf8ba2e36fbd15859e"},
- {file = "coverage-7.13.0-cp313-cp313t-win32.whl", hash = "sha256:5f8a0297355e652001015e93be345ee54393e45dc3050af4a0475c5a2b767d46"},
- {file = "coverage-7.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6abb3a4c52f05e08460bd9acf04fec027f8718ecaa0d09c40ffbc3fbd70ecc39"},
- {file = "coverage-7.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:3ad968d1e3aa6ce5be295ab5fe3ae1bf5bb4769d0f98a80a0252d543a2ef2e9e"},
- {file = "coverage-7.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:453b7ec753cf5e4356e14fe858064e5520c460d3bbbcb9c35e55c0d21155c256"},
- {file = "coverage-7.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:af827b7cbb303e1befa6c4f94fd2bf72f108089cfa0f8abab8f4ca553cf5ca5a"},
- {file = "coverage-7.13.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9987a9e4f8197a1000280f7cc089e3ea2c8b3c0a64d750537809879a7b4ceaf9"},
- {file = "coverage-7.13.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3188936845cd0cb114fa6a51842a304cdbac2958145d03be2377ec41eb285d19"},
- {file = "coverage-7.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2bdb3babb74079f021696cb46b8bb5f5661165c385d3a238712b031a12355be"},
- {file = "coverage-7.13.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7464663eaca6adba4175f6c19354feea61ebbdd735563a03d1e472c7072d27bb"},
- {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8069e831f205d2ff1f3d355e82f511eb7c5522d7d413f5db5756b772ec8697f8"},
- {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6fb2d5d272341565f08e962cce14cdf843a08ac43bd621783527adb06b089c4b"},
- {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5e70f92ef89bac1ac8a99b3324923b4749f008fdbd7aa9cb35e01d7a284a04f9"},
- {file = "coverage-7.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4b5de7d4583e60d5fd246dd57fcd3a8aa23c6e118a8c72b38adf666ba8e7e927"},
- {file = "coverage-7.13.0-cp314-cp314-win32.whl", hash = "sha256:a6c6e16b663be828a8f0b6c5027d36471d4a9f90d28444aa4ced4d48d7d6ae8f"},
- {file = "coverage-7.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:0900872f2fdb3ee5646b557918d02279dc3af3dfb39029ac4e945458b13f73bc"},
- {file = "coverage-7.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:3a10260e6a152e5f03f26db4a407c4c62d3830b9af9b7c0450b183615f05d43b"},
- {file = "coverage-7.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9097818b6cc1cfb5f174e3263eba4a62a17683bcfe5c4b5d07f4c97fa51fbf28"},
- {file = "coverage-7.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0018f73dfb4301a89292c73be6ba5f58722ff79f51593352759c1790ded1cabe"},
- {file = "coverage-7.13.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:166ad2a22ee770f5656e1257703139d3533b4a0b6909af67c6b4a3adc1c98657"},
- {file = "coverage-7.13.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f6aaef16d65d1787280943f1c8718dc32e9cf141014e4634d64446702d26e0ff"},
- {file = "coverage-7.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e999e2dcc094002d6e2c7bbc1fb85b58ba4f465a760a8014d97619330cdbbbf3"},
- {file = "coverage-7.13.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:00c3d22cf6fb1cf3bf662aaaa4e563be8243a5ed2630339069799835a9cc7f9b"},
- {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22ccfe8d9bb0d6134892cbe1262493a8c70d736b9df930f3f3afae0fe3ac924d"},
- {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9372dff5ea15930fea0445eaf37bbbafbc771a49e70c0aeed8b4e2c2614cc00e"},
- {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:69ac2c492918c2461bc6ace42d0479638e60719f2a4ef3f0815fa2df88e9f940"},
- {file = "coverage-7.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:739c6c051a7540608d097b8e13c76cfa85263ced467168dc6b477bae3df7d0e2"},
- {file = "coverage-7.13.0-cp314-cp314t-win32.whl", hash = "sha256:fe81055d8c6c9de76d60c94ddea73c290b416e061d40d542b24a5871bad498b7"},
- {file = "coverage-7.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:445badb539005283825959ac9fa4a28f712c214b65af3a2c464f1adc90f5fcbc"},
- {file = "coverage-7.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:de7f6748b890708578fc4b7bb967d810aeb6fcc9bff4bb77dbca77dab2f9df6a"},
- {file = "coverage-7.13.0-py3-none-any.whl", hash = "sha256:850d2998f380b1e266459ca5b47bc9e7daf9af1d070f66317972f382d46f1904"},
- {file = "coverage-7.13.0.tar.gz", hash = "sha256:a394aa27f2d7ff9bc04cf703817773a59ad6dfbd577032e690f961d2460ee936"},
+ {file = "coverage-7.13.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:0b4f345f7265cdbdb5ec2521ffff15fa49de6d6c39abf89fc7ad68aa9e3a55f0"},
+ {file = "coverage-7.13.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:96c3be8bae9d0333e403cc1a8eb078a7f928b5650bae94a18fb4820cc993fb9b"},
+ {file = "coverage-7.13.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:d6f4a21328ea49d38565b55599e1c02834e76583a6953e5586d65cb1efebd8f8"},
+ {file = "coverage-7.13.3-cp310-cp310-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fc970575799a9d17d5c3fafd83a0f6ccf5d5117cdc9ad6fbd791e9ead82418b0"},
+ {file = "coverage-7.13.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:87ff33b652b3556b05e204ae20793d1f872161b0fa5ec8a9ac76f8430e152ed6"},
+ {file = "coverage-7.13.3-cp310-cp310-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7df8759ee57b9f3f7b66799b7660c282f4375bef620ade1686d6a7b03699e75f"},
+ {file = "coverage-7.13.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:f45c9bcb16bee25a798ccba8a2f6a1251b19de6a0d617bb365d7d2f386c4e20e"},
+ {file = "coverage-7.13.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:318b2e4753cbf611061e01b6cc81477e1cdfeb69c36c4a14e6595e674caadb56"},
+ {file = "coverage-7.13.3-cp310-cp310-musllinux_1_2_riscv64.whl", hash = "sha256:24db3959de8ee394eeeca89ccb8ba25305c2da9a668dd44173394cbd5aa0777f"},
+ {file = "coverage-7.13.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:be14d0622125edef21b3a4d8cd2d138c4872bf6e38adc90fd92385e3312f406a"},
+ {file = "coverage-7.13.3-cp310-cp310-win32.whl", hash = "sha256:53be4aab8ddef18beb6188f3a3fdbf4d1af2277d098d4e618be3a8e6c88e74be"},
+ {file = "coverage-7.13.3-cp310-cp310-win_amd64.whl", hash = "sha256:bfeee64ad8b4aae3233abb77eb6b52b51b05fa89da9645518671b9939a78732b"},
+ {file = "coverage-7.13.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5907605ee20e126eeee2abe14aae137043c2c8af2fa9b38d2ab3b7a6b8137f73"},
+ {file = "coverage-7.13.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a88705500988c8acad8b8fd86c2a933d3aa96bec1ddc4bc5cb256360db7bbd00"},
+ {file = "coverage-7.13.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bbb5aa9016c4c29e3432e087aa29ebee3f8fda089cfbfb4e6d64bd292dcd1c2"},
+ {file = "coverage-7.13.3-cp311-cp311-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0c2be202a83dde768937a61cdc5d06bf9fb204048ca199d93479488e6247656c"},
+ {file = "coverage-7.13.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0f45e32ef383ce56e0ca099b2e02fcdf7950be4b1b56afaab27b4ad790befe5b"},
+ {file = "coverage-7.13.3-cp311-cp311-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:6ed2e787249b922a93cd95c671cc9f4c9797a106e81b455c83a9ddb9d34590c0"},
+ {file = "coverage-7.13.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:05dd25b21afffe545e808265897c35f32d3e4437663923e0d256d9ab5031fb14"},
+ {file = "coverage-7.13.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:46d29926349b5c4f1ea4fca95e8c892835515f3600995a383fa9a923b5739ea4"},
+ {file = "coverage-7.13.3-cp311-cp311-musllinux_1_2_riscv64.whl", hash = "sha256:fae6a21537519c2af00245e834e5bf2884699cc7c1055738fd0f9dc37a3644ad"},
+ {file = "coverage-7.13.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:c672d4e2f0575a4ca2bf2aa0c5ced5188220ab806c1bb6d7179f70a11a017222"},
+ {file = "coverage-7.13.3-cp311-cp311-win32.whl", hash = "sha256:fcda51c918c7a13ad93b5f89a58d56e3a072c9e0ba5c231b0ed81404bf2648fb"},
+ {file = "coverage-7.13.3-cp311-cp311-win_amd64.whl", hash = "sha256:d1a049b5c51b3b679928dd35e47c4a2235e0b6128b479a7596d0ef5b42fa6301"},
+ {file = "coverage-7.13.3-cp311-cp311-win_arm64.whl", hash = "sha256:79f2670c7e772f4917895c3d89aad59e01f3dbe68a4ed2d0373b431fad1dcfba"},
+ {file = "coverage-7.13.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ed48b4170caa2c4420e0cd27dc977caaffc7eecc317355751df8373dddcef595"},
+ {file = "coverage-7.13.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8f2adf4bcffbbec41f366f2e6dffb9d24e8172d16e91da5799c9b7ed6b5716e6"},
+ {file = "coverage-7.13.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:01119735c690786b6966a1e9f098da4cd7ca9174c4cfe076d04e653105488395"},
+ {file = "coverage-7.13.3-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:8bb09e83c603f152d855f666d70a71765ca8e67332e5829e62cb9466c176af23"},
+ {file = "coverage-7.13.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b607a40cba795cfac6d130220d25962931ce101f2f478a29822b19755377fb34"},
+ {file = "coverage-7.13.3-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:44f14a62f5da2e9aedf9080e01d2cda61df39197d48e323538ec037336d68da8"},
+ {file = "coverage-7.13.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:debf29e0b157769843dff0981cc76f79e0ed04e36bb773c6cac5f6029054bd8a"},
+ {file = "coverage-7.13.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:824bb95cd71604031ae9a48edb91fd6effde669522f960375668ed21b36e3ec4"},
+ {file = "coverage-7.13.3-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:8f1010029a5b52dc427c8e2a8dbddb2303ddd180b806687d1acd1bb1d06649e7"},
+ {file = "coverage-7.13.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cd5dee4fd7659d8306ffa79eeaaafd91fa30a302dac3af723b9b469e549247e0"},
+ {file = "coverage-7.13.3-cp312-cp312-win32.whl", hash = "sha256:f7f153d0184d45f3873b3ad3ad22694fd73aadcb8cdbc4337ab4b41ea6b4dff1"},
+ {file = "coverage-7.13.3-cp312-cp312-win_amd64.whl", hash = "sha256:03a6e5e1e50819d6d7436f5bc40c92ded7e484e400716886ac921e35c133149d"},
+ {file = "coverage-7.13.3-cp312-cp312-win_arm64.whl", hash = "sha256:51c4c42c0e7d09a822b08b6cf79b3c4db8333fffde7450da946719ba0d45730f"},
+ {file = "coverage-7.13.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:853c3d3c79ff0db65797aad79dee6be020efd218ac4510f15a205f1e8d13ce25"},
+ {file = "coverage-7.13.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:f75695e157c83d374f88dcc646a60cb94173304a9258b2e74ba5a66b7614a51a"},
+ {file = "coverage-7.13.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:2d098709621d0819039f3f1e471ee554f55a0b2ac0d816883c765b14129b5627"},
+ {file = "coverage-7.13.3-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:16d23d6579cf80a474ad160ca14d8b319abaa6db62759d6eef53b2fc979b58c8"},
+ {file = "coverage-7.13.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00d34b29a59d2076e6f318b30a00a69bf63687e30cd882984ed444e753990cc1"},
+ {file = "coverage-7.13.3-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:ab6d72bffac9deb6e6cb0f61042e748de3f9f8e98afb0375a8e64b0b6e11746b"},
+ {file = "coverage-7.13.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:e129328ad1258e49cae0123a3b5fcb93d6c2fa90d540f0b4c7cdcdc019aaa3dc"},
+ {file = "coverage-7.13.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:2213a8d88ed35459bda71597599d4eec7c2ebad201c88f0bfc2c26fd9b0dd2ea"},
+ {file = "coverage-7.13.3-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:00dd3f02de6d5f5c9c3d95e3e036c3c2e2a669f8bf2d3ceb92505c4ce7838f67"},
+ {file = "coverage-7.13.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f9bada7bc660d20b23d7d312ebe29e927b655cf414dadcdb6335a2075695bd86"},
+ {file = "coverage-7.13.3-cp313-cp313-win32.whl", hash = "sha256:75b3c0300f3fa15809bd62d9ca8b170eb21fcf0100eb4b4154d6dc8b3a5bbd43"},
+ {file = "coverage-7.13.3-cp313-cp313-win_amd64.whl", hash = "sha256:a2f7589c6132c44c53f6e705e1a6677e2b7821378c22f7703b2cf5388d0d4587"},
+ {file = "coverage-7.13.3-cp313-cp313-win_arm64.whl", hash = "sha256:123ceaf2b9d8c614f01110f908a341e05b1b305d6b2ada98763b9a5a59756051"},
+ {file = "coverage-7.13.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:cc7fd0f726795420f3678ac82ff882c7fc33770bd0074463b5aef7293285ace9"},
+ {file = "coverage-7.13.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:d358dc408edc28730aed5477a69338e444e62fba0b7e9e4a131c505fadad691e"},
+ {file = "coverage-7.13.3-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:5d67b9ed6f7b5527b209b24b3df9f2e5bf0198c1bbf99c6971b0e2dcb7e2a107"},
+ {file = "coverage-7.13.3-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:59224bfb2e9b37c1335ae35d00daa3a5b4e0b1a20f530be208fff1ecfa436f43"},
+ {file = "coverage-7.13.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ae9306b5299e31e31e0d3b908c66bcb6e7e3ddca143dea0266e9ce6c667346d3"},
+ {file = "coverage-7.13.3-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:343aaeb5f8bb7bcd38620fd7bc56e6ee8207847d8c6103a1e7b72322d381ba4a"},
+ {file = "coverage-7.13.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:b2182129f4c101272ff5f2f18038d7b698db1bf8e7aa9e615cb48440899ad32e"},
+ {file = "coverage-7.13.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:94d2ac94bd0cc57c5626f52f8c2fffed1444b5ae8c9fc68320306cc2b255e155"},
+ {file = "coverage-7.13.3-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:65436cde5ecabe26fb2f0bf598962f0a054d3f23ad529361326ac002c61a2a1e"},
+ {file = "coverage-7.13.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:db83b77f97129813dbd463a67e5335adc6a6a91db652cc085d60c2d512746f96"},
+ {file = "coverage-7.13.3-cp313-cp313t-win32.whl", hash = "sha256:dfb428e41377e6b9ba1b0a32df6db5409cb089a0ed1d0a672dc4953ec110d84f"},
+ {file = "coverage-7.13.3-cp313-cp313t-win_amd64.whl", hash = "sha256:5badd7e596e6b0c89aa8ec6d37f4473e4357f982ce57f9a2942b0221cd9cf60c"},
+ {file = "coverage-7.13.3-cp313-cp313t-win_arm64.whl", hash = "sha256:989aa158c0eb19d83c76c26f4ba00dbb272485c56e452010a3450bdbc9daafd9"},
+ {file = "coverage-7.13.3-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:c6f6169bbdbdb85aab8ac0392d776948907267fcc91deeacf6f9d55f7a83ae3b"},
+ {file = "coverage-7.13.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:2f5e731627a3d5ef11a2a35aa0c6f7c435867c7ccbc391268eb4f2ca5dbdcc10"},
+ {file = "coverage-7.13.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9db3a3285d91c0b70fab9f39f0a4aa37d375873677efe4e71e58d8321e8c5d39"},
+ {file = "coverage-7.13.3-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:06e49c5897cb12e3f7ecdc111d44e97c4f6d0557b81a7a0204ed70a8b038f86f"},
+ {file = "coverage-7.13.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fb25061a66802df9fc13a9ba1967d25faa4dae0418db469264fd9860a921dde4"},
+ {file = "coverage-7.13.3-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:99fee45adbb1caeb914da16f70e557fb7ff6ddc9e4b14de665bd41af631367ef"},
+ {file = "coverage-7.13.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:318002f1fd819bdc1651c619268aa5bc853c35fa5cc6d1e8c96bd9cd6c828b75"},
+ {file = "coverage-7.13.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:71295f2d1d170b9977dc386d46a7a1b7cbb30e5405492529b4c930113a33f895"},
+ {file = "coverage-7.13.3-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5b1ad2e0dc672625c44bc4fe34514602a9fd8b10d52ddc414dc585f74453516c"},
+ {file = "coverage-7.13.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b2beb64c145593a50d90db5c7178f55daeae129123b0d265bdb3cbec83e5194a"},
+ {file = "coverage-7.13.3-cp314-cp314-win32.whl", hash = "sha256:3d1aed4f4e837a832df2f3b4f68a690eede0de4560a2dbc214ea0bc55aabcdb4"},
+ {file = "coverage-7.13.3-cp314-cp314-win_amd64.whl", hash = "sha256:9f9efbbaf79f935d5fbe3ad814825cbce4f6cdb3054384cb49f0c0f496125fa0"},
+ {file = "coverage-7.13.3-cp314-cp314-win_arm64.whl", hash = "sha256:31b6e889c53d4e6687ca63706148049494aace140cffece1c4dc6acadb70a7b3"},
+ {file = "coverage-7.13.3-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:c5e9787cec750793a19a28df7edd85ac4e49d3fb91721afcdc3b86f6c08d9aa8"},
+ {file = "coverage-7.13.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:e5b86db331c682fd0e4be7098e6acee5e8a293f824d41487c667a93705d415ca"},
+ {file = "coverage-7.13.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:edc7754932682d52cf6e7a71806e529ecd5ce660e630e8bd1d37109a2e5f63ba"},
+ {file = "coverage-7.13.3-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:d3a16d6398666510a6886f67f43d9537bfd0e13aca299688a19daa84f543122f"},
+ {file = "coverage-7.13.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:303d38b19626c1981e1bb067a9928236d88eb0e4479b18a74812f05a82071508"},
+ {file = "coverage-7.13.3-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:284e06eadfe15ddfee2f4ee56631f164ef897a7d7d5a15bca5f0bb88889fc5ba"},
+ {file = "coverage-7.13.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:d401f0864a1d3198422816878e4e84ca89ec1c1bf166ecc0ae01380a39b888cd"},
+ {file = "coverage-7.13.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:3f379b02c18a64de78c4ccdddf1c81c2c5ae1956c72dacb9133d7dd7809794ab"},
+ {file = "coverage-7.13.3-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:7a482f2da9086971efb12daca1d6547007ede3674ea06e16d7663414445c683e"},
+ {file = "coverage-7.13.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:562136b0d401992118d9b49fbee5454e16f95f85b120a4226a04d816e33fe024"},
+ {file = "coverage-7.13.3-cp314-cp314t-win32.whl", hash = "sha256:ca46e5c3be3b195098dd88711890b8011a9fa4feca942292bb84714ce5eab5d3"},
+ {file = "coverage-7.13.3-cp314-cp314t-win_amd64.whl", hash = "sha256:06d316dbb3d9fd44cca05b2dbcfbef22948493d63a1f28e828d43e6cc505fed8"},
+ {file = "coverage-7.13.3-cp314-cp314t-win_arm64.whl", hash = "sha256:299d66e9218193f9dc6e4880629ed7c4cd23486005166247c283fb98531656c3"},
+ {file = "coverage-7.13.3-py3-none-any.whl", hash = "sha256:90a8af9dba6429b2573199622d72e0ebf024d6276f16abce394ad4d181bb0910"},
+ {file = "coverage-7.13.3.tar.gz", hash = "sha256:f7f6182d3dfb8802c1747eacbfe611b669455b69b7c037484bb1efbbb56711ac"},
]
[package.extras]
@@ -934,14 +933,14 @@ tests = ["pytest", "pytest-cov", "pytest-xdist"]
[[package]]
name = "django"
-version = "5.2.9"
+version = "5.2.11"
description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design."
optional = false
python-versions = ">=3.10"
groups = ["main", "dev"]
files = [
- {file = "django-5.2.9-py3-none-any.whl", hash = "sha256:3a4ea88a70370557ab1930b332fd2887a9f48654261cdffda663fef5976bb00a"},
- {file = "django-5.2.9.tar.gz", hash = "sha256:16b5ccfc5e8c27e6c0561af551d2ea32852d7352c67d452ae3e76b4f6b2ca495"},
+ {file = "django-5.2.11-py3-none-any.whl", hash = "sha256:e7130df33ada9ab5e5e929bc19346a20fe383f5454acb2cc004508f242ee92c0"},
+ {file = "django-5.2.11.tar.gz", hash = "sha256:7f2d292ad8b9ee35e405d965fbbad293758b858c34bbf7f3df551aeeac6f02d3"},
]
[package.dependencies]
@@ -955,19 +954,19 @@ bcrypt = ["bcrypt"]
[[package]]
name = "django-stubs"
-version = "5.2.8"
+version = "5.2.9"
description = "Mypy stubs for Django"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "django_stubs-5.2.8-py3-none-any.whl", hash = "sha256:a3c63119fd7062ac63d58869698d07c9e5ec0561295c4e700317c54e8d26716c"},
- {file = "django_stubs-5.2.8.tar.gz", hash = "sha256:9bba597c9a8ed8c025cae4696803d5c8be1cf55bfc7648a084cbf864187e2f8b"},
+ {file = "django_stubs-5.2.9-py3-none-any.whl", hash = "sha256:2317a7130afdaa76f6ff7f623650d7f3bf1b6c86a60f95840e14e6ec6de1a7cd"},
+ {file = "django_stubs-5.2.9.tar.gz", hash = "sha256:c192257120b08785cfe6f2f1c91f1797aceae8e9daa689c336e52c91e8f6a493"},
]
[package.dependencies]
django = "*"
-django-stubs-ext = ">=5.2.8"
+django-stubs-ext = ">=5.2.9"
types-pyyaml = "*"
typing-extensions = ">=4.11.0"
@@ -978,38 +977,20 @@ redis = ["redis", "types-redis"]
[[package]]
name = "django-stubs-ext"
-version = "5.2.8"
+version = "5.2.9"
description = "Monkey-patching and extensions for django-stubs"
optional = false
python-versions = ">=3.10"
groups = ["dev"]
files = [
- {file = "django_stubs_ext-5.2.8-py3-none-any.whl", hash = "sha256:1dd5470c9675591362c78a157a3cf8aec45d0e7a7f0cf32f227a1363e54e0652"},
- {file = "django_stubs_ext-5.2.8.tar.gz", hash = "sha256:b39938c46d7a547cd84e4a6378dbe51a3dd64d70300459087229e5fee27e5c6b"},
+ {file = "django_stubs_ext-5.2.9-py3-none-any.whl", hash = "sha256:230c51575551b0165be40177f0f6805f1e3ebf799b835c85f5d64c371ca6cf71"},
+ {file = "django_stubs_ext-5.2.9.tar.gz", hash = "sha256:6db4054d1580657b979b7d391474719f1a978773e66c7070a5e246cd445a25a9"},
]
[package.dependencies]
django = "*"
typing-extensions = "*"
-[[package]]
-name = "exceptiongroup"
-version = "1.3.1"
-description = "Backport of PEP 654 (exception groups)"
-optional = false
-python-versions = ">=3.7"
-groups = ["main"]
-files = [
- {file = "exceptiongroup-1.3.1-py3-none-any.whl", hash = "sha256:a7a39a3bd276781e98394987d3a5701d0c4edffb633bb7a5144577f82c773598"},
- {file = "exceptiongroup-1.3.1.tar.gz", hash = "sha256:8b412432c6055b0b7d14c310000ae93352ed6754f70fa8f7c34141f91c4e3219"},
-]
-
-[package.dependencies]
-typing-extensions = {version = ">=4.6.0", markers = "python_version < \"3.13\""}
-
-[package.extras]
-test = ["pytest (>=6)"]
-
[[package]]
name = "fabric"
version = "2.7.1"
@@ -1033,26 +1014,26 @@ testing = ["mock (>=2.0.0,<3.0)"]
[[package]]
name = "fastapi"
-version = "0.124.0"
+version = "0.128.0"
description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "fastapi-0.124.0-py3-none-any.whl", hash = "sha256:91596bdc6dde303c318f06e8d2bc75eafb341fc793a0c9c92c0bc1db1ac52480"},
- {file = "fastapi-0.124.0.tar.gz", hash = "sha256:260cd178ad75e6d259991f2fd9b0fee924b224850079df576a3ba604ce58f4e6"},
+ {file = "fastapi-0.128.0-py3-none-any.whl", hash = "sha256:aebd93f9716ee3b4f4fcfe13ffb7cf308d99c9f3ab5622d8877441072561582d"},
+ {file = "fastapi-0.128.0.tar.gz", hash = "sha256:1cc179e1cef10a6be60ffe429f79b829dce99d8de32d7acb7e6c8dfdf7f2645a"},
]
[package.dependencies]
annotated-doc = ">=0.0.2"
-pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
+pydantic = ">=2.7.0"
starlette = ">=0.40.0,<0.51.0"
typing-extensions = ">=4.8.0"
[package.extras]
all = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=3.1.5)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
-standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
-standard-no-fastapi-cloud-cli = ["email-validator (>=2.0.0)", "fastapi-cli[standard-no-fastapi-cloud-cli] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
+standard = ["email-validator (>=2.0.0)", "fastapi-cli[standard] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
+standard-no-fastapi-cloud-cli = ["email-validator (>=2.0.0)", "fastapi-cli[standard-no-fastapi-cloud-cli] (>=0.0.8)", "httpx (>=0.23.0,<1.0.0)", "jinja2 (>=3.1.5)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.18)", "uvicorn[standard] (>=0.12.0)"]
[[package]]
name = "flake8"
@@ -1109,62 +1090,62 @@ test = ["pytest", "pytest-cov", "pytest-mpl", "pytest-subtests"]
[[package]]
name = "fonttools"
-version = "4.61.0"
+version = "4.61.1"
description = "Tools to manipulate font files"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "fonttools-4.61.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:dc25a4a9c1225653e4431a9413d0381b1c62317b0f543bdcec24e1991f612f33"},
- {file = "fonttools-4.61.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6b493c32d2555e9944ec1b911ea649ff8f01a649ad9cba6c118d6798e932b3f0"},
- {file = "fonttools-4.61.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ad751319dc532a79bdf628b8439af167181b4210a0cd28a8935ca615d9fdd727"},
- {file = "fonttools-4.61.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2de14557d113faa5fb519f7f29c3abe4d69c17fe6a5a2595cc8cda7338029219"},
- {file = "fonttools-4.61.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:59587bbe455dbdf75354a9dbca1697a35a8903e01fab4248d6b98a17032cee52"},
- {file = "fonttools-4.61.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:46cb3d9279f758ac0cf671dc3482da877104b65682679f01b246515db03dbb72"},
- {file = "fonttools-4.61.0-cp310-cp310-win32.whl", hash = "sha256:58b4f1b78dfbfe855bb8a6801b31b8cdcca0e2847ec769ad8e0b0b692832dd3b"},
- {file = "fonttools-4.61.0-cp310-cp310-win_amd64.whl", hash = "sha256:68704a8bbe0b61976262b255e90cde593dc0fe3676542d9b4d846bad2a890a76"},
- {file = "fonttools-4.61.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a32a16951cbf113d38f1dd8551b277b6e06e0f6f776fece0f99f746d739e1be3"},
- {file = "fonttools-4.61.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:328a9c227984bebaf69f3ac9062265f8f6acc7ddf2e4e344c63358579af0aa3d"},
- {file = "fonttools-4.61.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2f0bafc8a3b3749c69cc610e5aa3da832d39c2a37a68f03d18ec9a02ecaac04a"},
- {file = "fonttools-4.61.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b5ca59b7417d149cf24e4c1933c9f44b2957424fc03536f132346d5242e0ebe5"},
- {file = "fonttools-4.61.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:df8cbce85cf482eb01f4551edca978c719f099c623277bda8332e5dbe7dba09d"},
- {file = "fonttools-4.61.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7fb5b84f48a6a733ca3d7f41aa9551908ccabe8669ffe79586560abcc00a9cfd"},
- {file = "fonttools-4.61.0-cp311-cp311-win32.whl", hash = "sha256:787ef9dfd1ea9fe49573c272412ae5f479d78e671981819538143bec65863865"},
- {file = "fonttools-4.61.0-cp311-cp311-win_amd64.whl", hash = "sha256:14fafda386377b6131d9e448af42d0926bad47e038de0e5ba1d58c25d621f028"},
- {file = "fonttools-4.61.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:e24a1565c4e57111ec7f4915f8981ecbb61adf66a55f378fdc00e206059fcfef"},
- {file = "fonttools-4.61.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e2bfacb5351303cae9f072ccf3fc6ecb437a6f359c0606bae4b1ab6715201d87"},
- {file = "fonttools-4.61.0-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:0bdcf2e29d65c26299cc3d502f4612365e8b90a939f46cd92d037b6cb7bb544a"},
- {file = "fonttools-4.61.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e6cd0d9051b8ddaf7385f99dd82ec2a058e2b46cf1f1961e68e1ff20fcbb61af"},
- {file = "fonttools-4.61.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e074bc07c31406f45c418e17c1722e83560f181d122c412fa9e815df0ff74810"},
- {file = "fonttools-4.61.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5a9b78da5d5faa17e63b2404b77feeae105c1b7e75f26020ab7a27b76e02039f"},
- {file = "fonttools-4.61.0-cp312-cp312-win32.whl", hash = "sha256:9821ed77bb676736b88fa87a737c97b6af06e8109667e625a4f00158540ce044"},
- {file = "fonttools-4.61.0-cp312-cp312-win_amd64.whl", hash = "sha256:0011d640afa61053bc6590f9a3394bd222de7cfde19346588beabac374e9d8ac"},
- {file = "fonttools-4.61.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:ba774b8cbd8754f54b8eb58124e8bd45f736b2743325ab1a5229698942b9b433"},
- {file = "fonttools-4.61.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c84b430616ed73ce46e9cafd0bf0800e366a3e02fb7e1ad7c1e214dbe3862b1f"},
- {file = "fonttools-4.61.0-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:b2b734d8391afe3c682320840c8191de9bd24e7eb85768dd4dc06ed1b63dbb1b"},
- {file = "fonttools-4.61.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a5c5fff72bf31b0e558ed085e4fd7ed96eb85881404ecc39ed2a779e7cf724eb"},
- {file = "fonttools-4.61.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:14a290c5c93fcab76b7f451e6a4b7721b712d90b3b5ed6908f1abcf794e90d6d"},
- {file = "fonttools-4.61.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:13e3e20a5463bfeb77b3557d04b30bd6a96a6bb5c15c7b2e7908903e69d437a0"},
- {file = "fonttools-4.61.0-cp313-cp313-win32.whl", hash = "sha256:6781e7a4bb010be1cd69a29927b0305c86b843395f2613bdabe115f7d6ea7f34"},
- {file = "fonttools-4.61.0-cp313-cp313-win_amd64.whl", hash = "sha256:c53b47834ae41e8e4829171cc44fec0fdf125545a15f6da41776b926b9645a9a"},
- {file = "fonttools-4.61.0-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:96dfc9bc1f2302224e48e6ee37e656eddbab810b724b52e9d9c13a57a6abad01"},
- {file = "fonttools-4.61.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:3b2065d94e5d63aafc2591c8b6ccbdb511001d9619f1bca8ad39b745ebeb5efa"},
- {file = "fonttools-4.61.0-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:e0d87e81e4d869549585ba0beb3f033718501c1095004f5e6aef598d13ebc216"},
- {file = "fonttools-4.61.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1cfa2eb9bae650e58f0e8ad53c49d19a844d6034d6b259f30f197238abc1ccee"},
- {file = "fonttools-4.61.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:4238120002e68296d55e091411c09eab94e111c8ce64716d17df53fd0eb3bb3d"},
- {file = "fonttools-4.61.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b6ceac262cc62bec01b3bb59abccf41b24ef6580869e306a4e88b7e56bb4bdda"},
- {file = "fonttools-4.61.0-cp314-cp314-win32.whl", hash = "sha256:adbb4ecee1a779469a77377bbe490565effe8fce6fb2e6f95f064de58f8bac85"},
- {file = "fonttools-4.61.0-cp314-cp314-win_amd64.whl", hash = "sha256:02bdf8e04d1a70476564b8640380f04bb4ac74edc1fc71f1bacb840b3e398ee9"},
- {file = "fonttools-4.61.0-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:627216062d90ab0d98215176d8b9562c4dd5b61271d35f130bcd30f6a8aaa33a"},
- {file = "fonttools-4.61.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:7b446623c9cd5f14a59493818eaa80255eec2468c27d2c01b56e05357c263195"},
- {file = "fonttools-4.61.0-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:70e2a0c0182ee75e493ef33061bfebf140ea57e035481d2f95aa03b66c7a0e05"},
- {file = "fonttools-4.61.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9064b0f55b947e929ac669af5311ab1f26f750214db6dd9a0c97e091e918f486"},
- {file = "fonttools-4.61.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2cb5e45a824ce14b90510024d0d39dae51bd4fbb54c42a9334ea8c8cf4d95cbe"},
- {file = "fonttools-4.61.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:6e5ca8c62efdec7972dfdfd454415c4db49b89aeaefaaacada432f3b7eea9866"},
- {file = "fonttools-4.61.0-cp314-cp314t-win32.whl", hash = "sha256:63c7125d31abe3e61d7bb917329b5543c5b3448db95f24081a13aaf064360fc8"},
- {file = "fonttools-4.61.0-cp314-cp314t-win_amd64.whl", hash = "sha256:67d841aa272be5500de7f447c40d1d8452783af33b4c3599899319f6ef9ad3c1"},
- {file = "fonttools-4.61.0-py3-none-any.whl", hash = "sha256:276f14c560e6f98d24ef7f5f44438e55ff5a67f78fa85236b218462c9f5d0635"},
- {file = "fonttools-4.61.0.tar.gz", hash = "sha256:ec520a1f0c7758d7a858a00f090c1745f6cde6a7c5e76fb70ea4044a15f712e7"},
+ {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7c7db70d57e5e1089a274cbb2b1fd635c9a24de809a231b154965d415d6c6d24"},
+ {file = "fonttools-4.61.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5fe9fd43882620017add5eabb781ebfbc6998ee49b35bd7f8f79af1f9f99a958"},
+ {file = "fonttools-4.61.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d8db08051fc9e7d8bc622f2112511b8107d8f27cd89e2f64ec45e9825e8288da"},
+ {file = "fonttools-4.61.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a76d4cb80f41ba94a6691264be76435e5f72f2cb3cab0b092a6212855f71c2f6"},
+ {file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a13fc8aeb24bad755eea8f7f9d409438eb94e82cf86b08fe77a03fbc8f6a96b1"},
+ {file = "fonttools-4.61.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:b846a1fcf8beadeb9ea4f44ec5bdde393e2f1569e17d700bfc49cd69bde75881"},
+ {file = "fonttools-4.61.1-cp310-cp310-win32.whl", hash = "sha256:78a7d3ab09dc47ac1a363a493e6112d8cabed7ba7caad5f54dbe2f08676d1b47"},
+ {file = "fonttools-4.61.1-cp310-cp310-win_amd64.whl", hash = "sha256:eff1ac3cc66c2ac7cda1e64b4e2f3ffef474b7335f92fc3833fc632d595fcee6"},
+ {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:c6604b735bb12fef8e0efd5578c9fb5d3d8532d5001ea13a19cddf295673ee09"},
+ {file = "fonttools-4.61.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5ce02f38a754f207f2f06557523cd39a06438ba3aafc0639c477ac409fc64e37"},
+ {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:77efb033d8d7ff233385f30c62c7c79271c8885d5c9657d967ede124671bbdfb"},
+ {file = "fonttools-4.61.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:75c1a6dfac6abd407634420c93864a1e274ebc1c7531346d9254c0d8f6ca00f9"},
+ {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0de30bfe7745c0d1ffa2b0b7048fb7123ad0d71107e10ee090fa0b16b9452e87"},
+ {file = "fonttools-4.61.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:58b0ee0ab5b1fc9921eccfe11d1435added19d6494dde14e323f25ad2bc30c56"},
+ {file = "fonttools-4.61.1-cp311-cp311-win32.whl", hash = "sha256:f79b168428351d11e10c5aeb61a74e1851ec221081299f4cf56036a95431c43a"},
+ {file = "fonttools-4.61.1-cp311-cp311-win_amd64.whl", hash = "sha256:fe2efccb324948a11dd09d22136fe2ac8a97d6c1347cf0b58a911dcd529f66b7"},
+ {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:f3cb4a569029b9f291f88aafc927dd53683757e640081ca8c412781ea144565e"},
+ {file = "fonttools-4.61.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:41a7170d042e8c0024703ed13b71893519a1a6d6e18e933e3ec7507a2c26a4b2"},
+ {file = "fonttools-4.61.1-cp312-cp312-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:10d88e55330e092940584774ee5e8a6971b01fc2f4d3466a1d6c158230880796"},
+ {file = "fonttools-4.61.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:15acc09befd16a0fb8a8f62bc147e1a82817542d72184acca9ce6e0aeda9fa6d"},
+ {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:e6bcdf33aec38d16508ce61fd81838f24c83c90a1d1b8c68982857038673d6b8"},
+ {file = "fonttools-4.61.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5fade934607a523614726119164ff621e8c30e8fa1ffffbbd358662056ba69f0"},
+ {file = "fonttools-4.61.1-cp312-cp312-win32.whl", hash = "sha256:75da8f28eff26defba42c52986de97b22106cb8f26515b7c22443ebc9c2d3261"},
+ {file = "fonttools-4.61.1-cp312-cp312-win_amd64.whl", hash = "sha256:497c31ce314219888c0e2fce5ad9178ca83fe5230b01a5006726cdf3ac9f24d9"},
+ {file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:8c56c488ab471628ff3bfa80964372fc13504ece601e0d97a78ee74126b2045c"},
+ {file = "fonttools-4.61.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:dc492779501fa723b04d0ab1f5be046797fee17d27700476edc7ee9ae535a61e"},
+ {file = "fonttools-4.61.1-cp313-cp313-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:64102ca87e84261419c3747a0d20f396eb024bdbeb04c2bfb37e2891f5fadcb5"},
+ {file = "fonttools-4.61.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4c1b526c8d3f615a7b1867f38a9410849c8f4aef078535742198e942fba0e9bd"},
+ {file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:41ed4b5ec103bd306bb68f81dc166e77409e5209443e5773cb4ed837bcc9b0d3"},
+ {file = "fonttools-4.61.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b501c862d4901792adaec7c25b1ecc749e2662543f68bb194c42ba18d6eec98d"},
+ {file = "fonttools-4.61.1-cp313-cp313-win32.whl", hash = "sha256:4d7092bb38c53bbc78e9255a59158b150bcdc115a1e3b3ce0b5f267dc35dd63c"},
+ {file = "fonttools-4.61.1-cp313-cp313-win_amd64.whl", hash = "sha256:21e7c8d76f62ab13c9472ccf74515ca5b9a761d1bde3265152a6dc58700d895b"},
+ {file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_universal2.whl", hash = "sha256:fff4f534200a04b4a36e7ae3cb74493afe807b517a09e99cb4faa89a34ed6ecd"},
+ {file = "fonttools-4.61.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:d9203500f7c63545b4ce3799319fe4d9feb1a1b89b28d3cb5abd11b9dd64147e"},
+ {file = "fonttools-4.61.1-cp314-cp314-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:fa646ecec9528bef693415c79a86e733c70a4965dd938e9a226b0fc64c9d2e6c"},
+ {file = "fonttools-4.61.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f35ad7805edba3aac1a3710d104592df59f4b957e30108ae0ba6c10b11dd75"},
+ {file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b931ae8f62db78861b0ff1ac017851764602288575d65b8e8ff1963fed419063"},
+ {file = "fonttools-4.61.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b148b56f5de675ee16d45e769e69f87623a4944f7443850bf9a9376e628a89d2"},
+ {file = "fonttools-4.61.1-cp314-cp314-win32.whl", hash = "sha256:9b666a475a65f4e839d3d10473fad6d47e0a9db14a2f4a224029c5bfde58ad2c"},
+ {file = "fonttools-4.61.1-cp314-cp314-win_amd64.whl", hash = "sha256:4f5686e1fe5fce75d82d93c47a438a25bf0d1319d2843a926f741140b2b16e0c"},
+ {file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_universal2.whl", hash = "sha256:e76ce097e3c57c4bcb67c5aa24a0ecdbd9f74ea9219997a707a4061fbe2707aa"},
+ {file = "fonttools-4.61.1-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9cfef3ab326780c04d6646f68d4b4742aae222e8b8ea1d627c74e38afcbc9d91"},
+ {file = "fonttools-4.61.1-cp314-cp314t-manylinux1_x86_64.manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:a75c301f96db737e1c5ed5fd7d77d9c34466de16095a266509e13da09751bd19"},
+ {file = "fonttools-4.61.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:91669ccac46bbc1d09e9273546181919064e8df73488ea087dcac3e2968df9ba"},
+ {file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:c33ab3ca9d3ccd581d58e989d67554e42d8d4ded94ab3ade3508455fe70e65f7"},
+ {file = "fonttools-4.61.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:664c5a68ec406f6b1547946683008576ef8b38275608e1cee6c061828171c118"},
+ {file = "fonttools-4.61.1-cp314-cp314t-win32.whl", hash = "sha256:aed04cabe26f30c1647ef0e8fbb207516fd40fe9472e9439695f5c6998e60ac5"},
+ {file = "fonttools-4.61.1-cp314-cp314t-win_amd64.whl", hash = "sha256:2180f14c141d2f0f3da43f3a81bc8aa4684860f6b0e6f9e165a4831f24e6a23b"},
+ {file = "fonttools-4.61.1-py3-none-any.whl", hash = "sha256:17d2bf5d541add43822bcf0c43d7d847b160c9bb01d15d5007d84e2217aaa371"},
+ {file = "fonttools-4.61.1.tar.gz", hash = "sha256:6675329885c44657f826ef01d9e4fb33b9158e9d93c537d84ad8399539bc6f69"},
]
[package.extras]
@@ -1375,21 +1356,21 @@ files = [
[[package]]
name = "kombu"
-version = "5.6.1"
+version = "5.6.2"
description = "Messaging library for Python."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "kombu-5.6.1-py3-none-any.whl", hash = "sha256:b69e3f5527ec32fc5196028a36376501682973e9620d6175d1c3d4eaf7e95409"},
- {file = "kombu-5.6.1.tar.gz", hash = "sha256:90f1febb57ad4f53ca327a87598191b2520e0c793c75ea3b88d98e3b111282e4"},
+ {file = "kombu-5.6.2-py3-none-any.whl", hash = "sha256:efcfc559da324d41d61ca311b0c64965ea35b4c55cc04ee36e55386145dace93"},
+ {file = "kombu-5.6.2.tar.gz", hash = "sha256:8060497058066c6f5aed7c26d7cd0d3b574990b09de842a8c5aaed0b92cc5a55"},
]
[package.dependencies]
amqp = ">=5.1.1,<6.0.0"
packaging = "*"
redis = {version = ">=4.5.2,<4.5.5 || >4.5.5,<5.0.2 || >5.0.2,<6.5", optional = true, markers = "extra == \"redis\""}
-tzdata = {version = ">=2025.2", markers = "python_version >= \"3.9\""}
+tzdata = ">=2025.2"
vine = "5.1.0"
[package.extras]
@@ -1412,88 +1393,89 @@ zookeeper = ["kazoo (>=2.8.0)"]
[[package]]
name = "librt"
-version = "0.7.3"
+version = "0.7.8"
description = "Mypyc runtime library"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
-files = [
- {file = "librt-0.7.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:2682162855a708e3270eba4b92026b93f8257c3e65278b456c77631faf0f4f7a"},
- {file = "librt-0.7.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:440c788f707c061d237c1e83edf6164ff19f5c0f823a3bf054e88804ebf971ec"},
- {file = "librt-0.7.3-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:399938edbd3d78339f797d685142dd8a623dfaded023cf451033c85955e4838a"},
- {file = "librt-0.7.3-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1975eda520957c6e0eb52d12968dd3609ffb7eef05d4223d097893d6daf1d8a7"},
- {file = "librt-0.7.3-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f9da128d0edf990cf0d2ca011b02cd6f639e79286774bd5b0351245cbb5a6e51"},
- {file = "librt-0.7.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:e19acfde38cb532a560b98f473adc741c941b7a9bc90f7294bc273d08becb58b"},
- {file = "librt-0.7.3-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:7b4f57f7a0c65821c5441d98c47ff7c01d359b1e12328219709bdd97fdd37f90"},
- {file = "librt-0.7.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:256793988bff98040de23c57cf36e1f4c2f2dc3dcd17537cdac031d3b681db71"},
- {file = "librt-0.7.3-cp310-cp310-win32.whl", hash = "sha256:fcb72249ac4ea81a7baefcbff74df7029c3cb1cf01a711113fa052d563639c9c"},
- {file = "librt-0.7.3-cp310-cp310-win_amd64.whl", hash = "sha256:4887c29cadbdc50640179e3861c276325ff2986791e6044f73136e6e798ff806"},
- {file = "librt-0.7.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:687403cced6a29590e6be6964463835315905221d797bc5c934a98750fe1a9af"},
- {file = "librt-0.7.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:24d70810f6e2ea853ff79338001533716b373cc0f63e2a0be5bc96129edb5fb5"},
- {file = "librt-0.7.3-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:bf8c7735fbfc0754111f00edda35cf9e98a8d478de6c47b04eaa9cef4300eaa7"},
- {file = "librt-0.7.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e32d43610dff472eab939f4d7fbdd240d1667794192690433672ae22d7af8445"},
- {file = "librt-0.7.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:adeaa886d607fb02563c1f625cf2ee58778a2567c0c109378da8f17ec3076ad7"},
- {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:572a24fc5958c61431da456a0ef1eeea6b4989d81eeb18b8e5f1f3077592200b"},
- {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:6488e69d408b492e08bfb68f20c4a899a354b4386a446ecd490baff8d0862720"},
- {file = "librt-0.7.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:ed028fc3d41adda916320712838aec289956c89b4f0a361ceadf83a53b4c047a"},
- {file = "librt-0.7.3-cp311-cp311-win32.whl", hash = "sha256:2cf9d73499486ce39eebbff5f42452518cc1f88d8b7ea4a711ab32962b176ee2"},
- {file = "librt-0.7.3-cp311-cp311-win_amd64.whl", hash = "sha256:35f1609e3484a649bb80431310ddbec81114cd86648f1d9482bc72a3b86ded2e"},
- {file = "librt-0.7.3-cp311-cp311-win_arm64.whl", hash = "sha256:550fdbfbf5bba6a2960b27376ca76d6aaa2bd4b1a06c4255edd8520c306fcfc0"},
- {file = "librt-0.7.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fa9ac2e49a6bee56e47573a6786cb635e128a7b12a0dc7851090037c0d397a3"},
- {file = "librt-0.7.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2e980cf1ed1a2420a6424e2ed884629cdead291686f1048810a817de07b5eb18"},
- {file = "librt-0.7.3-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e094e445c37c57e9ec612847812c301840239d34ccc5d153a982fa9814478c60"},
- {file = "librt-0.7.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aca73d70c3f553552ba9133d4a09e767dcfeee352d8d8d3eb3f77e38a3beb3ed"},
- {file = "librt-0.7.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c634a0a6db395fdaba0361aa78395597ee72c3aad651b9a307a3a7eaf5efd67e"},
- {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:a59a69deeb458c858b8fea6acf9e2acd5d755d76cd81a655256bc65c20dfff5b"},
- {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:d91e60ac44bbe3a77a67af4a4c13114cbe9f6d540337ce22f2c9eaf7454ca71f"},
- {file = "librt-0.7.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:703456146dc2bf430f7832fd1341adac5c893ec3c1430194fdcefba00012555c"},
- {file = "librt-0.7.3-cp312-cp312-win32.whl", hash = "sha256:b7c1239b64b70be7759554ad1a86288220bbb04d68518b527783c4ad3fb4f80b"},
- {file = "librt-0.7.3-cp312-cp312-win_amd64.whl", hash = "sha256:ef59c938f72bdbc6ab52dc50f81d0637fde0f194b02d636987cea2ab30f8f55a"},
- {file = "librt-0.7.3-cp312-cp312-win_arm64.whl", hash = "sha256:ff21c554304e8226bf80c3a7754be27c6c3549a9fec563a03c06ee8f494da8fc"},
- {file = "librt-0.7.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:56f2a47beda8409061bc1c865bef2d4bd9ff9255219402c0817e68ab5ad89aed"},
- {file = "librt-0.7.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:14569ac5dd38cfccf0a14597a88038fb16811a6fede25c67b79c6d50fc2c8fdc"},
- {file = "librt-0.7.3-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6038ccbd5968325a5d6fd393cf6e00b622a8de545f0994b89dd0f748dcf3e19e"},
- {file = "librt-0.7.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d39079379a9a28e74f4d57dc6357fa310a1977b51ff12239d7271ec7e71d67f5"},
- {file = "librt-0.7.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8837d5a52a2d7aa9f4c3220a8484013aed1d8ad75240d9a75ede63709ef89055"},
- {file = "librt-0.7.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:399bbd7bcc1633c3e356ae274a1deb8781c7bf84d9c7962cc1ae0c6e87837292"},
- {file = "librt-0.7.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:8d8cf653e798ee4c4e654062b633db36984a1572f68c3aa25e364a0ddfbbb910"},
- {file = "librt-0.7.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:2f03484b54bf4ae80ab2e504a8d99d20d551bfe64a7ec91e218010b467d77093"},
- {file = "librt-0.7.3-cp313-cp313-win32.whl", hash = "sha256:44b3689b040df57f492e02cd4f0bacd1b42c5400e4b8048160c9d5e866de8abe"},
- {file = "librt-0.7.3-cp313-cp313-win_amd64.whl", hash = "sha256:6b407c23f16ccc36614c136251d6b32bf30de7a57f8e782378f1107be008ddb0"},
- {file = "librt-0.7.3-cp313-cp313-win_arm64.whl", hash = "sha256:abfc57cab3c53c4546aee31859ef06753bfc136c9d208129bad23e2eca39155a"},
- {file = "librt-0.7.3-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:120dd21d46ff875e849f1aae19346223cf15656be489242fe884036b23d39e93"},
- {file = "librt-0.7.3-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:1617bea5ab31266e152871208502ee943cb349c224846928a1173c864261375e"},
- {file = "librt-0.7.3-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:93b2a1f325fefa1482516ced160c8c7b4b8d53226763fa6c93d151fa25164207"},
- {file = "librt-0.7.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3d4801db8354436fd3936531e7f0e4feb411f62433a6b6cb32bb416e20b529f"},
- {file = "librt-0.7.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11ad45122bbed42cfc8b0597450660126ef28fd2d9ae1a219bc5af8406f95678"},
- {file = "librt-0.7.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:6b4e7bff1d76dd2b46443078519dc75df1b5e01562345f0bb740cea5266d8218"},
- {file = "librt-0.7.3-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:d86f94743a11873317094326456b23f8a5788bad9161fd2f0e52088c33564620"},
- {file = "librt-0.7.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:754a0d09997095ad764ccef050dd5bf26cbf457aab9effcba5890dad081d879e"},
- {file = "librt-0.7.3-cp314-cp314-win32.whl", hash = "sha256:fbd7351d43b80d9c64c3cfcb50008f786cc82cba0450e8599fdd64f264320bd3"},
- {file = "librt-0.7.3-cp314-cp314-win_amd64.whl", hash = "sha256:d376a35c6561e81d2590506804b428fc1075fcc6298fc5bb49b771534c0ba010"},
- {file = "librt-0.7.3-cp314-cp314-win_arm64.whl", hash = "sha256:cbdb3f337c88b43c3b49ca377731912c101178be91cb5071aac48faa898e6f8e"},
- {file = "librt-0.7.3-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:9f0e0927efe87cd42ad600628e595a1a0aa1c64f6d0b55f7e6059079a428641a"},
- {file = "librt-0.7.3-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:020c6db391268bcc8ce75105cb572df8cb659a43fd347366aaa407c366e5117a"},
- {file = "librt-0.7.3-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7af7785f5edd1f418da09a8cdb9ec84b0213e23d597413e06525340bcce1ea4f"},
- {file = "librt-0.7.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8ccadf260bb46a61b9c7e89e2218f6efea9f3eeaaab4e3d1f58571890e54858e"},
- {file = "librt-0.7.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d9883b2d819ce83f87ba82a746c81d14ada78784db431e57cc9719179847376e"},
- {file = "librt-0.7.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:59cb0470612d21fa1efddfa0dd710756b50d9c7fb6c1236bbf8ef8529331dc70"},
- {file = "librt-0.7.3-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:1fe603877e1865b5fd047a5e40379509a4a60204aa7aa0f72b16f7a41c3f0712"},
- {file = "librt-0.7.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5460d99ed30f043595bbdc888f542bad2caeb6226b01c33cda3ae444e8f82d42"},
- {file = "librt-0.7.3-cp314-cp314t-win32.whl", hash = "sha256:d09f677693328503c9e492e33e9601464297c01f9ebd966ea8fc5308f3069bfd"},
- {file = "librt-0.7.3-cp314-cp314t-win_amd64.whl", hash = "sha256:25711f364c64cab2c910a0247e90b51421e45dbc8910ceeb4eac97a9e132fc6f"},
- {file = "librt-0.7.3-cp314-cp314t-win_arm64.whl", hash = "sha256:a9f9b661f82693eb56beb0605156c7fca57f535704ab91837405913417d6990b"},
- {file = "librt-0.7.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cd8551aa21df6c60baa2624fd086ae7486bdde00c44097b32e1d1b1966e365e0"},
- {file = "librt-0.7.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:6eb9295c730e26b849ed1f4022735f36863eb46b14b6e10604c1c39b8b5efaea"},
- {file = "librt-0.7.3-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:3edbf257c40d21a42615e9e332a6b10a8bacaaf58250aed8552a14a70efd0d65"},
- {file = "librt-0.7.3-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7b29e97273bd6999e2bfe9fe3531b1f4f64effd28327bced048a33e49b99674a"},
- {file = "librt-0.7.3-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e40520c37926166c24d0c2e0f3bc3a5f46646c34bdf7b4ea9747c297d6ee809"},
- {file = "librt-0.7.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:6bdd9adfca615903578d2060ee8a6eb1c24eaf54919ff0ddc820118e5718931b"},
- {file = "librt-0.7.3-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f57aca20e637750a2c18d979f7096e2c2033cc40cf7ed201494318de1182f135"},
- {file = "librt-0.7.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:cad9971881e4fec00d96af7eaf4b63aa7a595696fc221808b0d3ce7ca9743258"},
- {file = "librt-0.7.3-cp39-cp39-win32.whl", hash = "sha256:170cdb8436188347af17bf9cccf3249ba581c933ed56d926497119d4cf730cec"},
- {file = "librt-0.7.3-cp39-cp39-win_amd64.whl", hash = "sha256:b278a9248a4e3260fee3db7613772ca9ab6763a129d6d6f29555e2f9b168216d"},
- {file = "librt-0.7.3.tar.gz", hash = "sha256:3ec50cf65235ff5c02c5b747748d9222e564ad48597122a361269dd3aa808798"},
+markers = "platform_python_implementation != \"PyPy\""
+files = [
+ {file = "librt-0.7.8-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:b45306a1fc5f53c9330fbee134d8b3227fe5da2ab09813b892790400aa49352d"},
+ {file = "librt-0.7.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:864c4b7083eeee250ed55135d2127b260d7eb4b5e953a9e5df09c852e327961b"},
+ {file = "librt-0.7.8-cp310-cp310-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:6938cc2de153bc927ed8d71c7d2f2ae01b4e96359126c602721340eb7ce1a92d"},
+ {file = "librt-0.7.8-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:66daa6ac5de4288a5bbfbe55b4caa7bf0cd26b3269c7a476ffe8ce45f837f87d"},
+ {file = "librt-0.7.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4864045f49dc9c974dadb942ac56a74cd0479a2aafa51ce272c490a82322ea3c"},
+ {file = "librt-0.7.8-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a36515b1328dc5b3ffce79fe204985ca8572525452eacabee2166f44bb387b2c"},
+ {file = "librt-0.7.8-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b7e7f140c5169798f90b80d6e607ed2ba5059784968a004107c88ad61fb3641d"},
+ {file = "librt-0.7.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ff71447cb778a4f772ddc4ce360e6ba9c95527ed84a52096bd1bbf9fee2ec7c0"},
+ {file = "librt-0.7.8-cp310-cp310-win32.whl", hash = "sha256:047164e5f68b7a8ebdf9fae91a3c2161d3192418aadd61ddd3a86a56cbe3dc85"},
+ {file = "librt-0.7.8-cp310-cp310-win_amd64.whl", hash = "sha256:d6f254d096d84156a46a84861183c183d30734e52383602443292644d895047c"},
+ {file = "librt-0.7.8-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ff3e9c11aa260c31493d4b3197d1e28dd07768594a4f92bec4506849d736248f"},
+ {file = "librt-0.7.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ddb52499d0b3ed4aa88746aaf6f36a08314677d5c346234c3987ddc506404eac"},
+ {file = "librt-0.7.8-cp311-cp311-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:e9c0afebbe6ce177ae8edba0c7c4d626f2a0fc12c33bb993d163817c41a7a05c"},
+ {file = "librt-0.7.8-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:631599598e2c76ded400c0a8722dec09217c89ff64dc54b060f598ed68e7d2a8"},
+ {file = "librt-0.7.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9c1ba843ae20db09b9d5c80475376168feb2640ce91cd9906414f23cc267a1ff"},
+ {file = "librt-0.7.8-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b5b007bb22ea4b255d3ee39dfd06d12534de2fcc3438567d9f48cdaf67ae1ae3"},
+ {file = "librt-0.7.8-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:dbd79caaf77a3f590cbe32dc2447f718772d6eea59656a7dcb9311161b10fa75"},
+ {file = "librt-0.7.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:87808a8d1e0bd62a01cafc41f0fd6818b5a5d0ca0d8a55326a81643cdda8f873"},
+ {file = "librt-0.7.8-cp311-cp311-win32.whl", hash = "sha256:31724b93baa91512bd0a376e7cf0b59d8b631ee17923b1218a65456fa9bda2e7"},
+ {file = "librt-0.7.8-cp311-cp311-win_amd64.whl", hash = "sha256:978e8b5f13e52cf23a9e80f3286d7546baa70bc4ef35b51d97a709d0b28e537c"},
+ {file = "librt-0.7.8-cp311-cp311-win_arm64.whl", hash = "sha256:20e3946863d872f7cabf7f77c6c9d370b8b3d74333d3a32471c50d3a86c0a232"},
+ {file = "librt-0.7.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:9b6943885b2d49c48d0cff23b16be830ba46b0152d98f62de49e735c6e655a63"},
+ {file = "librt-0.7.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:46ef1f4b9b6cc364b11eea0ecc0897314447a66029ee1e55859acb3dd8757c93"},
+ {file = "librt-0.7.8-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:907ad09cfab21e3c86e8f1f87858f7049d1097f77196959c033612f532b4e592"},
+ {file = "librt-0.7.8-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2991b6c3775383752b3ca0204842743256f3ad3deeb1d0adc227d56b78a9a850"},
+ {file = "librt-0.7.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:03679b9856932b8c8f674e87aa3c55ea11c9274301f76ae8dc4d281bda55cf62"},
+ {file = "librt-0.7.8-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:3968762fec1b2ad34ce57458b6de25dbb4142713e9ca6279a0d352fa4e9f452b"},
+ {file = "librt-0.7.8-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:bb7a7807523a31f03061288cc4ffc065d684c39db7644c676b47d89553c0d714"},
+ {file = "librt-0.7.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ad64a14b1e56e702e19b24aae108f18ad1bf7777f3af5fcd39f87d0c5a814449"},
+ {file = "librt-0.7.8-cp312-cp312-win32.whl", hash = "sha256:0241a6ed65e6666236ea78203a73d800dbed896cf12ae25d026d75dc1fcd1dac"},
+ {file = "librt-0.7.8-cp312-cp312-win_amd64.whl", hash = "sha256:6db5faf064b5bab9675c32a873436b31e01d66ca6984c6f7f92621656033a708"},
+ {file = "librt-0.7.8-cp312-cp312-win_arm64.whl", hash = "sha256:57175aa93f804d2c08d2edb7213e09276bd49097611aefc37e3fa38d1fb99ad0"},
+ {file = "librt-0.7.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4c3995abbbb60b3c129490fa985dfe6cac11d88fc3c36eeb4fb1449efbbb04fc"},
+ {file = "librt-0.7.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:44e0c2cbc9bebd074cf2cdbe472ca185e824be4e74b1c63a8e934cea674bebf2"},
+ {file = "librt-0.7.8-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:4d2f1e492cae964b3463a03dc77a7fe8742f7855d7258c7643f0ee32b6651dd3"},
+ {file = "librt-0.7.8-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:451e7ffcef8f785831fdb791bd69211f47e95dc4c6ddff68e589058806f044c6"},
+ {file = "librt-0.7.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3469e1af9f1380e093ae06bedcbdd11e407ac0b303a56bbe9afb1d6824d4982d"},
+ {file = "librt-0.7.8-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f11b300027ce19a34f6d24ebb0a25fd0e24a9d53353225a5c1e6cadbf2916b2e"},
+ {file = "librt-0.7.8-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:4adc73614f0d3c97874f02f2c7fd2a27854e7e24ad532ea6b965459c5b757eca"},
+ {file = "librt-0.7.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:60c299e555f87e4c01b2eca085dfccda1dde87f5a604bb45c2906b8305819a93"},
+ {file = "librt-0.7.8-cp313-cp313-win32.whl", hash = "sha256:b09c52ed43a461994716082ee7d87618096851319bf695d57ec123f2ab708951"},
+ {file = "librt-0.7.8-cp313-cp313-win_amd64.whl", hash = "sha256:f8f4a901a3fa28969d6e4519deceab56c55a09d691ea7b12ca830e2fa3461e34"},
+ {file = "librt-0.7.8-cp313-cp313-win_arm64.whl", hash = "sha256:43d4e71b50763fcdcf64725ac680d8cfa1706c928b844794a7aa0fa9ac8e5f09"},
+ {file = "librt-0.7.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:be927c3c94c74b05128089a955fba86501c3b544d1d300282cc1b4bd370cb418"},
+ {file = "librt-0.7.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:7b0803e9008c62a7ef79058233db7ff6f37a9933b8f2573c05b07ddafa226611"},
+ {file = "librt-0.7.8-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:79feb4d00b2a4e0e05c9c56df707934f41fcb5fe53fd9efb7549068d0495b758"},
+ {file = "librt-0.7.8-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9122094e3f24aa759c38f46bd8863433820654927370250f460ae75488b66ea"},
+ {file = "librt-0.7.8-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7e03bea66af33c95ce3addf87a9bf1fcad8d33e757bc479957ddbc0e4f7207ac"},
+ {file = "librt-0.7.8-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f1ade7f31675db00b514b98f9ab9a7698c7282dad4be7492589109471852d398"},
+ {file = "librt-0.7.8-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:a14229ac62adcf1b90a15992f1ab9c69ae8b99ffb23cb64a90878a6e8a2f5b81"},
+ {file = "librt-0.7.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:5bcaaf624fd24e6a0cb14beac37677f90793a96864c67c064a91458611446e83"},
+ {file = "librt-0.7.8-cp314-cp314-win32.whl", hash = "sha256:7aa7d5457b6c542ecaed79cec4ad98534373c9757383973e638ccced0f11f46d"},
+ {file = "librt-0.7.8-cp314-cp314-win_amd64.whl", hash = "sha256:3d1322800771bee4a91f3b4bd4e49abc7d35e65166821086e5afd1e6c0d9be44"},
+ {file = "librt-0.7.8-cp314-cp314-win_arm64.whl", hash = "sha256:5363427bc6a8c3b1719f8f3845ea53553d301382928a86e8fab7984426949bce"},
+ {file = "librt-0.7.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:ca916919793a77e4a98d4a1701e345d337ce53be4a16620f063191f7322ac80f"},
+ {file = "librt-0.7.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:54feb7b4f2f6706bb82325e836a01be805770443e2400f706e824e91f6441dde"},
+ {file = "librt-0.7.8-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:39a4c76fee41007070f872b648cc2f711f9abf9a13d0c7162478043377b52c8e"},
+ {file = "librt-0.7.8-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ac9c8a458245c7de80bc1b9765b177055efff5803f08e548dd4bb9ab9a8d789b"},
+ {file = "librt-0.7.8-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:95b67aa7eff150f075fda09d11f6bfb26edffd300f6ab1666759547581e8f666"},
+ {file = "librt-0.7.8-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:535929b6eff670c593c34ff435d5440c3096f20fa72d63444608a5aef64dd581"},
+ {file = "librt-0.7.8-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:63937bd0f4d1cb56653dc7ae900d6c52c41f0015e25aaf9902481ee79943b33a"},
+ {file = "librt-0.7.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:cf243da9e42d914036fd362ac3fa77d80a41cadcd11ad789b1b5eec4daaf67ca"},
+ {file = "librt-0.7.8-cp314-cp314t-win32.whl", hash = "sha256:171ca3a0a06c643bd0a2f62a8944e1902c94aa8e5da4db1ea9a8daf872685365"},
+ {file = "librt-0.7.8-cp314-cp314t-win_amd64.whl", hash = "sha256:445b7304145e24c60288a2f172b5ce2ca35c0f81605f5299f3fa567e189d2e32"},
+ {file = "librt-0.7.8-cp314-cp314t-win_arm64.whl", hash = "sha256:8766ece9de08527deabcd7cb1b4f1a967a385d26e33e536d6d8913db6ef74f06"},
+ {file = "librt-0.7.8-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c7e8f88f79308d86d8f39c491773cbb533d6cb7fa6476f35d711076ee04fceb6"},
+ {file = "librt-0.7.8-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:389bd25a0db916e1d6bcb014f11aa9676cedaa485e9ec3752dfe19f196fd377b"},
+ {file = "librt-0.7.8-cp39-cp39-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:73fd300f501a052f2ba52ede721232212f3b06503fa12665408ecfc9d8fd149c"},
+ {file = "librt-0.7.8-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d772edc6a5f7835635c7562f6688e031f0b97e31d538412a852c49c9a6c92d5"},
+ {file = "librt-0.7.8-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bfde8a130bd0f239e45503ab39fab239ace094d63ee1d6b67c25a63d741c0f71"},
+ {file = "librt-0.7.8-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:fdec6e2368ae4f796fc72fad7fd4bd1753715187e6d870932b0904609e7c878e"},
+ {file = "librt-0.7.8-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:00105e7d541a8f2ee5be52caacea98a005e0478cfe78c8080fbb7b5d2b340c63"},
+ {file = "librt-0.7.8-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c6f8947d3dfd7f91066c5b4385812c18be26c9d5a99ca56667547f2c39149d94"},
+ {file = "librt-0.7.8-cp39-cp39-win32.whl", hash = "sha256:41d7bb1e07916aeb12ae4a44e3025db3691c4149ab788d0315781b4d29b86afb"},
+ {file = "librt-0.7.8-cp39-cp39-win_amd64.whl", hash = "sha256:e90a8e237753c83b8e484d478d9a996dc5e39fd5bd4c6ce32563bc8123f132be"},
+ {file = "librt-0.7.8.tar.gz", hash = "sha256:1a4ede613941d9c3470b0368be851df6bb78ab218635512d0370b27a277a0862"},
]
[[package]]
@@ -1513,67 +1495,67 @@ url = "../magnettools-1.1.0-cp311-cp311-linux_x86_64.whl"
[[package]]
name = "matplotlib"
-version = "3.10.7"
+version = "3.10.8"
description = "Python plotting package"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "matplotlib-3.10.7-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:7ac81eee3b7c266dd92cee1cd658407b16c57eed08c7421fa354ed68234de380"},
- {file = "matplotlib-3.10.7-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:667ecd5d8d37813a845053d8f5bf110b534c3c9f30e69ebd25d4701385935a6d"},
- {file = "matplotlib-3.10.7-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cc1c51b846aca49a5a8b44fbba6a92d583a35c64590ad9e1e950dc88940a4297"},
- {file = "matplotlib-3.10.7-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a11c2e9e72e7de09b7b72e62f3df23317c888299c875e2b778abf1eda8c0a42"},
- {file = "matplotlib-3.10.7-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f19410b486fdd139885ace124e57f938c1e6a3210ea13dd29cab58f5d4bc12c7"},
- {file = "matplotlib-3.10.7-cp310-cp310-win_amd64.whl", hash = "sha256:b498e9e4022f93de2d5a37615200ca01297ceebbb56fe4c833f46862a490f9e3"},
- {file = "matplotlib-3.10.7-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:53b492410a6cd66c7a471de6c924f6ede976e963c0f3097a3b7abfadddc67d0a"},
- {file = "matplotlib-3.10.7-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d9749313deb729f08207718d29c86246beb2ea3fdba753595b55901dee5d2fd6"},
- {file = "matplotlib-3.10.7-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:2222c7ba2cbde7fe63032769f6eb7e83ab3227f47d997a8453377709b7fe3a5a"},
- {file = "matplotlib-3.10.7-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e91f61a064c92c307c5a9dc8c05dc9f8a68f0a3be199d9a002a0622e13f874a1"},
- {file = "matplotlib-3.10.7-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:6f1851eab59ca082c95df5a500106bad73672645625e04538b3ad0f69471ffcc"},
- {file = "matplotlib-3.10.7-cp311-cp311-win_amd64.whl", hash = "sha256:6516ce375109c60ceec579e699524e9d504cd7578506f01150f7a6bc174a775e"},
- {file = "matplotlib-3.10.7-cp311-cp311-win_arm64.whl", hash = "sha256:b172db79759f5f9bc13ef1c3ef8b9ee7b37b0247f987fbbbdaa15e4f87fd46a9"},
- {file = "matplotlib-3.10.7-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:7a0edb7209e21840e8361e91ea84ea676658aa93edd5f8762793dec77a4a6748"},
- {file = "matplotlib-3.10.7-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c380371d3c23e0eadf8ebff114445b9f970aff2010198d498d4ab4c3b41eea4f"},
- {file = "matplotlib-3.10.7-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d5f256d49fea31f40f166a5e3131235a5d2f4b7f44520b1cf0baf1ce568ccff0"},
- {file = "matplotlib-3.10.7-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11ae579ac83cdf3fb72573bb89f70e0534de05266728740d478f0f818983c695"},
- {file = "matplotlib-3.10.7-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:4c14b6acd16cddc3569a2d515cfdd81c7a68ac5639b76548cfc1a9e48b20eb65"},
- {file = "matplotlib-3.10.7-cp312-cp312-win_amd64.whl", hash = "sha256:0d8c32b7ea6fb80b1aeff5a2ceb3fb9778e2759e899d9beff75584714afcc5ee"},
- {file = "matplotlib-3.10.7-cp312-cp312-win_arm64.whl", hash = "sha256:5f3f6d315dcc176ba7ca6e74c7768fb7e4cf566c49cb143f6bc257b62e634ed8"},
- {file = "matplotlib-3.10.7-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:1d9d3713a237970569156cfb4de7533b7c4eacdd61789726f444f96a0d28f57f"},
- {file = "matplotlib-3.10.7-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:37a1fea41153dd6ee061d21ab69c9cf2cf543160b1b85d89cd3d2e2a7902ca4c"},
- {file = "matplotlib-3.10.7-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:b3c4ea4948d93c9c29dc01c0c23eef66f2101bf75158c291b88de6525c55c3d1"},
- {file = "matplotlib-3.10.7-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:22df30ffaa89f6643206cf13877191c63a50e8f800b038bc39bee9d2d4957632"},
- {file = "matplotlib-3.10.7-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:b69676845a0a66f9da30e87f48be36734d6748024b525ec4710be40194282c84"},
- {file = "matplotlib-3.10.7-cp313-cp313-win_amd64.whl", hash = "sha256:744991e0cc863dd669c8dc9136ca4e6e0082be2070b9d793cbd64bec872a6815"},
- {file = "matplotlib-3.10.7-cp313-cp313-win_arm64.whl", hash = "sha256:fba2974df0bf8ce3c995fa84b79cde38326e0f7b5409e7a3a481c1141340bcf7"},
- {file = "matplotlib-3.10.7-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:932c55d1fa7af4423422cb6a492a31cbcbdbe68fd1a9a3f545aa5e7a143b5355"},
- {file = "matplotlib-3.10.7-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5e38c2d581d62ee729a6e144c47a71b3f42fb4187508dbbf4fe71d5612c3433b"},
- {file = "matplotlib-3.10.7-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:786656bb13c237bbcebcd402f65f44dd61ead60ee3deb045af429d889c8dbc67"},
- {file = "matplotlib-3.10.7-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09d7945a70ea43bf9248f4b6582734c2fe726723204a76eca233f24cffc7ef67"},
- {file = "matplotlib-3.10.7-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:d0b181e9fa8daf1d9f2d4c547527b167cb8838fc587deabca7b5c01f97199e84"},
- {file = "matplotlib-3.10.7-cp313-cp313t-win_amd64.whl", hash = "sha256:31963603041634ce1a96053047b40961f7a29eb8f9a62e80cc2c0427aa1d22a2"},
- {file = "matplotlib-3.10.7-cp313-cp313t-win_arm64.whl", hash = "sha256:aebed7b50aa6ac698c90f60f854b47e48cd2252b30510e7a1feddaf5a3f72cbf"},
- {file = "matplotlib-3.10.7-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:d883460c43e8c6b173fef244a2341f7f7c0e9725c7fe68306e8e44ed9c8fb100"},
- {file = "matplotlib-3.10.7-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:07124afcf7a6504eafcb8ce94091c5898bbdd351519a1beb5c45f7a38c67e77f"},
- {file = "matplotlib-3.10.7-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c17398b709a6cce3d9fdb1595c33e356d91c098cd9486cb2cc21ea2ea418e715"},
- {file = "matplotlib-3.10.7-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7146d64f561498764561e9cd0ed64fcf582e570fc519e6f521e2d0cfd43365e1"},
- {file = "matplotlib-3.10.7-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:90ad854c0a435da3104c01e2c6f0028d7e719b690998a2333d7218db80950722"},
- {file = "matplotlib-3.10.7-cp314-cp314-win_amd64.whl", hash = "sha256:4645fc5d9d20ffa3a39361fcdbcec731382763b623b72627806bf251b6388866"},
- {file = "matplotlib-3.10.7-cp314-cp314-win_arm64.whl", hash = "sha256:9257be2f2a03415f9105c486d304a321168e61ad450f6153d77c69504ad764bb"},
- {file = "matplotlib-3.10.7-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:1e4bbad66c177a8fdfa53972e5ef8be72a5f27e6a607cec0d8579abd0f3102b1"},
- {file = "matplotlib-3.10.7-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d8eb7194b084b12feb19142262165832fc6ee879b945491d1c3d4660748020c4"},
- {file = "matplotlib-3.10.7-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b4d41379b05528091f00e1728004f9a8d7191260f3862178b88e8fd770206318"},
- {file = "matplotlib-3.10.7-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4a74f79fafb2e177f240579bc83f0b60f82cc47d2f1d260f422a0627207008ca"},
- {file = "matplotlib-3.10.7-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:702590829c30aada1e8cef0568ddbffa77ca747b4d6e36c6d173f66e301f89cc"},
- {file = "matplotlib-3.10.7-cp314-cp314t-win_amd64.whl", hash = "sha256:f79d5de970fc90cd5591f60053aecfce1fcd736e0303d9f0bf86be649fa68fb8"},
- {file = "matplotlib-3.10.7-cp314-cp314t-win_arm64.whl", hash = "sha256:cb783436e47fcf82064baca52ce748af71725d0352e1d31564cbe9c95df92b9c"},
- {file = "matplotlib-3.10.7-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:5c09cf8f2793f81368f49f118b6f9f937456362bee282eac575cca7f84cda537"},
- {file = "matplotlib-3.10.7-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:de66744b2bb88d5cd27e80dfc2ec9f0517d0a46d204ff98fe9e5f2864eb67657"},
- {file = "matplotlib-3.10.7-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:53cc80662dd197ece414dd5b66e07370201515a3eaf52e7c518c68c16814773b"},
- {file = "matplotlib-3.10.7-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:15112bcbaef211bd663fa935ec33313b948e214454d949b723998a43357b17b0"},
- {file = "matplotlib-3.10.7-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:d2a959c640cdeecdd2ec3136e8ea0441da59bcaf58d67e9c590740addba2cb68"},
- {file = "matplotlib-3.10.7-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3886e47f64611046bc1db523a09dd0a0a6bed6081e6f90e13806dd1d1d1b5e91"},
- {file = "matplotlib-3.10.7.tar.gz", hash = "sha256:a06ba7e2a2ef9131c79c49e63dad355d2d878413a0376c1727c8b9335ff731c7"},
+ {file = "matplotlib-3.10.8-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:00270d217d6b20d14b584c521f810d60c5c78406dc289859776550df837dcda7"},
+ {file = "matplotlib-3.10.8-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:37b3c1cc42aa184b3f738cfa18c1c1d72fd496d85467a6cf7b807936d39aa656"},
+ {file = "matplotlib-3.10.8-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:ee40c27c795bda6a5292e9cff9890189d32f7e3a0bf04e0e3c9430c4a00c37df"},
+ {file = "matplotlib-3.10.8-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a48f2b74020919552ea25d222d5cc6af9ca3f4eb43a93e14d068457f545c2a17"},
+ {file = "matplotlib-3.10.8-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:f254d118d14a7f99d616271d6c3c27922c092dac11112670b157798b89bf4933"},
+ {file = "matplotlib-3.10.8-cp310-cp310-win_amd64.whl", hash = "sha256:f9b587c9c7274c1613a30afabf65a272114cd6cdbe67b3406f818c79d7ab2e2a"},
+ {file = "matplotlib-3.10.8-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:6be43b667360fef5c754dda5d25a32e6307a03c204f3c0fc5468b78fa87b4160"},
+ {file = "matplotlib-3.10.8-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a2b336e2d91a3d7006864e0990c83b216fcdca64b5a6484912902cef87313d78"},
+ {file = "matplotlib-3.10.8-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:efb30e3baaea72ce5928e32bab719ab4770099079d66726a62b11b1ef7273be4"},
+ {file = "matplotlib-3.10.8-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d56a1efd5bfd61486c8bc968fa18734464556f0fb8e51690f4ac25d85cbbbbc2"},
+ {file = "matplotlib-3.10.8-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:238b7ce5717600615c895050239ec955d91f321c209dd110db988500558e70d6"},
+ {file = "matplotlib-3.10.8-cp311-cp311-win_amd64.whl", hash = "sha256:18821ace09c763ec93aef5eeff087ee493a24051936d7b9ebcad9662f66501f9"},
+ {file = "matplotlib-3.10.8-cp311-cp311-win_arm64.whl", hash = "sha256:bab485bcf8b1c7d2060b4fcb6fc368a9e6f4cd754c9c2fea281f4be21df394a2"},
+ {file = "matplotlib-3.10.8-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:64fcc24778ca0404ce0cb7b6b77ae1f4c7231cdd60e6778f999ee05cbd581b9a"},
+ {file = "matplotlib-3.10.8-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:b9a5ca4ac220a0cdd1ba6bcba3608547117d30468fefce49bb26f55c1a3d5c58"},
+ {file = "matplotlib-3.10.8-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3ab4aabc72de4ff77b3ec33a6d78a68227bf1123465887f9905ba79184a1cc04"},
+ {file = "matplotlib-3.10.8-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:24d50994d8c5816ddc35411e50a86ab05f575e2530c02752e02538122613371f"},
+ {file = "matplotlib-3.10.8-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:99eefd13c0dc3b3c1b4d561c1169e65fe47aab7b8158754d7c084088e2329466"},
+ {file = "matplotlib-3.10.8-cp312-cp312-win_amd64.whl", hash = "sha256:dd80ecb295460a5d9d260df63c43f4afbdd832d725a531f008dad1664f458adf"},
+ {file = "matplotlib-3.10.8-cp312-cp312-win_arm64.whl", hash = "sha256:3c624e43ed56313651bc18a47f838b60d7b8032ed348911c54906b130b20071b"},
+ {file = "matplotlib-3.10.8-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:3f2e409836d7f5ac2f1c013110a4d50b9f7edc26328c108915f9075d7d7a91b6"},
+ {file = "matplotlib-3.10.8-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:56271f3dac49a88d7fca5060f004d9d22b865f743a12a23b1e937a0be4818ee1"},
+ {file = "matplotlib-3.10.8-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a0a7f52498f72f13d4a25ea70f35f4cb60642b466cbb0a9be951b5bc3f45a486"},
+ {file = "matplotlib-3.10.8-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:646d95230efb9ca614a7a594d4fcacde0ac61d25e37dd51710b36477594963ce"},
+ {file = "matplotlib-3.10.8-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f89c151aab2e2e23cb3fe0acad1e8b82841fd265379c4cecd0f3fcb34c15e0f6"},
+ {file = "matplotlib-3.10.8-cp313-cp313-win_amd64.whl", hash = "sha256:e8ea3e2d4066083e264e75c829078f9e149fa119d27e19acd503de65e0b13149"},
+ {file = "matplotlib-3.10.8-cp313-cp313-win_arm64.whl", hash = "sha256:c108a1d6fa78a50646029cb6d49808ff0fc1330fda87fa6f6250c6b5369b6645"},
+ {file = "matplotlib-3.10.8-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:ad3d9833a64cf48cc4300f2b406c3d0f4f4724a91c0bd5640678a6ba7c102077"},
+ {file = "matplotlib-3.10.8-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:eb3823f11823deade26ce3b9f40dcb4a213da7a670013929f31d5f5ed1055b22"},
+ {file = "matplotlib-3.10.8-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d9050fee89a89ed57b4fb2c1bfac9a3d0c57a0d55aed95949eedbc42070fea39"},
+ {file = "matplotlib-3.10.8-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b44d07310e404ba95f8c25aa5536f154c0a8ec473303535949e52eb71d0a1565"},
+ {file = "matplotlib-3.10.8-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0a33deb84c15ede243aead39f77e990469fff93ad1521163305095b77b72ce4a"},
+ {file = "matplotlib-3.10.8-cp313-cp313t-win_amd64.whl", hash = "sha256:3a48a78d2786784cc2413e57397981fb45c79e968d99656706018d6e62e57958"},
+ {file = "matplotlib-3.10.8-cp313-cp313t-win_arm64.whl", hash = "sha256:15d30132718972c2c074cd14638c7f4592bd98719e2308bccea40e0538bc0cb5"},
+ {file = "matplotlib-3.10.8-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b53285e65d4fa4c86399979e956235deb900be5baa7fc1218ea67fbfaeaadd6f"},
+ {file = "matplotlib-3.10.8-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:32f8dce744be5569bebe789e46727946041199030db8aeb2954d26013a0eb26b"},
+ {file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4cf267add95b1c88300d96ca837833d4112756045364f5c734a2276038dae27d"},
+ {file = "matplotlib-3.10.8-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2cf5bd12cecf46908f286d7838b2abc6c91cda506c0445b8223a7c19a00df008"},
+ {file = "matplotlib-3.10.8-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:41703cc95688f2516b480f7f339d8851a6035f18e100ee6a32bc0b8536a12a9c"},
+ {file = "matplotlib-3.10.8-cp314-cp314-win_amd64.whl", hash = "sha256:83d282364ea9f3e52363da262ce32a09dfe241e4080dcedda3c0db059d3c1f11"},
+ {file = "matplotlib-3.10.8-cp314-cp314-win_arm64.whl", hash = "sha256:2c1998e92cd5999e295a731bcb2911c75f597d937341f3030cc24ef2733d78a8"},
+ {file = "matplotlib-3.10.8-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:b5a2b97dbdc7d4f353ebf343744f1d1f1cca8aa8bfddb4262fcf4306c3761d50"},
+ {file = "matplotlib-3.10.8-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:3f5c3e4da343bba819f0234186b9004faba952cc420fbc522dc4e103c1985908"},
+ {file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f62550b9a30afde8c1c3ae450e5eb547d579dd69b25c2fc7a1c67f934c1717a"},
+ {file = "matplotlib-3.10.8-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:495672de149445ec1b772ff2c9ede9b769e3cb4f0d0aa7fa730d7f59e2d4e1c1"},
+ {file = "matplotlib-3.10.8-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:595ba4d8fe983b88f0eec8c26a241e16d6376fe1979086232f481f8f3f67494c"},
+ {file = "matplotlib-3.10.8-cp314-cp314t-win_amd64.whl", hash = "sha256:25d380fe8b1dc32cf8f0b1b448470a77afb195438bafdf1d858bfb876f3edf7b"},
+ {file = "matplotlib-3.10.8-cp314-cp314t-win_arm64.whl", hash = "sha256:113bb52413ea508ce954a02c10ffd0d565f9c3bc7f2eddc27dfe1731e71c7b5f"},
+ {file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f97aeb209c3d2511443f8797e3e5a569aebb040d4f8bc79aa3ee78a8fb9e3dd8"},
+ {file = "matplotlib-3.10.8-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:fb061f596dad3a0f52b60dc6a5dec4a0c300dec41e058a7efe09256188d170b7"},
+ {file = "matplotlib-3.10.8-pp310-pypy310_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:12d90df9183093fcd479f4172ac26b322b1248b15729cb57f42f71f24c7e37a3"},
+ {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:6da7c2ce169267d0d066adcf63758f0604aa6c3eebf67458930f9d9b79ad1db1"},
+ {file = "matplotlib-3.10.8-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:9153c3292705be9f9c64498a8872118540c3f4123d1a1c840172edf262c8be4a"},
+ {file = "matplotlib-3.10.8-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:1ae029229a57cd1e8fe542485f27e7ca7b23aa9e8944ddb4985d0bc444f1eca2"},
+ {file = "matplotlib-3.10.8.tar.gz", hash = "sha256:2299372c19d56bcd35cf05a2738308758d32b9eaed2371898d8f5bd33f084aa3"},
]
[package.dependencies]
@@ -1641,54 +1623,54 @@ docs = ["pandas", "pydata_sphinx_theme (!=0.10.1)", "sphinx", "sphinx-gallery (>
[[package]]
name = "mypy"
-version = "1.19.0"
+version = "1.19.1"
description = "Optional static typing for Python"
optional = false
python-versions = ">=3.9"
groups = ["dev"]
files = [
- {file = "mypy-1.19.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6148ede033982a8c5ca1143de34c71836a09f105068aaa8b7d5edab2b053e6c8"},
- {file = "mypy-1.19.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a9ac09e52bb0f7fb912f5d2a783345c72441a08ef56ce3e17c1752af36340a39"},
- {file = "mypy-1.19.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11f7254c15ab3f8ed68f8e8f5cbe88757848df793e31c36aaa4d4f9783fd08ab"},
- {file = "mypy-1.19.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:318ba74f75899b0e78b847d8c50821e4c9637c79d9a59680fc1259f29338cb3e"},
- {file = "mypy-1.19.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:cf7d84f497f78b682edd407f14a7b6e1a2212b433eedb054e2081380b7395aa3"},
- {file = "mypy-1.19.0-cp310-cp310-win_amd64.whl", hash = "sha256:c3385246593ac2b97f155a0e9639be906e73534630f663747c71908dfbf26134"},
- {file = "mypy-1.19.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:a31e4c28e8ddb042c84c5e977e28a21195d086aaffaf08b016b78e19c9ef8106"},
- {file = "mypy-1.19.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:34ec1ac66d31644f194b7c163d7f8b8434f1b49719d403a5d26c87fff7e913f7"},
- {file = "mypy-1.19.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:cb64b0ba5980466a0f3f9990d1c582bcab8db12e29815ecb57f1408d99b4bff7"},
- {file = "mypy-1.19.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:120cffe120cca5c23c03c77f84abc0c14c5d2e03736f6c312480020082f1994b"},
- {file = "mypy-1.19.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:7a500ab5c444268a70565e374fc803972bfd1f09545b13418a5174e29883dab7"},
- {file = "mypy-1.19.0-cp311-cp311-win_amd64.whl", hash = "sha256:c14a98bc63fd867530e8ec82f217dae29d0550c86e70debc9667fff1ec83284e"},
- {file = "mypy-1.19.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0fb3115cb8fa7c5f887c8a8d81ccdcb94cff334684980d847e5a62e926910e1d"},
- {file = "mypy-1.19.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:f3e19e3b897562276bb331074d64c076dbdd3e79213f36eed4e592272dabd760"},
- {file = "mypy-1.19.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b9d491295825182fba01b6ffe2c6fe4e5a49dbf4e2bb4d1217b6ced3b4797bc6"},
- {file = "mypy-1.19.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6016c52ab209919b46169651b362068f632efcd5eb8ef9d1735f6f86da7853b2"},
- {file = "mypy-1.19.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:f188dcf16483b3e59f9278c4ed939ec0254aa8a60e8fc100648d9ab5ee95a431"},
- {file = "mypy-1.19.0-cp312-cp312-win_amd64.whl", hash = "sha256:0e3c3d1e1d62e678c339e7ade72746a9e0325de42cd2cccc51616c7b2ed1a018"},
- {file = "mypy-1.19.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7686ed65dbabd24d20066f3115018d2dce030d8fa9db01aa9f0a59b6813e9f9e"},
- {file = "mypy-1.19.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:fd4a985b2e32f23bead72e2fb4bbe5d6aceee176be471243bd831d5b2644672d"},
- {file = "mypy-1.19.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc51a5b864f73a3a182584b1ac75c404396a17eced54341629d8bdcb644a5bba"},
- {file = "mypy-1.19.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:37af5166f9475872034b56c5efdcf65ee25394e9e1d172907b84577120714364"},
- {file = "mypy-1.19.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:510c014b722308c9bd377993bcbf9a07d7e0692e5fa8fc70e639c1eb19fc6bee"},
- {file = "mypy-1.19.0-cp313-cp313-win_amd64.whl", hash = "sha256:cabbee74f29aa9cd3b444ec2f1e4fa5a9d0d746ce7567a6a609e224429781f53"},
- {file = "mypy-1.19.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:f2e36bed3c6d9b5f35d28b63ca4b727cb0228e480826ffc8953d1892ddc8999d"},
- {file = "mypy-1.19.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:a18d8abdda14035c5718acb748faec09571432811af129bf0d9e7b2d6699bf18"},
- {file = "mypy-1.19.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f75e60aca3723a23511948539b0d7ed514dda194bc3755eae0bfc7a6b4887aa7"},
- {file = "mypy-1.19.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8f44f2ae3c58421ee05fe609160343c25f70e3967f6e32792b5a78006a9d850f"},
- {file = "mypy-1.19.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:63ea6a00e4bd6822adbfc75b02ab3653a17c02c4347f5bb0cf1d5b9df3a05835"},
- {file = "mypy-1.19.0-cp314-cp314-win_amd64.whl", hash = "sha256:3ad925b14a0bb99821ff6f734553294aa6a3440a8cb082fe1f5b84dfb662afb1"},
- {file = "mypy-1.19.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:0dde5cb375cb94deff0d4b548b993bec52859d1651e073d63a1386d392a95495"},
- {file = "mypy-1.19.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1cf9c59398db1c68a134b0b5354a09a1e124523f00bacd68e553b8bd16ff3299"},
- {file = "mypy-1.19.0-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3210d87b30e6af9c8faed61be2642fcbe60ef77cec64fa1ef810a630a4cf671c"},
- {file = "mypy-1.19.0-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:e2c1101ab41d01303103ab6ef82cbbfedb81c1a060c868fa7cc013d573d37ab5"},
- {file = "mypy-1.19.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:0ea4fd21bb48f0da49e6d3b37ef6bd7e8228b9fe41bbf4d80d9364d11adbd43c"},
- {file = "mypy-1.19.0-cp39-cp39-win_amd64.whl", hash = "sha256:16f76ff3f3fd8137aadf593cb4607d82634fca675e8211ad75c43d86033ee6c6"},
- {file = "mypy-1.19.0-py3-none-any.whl", hash = "sha256:0c01c99d626380752e527d5ce8e69ffbba2046eb8a060db0329690849cf9b6f9"},
- {file = "mypy-1.19.0.tar.gz", hash = "sha256:f6b874ca77f733222641e5c46e4711648c4037ea13646fd0cdc814c2eaec2528"},
+ {file = "mypy-1.19.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f05aa3d375b385734388e844bc01733bd33c644ab48e9684faa54e5389775ec"},
+ {file = "mypy-1.19.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:022ea7279374af1a5d78dfcab853fe6a536eebfda4b59deab53cd21f6cd9f00b"},
+ {file = "mypy-1.19.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ee4c11e460685c3e0c64a4c5de82ae143622410950d6be863303a1c4ba0e36d6"},
+ {file = "mypy-1.19.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:de759aafbae8763283b2ee5869c7255391fbc4de3ff171f8f030b5ec48381b74"},
+ {file = "mypy-1.19.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:ab43590f9cd5108f41aacf9fca31841142c786827a74ab7cc8a2eacb634e09a1"},
+ {file = "mypy-1.19.1-cp310-cp310-win_amd64.whl", hash = "sha256:2899753e2f61e571b3971747e302d5f420c3fd09650e1951e99f823bc3089dac"},
+ {file = "mypy-1.19.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:d8dfc6ab58ca7dda47d9237349157500468e404b17213d44fc1cb77bce532288"},
+ {file = "mypy-1.19.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:e3f276d8493c3c97930e354b2595a44a21348b320d859fb4a2b9f66da9ed27ab"},
+ {file = "mypy-1.19.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:2abb24cf3f17864770d18d673c85235ba52456b36a06b6afc1e07c1fdcd3d0e6"},
+ {file = "mypy-1.19.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a009ffa5a621762d0c926a078c2d639104becab69e79538a494bcccb62cc0331"},
+ {file = "mypy-1.19.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:f7cee03c9a2e2ee26ec07479f38ea9c884e301d42c6d43a19d20fb014e3ba925"},
+ {file = "mypy-1.19.1-cp311-cp311-win_amd64.whl", hash = "sha256:4b84a7a18f41e167f7995200a1d07a4a6810e89d29859df936f1c3923d263042"},
+ {file = "mypy-1.19.1-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a8174a03289288c1f6c46d55cef02379b478bfbc8e358e02047487cad44c6ca1"},
+ {file = "mypy-1.19.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ffcebe56eb09ff0c0885e750036a095e23793ba6c2e894e7e63f6d89ad51f22e"},
+ {file = "mypy-1.19.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b64d987153888790bcdb03a6473d321820597ab8dd9243b27a92153c4fa50fd2"},
+ {file = "mypy-1.19.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c35d298c2c4bba75feb2195655dfea8124d855dfd7343bf8b8c055421eaf0cf8"},
+ {file = "mypy-1.19.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:34c81968774648ab5ac09c29a375fdede03ba253f8f8287847bd480782f73a6a"},
+ {file = "mypy-1.19.1-cp312-cp312-win_amd64.whl", hash = "sha256:b10e7c2cd7870ba4ad9b2d8a6102eb5ffc1f16ca35e3de6bfa390c1113029d13"},
+ {file = "mypy-1.19.1-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:e3157c7594ff2ef1634ee058aafc56a82db665c9438fd41b390f3bde1ab12250"},
+ {file = "mypy-1.19.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bdb12f69bcc02700c2b47e070238f42cb87f18c0bc1fc4cdb4fb2bc5fd7a3b8b"},
+ {file = "mypy-1.19.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f859fb09d9583a985be9a493d5cfc5515b56b08f7447759a0c5deaf68d80506e"},
+ {file = "mypy-1.19.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c9a6538e0415310aad77cb94004ca6482330fece18036b5f360b62c45814c4ef"},
+ {file = "mypy-1.19.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:da4869fc5e7f62a88f3fe0b5c919d1d9f7ea3cef92d3689de2823fd27e40aa75"},
+ {file = "mypy-1.19.1-cp313-cp313-win_amd64.whl", hash = "sha256:016f2246209095e8eda7538944daa1d60e1e8134d98983b9fc1e92c1fc0cb8dd"},
+ {file = "mypy-1.19.1-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:06e6170bd5836770e8104c8fdd58e5e725cfeb309f0a6c681a811f557e97eac1"},
+ {file = "mypy-1.19.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:804bd67b8054a85447c8954215a906d6eff9cabeabe493fb6334b24f4bfff718"},
+ {file = "mypy-1.19.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:21761006a7f497cb0d4de3d8ef4ca70532256688b0523eee02baf9eec895e27b"},
+ {file = "mypy-1.19.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:28902ee51f12e0f19e1e16fbe2f8f06b6637f482c459dd393efddd0ec7f82045"},
+ {file = "mypy-1.19.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:481daf36a4c443332e2ae9c137dfee878fcea781a2e3f895d54bd3002a900957"},
+ {file = "mypy-1.19.1-cp314-cp314-win_amd64.whl", hash = "sha256:8bb5c6f6d043655e055be9b542aa5f3bdd30e4f3589163e85f93f3640060509f"},
+ {file = "mypy-1.19.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7bcfc336a03a1aaa26dfce9fff3e287a3ba99872a157561cbfcebe67c13308e3"},
+ {file = "mypy-1.19.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b7951a701c07ea584c4fe327834b92a30825514c868b1f69c30445093fdd9d5a"},
+ {file = "mypy-1.19.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b13cfdd6c87fc3efb69ea4ec18ef79c74c3f98b4e5498ca9b85ab3b2c2329a67"},
+ {file = "mypy-1.19.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4f28f99c824ecebcdaa2e55d82953e38ff60ee5ec938476796636b86afa3956e"},
+ {file = "mypy-1.19.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:c608937067d2fc5a4dd1a5ce92fd9e1398691b8c5d012d66e1ddd430e9244376"},
+ {file = "mypy-1.19.1-cp39-cp39-win_amd64.whl", hash = "sha256:409088884802d511ee52ca067707b90c883426bd95514e8cfda8281dc2effe24"},
+ {file = "mypy-1.19.1-py3-none-any.whl", hash = "sha256:f1235f5ea01b7db5468d53ece6aaddf1ad0b88d9e7462b86ef96fe04995d7247"},
+ {file = "mypy-1.19.1.tar.gz", hash = "sha256:19d88bb05303fe63f71dd2c6270daca27cb9401c4ca8255fe50d1d920e0eb9ba"},
]
[package.dependencies]
-librt = ">=0.6.2"
+librt = {version = ">=0.6.2", markers = "platform_python_implementation != \"PyPy\""}
mypy_extensions = ">=1.0.0"
pathspec = ">=0.9.0"
typing_extensions = ">=4.6.0"
@@ -1714,98 +1696,96 @@ files = [
[[package]]
name = "numpy"
-version = "2.3.5"
+version = "2.4.2"
description = "Fundamental package for array computing in Python"
optional = false
python-versions = ">=3.11"
groups = ["main"]
files = [
- {file = "numpy-2.3.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:de5672f4a7b200c15a4127042170a694d4df43c992948f5e1af57f0174beed10"},
- {file = "numpy-2.3.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:acfd89508504a19ed06ef963ad544ec6664518c863436306153e13e94605c218"},
- {file = "numpy-2.3.5-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:ffe22d2b05504f786c867c8395de703937f934272eb67586817b46188b4ded6d"},
- {file = "numpy-2.3.5-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:872a5cf366aec6bb1147336480fef14c9164b154aeb6542327de4970282cd2f5"},
- {file = "numpy-2.3.5-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:3095bdb8dd297e5920b010e96134ed91d852d81d490e787beca7e35ae1d89cf7"},
- {file = "numpy-2.3.5-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8cba086a43d54ca804ce711b2a940b16e452807acebe7852ff327f1ecd49b0d4"},
- {file = "numpy-2.3.5-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:6cf9b429b21df6b99f4dee7a1218b8b7ffbbe7df8764dc0bd60ce8a0708fed1e"},
- {file = "numpy-2.3.5-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:396084a36abdb603546b119d96528c2f6263921c50df3c8fd7cb28873a237748"},
- {file = "numpy-2.3.5-cp311-cp311-win32.whl", hash = "sha256:b0c7088a73aef3d687c4deef8452a3ac7c1be4e29ed8bf3b366c8111128ac60c"},
- {file = "numpy-2.3.5-cp311-cp311-win_amd64.whl", hash = "sha256:a414504bef8945eae5f2d7cb7be2d4af77c5d1cb5e20b296c2c25b61dff2900c"},
- {file = "numpy-2.3.5-cp311-cp311-win_arm64.whl", hash = "sha256:0cd00b7b36e35398fa2d16af7b907b65304ef8bb4817a550e06e5012929830fa"},
- {file = "numpy-2.3.5-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:74ae7b798248fe62021dbf3c914245ad45d1a6b0cb4a29ecb4b31d0bfbc4cc3e"},
- {file = "numpy-2.3.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee3888d9ff7c14604052b2ca5535a30216aa0a58e948cdd3eeb8d3415f638769"},
- {file = "numpy-2.3.5-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:612a95a17655e213502f60cfb9bf9408efdc9eb1d5f50535cc6eb365d11b42b5"},
- {file = "numpy-2.3.5-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3101e5177d114a593d79dd79658650fe28b5a0d8abeb8ce6f437c0e6df5be1a4"},
- {file = "numpy-2.3.5-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:8b973c57ff8e184109db042c842423ff4f60446239bd585a5131cc47f06f789d"},
- {file = "numpy-2.3.5-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0d8163f43acde9a73c2a33605353a4f1bc4798745a8b1d73183b28e5b435ae28"},
- {file = "numpy-2.3.5-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:51c1e14eb1e154ebd80e860722f9e6ed6ec89714ad2db2d3aa33c31d7c12179b"},
- {file = "numpy-2.3.5-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:b46b4ec24f7293f23adcd2d146960559aaf8020213de8ad1909dba6c013bf89c"},
- {file = "numpy-2.3.5-cp312-cp312-win32.whl", hash = "sha256:3997b5b3c9a771e157f9aae01dd579ee35ad7109be18db0e85dbdbe1de06e952"},
- {file = "numpy-2.3.5-cp312-cp312-win_amd64.whl", hash = "sha256:86945f2ee6d10cdfd67bcb4069c1662dd711f7e2a4343db5cecec06b87cf31aa"},
- {file = "numpy-2.3.5-cp312-cp312-win_arm64.whl", hash = "sha256:f28620fe26bee16243be2b7b874da327312240a7cdc38b769a697578d2100013"},
- {file = "numpy-2.3.5-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:d0f23b44f57077c1ede8c5f26b30f706498b4862d3ff0a7298b8411dd2f043ff"},
- {file = "numpy-2.3.5-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa5bc7c5d59d831d9773d1170acac7893ce3a5e130540605770ade83280e7188"},
- {file = "numpy-2.3.5-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:ccc933afd4d20aad3c00bcef049cb40049f7f196e0397f1109dba6fed63267b0"},
- {file = "numpy-2.3.5-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:afaffc4393205524af9dfa400fa250143a6c3bc646c08c9f5e25a9f4b4d6a903"},
- {file = "numpy-2.3.5-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:9c75442b2209b8470d6d5d8b1c25714270686f14c749028d2199c54e29f20b4d"},
- {file = "numpy-2.3.5-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:11e06aa0af8c0f05104d56450d6093ee639e15f24ecf62d417329d06e522e017"},
- {file = "numpy-2.3.5-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:ed89927b86296067b4f81f108a2271d8926467a8868e554eaf370fc27fa3ccaf"},
- {file = "numpy-2.3.5-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:51c55fe3451421f3a6ef9a9c1439e82101c57a2c9eab9feb196a62b1a10b58ce"},
- {file = "numpy-2.3.5-cp313-cp313-win32.whl", hash = "sha256:1978155dd49972084bd6ef388d66ab70f0c323ddee6f693d539376498720fb7e"},
- {file = "numpy-2.3.5-cp313-cp313-win_amd64.whl", hash = "sha256:00dc4e846108a382c5869e77c6ed514394bdeb3403461d25a829711041217d5b"},
- {file = "numpy-2.3.5-cp313-cp313-win_arm64.whl", hash = "sha256:0472f11f6ec23a74a906a00b48a4dcf3849209696dff7c189714511268d103ae"},
- {file = "numpy-2.3.5-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:414802f3b97f3c1eef41e530aaba3b3c1620649871d8cb38c6eaff034c2e16bd"},
- {file = "numpy-2.3.5-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5ee6609ac3604fa7780e30a03e5e241a7956f8e2fcfe547d51e3afa5247ac47f"},
- {file = "numpy-2.3.5-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:86d835afea1eaa143012a2d7a3f45a3adce2d7adc8b4961f0b362214d800846a"},
- {file = "numpy-2.3.5-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:30bc11310e8153ca664b14c5f1b73e94bd0503681fcf136a163de856f3a50139"},
- {file = "numpy-2.3.5-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:1062fde1dcf469571705945b0f221b73928f34a20c904ffb45db101907c3454e"},
- {file = "numpy-2.3.5-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:ce581db493ea1a96c0556360ede6607496e8bf9b3a8efa66e06477267bc831e9"},
- {file = "numpy-2.3.5-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:cc8920d2ec5fa99875b670bb86ddeb21e295cb07aa331810d9e486e0b969d946"},
- {file = "numpy-2.3.5-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:9ee2197ef8c4f0dfe405d835f3b6a14f5fee7782b5de51ba06fb65fc9b36e9f1"},
- {file = "numpy-2.3.5-cp313-cp313t-win32.whl", hash = "sha256:70b37199913c1bd300ff6e2693316c6f869c7ee16378faf10e4f5e3275b299c3"},
- {file = "numpy-2.3.5-cp313-cp313t-win_amd64.whl", hash = "sha256:b501b5fa195cc9e24fe102f21ec0a44dffc231d2af79950b451e0d99cea02234"},
- {file = "numpy-2.3.5-cp313-cp313t-win_arm64.whl", hash = "sha256:a80afd79f45f3c4a7d341f13acbe058d1ca8ac017c165d3fa0d3de6bc1a079d7"},
- {file = "numpy-2.3.5-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:bf06bc2af43fa8d32d30fae16ad965663e966b1a3202ed407b84c989c3221e82"},
- {file = "numpy-2.3.5-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:052e8c42e0c49d2575621c158934920524f6c5da05a1d3b9bab5d8e259e045f0"},
- {file = "numpy-2.3.5-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:1ed1ec893cff7040a02c8aa1c8611b94d395590d553f6b53629a4461dc7f7b63"},
- {file = "numpy-2.3.5-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:2dcd0808a421a482a080f89859a18beb0b3d1e905b81e617a188bd80422d62e9"},
- {file = "numpy-2.3.5-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:727fd05b57df37dc0bcf1a27767a3d9a78cbbc92822445f32cc3436ba797337b"},
- {file = "numpy-2.3.5-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:fffe29a1ef00883599d1dc2c51aa2e5d80afe49523c261a74933df395c15c520"},
- {file = "numpy-2.3.5-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8f7f0e05112916223d3f438f293abf0727e1181b5983f413dfa2fefc4098245c"},
- {file = "numpy-2.3.5-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:2e2eb32ddb9ccb817d620ac1d8dae7c3f641c1e5f55f531a33e8ab97960a75b8"},
- {file = "numpy-2.3.5-cp314-cp314-win32.whl", hash = "sha256:66f85ce62c70b843bab1fb14a05d5737741e74e28c7b8b5a064de10142fad248"},
- {file = "numpy-2.3.5-cp314-cp314-win_amd64.whl", hash = "sha256:e6a0bc88393d65807d751a614207b7129a310ca4fe76a74e5c7da5fa5671417e"},
- {file = "numpy-2.3.5-cp314-cp314-win_arm64.whl", hash = "sha256:aeffcab3d4b43712bb7a60b65f6044d444e75e563ff6180af8f98dd4b905dfd2"},
- {file = "numpy-2.3.5-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:17531366a2e3a9e30762c000f2c43a9aaa05728712e25c11ce1dbe700c53ad41"},
- {file = "numpy-2.3.5-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:d21644de1b609825ede2f48be98dfde4656aefc713654eeee280e37cadc4e0ad"},
- {file = "numpy-2.3.5-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:c804e3a5aba5460c73955c955bdbd5c08c354954e9270a2c1565f62e866bdc39"},
- {file = "numpy-2.3.5-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:cc0a57f895b96ec78969c34f682c602bf8da1a0270b09bc65673df2e7638ec20"},
- {file = "numpy-2.3.5-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:900218e456384ea676e24ea6a0417f030a3b07306d29d7ad843957b40a9d8d52"},
- {file = "numpy-2.3.5-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:09a1bea522b25109bf8e6f3027bd810f7c1085c64a0c7ce050c1676ad0ba010b"},
- {file = "numpy-2.3.5-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:04822c00b5fd0323c8166d66c701dc31b7fbd252c100acd708c48f763968d6a3"},
- {file = "numpy-2.3.5-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:d6889ec4ec662a1a37eb4b4fb26b6100841804dac55bd9df579e326cdc146227"},
- {file = "numpy-2.3.5-cp314-cp314t-win32.whl", hash = "sha256:93eebbcf1aafdf7e2ddd44c2923e2672e1010bddc014138b229e49725b4d6be5"},
- {file = "numpy-2.3.5-cp314-cp314t-win_amd64.whl", hash = "sha256:c8a9958e88b65c3b27e22ca2a076311636850b612d6bbfb76e8d156aacde2aaf"},
- {file = "numpy-2.3.5-cp314-cp314t-win_arm64.whl", hash = "sha256:6203fdf9f3dc5bdaed7319ad8698e685c7a3be10819f41d32a0723e611733b42"},
- {file = "numpy-2.3.5-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:f0963b55cdd70fad460fa4c1341f12f976bb26cb66021a5580329bd498988310"},
- {file = "numpy-2.3.5-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:f4255143f5160d0de972d28c8f9665d882b5f61309d8362fdd3e103cf7bf010c"},
- {file = "numpy-2.3.5-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:a4b9159734b326535f4dd01d947f919c6eefd2d9827466a696c44ced82dfbc18"},
- {file = "numpy-2.3.5-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:2feae0d2c91d46e59fcd62784a3a83b3fb677fead592ce51b5a6fbb4f95965ff"},
- {file = "numpy-2.3.5-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:ffac52f28a7849ad7576293c0cb7b9f08304e8f7d738a8cb8a90ec4c55a998eb"},
- {file = "numpy-2.3.5-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:63c0e9e7eea69588479ebf4a8a270d5ac22763cc5854e9a7eae952a3908103f7"},
- {file = "numpy-2.3.5-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:f16417ec91f12f814b10bafe79ef77e70113a2f5f7018640e7425ff979253425"},
- {file = "numpy-2.3.5.tar.gz", hash = "sha256:784db1dcdab56bf0517743e746dfb0f885fc68d948aba86eeec2cba234bdf1c0"},
+ {file = "numpy-2.4.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e7e88598032542bd49af7c4747541422884219056c268823ef6e5e89851c8825"},
+ {file = "numpy-2.4.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:7edc794af8b36ca37ef5fcb5e0d128c7e0595c7b96a2318d1badb6fcd8ee86b1"},
+ {file = "numpy-2.4.2-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:6e9f61981ace1360e42737e2bae58b27bf28a1b27e781721047d84bd754d32e7"},
+ {file = "numpy-2.4.2-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:cb7bbb88aa74908950d979eeaa24dbdf1a865e3c7e45ff0121d8f70387b55f73"},
+ {file = "numpy-2.4.2-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4f069069931240b3fc703f1e23df63443dbd6390614c8c44a87d96cd0ec81eb1"},
+ {file = "numpy-2.4.2-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c02ef4401a506fb60b411467ad501e1429a3487abca4664871d9ae0b46c8ba32"},
+ {file = "numpy-2.4.2-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:2653de5c24910e49c2b106499803124dde62a5a1fe0eedeaecf4309a5f639390"},
+ {file = "numpy-2.4.2-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1ae241bbfc6ae276f94a170b14785e561cb5e7f626b6688cf076af4110887413"},
+ {file = "numpy-2.4.2-cp311-cp311-win32.whl", hash = "sha256:df1b10187212b198dd45fa943d8985a3c8cf854aed4923796e0e019e113a1bda"},
+ {file = "numpy-2.4.2-cp311-cp311-win_amd64.whl", hash = "sha256:b9c618d56a29c9cb1c4da979e9899be7578d2e0b3c24d52079c166324c9e8695"},
+ {file = "numpy-2.4.2-cp311-cp311-win_arm64.whl", hash = "sha256:47c5a6ed21d9452b10227e5e8a0e1c22979811cad7dcc19d8e3e2fb8fa03f1a3"},
+ {file = "numpy-2.4.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:21982668592194c609de53ba4933a7471880ccbaadcc52352694a59ecc860b3a"},
+ {file = "numpy-2.4.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40397bda92382fcec844066efb11f13e1c9a3e2a8e8f318fb72ed8b6db9f60f1"},
+ {file = "numpy-2.4.2-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:b3a24467af63c67829bfaa61eecf18d5432d4f11992688537be59ecd6ad32f5e"},
+ {file = "numpy-2.4.2-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:805cc8de9fd6e7a22da5aed858e0ab16be5a4db6c873dde1d7451c541553aa27"},
+ {file = "numpy-2.4.2-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d82351358ffbcdcd7b686b90742a9b86632d6c1c051016484fa0b326a0a1548"},
+ {file = "numpy-2.4.2-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e35d3e0144137d9fdae62912e869136164534d64a169f86438bc9561b6ad49f"},
+ {file = "numpy-2.4.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:adb6ed2ad29b9e15321d167d152ee909ec73395901b70936f029c3bc6d7f4460"},
+ {file = "numpy-2.4.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:8906e71fd8afcb76580404e2a950caef2685df3d2a57fe82a86ac8d33cc007ba"},
+ {file = "numpy-2.4.2-cp312-cp312-win32.whl", hash = "sha256:ec055f6dae239a6299cace477b479cca2fc125c5675482daf1dd886933a1076f"},
+ {file = "numpy-2.4.2-cp312-cp312-win_amd64.whl", hash = "sha256:209fae046e62d0ce6435fcfe3b1a10537e858249b3d9b05829e2a05218296a85"},
+ {file = "numpy-2.4.2-cp312-cp312-win_arm64.whl", hash = "sha256:fbde1b0c6e81d56f5dccd95dd4a711d9b95df1ae4009a60887e56b27e8d903fa"},
+ {file = "numpy-2.4.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:25f2059807faea4b077a2b6837391b5d830864b3543627f381821c646f31a63c"},
+ {file = "numpy-2.4.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:bd3a7a9f5847d2fb8c2c6d1c862fa109c31a9abeca1a3c2bd5a64572955b2979"},
+ {file = "numpy-2.4.2-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:8e4549f8a3c6d13d55041925e912bfd834285ef1dd64d6bc7d542583355e2e98"},
+ {file = "numpy-2.4.2-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:aea4f66ff44dfddf8c2cffd66ba6538c5ec67d389285292fe428cb2c738c8aef"},
+ {file = "numpy-2.4.2-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:c3cd545784805de05aafe1dde61752ea49a359ccba9760c1e5d1c88a93bbf2b7"},
+ {file = "numpy-2.4.2-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d0d9b7c93578baafcbc5f0b83eaf17b79d345c6f36917ba0c67f45226911d499"},
+ {file = "numpy-2.4.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:f74f0f7779cc7ae07d1810aab8ac6b1464c3eafb9e283a40da7309d5e6e48fbb"},
+ {file = "numpy-2.4.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:c7ac672d699bf36275c035e16b65539931347d68b70667d28984c9fb34e07fa7"},
+ {file = "numpy-2.4.2-cp313-cp313-win32.whl", hash = "sha256:8e9afaeb0beff068b4d9cd20d322ba0ee1cecfb0b08db145e4ab4dd44a6b5110"},
+ {file = "numpy-2.4.2-cp313-cp313-win_amd64.whl", hash = "sha256:7df2de1e4fba69a51c06c28f5a3de36731eb9639feb8e1cf7e4a7b0daf4cf622"},
+ {file = "numpy-2.4.2-cp313-cp313-win_arm64.whl", hash = "sha256:0fece1d1f0a89c16b03442eae5c56dc0be0c7883b5d388e0c03f53019a4bfd71"},
+ {file = "numpy-2.4.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:5633c0da313330fd20c484c78cdd3f9b175b55e1a766c4a174230c6b70ad8262"},
+ {file = "numpy-2.4.2-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:d9f64d786b3b1dd742c946c42d15b07497ed14af1a1f3ce840cce27daa0ce913"},
+ {file = "numpy-2.4.2-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:b21041e8cb6a1eb5312dd1d2f80a94d91efffb7a06b70597d44f1bd2dfc315ab"},
+ {file = "numpy-2.4.2-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:00ab83c56211a1d7c07c25e3217ea6695e50a3e2f255053686b081dc0b091a82"},
+ {file = "numpy-2.4.2-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2fb882da679409066b4603579619341c6d6898fc83a8995199d5249f986e8e8f"},
+ {file = "numpy-2.4.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:66cb9422236317f9d44b67b4d18f44efe6e9c7f8794ac0462978513359461554"},
+ {file = "numpy-2.4.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:0f01dcf33e73d80bd8dc0f20a71303abbafa26a19e23f6b68d1aa9990af90257"},
+ {file = "numpy-2.4.2-cp313-cp313t-win32.whl", hash = "sha256:52b913ec40ff7ae845687b0b34d8d93b60cb66dcee06996dd5c99f2fc9328657"},
+ {file = "numpy-2.4.2-cp313-cp313t-win_amd64.whl", hash = "sha256:5eea80d908b2c1f91486eb95b3fb6fab187e569ec9752ab7d9333d2e66bf2d6b"},
+ {file = "numpy-2.4.2-cp313-cp313t-win_arm64.whl", hash = "sha256:fd49860271d52127d61197bb50b64f58454e9f578cb4b2c001a6de8b1f50b0b1"},
+ {file = "numpy-2.4.2-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:444be170853f1f9d528428eceb55f12918e4fda5d8805480f36a002f1415e09b"},
+ {file = "numpy-2.4.2-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:d1240d50adff70c2a88217698ca844723068533f3f5c5fa6ee2e3220e3bdb000"},
+ {file = "numpy-2.4.2-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:7cdde6de52fb6664b00b056341265441192d1291c130e99183ec0d4b110ff8b1"},
+ {file = "numpy-2.4.2-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:cda077c2e5b780200b6b3e09d0b42205a3d1c68f30c6dceb90401c13bff8fe74"},
+ {file = "numpy-2.4.2-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d30291931c915b2ab5717c2974bb95ee891a1cf22ebc16a8006bd59cd210d40a"},
+ {file = "numpy-2.4.2-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bba37bc29d4d85761deed3954a1bc62be7cf462b9510b51d367b769a8c8df325"},
+ {file = "numpy-2.4.2-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:b2f0073ed0868db1dcd86e052d37279eef185b9c8db5bf61f30f46adac63c909"},
+ {file = "numpy-2.4.2-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:7f54844851cdb630ceb623dcec4db3240d1ac13d4990532446761baede94996a"},
+ {file = "numpy-2.4.2-cp314-cp314-win32.whl", hash = "sha256:12e26134a0331d8dbd9351620f037ec470b7c75929cb8a1537f6bfe411152a1a"},
+ {file = "numpy-2.4.2-cp314-cp314-win_amd64.whl", hash = "sha256:068cdb2d0d644cdb45670810894f6a0600797a69c05f1ac478e8d31670b8ee75"},
+ {file = "numpy-2.4.2-cp314-cp314-win_arm64.whl", hash = "sha256:6ed0be1ee58eef41231a5c943d7d1375f093142702d5723ca2eb07db9b934b05"},
+ {file = "numpy-2.4.2-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:98f16a80e917003a12c0580f97b5f875853ebc33e2eaa4bccfc8201ac6869308"},
+ {file = "numpy-2.4.2-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:20abd069b9cda45874498b245c8015b18ace6de8546bf50dfa8cea1696ed06ef"},
+ {file = "numpy-2.4.2-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:e98c97502435b53741540a5717a6749ac2ada901056c7db951d33e11c885cc7d"},
+ {file = "numpy-2.4.2-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:da6cad4e82cb893db4b69105c604d805e0c3ce11501a55b5e9f9083b47d2ffe8"},
+ {file = "numpy-2.4.2-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9e4424677ce4b47fe73c8b5556d876571f7c6945d264201180db2dc34f676ab5"},
+ {file = "numpy-2.4.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:2b8f157c8a6f20eb657e240f8985cc135598b2b46985c5bccbde7616dc9c6b1e"},
+ {file = "numpy-2.4.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:5daf6f3914a733336dab21a05cdec343144600e964d2fcdabaac0c0269874b2a"},
+ {file = "numpy-2.4.2-cp314-cp314t-win32.whl", hash = "sha256:8c50dd1fc8826f5b26a5ee4d77ca55d88a895f4e4819c7ecc2a9f5905047a443"},
+ {file = "numpy-2.4.2-cp314-cp314t-win_amd64.whl", hash = "sha256:fcf92bee92742edd401ba41135185866f7026c502617f422eb432cfeca4fe236"},
+ {file = "numpy-2.4.2-cp314-cp314t-win_arm64.whl", hash = "sha256:1f92f53998a17265194018d1cc321b2e96e900ca52d54c7c77837b71b9465181"},
+ {file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:89f7268c009bc492f506abd6f5265defa7cb3f7487dc21d357c3d290add45082"},
+ {file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:e6dee3bb76aa4009d5a912180bf5b2de012532998d094acee25d9cb8dee3e44a"},
+ {file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_arm64.whl", hash = "sha256:cd2bd2bbed13e213d6b55dc1d035a4f91748a7d3edc9480c13898b0353708920"},
+ {file = "numpy-2.4.2-pp311-pypy311_pp73-macosx_14_0_x86_64.whl", hash = "sha256:cf28c0c1d4c4bf00f509fa7eb02c58d7caf221b50b467bcb0d9bbf1584d5c821"},
+ {file = "numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e04ae107ac591763a47398bb45b568fc38f02dbc4aa44c063f67a131f99346cb"},
+ {file = "numpy-2.4.2-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:602f65afdef699cda27ec0b9224ae5dc43e328f4c24c689deaf77133dbee74d0"},
+ {file = "numpy-2.4.2-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:be71bf1edb48ebbbf7f6337b5bfd2f895d1902f6335a5830b20141fc126ffba0"},
+ {file = "numpy-2.4.2.tar.gz", hash = "sha256:659a6107e31a83c4e33f763942275fd278b21d095094044eb35569e86a21ddae"},
]
[[package]]
name = "packaging"
-version = "25.0"
+version = "26.0"
description = "Core utilities for Python packages"
optional = false
python-versions = ">=3.8"
groups = ["main", "dev"]
files = [
- {file = "packaging-25.0-py3-none-any.whl", hash = "sha256:29572ef2b1f17581046b3a2227d5c611fb25ec70ca1ba8554b24b0e69331a484"},
- {file = "packaging-25.0.tar.gz", hash = "sha256:d443872c98d677bf60f6a1f2f8c1cb748e8fe762d2bf9d3148b5599295b0fc4f"},
+ {file = "packaging-26.0-py3-none-any.whl", hash = "sha256:b36f1fef9334a5588b4166f8bcd26a14e521f2b55e6b9de3aaa80d3ff7a37529"},
+ {file = "packaging-26.0.tar.gz", hash = "sha256:00243ae351a257117b6a241061796684b084ed1c516a08c48a3f7e147a9d80b4"},
]
[[package]]
@@ -1946,115 +1926,121 @@ six = "*"
[[package]]
name = "pathspec"
-version = "0.12.1"
+version = "1.0.4"
description = "Utility library for gitignore style pattern matching of file paths."
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.9"
groups = ["dev"]
files = [
- {file = "pathspec-0.12.1-py3-none-any.whl", hash = "sha256:a0d503e138a4c123b27490a4f7beda6a01c6f288df0e4a8b79c7eb0dc7b4cc08"},
- {file = "pathspec-0.12.1.tar.gz", hash = "sha256:a482d51503a1ab33b1c67a6c3813a26953dbdc71c31dacaef9a838c4e29f5712"},
+ {file = "pathspec-1.0.4-py3-none-any.whl", hash = "sha256:fb6ae2fd4e7c921a165808a552060e722767cfa526f99ca5156ed2ce45a5c723"},
+ {file = "pathspec-1.0.4.tar.gz", hash = "sha256:0210e2ae8a21a9137c0d470578cb0e595af87edaa6ebf12ff176f14a02e0e645"},
]
+[package.extras]
+hyperscan = ["hyperscan (>=0.7)"]
+optional = ["typing-extensions (>=4)"]
+re2 = ["google-re2 (>=1.1)"]
+tests = ["pytest (>=9)", "typing-extensions (>=4.15)"]
+
[[package]]
name = "pillow"
-version = "12.0.0"
+version = "12.1.0"
description = "Python Imaging Library (fork)"
optional = false
python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "pillow-12.0.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:3adfb466bbc544b926d50fe8f4a4e6abd8c6bffd28a26177594e6e9b2b76572b"},
- {file = "pillow-12.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:1ac11e8ea4f611c3c0147424eae514028b5e9077dd99ab91e1bd7bc33ff145e1"},
- {file = "pillow-12.0.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d49e2314c373f4c2b39446fb1a45ed333c850e09d0c59ac79b72eb3b95397363"},
- {file = "pillow-12.0.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:c7b2a63fd6d5246349f3d3f37b14430d73ee7e8173154461785e43036ffa96ca"},
- {file = "pillow-12.0.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:d64317d2587c70324b79861babb9c09f71fbb780bad212018874b2c013d8600e"},
- {file = "pillow-12.0.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d77153e14b709fd8b8af6f66a3afbb9ed6e9fc5ccf0b6b7e1ced7b036a228782"},
- {file = "pillow-12.0.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:32ed80ea8a90ee3e6fa08c21e2e091bba6eda8eccc83dbc34c95169507a91f10"},
- {file = "pillow-12.0.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:c828a1ae702fc712978bda0320ba1b9893d99be0badf2647f693cc01cf0f04fa"},
- {file = "pillow-12.0.0-cp310-cp310-win32.whl", hash = "sha256:bd87e140e45399c818fac4247880b9ce719e4783d767e030a883a970be632275"},
- {file = "pillow-12.0.0-cp310-cp310-win_amd64.whl", hash = "sha256:455247ac8a4cfb7b9bc45b7e432d10421aea9fc2e74d285ba4072688a74c2e9d"},
- {file = "pillow-12.0.0-cp310-cp310-win_arm64.whl", hash = "sha256:6ace95230bfb7cd79ef66caa064bbe2f2a1e63d93471c3a2e1f1348d9f22d6b7"},
- {file = "pillow-12.0.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:0fd00cac9c03256c8b2ff58f162ebcd2587ad3e1f2e397eab718c47e24d231cc"},
- {file = "pillow-12.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a3475b96f5908b3b16c47533daaa87380c491357d197564e0ba34ae75c0f3257"},
- {file = "pillow-12.0.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:110486b79f2d112cf6add83b28b627e369219388f64ef2f960fef9ebaf54c642"},
- {file = "pillow-12.0.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:5269cc1caeedb67e6f7269a42014f381f45e2e7cd42d834ede3c703a1d915fe3"},
- {file = "pillow-12.0.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:aa5129de4e174daccbc59d0a3b6d20eaf24417d59851c07ebb37aeb02947987c"},
- {file = "pillow-12.0.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bee2a6db3a7242ea309aa7ee8e2780726fed67ff4e5b40169f2c940e7eb09227"},
- {file = "pillow-12.0.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:90387104ee8400a7b4598253b4c406f8958f59fcf983a6cea2b50d59f7d63d0b"},
- {file = "pillow-12.0.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:bc91a56697869546d1b8f0a3ff35224557ae7f881050e99f615e0119bf934b4e"},
- {file = "pillow-12.0.0-cp311-cp311-win32.whl", hash = "sha256:27f95b12453d165099c84f8a8bfdfd46b9e4bda9e0e4b65f0635430027f55739"},
- {file = "pillow-12.0.0-cp311-cp311-win_amd64.whl", hash = "sha256:b583dc9070312190192631373c6c8ed277254aa6e6084b74bdd0a6d3b221608e"},
- {file = "pillow-12.0.0-cp311-cp311-win_arm64.whl", hash = "sha256:759de84a33be3b178a64c8ba28ad5c135900359e85fb662bc6e403ad4407791d"},
- {file = "pillow-12.0.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:53561a4ddc36facb432fae7a9d8afbfaf94795414f5cdc5fc52f28c1dca90371"},
- {file = "pillow-12.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:71db6b4c1653045dacc1585c1b0d184004f0d7e694c7b34ac165ca70c0838082"},
- {file = "pillow-12.0.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:2fa5f0b6716fc88f11380b88b31fe591a06c6315e955c096c35715788b339e3f"},
- {file = "pillow-12.0.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:82240051c6ca513c616f7f9da06e871f61bfd7805f566275841af15015b8f98d"},
- {file = "pillow-12.0.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:55f818bd74fe2f11d4d7cbc65880a843c4075e0ac7226bc1a23261dbea531953"},
- {file = "pillow-12.0.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b87843e225e74576437fd5b6a4c2205d422754f84a06942cfaf1dc32243e45a8"},
- {file = "pillow-12.0.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:c607c90ba67533e1b2355b821fef6764d1dd2cbe26b8c1005ae84f7aea25ff79"},
- {file = "pillow-12.0.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:21f241bdd5080a15bc86d3466a9f6074a9c2c2b314100dd896ac81ee6db2f1ba"},
- {file = "pillow-12.0.0-cp312-cp312-win32.whl", hash = "sha256:dd333073e0cacdc3089525c7df7d39b211bcdf31fc2824e49d01c6b6187b07d0"},
- {file = "pillow-12.0.0-cp312-cp312-win_amd64.whl", hash = "sha256:9fe611163f6303d1619bbcb653540a4d60f9e55e622d60a3108be0d5b441017a"},
- {file = "pillow-12.0.0-cp312-cp312-win_arm64.whl", hash = "sha256:7dfb439562f234f7d57b1ac6bc8fe7f838a4bd49c79230e0f6a1da93e82f1fad"},
- {file = "pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:0869154a2d0546545cde61d1789a6524319fc1897d9ee31218eae7a60ccc5643"},
- {file = "pillow-12.0.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:a7921c5a6d31b3d756ec980f2f47c0cfdbce0fc48c22a39347a895f41f4a6ea4"},
- {file = "pillow-12.0.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:1ee80a59f6ce048ae13cda1abf7fbd2a34ab9ee7d401c46be3ca685d1999a399"},
- {file = "pillow-12.0.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:c50f36a62a22d350c96e49ad02d0da41dbd17ddc2e29750dbdba4323f85eb4a5"},
- {file = "pillow-12.0.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:5193fde9a5f23c331ea26d0cf171fbf67e3f247585f50c08b3e205c7aeb4589b"},
- {file = "pillow-12.0.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bde737cff1a975b70652b62d626f7785e0480918dece11e8fef3c0cf057351c3"},
- {file = "pillow-12.0.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:a6597ff2b61d121172f5844b53f21467f7082f5fb385a9a29c01414463f93b07"},
- {file = "pillow-12.0.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b817e7035ea7f6b942c13aa03bb554fc44fea70838ea21f8eb31c638326584e"},
- {file = "pillow-12.0.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:f4f1231b7dec408e8670264ce63e9c71409d9583dd21d32c163e25213ee2a344"},
- {file = "pillow-12.0.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:6e51b71417049ad6ab14c49608b4a24d8fb3fe605e5dfabfe523b58064dc3d27"},
- {file = "pillow-12.0.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d120c38a42c234dc9a8c5de7ceaaf899cf33561956acb4941653f8bdc657aa79"},
- {file = "pillow-12.0.0-cp313-cp313-win32.whl", hash = "sha256:4cc6b3b2efff105c6a1656cfe59da4fdde2cda9af1c5e0b58529b24525d0a098"},
- {file = "pillow-12.0.0-cp313-cp313-win_amd64.whl", hash = "sha256:4cf7fed4b4580601c4345ceb5d4cbf5a980d030fd5ad07c4d2ec589f95f09905"},
- {file = "pillow-12.0.0-cp313-cp313-win_arm64.whl", hash = "sha256:9f0b04c6b8584c2c193babcccc908b38ed29524b29dd464bc8801bf10d746a3a"},
- {file = "pillow-12.0.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7fa22993bac7b77b78cae22bad1e2a987ddf0d9015c63358032f84a53f23cdc3"},
- {file = "pillow-12.0.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:f135c702ac42262573fe9714dfe99c944b4ba307af5eb507abef1667e2cbbced"},
- {file = "pillow-12.0.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:c85de1136429c524e55cfa4e033b4a7940ac5c8ee4d9401cc2d1bf48154bbc7b"},
- {file = "pillow-12.0.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:38df9b4bfd3db902c9c2bd369bcacaf9d935b2fff73709429d95cc41554f7b3d"},
- {file = "pillow-12.0.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:7d87ef5795da03d742bf49439f9ca4d027cde49c82c5371ba52464aee266699a"},
- {file = "pillow-12.0.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:aff9e4d82d082ff9513bdd6acd4f5bd359f5b2c870907d2b0a9c5e10d40c88fe"},
- {file = "pillow-12.0.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:8d8ca2b210ada074d57fcee40c30446c9562e542fc46aedc19baf758a93532ee"},
- {file = "pillow-12.0.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:99a7f72fb6249302aa62245680754862a44179b545ded638cf1fef59befb57ef"},
- {file = "pillow-12.0.0-cp313-cp313t-win32.whl", hash = "sha256:4078242472387600b2ce8d93ade8899c12bf33fa89e55ec89fe126e9d6d5d9e9"},
- {file = "pillow-12.0.0-cp313-cp313t-win_amd64.whl", hash = "sha256:2c54c1a783d6d60595d3514f0efe9b37c8808746a66920315bfd34a938d7994b"},
- {file = "pillow-12.0.0-cp313-cp313t-win_arm64.whl", hash = "sha256:26d9f7d2b604cd23aba3e9faf795787456ac25634d82cd060556998e39c6fa47"},
- {file = "pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:beeae3f27f62308f1ddbcfb0690bf44b10732f2ef43758f169d5e9303165d3f9"},
- {file = "pillow-12.0.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:d4827615da15cd59784ce39d3388275ec093ae3ee8d7f0c089b76fa87af756c2"},
- {file = "pillow-12.0.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:3e42edad50b6909089750e65c91aa09aaf1e0a71310d383f11321b27c224ed8a"},
- {file = "pillow-12.0.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e5d8efac84c9afcb40914ab49ba063d94f5dbdf5066db4482c66a992f47a3a3b"},
- {file = "pillow-12.0.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:266cd5f2b63ff316d5a1bba46268e603c9caf5606d44f38c2873c380950576ad"},
- {file = "pillow-12.0.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:58eea5ebe51504057dd95c5b77d21700b77615ab0243d8152793dc00eb4faf01"},
- {file = "pillow-12.0.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f13711b1a5ba512d647a0e4ba79280d3a9a045aaf7e0cc6fbe96b91d4cdf6b0c"},
- {file = "pillow-12.0.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6846bd2d116ff42cba6b646edf5bf61d37e5cbd256425fa089fee4ff5c07a99e"},
- {file = "pillow-12.0.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:c98fa880d695de164b4135a52fd2e9cd7b7c90a9d8ac5e9e443a24a95ef9248e"},
- {file = "pillow-12.0.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:fa3ed2a29a9e9d2d488b4da81dcb54720ac3104a20bf0bd273f1e4648aff5af9"},
- {file = "pillow-12.0.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:d034140032870024e6b9892c692fe2968493790dd57208b2c37e3fb35f6df3ab"},
- {file = "pillow-12.0.0-cp314-cp314-win32.whl", hash = "sha256:1b1b133e6e16105f524a8dec491e0586d072948ce15c9b914e41cdadd209052b"},
- {file = "pillow-12.0.0-cp314-cp314-win_amd64.whl", hash = "sha256:8dc232e39d409036af549c86f24aed8273a40ffa459981146829a324e0848b4b"},
- {file = "pillow-12.0.0-cp314-cp314-win_arm64.whl", hash = "sha256:d52610d51e265a51518692045e372a4c363056130d922a7351429ac9f27e70b0"},
- {file = "pillow-12.0.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:1979f4566bb96c1e50a62d9831e2ea2d1211761e5662afc545fa766f996632f6"},
- {file = "pillow-12.0.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:b2e4b27a6e15b04832fe9bf292b94b5ca156016bbc1ea9c2c20098a0320d6cf6"},
- {file = "pillow-12.0.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fb3096c30df99fd01c7bf8e544f392103d0795b9f98ba71a8054bcbf56b255f1"},
- {file = "pillow-12.0.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7438839e9e053ef79f7112c881cef684013855016f928b168b81ed5835f3e75e"},
- {file = "pillow-12.0.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5d5c411a8eaa2299322b647cd932586b1427367fd3184ffbb8f7a219ea2041ca"},
- {file = "pillow-12.0.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d7e091d464ac59d2c7ad8e7e08105eaf9dafbc3883fd7265ffccc2baad6ac925"},
- {file = "pillow-12.0.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:792a2c0be4dcc18af9d4a2dfd8a11a17d5e25274a1062b0ec1c2d79c76f3e7f8"},
- {file = "pillow-12.0.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:afbefa430092f71a9593a99ab6a4e7538bc9eabbf7bf94f91510d3503943edc4"},
- {file = "pillow-12.0.0-cp314-cp314t-win32.whl", hash = "sha256:3830c769decf88f1289680a59d4f4c46c72573446352e2befec9a8512104fa52"},
- {file = "pillow-12.0.0-cp314-cp314t-win_amd64.whl", hash = "sha256:905b0365b210c73afb0ebe9101a32572152dfd1c144c7e28968a331b9217b94a"},
- {file = "pillow-12.0.0-cp314-cp314t-win_arm64.whl", hash = "sha256:99353a06902c2e43b43e8ff74ee65a7d90307d82370604746738a1e0661ccca7"},
- {file = "pillow-12.0.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:b22bd8c974942477156be55a768f7aa37c46904c175be4e158b6a86e3a6b7ca8"},
- {file = "pillow-12.0.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:805ebf596939e48dbb2e4922a1d3852cfc25c38160751ce02da93058b48d252a"},
- {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:cae81479f77420d217def5f54b5b9d279804d17e982e0f2fa19b1d1e14ab5197"},
- {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:aeaefa96c768fc66818730b952a862235d68825c178f1b3ffd4efd7ad2edcb7c"},
- {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:09f2d0abef9e4e2f349305a4f8cc784a8a6c2f58a8c4892eea13b10a943bd26e"},
- {file = "pillow-12.0.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:bdee52571a343d721fb2eb3b090a82d959ff37fc631e3f70422e0c2e029f3e76"},
- {file = "pillow-12.0.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:b290fd8aa38422444d4b50d579de197557f182ef1068b75f5aa8558638b8d0a5"},
- {file = "pillow-12.0.0.tar.gz", hash = "sha256:87d4f8125c9988bfbed67af47dd7a953e2fc7b0cc1e7800ec6d2080d490bb353"},
+ {file = "pillow-12.1.0-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:fb125d860738a09d363a88daa0f59c4533529a90e564785e20fe875b200b6dbd"},
+ {file = "pillow-12.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:cad302dc10fac357d3467a74a9561c90609768a6f73a1923b0fd851b6486f8b0"},
+ {file = "pillow-12.1.0-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:a40905599d8079e09f25027423aed94f2823adaf2868940de991e53a449e14a8"},
+ {file = "pillow-12.1.0-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:92a7fe4225365c5e3a8e598982269c6d6698d3e783b3b1ae979e7819f9cd55c1"},
+ {file = "pillow-12.1.0-cp310-cp310-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f10c98f49227ed8383d28174ee95155a675c4ed7f85e2e573b04414f7e371bda"},
+ {file = "pillow-12.1.0-cp310-cp310-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8637e29d13f478bc4f153d8daa9ffb16455f0a6cb287da1b432fdad2bfbd66c7"},
+ {file = "pillow-12.1.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:21e686a21078b0f9cb8c8a961d99e6a4ddb88e0fc5ea6e130172ddddc2e5221a"},
+ {file = "pillow-12.1.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:2415373395a831f53933c23ce051021e79c8cd7979822d8cc478547a3f4da8ef"},
+ {file = "pillow-12.1.0-cp310-cp310-win32.whl", hash = "sha256:e75d3dba8fc1ddfec0cd752108f93b83b4f8d6ab40e524a95d35f016b9683b09"},
+ {file = "pillow-12.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:64efdf00c09e31efd754448a383ea241f55a994fd079866b92d2bbff598aad91"},
+ {file = "pillow-12.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f188028b5af6b8fb2e9a76ac0f841a575bd1bd396e46ef0840d9b88a48fdbcea"},
+ {file = "pillow-12.1.0-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:a83e0850cb8f5ac975291ebfc4170ba481f41a28065277f7f735c202cd8e0af3"},
+ {file = "pillow-12.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b6e53e82ec2db0717eabb276aa56cf4e500c9a7cec2c2e189b55c24f65a3e8c0"},
+ {file = "pillow-12.1.0-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:40a8e3b9e8773876d6e30daed22f016509e3987bab61b3b7fe309d7019a87451"},
+ {file = "pillow-12.1.0-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:800429ac32c9b72909c671aaf17ecd13110f823ddb7db4dfef412a5587c2c24e"},
+ {file = "pillow-12.1.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0b022eaaf709541b391ee069f0022ee5b36c709df71986e3f7be312e46f42c84"},
+ {file = "pillow-12.1.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:1f345e7bc9d7f368887c712aa5054558bad44d2a301ddf9248599f4161abc7c0"},
+ {file = "pillow-12.1.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:d70347c8a5b7ccd803ec0c85c8709f036e6348f1e6a5bf048ecd9c64d3550b8b"},
+ {file = "pillow-12.1.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1fcc52d86ce7a34fd17cb04e87cfdb164648a3662a6f20565910a99653d66c18"},
+ {file = "pillow-12.1.0-cp311-cp311-win32.whl", hash = "sha256:3ffaa2f0659e2f740473bcf03c702c39a8d4b2b7ffc629052028764324842c64"},
+ {file = "pillow-12.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:806f3987ffe10e867bab0ddad45df1148a2b98221798457fa097ad85d6e8bc75"},
+ {file = "pillow-12.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9f5fefaca968e700ad1a4a9de98bf0869a94e397fe3524c4c9450c1445252304"},
+ {file = "pillow-12.1.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:a332ac4ccb84b6dde65dbace8431f3af08874bf9770719d32a635c4ef411b18b"},
+ {file = "pillow-12.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:907bfa8a9cb790748a9aa4513e37c88c59660da3bcfffbd24a7d9e6abf224551"},
+ {file = "pillow-12.1.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:efdc140e7b63b8f739d09a99033aa430accce485ff78e6d311973a67b6bf3208"},
+ {file = "pillow-12.1.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:bef9768cab184e7ae6e559c032e95ba8d07b3023c289f79a2bd36e8bf85605a5"},
+ {file = "pillow-12.1.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:742aea052cf5ab5034a53c3846165bc3ce88d7c38e954120db0ab867ca242661"},
+ {file = "pillow-12.1.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:a6dfc2af5b082b635af6e08e0d1f9f1c4e04d17d4e2ca0ef96131e85eda6eb17"},
+ {file = "pillow-12.1.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:609e89d9f90b581c8d16358c9087df76024cf058fa693dd3e1e1620823f39670"},
+ {file = "pillow-12.1.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:43b4899cfd091a9693a1278c4982f3e50f7fb7cff5153b05174b4afc9593b616"},
+ {file = "pillow-12.1.0-cp312-cp312-win32.whl", hash = "sha256:aa0c9cc0b82b14766a99fbe6084409972266e82f459821cd26997a488a7261a7"},
+ {file = "pillow-12.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:d70534cea9e7966169ad29a903b99fc507e932069a881d0965a1a84bb57f6c6d"},
+ {file = "pillow-12.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:65b80c1ee7e14a87d6a068dd3b0aea268ffcabfe0498d38661b00c5b4b22e74c"},
+ {file = "pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphoneos.whl", hash = "sha256:7b5dd7cbae20285cdb597b10eb5a2c13aa9de6cde9bb64a3c1317427b1db1ae1"},
+ {file = "pillow-12.1.0-cp313-cp313-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:29a4cef9cb672363926f0470afc516dbf7305a14d8c54f7abbb5c199cd8f8179"},
+ {file = "pillow-12.1.0-cp313-cp313-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:681088909d7e8fa9e31b9799aaa59ba5234c58e5e4f1951b4c4d1082a2e980e0"},
+ {file = "pillow-12.1.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:983976c2ab753166dc66d36af6e8ec15bb511e4a25856e2227e5f7e00a160587"},
+ {file = "pillow-12.1.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:db44d5c160a90df2d24a24760bbd37607d53da0b34fb546c4c232af7192298ac"},
+ {file = "pillow-12.1.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:6b7a9d1db5dad90e2991645874f708e87d9a3c370c243c2d7684d28f7e133e6b"},
+ {file = "pillow-12.1.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:6258f3260986990ba2fa8a874f8b6e808cf5abb51a94015ca3dc3c68aa4f30ea"},
+ {file = "pillow-12.1.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e115c15e3bc727b1ca3e641a909f77f8ca72a64fff150f666fcc85e57701c26c"},
+ {file = "pillow-12.1.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6741e6f3074a35e47c77b23a4e4f2d90db3ed905cb1c5e6e0d49bff2045632bc"},
+ {file = "pillow-12.1.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:935b9d1aed48fcfb3f838caac506f38e29621b44ccc4f8a64d575cb1b2a88644"},
+ {file = "pillow-12.1.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:5fee4c04aad8932da9f8f710af2c1a15a83582cfb884152a9caa79d4efcdbf9c"},
+ {file = "pillow-12.1.0-cp313-cp313-win32.whl", hash = "sha256:a786bf667724d84aa29b5db1c61b7bfdde380202aaca12c3461afd6b71743171"},
+ {file = "pillow-12.1.0-cp313-cp313-win_amd64.whl", hash = "sha256:461f9dfdafa394c59cd6d818bdfdbab4028b83b02caadaff0ffd433faf4c9a7a"},
+ {file = "pillow-12.1.0-cp313-cp313-win_arm64.whl", hash = "sha256:9212d6b86917a2300669511ed094a9406888362e085f2431a7da985a6b124f45"},
+ {file = "pillow-12.1.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:00162e9ca6d22b7c3ee8e61faa3c3253cd19b6a37f126cad04f2f88b306f557d"},
+ {file = "pillow-12.1.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:7d6daa89a00b58c37cb1747ec9fb7ac3bc5ffd5949f5888657dfddde6d1312e0"},
+ {file = "pillow-12.1.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e2479c7f02f9d505682dc47df8c0ea1fc5e264c4d1629a5d63fe3e2334b89554"},
+ {file = "pillow-12.1.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:f188d580bd870cda1e15183790d1cc2fa78f666e76077d103edf048eed9c356e"},
+ {file = "pillow-12.1.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0fde7ec5538ab5095cc02df38ee99b0443ff0e1c847a045554cf5f9af1f4aa82"},
+ {file = "pillow-12.1.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0ed07dca4a8464bada6139ab38f5382f83e5f111698caf3191cb8dbf27d908b4"},
+ {file = "pillow-12.1.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:f45bd71d1fa5e5749587613037b172e0b3b23159d1c00ef2fc920da6f470e6f0"},
+ {file = "pillow-12.1.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:277518bf4fe74aa91489e1b20577473b19ee70fb97c374aa50830b279f25841b"},
+ {file = "pillow-12.1.0-cp313-cp313t-win32.whl", hash = "sha256:7315f9137087c4e0ee73a761b163fc9aa3b19f5f606a7fc08d83fd3e4379af65"},
+ {file = "pillow-12.1.0-cp313-cp313t-win_amd64.whl", hash = "sha256:0ddedfaa8b5f0b4ffbc2fa87b556dc59f6bb4ecb14a53b33f9189713ae8053c0"},
+ {file = "pillow-12.1.0-cp313-cp313t-win_arm64.whl", hash = "sha256:80941e6d573197a0c28f394753de529bb436b1ca990ed6e765cf42426abc39f8"},
+ {file = "pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphoneos.whl", hash = "sha256:5cb7bc1966d031aec37ddb9dcf15c2da5b2e9f7cc3ca7c54473a20a927e1eb91"},
+ {file = "pillow-12.1.0-cp314-cp314-ios_13_0_arm64_iphonesimulator.whl", hash = "sha256:97e9993d5ed946aba26baf9c1e8cf18adbab584b99f452ee72f7ee8acb882796"},
+ {file = "pillow-12.1.0-cp314-cp314-ios_13_0_x86_64_iphonesimulator.whl", hash = "sha256:414b9a78e14ffeb98128863314e62c3f24b8a86081066625700b7985b3f529bd"},
+ {file = "pillow-12.1.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:e6bdb408f7c9dd2a5ff2b14a3b0bb6d4deb29fb9961e6eb3ae2031ae9a5cec13"},
+ {file = "pillow-12.1.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:3413c2ae377550f5487991d444428f1a8ae92784aac79caa8b1e3b89b175f77e"},
+ {file = "pillow-12.1.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e5dcbe95016e88437ecf33544ba5db21ef1b8dd6e1b434a2cb2a3d605299e643"},
+ {file = "pillow-12.1.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d0a7735df32ccbcc98b98a1ac785cc4b19b580be1bdf0aeb5c03223220ea09d5"},
+ {file = "pillow-12.1.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0c27407a2d1b96774cbc4a7594129cc027339fd800cd081e44497722ea1179de"},
+ {file = "pillow-12.1.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:15c794d74303828eaa957ff8070846d0efe8c630901a1c753fdc63850e19ecd9"},
+ {file = "pillow-12.1.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:c990547452ee2800d8506c4150280757f88532f3de2a58e3022e9b179107862a"},
+ {file = "pillow-12.1.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b63e13dd27da389ed9475b3d28510f0f954bca0041e8e551b2a4eb1eab56a39a"},
+ {file = "pillow-12.1.0-cp314-cp314-win32.whl", hash = "sha256:1a949604f73eb07a8adab38c4fe50791f9919344398bdc8ac6b307f755fc7030"},
+ {file = "pillow-12.1.0-cp314-cp314-win_amd64.whl", hash = "sha256:4f9f6a650743f0ddee5593ac9e954ba1bdbc5e150bc066586d4f26127853ab94"},
+ {file = "pillow-12.1.0-cp314-cp314-win_arm64.whl", hash = "sha256:808b99604f7873c800c4840f55ff389936ef1948e4e87645eaf3fccbc8477ac4"},
+ {file = "pillow-12.1.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:bc11908616c8a283cf7d664f77411a5ed2a02009b0097ff8abbba5e79128ccf2"},
+ {file = "pillow-12.1.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:896866d2d436563fa2a43a9d72f417874f16b5545955c54a64941e87c1376c61"},
+ {file = "pillow-12.1.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8e178e3e99d3c0ea8fc64b88447f7cac8ccf058af422a6cedc690d0eadd98c51"},
+ {file = "pillow-12.1.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:079af2fb0c599c2ec144ba2c02766d1b55498e373b3ac64687e43849fbbef5bc"},
+ {file = "pillow-12.1.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:bdec5e43377761c5dbca620efb69a77f6855c5a379e32ac5b158f54c84212b14"},
+ {file = "pillow-12.1.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:565c986f4b45c020f5421a4cea13ef294dde9509a8577f29b2fc5edc7587fff8"},
+ {file = "pillow-12.1.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:43aca0a55ce1eefc0aefa6253661cb54571857b1a7b2964bd8a1e3ef4b729924"},
+ {file = "pillow-12.1.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:0deedf2ea233722476b3a81e8cdfbad786f7adbed5d848469fa59fe52396e4ef"},
+ {file = "pillow-12.1.0-cp314-cp314t-win32.whl", hash = "sha256:b17fbdbe01c196e7e159aacb889e091f28e61020a8abeac07b68079b6e626988"},
+ {file = "pillow-12.1.0-cp314-cp314t-win_amd64.whl", hash = "sha256:27b9baecb428899db6c0de572d6d305cfaf38ca1596b5c0542a5182e3e74e8c6"},
+ {file = "pillow-12.1.0-cp314-cp314t-win_arm64.whl", hash = "sha256:f61333d817698bdcdd0f9d7793e365ac3d2a21c1f1eb02b32ad6aefb8d8ea831"},
+ {file = "pillow-12.1.0-pp311-pypy311_pp73-macosx_10_15_x86_64.whl", hash = "sha256:ca94b6aac0d7af2a10ba08c0f888b3d5114439b6b3ef39968378723622fed377"},
+ {file = "pillow-12.1.0-pp311-pypy311_pp73-macosx_11_0_arm64.whl", hash = "sha256:351889afef0f485b84078ea40fe33727a0492b9af3904661b0abbafee0355b72"},
+ {file = "pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:bb0984b30e973f7e2884362b7d23d0a348c7143ee559f38ef3eaab640144204c"},
+ {file = "pillow-12.1.0-pp311-pypy311_pp73-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:84cabc7095dd535ca934d57e9ce2a72ffd216e435a84acb06b2277b1de2689bd"},
+ {file = "pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:53d8b764726d3af1a138dd353116f774e3862ec7e3794e0c8781e30db0f35dfc"},
+ {file = "pillow-12.1.0-pp311-pypy311_pp73-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:5da841d81b1a05ef940a8567da92decaa15bc4d7dedb540a8c219ad83d91808a"},
+ {file = "pillow-12.1.0-pp311-pypy311_pp73-win_amd64.whl", hash = "sha256:75af0b4c229ac519b155028fa1be632d812a519abba9b46b20e50c6caa184f19"},
+ {file = "pillow-12.1.0.tar.gz", hash = "sha256:5c5ae0a06e9ea030ab786b0251b32c7e4ce10e58d983c0d5c56029455180b5b9"},
]
[package.extras]
@@ -2300,15 +2286,15 @@ files = [
[[package]]
name = "pycparser"
-version = "2.23"
+version = "3.0"
description = "C parser in Python"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.10"
groups = ["main"]
markers = "implementation_name != \"PyPy\""
files = [
- {file = "pycparser-2.23-py3-none-any.whl", hash = "sha256:e5c6e8d3fbad53479cab09ac03729e0a9faf2bee3db8208a550daf5af81a5934"},
- {file = "pycparser-2.23.tar.gz", hash = "sha256:78816d4f24add8f10a06d6f05b4d424ad9e96cfebf68a4ddc99c65c0720d00c2"},
+ {file = "pycparser-3.0-py3-none-any.whl", hash = "sha256:b727414169a36b7d524c1c3e31839a521725078d7b2ff038656844266160a992"},
+ {file = "pycparser-3.0.tar.gz", hash = "sha256:600f49d217304a5902ac3c37e1281c9fe94e4d0489de643a9504c5cdfdfc6b29"},
]
[[package]]
@@ -2547,57 +2533,55 @@ windows-terminal = ["colorama (>=0.4.6)"]
[[package]]
name = "pyjwt"
-version = "2.10.1"
+version = "2.11.0"
description = "JSON Web Token implementation in Python"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "PyJWT-2.10.1-py3-none-any.whl", hash = "sha256:dcdd193e30abefd5debf142f9adfcdd2b58004e644f25406ffaebd50bd98dacb"},
- {file = "pyjwt-2.10.1.tar.gz", hash = "sha256:3cc5772eb20009233caf06e9d8a0577824723b44e6648ee0a2aedb6cf9381953"},
+ {file = "pyjwt-2.11.0-py3-none-any.whl", hash = "sha256:94a6bde30eb5c8e04fee991062b534071fd1439ef58d2adc9ccb823e7bcd0469"},
+ {file = "pyjwt-2.11.0.tar.gz", hash = "sha256:35f95c1f0fbe5d5ba6e43f00271c275f7a1a4db1dab27bf708073b75318ea623"},
]
[package.extras]
crypto = ["cryptography (>=3.4.0)"]
-dev = ["coverage[toml] (==5.0.4)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=6.0.0,<7.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"]
+dev = ["coverage[toml] (==7.10.7)", "cryptography (>=3.4.0)", "pre-commit", "pytest (>=8.4.2,<9.0.0)", "sphinx", "sphinx-rtd-theme", "zope.interface"]
docs = ["sphinx", "sphinx-rtd-theme", "zope.interface"]
-tests = ["coverage[toml] (==5.0.4)", "pytest (>=6.0.0,<7.0.0)"]
+tests = ["coverage[toml] (==7.10.7)", "pytest (>=8.4.2,<9.0.0)"]
[[package]]
name = "pynacl"
-version = "1.6.1"
+version = "1.6.2"
description = "Python binding to the Networking and Cryptography (NaCl) library"
optional = false
python-versions = ">=3.8"
groups = ["main"]
files = [
- {file = "pynacl-1.6.1-cp314-cp314t-macosx_10_10_universal2.whl", hash = "sha256:7d7c09749450c385301a3c20dca967a525152ae4608c0a096fe8464bfc3df93d"},
- {file = "pynacl-1.6.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:fc734c1696ffd49b40f7c1779c89ba908157c57345cf626be2e0719488a076d3"},
- {file = "pynacl-1.6.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:3cd787ec1f5c155dc8ecf39b1333cfef41415dc96d392f1ce288b4fe970df489"},
- {file = "pynacl-1.6.1-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b35d93ab2df03ecb3aa506be0d3c73609a51449ae0855c2e89c7ed44abde40b"},
- {file = "pynacl-1.6.1-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dece79aecbb8f4640a1adbb81e4aa3bfb0e98e99834884a80eb3f33c7c30e708"},
- {file = "pynacl-1.6.1-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:c2228054f04bf32d558fb89bb99f163a8197d5a9bf4efa13069a7fa8d4b93fc3"},
- {file = "pynacl-1.6.1-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:2b12f1b97346f177affcdfdc78875ff42637cb40dcf79484a97dae3448083a78"},
- {file = "pynacl-1.6.1-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:e735c3a1bdfde3834503baf1a6d74d4a143920281cb724ba29fb84c9f49b9c48"},
- {file = "pynacl-1.6.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:3384a454adf5d716a9fadcb5eb2e3e72cd49302d1374a60edc531c9957a9b014"},
- {file = "pynacl-1.6.1-cp314-cp314t-win32.whl", hash = "sha256:d8615ee34d01c8e0ab3f302dcdd7b32e2bcf698ba5f4809e7cc407c8cdea7717"},
- {file = "pynacl-1.6.1-cp314-cp314t-win_amd64.whl", hash = "sha256:5f5b35c1a266f8a9ad22525049280a600b19edd1f785bccd01ae838437dcf935"},
- {file = "pynacl-1.6.1-cp314-cp314t-win_arm64.whl", hash = "sha256:d984c91fe3494793b2a1fb1e91429539c6c28e9ec8209d26d25041ec599ccf63"},
- {file = "pynacl-1.6.1-cp38-abi3-macosx_10_10_universal2.whl", hash = "sha256:a6f9fd6d6639b1e81115c7f8ff16b8dedba1e8098d2756275d63d208b0e32021"},
- {file = "pynacl-1.6.1-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:e49a3f3d0da9f79c1bec2aa013261ab9fa651c7da045d376bd306cf7c1792993"},
- {file = "pynacl-1.6.1-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7713f8977b5d25f54a811ec9efa2738ac592e846dd6e8a4d3f7578346a841078"},
- {file = "pynacl-1.6.1-cp38-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5a3becafc1ee2e5ea7f9abc642f56b82dcf5be69b961e782a96ea52b55d8a9fc"},
- {file = "pynacl-1.6.1-cp38-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:4ce50d19f1566c391fedc8dc2f2f5be265ae214112ebe55315e41d1f36a7f0a9"},
- {file = "pynacl-1.6.1-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:543f869140f67d42b9b8d47f922552d7a967e6c116aad028c9bfc5f3f3b3a7b7"},
- {file = "pynacl-1.6.1-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:a2bb472458c7ca959aeeff8401b8efef329b0fc44a89d3775cffe8fad3398ad8"},
- {file = "pynacl-1.6.1-cp38-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:3206fa98737fdc66d59b8782cecc3d37d30aeec4593d1c8c145825a345bba0f0"},
- {file = "pynacl-1.6.1-cp38-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:53543b4f3d8acb344f75fd4d49f75e6572fce139f4bfb4815a9282296ff9f4c0"},
- {file = "pynacl-1.6.1-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:319de653ef84c4f04e045eb250e6101d23132372b0a61a7acf91bac0fda8e58c"},
- {file = "pynacl-1.6.1-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:262a8de6bba4aee8a66f5edf62c214b06647461c9b6b641f8cd0cb1e3b3196fe"},
- {file = "pynacl-1.6.1-cp38-abi3-win32.whl", hash = "sha256:9fd1a4eb03caf8a2fe27b515a998d26923adb9ddb68db78e35ca2875a3830dde"},
- {file = "pynacl-1.6.1-cp38-abi3-win_amd64.whl", hash = "sha256:a569a4069a7855f963940040f35e87d8bc084cb2d6347428d5ad20550a0a1a21"},
- {file = "pynacl-1.6.1-cp38-abi3-win_arm64.whl", hash = "sha256:5953e8b8cfadb10889a6e7bd0f53041a745d1b3d30111386a1bb37af171e6daf"},
- {file = "pynacl-1.6.1.tar.gz", hash = "sha256:8d361dac0309f2b6ad33b349a56cd163c98430d409fa503b10b70b3ad66eaa1d"},
+ {file = "pynacl-1.6.2-cp314-cp314t-macosx_10_10_universal2.whl", hash = "sha256:622d7b07cc5c02c666795792931b50c91f3ce3c2649762efb1ef0d5684c81594"},
+ {file = "pynacl-1.6.2-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:d071c6a9a4c94d79eb665db4ce5cedc537faf74f2355e4d502591d850d3913c0"},
+ {file = "pynacl-1.6.2-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:fe9847ca47d287af41e82be1dd5e23023d3c31a951da134121ab02e42ac218c9"},
+ {file = "pynacl-1.6.2-cp314-cp314t-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:04316d1fc625d860b6c162fff704eb8426b1a8bcd3abacea11142cbd99a6b574"},
+ {file = "pynacl-1.6.2-cp314-cp314t-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:44081faff368d6c5553ccf55322ef2819abb40e25afaec7e740f159f74813634"},
+ {file = "pynacl-1.6.2-cp314-cp314t-manylinux_2_34_aarch64.whl", hash = "sha256:a9f9932d8d2811ce1a8ffa79dcbdf3970e7355b5c8eb0c1a881a57e7f7d96e88"},
+ {file = "pynacl-1.6.2-cp314-cp314t-manylinux_2_34_x86_64.whl", hash = "sha256:bc4a36b28dd72fb4845e5d8f9760610588a96d5a51f01d84d8c6ff9849968c14"},
+ {file = "pynacl-1.6.2-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:3bffb6d0f6becacb6526f8f42adfb5efb26337056ee0831fb9a7044d1a964444"},
+ {file = "pynacl-1.6.2-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:2fef529ef3ee487ad8113d287a593fa26f48ee3620d92ecc6f1d09ea38e0709b"},
+ {file = "pynacl-1.6.2-cp314-cp314t-win32.whl", hash = "sha256:a84bf1c20339d06dc0c85d9aea9637a24f718f375d861b2668b2f9f96fa51145"},
+ {file = "pynacl-1.6.2-cp314-cp314t-win_amd64.whl", hash = "sha256:320ef68a41c87547c91a8b58903c9caa641ab01e8512ce291085b5fe2fcb7590"},
+ {file = "pynacl-1.6.2-cp314-cp314t-win_arm64.whl", hash = "sha256:d29bfe37e20e015a7d8b23cfc8bd6aa7909c92a1b8f41ee416bbb3e79ef182b2"},
+ {file = "pynacl-1.6.2-cp38-abi3-macosx_10_10_universal2.whl", hash = "sha256:c949ea47e4206af7c8f604b8278093b674f7c79ed0d4719cc836902bf4517465"},
+ {file = "pynacl-1.6.2-cp38-abi3-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8845c0631c0be43abdd865511c41eab235e0be69c81dc66a50911594198679b0"},
+ {file = "pynacl-1.6.2-cp38-abi3-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:22de65bb9010a725b0dac248f353bb072969c94fa8d6b1f34b87d7953cf7bbe4"},
+ {file = "pynacl-1.6.2-cp38-abi3-manylinux_2_26_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:46065496ab748469cdd999246d17e301b2c24ae2fdf739132e580a0e94c94a87"},
+ {file = "pynacl-1.6.2-cp38-abi3-manylinux_2_26_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8a66d6fb6ae7661c58995f9c6435bda2b1e68b54b598a6a10247bfcdadac996c"},
+ {file = "pynacl-1.6.2-cp38-abi3-manylinux_2_34_aarch64.whl", hash = "sha256:26bfcd00dcf2cf160f122186af731ae30ab120c18e8375684ec2670dccd28130"},
+ {file = "pynacl-1.6.2-cp38-abi3-manylinux_2_34_x86_64.whl", hash = "sha256:c8a231e36ec2cab018c4ad4358c386e36eede0319a0c41fed24f840b1dac59f6"},
+ {file = "pynacl-1.6.2-cp38-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:68be3a09455743ff9505491220b64440ced8973fe930f270c8e07ccfa25b1f9e"},
+ {file = "pynacl-1.6.2-cp38-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:8b097553b380236d51ed11356c953bf8ce36a29a3e596e934ecabe76c985a577"},
+ {file = "pynacl-1.6.2-cp38-abi3-win32.whl", hash = "sha256:5811c72b473b2f38f7e2a3dc4f8642e3a3e9b5e7317266e4ced1fba85cae41aa"},
+ {file = "pynacl-1.6.2-cp38-abi3-win_amd64.whl", hash = "sha256:62985f233210dee6548c223301b6c25440852e13d59a8b81490203c3227c5ba0"},
+ {file = "pynacl-1.6.2-cp38-abi3-win_arm64.whl", hash = "sha256:834a43af110f743a754448463e8fd61259cd4ab5bbedcf70f9dabad1d28a394c"},
+ {file = "pynacl-1.6.2.tar.gz", hash = "sha256:018494d6d696ae03c7e656e5e74cdfd8ea1326962cc401bcf018f1ed8436811c"},
]
[package.dependencies]
@@ -2609,14 +2593,14 @@ tests = ["hypothesis (>=3.27.0)", "pytest (>=7.4.0)", "pytest-cov (>=2.10.1)", "
[[package]]
name = "pyparsing"
-version = "3.2.5"
+version = "3.3.2"
description = "pyparsing - Classes and methods to define and execute parsing grammars"
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "pyparsing-3.2.5-py3-none-any.whl", hash = "sha256:e38a4f02064cf41fe6593d328d0512495ad1f3d8a91c4f73fc401b3079a59a5e"},
- {file = "pyparsing-3.2.5.tar.gz", hash = "sha256:2df8d5b7b2802ef88e8d016a2eb9c7aeaa923529cd251ed0fe4608275d4105b6"},
+ {file = "pyparsing-3.3.2-py3-none-any.whl", hash = "sha256:850ba148bd908d7e2411587e247a1e4f0327839c40e2e5e6d05a007ecc69911d"},
+ {file = "pyparsing-3.3.2.tar.gz", hash = "sha256:c777f4d763f140633dcb6d8a3eda953bf7a214dc4eff598413c070bcdc117cbc"},
]
[package.extras]
@@ -2712,7 +2696,7 @@ files = [
[[package]]
name = "python-magnetgeo"
-version = "1.0.0"
+version = "1.0.1"
description = "Python helpers to create HiFiMagnet cads and meshes"
optional = false
python-versions = ">=3.11"
@@ -2723,10 +2707,11 @@ develop = false
[package.dependencies]
pandas = ">=1.5.3"
pyyaml = ">=6.0.2,<7.0.0"
+xlwt = ">=1.3.0"
[package.extras]
dev = ["black (>=23.0.0)", "flake8 (>=6.0.0)", "isort (>=5.12.0)", "mypy (>=1.0.0)", "pytest (>=8.2.0)", "pytest-cov (>=4.0.0)", "tox (>=4.0.0)"]
-docs = ["sphinx (>=6.0.0)", "sphinx-autodoc-typehints (>=1.22.0)", "sphinx-rtd-theme (>=1.2.0)"]
+docs = ["myst-parser (>=0.18.0)", "sphinx (>=6.0.0)", "sphinx-autodoc-typehints (>=1.22.0)", "sphinx-rtd-theme (>=1.2.0)"]
test = ["pytest (>=8.2.0)", "pytest-cov (>=4.0.0)"]
[package.source]
@@ -2758,26 +2743,66 @@ url = "python_magnetsetup"
[[package]]
name = "python-multipart"
-version = "0.0.20"
+version = "0.0.22"
description = "A streaming multipart parser for Python"
optional = false
-python-versions = ">=3.8"
+python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "python_multipart-0.0.20-py3-none-any.whl", hash = "sha256:8a62d3a8335e06589fe01f2a3e178cdcc632f3fbe0d492ad9ee0ec35aab1f104"},
- {file = "python_multipart-0.0.20.tar.gz", hash = "sha256:8dd0cab45b8e23064ae09147625994d090fa46f5b0d1e13af944c331a7fa9d13"},
+ {file = "python_multipart-0.0.22-py3-none-any.whl", hash = "sha256:2b2cd894c83d21bf49d702499531c7bafd057d730c201782048f7945d82de155"},
+ {file = "python_multipart-0.0.22.tar.gz", hash = "sha256:7340bef99a7e0032613f56dc36027b959fd3b30a787ed62d310e951f7c3a3a58"},
]
[[package]]
name = "pytokens"
-version = "0.3.0"
+version = "0.4.1"
description = "A Fast, spec compliant Python 3.14+ tokenizer that runs on older Pythons."
optional = false
python-versions = ">=3.8"
groups = ["dev"]
files = [
- {file = "pytokens-0.3.0-py3-none-any.whl", hash = "sha256:95b2b5eaf832e469d141a378872480ede3f251a5a5041b8ec6e581d3ac71bbf3"},
- {file = "pytokens-0.3.0.tar.gz", hash = "sha256:2f932b14ed08de5fcf0b391ace2642f858f1394c0857202959000b68ed7a458a"},
+ {file = "pytokens-0.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2a44ed93ea23415c54f3face3b65ef2b844d96aeb3455b8a69b3df6beab6acc5"},
+ {file = "pytokens-0.4.1-cp310-cp310-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:add8bf86b71a5d9fb5b89f023a80b791e04fba57960aa790cc6125f7f1d39dfe"},
+ {file = "pytokens-0.4.1-cp310-cp310-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:670d286910b531c7b7e3c0b453fd8156f250adb140146d234a82219459b9640c"},
+ {file = "pytokens-0.4.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:4e691d7f5186bd2842c14813f79f8884bb03f5995f0575272009982c5ac6c0f7"},
+ {file = "pytokens-0.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:27b83ad28825978742beef057bfe406ad6ed524b2d28c252c5de7b4a6dd48fa2"},
+ {file = "pytokens-0.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:d70e77c55ae8380c91c0c18dea05951482e263982911fc7410b1ffd1dadd3440"},
+ {file = "pytokens-0.4.1-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a58d057208cb9075c144950d789511220b07636dd2e4708d5645d24de666bdc"},
+ {file = "pytokens-0.4.1-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:b49750419d300e2b5a3813cf229d4e5a4c728dae470bcc89867a9ad6f25a722d"},
+ {file = "pytokens-0.4.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:d9907d61f15bf7261d7e775bd5d7ee4d2930e04424bab1972591918497623a16"},
+ {file = "pytokens-0.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:ee44d0f85b803321710f9239f335aafe16553b39106384cef8e6de40cb4ef2f6"},
+ {file = "pytokens-0.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:140709331e846b728475786df8aeb27d24f48cbcf7bcd449f8de75cae7a45083"},
+ {file = "pytokens-0.4.1-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6d6c4268598f762bc8e91f5dbf2ab2f61f7b95bdc07953b602db879b3c8c18e1"},
+ {file = "pytokens-0.4.1-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:24afde1f53d95348b5a0eb19488661147285ca4dd7ed752bbc3e1c6242a304d1"},
+ {file = "pytokens-0.4.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:5ad948d085ed6c16413eb5fec6b3e02fa00dc29a2534f088d3302c47eb59adf9"},
+ {file = "pytokens-0.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:3f901fe783e06e48e8cbdc82d631fca8f118333798193e026a50ce1b3757ea68"},
+ {file = "pytokens-0.4.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:8bdb9d0ce90cbf99c525e75a2fa415144fd570a1ba987380190e8b786bc6ef9b"},
+ {file = "pytokens-0.4.1-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5502408cab1cb18e128570f8d598981c68a50d0cbd7c61312a90507cd3a1276f"},
+ {file = "pytokens-0.4.1-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:29d1d8fb1030af4d231789959f21821ab6325e463f0503a61d204343c9b355d1"},
+ {file = "pytokens-0.4.1-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:970b08dd6b86058b6dc07efe9e98414f5102974716232d10f32ff39701e841c4"},
+ {file = "pytokens-0.4.1-cp313-cp313-win_amd64.whl", hash = "sha256:9bd7d7f544d362576be74f9d5901a22f317efc20046efe2034dced238cbbfe78"},
+ {file = "pytokens-0.4.1-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:4a14d5f5fc78ce85e426aa159489e2d5961acf0e47575e08f35584009178e321"},
+ {file = "pytokens-0.4.1-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:97f50fd18543be72da51dd505e2ed20d2228c74e0464e4262e4899797803d7fa"},
+ {file = "pytokens-0.4.1-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dc74c035f9bfca0255c1af77ddd2d6ae8419012805453e4b0e7513e17904545d"},
+ {file = "pytokens-0.4.1-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:f66a6bbe741bd431f6d741e617e0f39ec7257ca1f89089593479347cc4d13324"},
+ {file = "pytokens-0.4.1-cp314-cp314-win_amd64.whl", hash = "sha256:b35d7e5ad269804f6697727702da3c517bb8a5228afa450ab0fa787732055fc9"},
+ {file = "pytokens-0.4.1-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:8fcb9ba3709ff77e77f1c7022ff11d13553f3c30299a9fe246a166903e9091eb"},
+ {file = "pytokens-0.4.1-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:79fc6b8699564e1f9b521582c35435f1bd32dd06822322ec44afdeba666d8cb3"},
+ {file = "pytokens-0.4.1-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d31b97b3de0f61571a124a00ffe9a81fb9939146c122c11060725bd5aea79975"},
+ {file = "pytokens-0.4.1-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:967cf6e3fd4adf7de8fc73cd3043754ae79c36475c1c11d514fc72cf5490094a"},
+ {file = "pytokens-0.4.1-cp314-cp314t-win_amd64.whl", hash = "sha256:584c80c24b078eec1e227079d56dc22ff755e0ba8654d8383b2c549107528918"},
+ {file = "pytokens-0.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:da5baeaf7116dced9c6bb76dc31ba04a2dc3695f3d9f74741d7910122b456edc"},
+ {file = "pytokens-0.4.1-cp38-cp38-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:11edda0942da80ff58c4408407616a310adecae1ddd22eef8c692fe266fa5009"},
+ {file = "pytokens-0.4.1-cp38-cp38-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:0fc71786e629cef478cbf29d7ea1923299181d0699dbe7c3c0f4a583811d9fc1"},
+ {file = "pytokens-0.4.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:dcafc12c30dbaf1e2af0490978352e0c4041a7cde31f4f81435c2a5e8b9cabb6"},
+ {file = "pytokens-0.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:42f144f3aafa5d92bad964d471a581651e28b24434d184871bd02e3a0d956037"},
+ {file = "pytokens-0.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:34bcc734bd2f2d5fe3b34e7b3c0116bfb2397f2d9666139988e7a3eb5f7400e3"},
+ {file = "pytokens-0.4.1-cp39-cp39-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:941d4343bf27b605e9213b26bfa1c4bf197c9c599a9627eb7305b0defcfe40c1"},
+ {file = "pytokens-0.4.1-cp39-cp39-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:3ad72b851e781478366288743198101e5eb34a414f1d5627cdd585ca3b25f1db"},
+ {file = "pytokens-0.4.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:682fa37ff4d8e95f7df6fe6fe6a431e8ed8e788023c6bcc0f0880a12eab80ad1"},
+ {file = "pytokens-0.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:30f51edd9bb7f85c748979384165601d028b84f7bd13fe14d3e065304093916a"},
+ {file = "pytokens-0.4.1-py3-none-any.whl", hash = "sha256:26cef14744a8385f35d0e095dc8b3a7583f6c953c2e3d269c7f82484bf5ad2de"},
+ {file = "pytokens-0.4.1.tar.gz", hash = "sha256:292052fe80923aae2260c073f822ceba21f3872ced9a68bb7953b348e561179a"},
]
[package.extras]
@@ -2922,81 +2947,81 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"]
[[package]]
name = "scipy"
-version = "1.16.3"
+version = "1.17.0"
description = "Fundamental algorithms for scientific computing in Python"
optional = false
python-versions = ">=3.11"
groups = ["main"]
files = [
- {file = "scipy-1.16.3-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:40be6cf99e68b6c4321e9f8782e7d5ff8265af28ef2cd56e9c9b2638fa08ad97"},
- {file = "scipy-1.16.3-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:8be1ca9170fcb6223cc7c27f4305d680ded114a1567c0bd2bfcbf947d1b17511"},
- {file = "scipy-1.16.3-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:bea0a62734d20d67608660f69dcda23e7f90fb4ca20974ab80b6ed40df87a005"},
- {file = "scipy-1.16.3-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:2a207a6ce9c24f1951241f4693ede2d393f59c07abc159b2cb2be980820e01fb"},
- {file = "scipy-1.16.3-cp311-cp311-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:532fb5ad6a87e9e9cd9c959b106b73145a03f04c7d57ea3e6f6bb60b86ab0876"},
- {file = "scipy-1.16.3-cp311-cp311-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:0151a0749efeaaab78711c78422d413c583b8cdd2011a3c1d6c794938ee9fdb2"},
- {file = "scipy-1.16.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:b7180967113560cca57418a7bc719e30366b47959dd845a93206fbed693c867e"},
- {file = "scipy-1.16.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:deb3841c925eeddb6afc1e4e4a45e418d19ec7b87c5df177695224078e8ec733"},
- {file = "scipy-1.16.3-cp311-cp311-win_amd64.whl", hash = "sha256:53c3844d527213631e886621df5695d35e4f6a75f620dca412bcd292f6b87d78"},
- {file = "scipy-1.16.3-cp311-cp311-win_arm64.whl", hash = "sha256:9452781bd879b14b6f055b26643703551320aa8d79ae064a71df55c00286a184"},
- {file = "scipy-1.16.3-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:81fc5827606858cf71446a5e98715ba0e11f0dbc83d71c7409d05486592a45d6"},
- {file = "scipy-1.16.3-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:c97176013d404c7346bf57874eaac5187d969293bf40497140b0a2b2b7482e07"},
- {file = "scipy-1.16.3-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:2b71d93c8a9936046866acebc915e2af2e292b883ed6e2cbe5c34beb094b82d9"},
- {file = "scipy-1.16.3-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:3d4a07a8e785d80289dfe66b7c27d8634a773020742ec7187b85ccc4b0e7b686"},
- {file = "scipy-1.16.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0553371015692a898e1aa858fed67a3576c34edefa6b7ebdb4e9dde49ce5c203"},
- {file = "scipy-1.16.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:72d1717fd3b5e6ec747327ce9bda32d5463f472c9dce9f54499e81fbd50245a1"},
- {file = "scipy-1.16.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fb2472e72e24d1530debe6ae078db70fb1605350c88a3d14bc401d6306dbffe"},
- {file = "scipy-1.16.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c5192722cffe15f9329a3948c4b1db789fbb1f05c97899187dcf009b283aea70"},
- {file = "scipy-1.16.3-cp312-cp312-win_amd64.whl", hash = "sha256:56edc65510d1331dae01ef9b658d428e33ed48b4f77b1d51caf479a0253f96dc"},
- {file = "scipy-1.16.3-cp312-cp312-win_arm64.whl", hash = "sha256:a8a26c78ef223d3e30920ef759e25625a0ecdd0d60e5a8818b7513c3e5384cf2"},
- {file = "scipy-1.16.3-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:d2ec56337675e61b312179a1ad124f5f570c00f920cc75e1000025451b88241c"},
- {file = "scipy-1.16.3-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:16b8bc35a4cc24db80a0ec836a9286d0e31b2503cb2fd7ff7fb0e0374a97081d"},
- {file = "scipy-1.16.3-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:5803c5fadd29de0cf27fa08ccbfe7a9e5d741bf63e4ab1085437266f12460ff9"},
- {file = "scipy-1.16.3-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:b81c27fc41954319a943d43b20e07c40bdcd3ff7cf013f4fb86286faefe546c4"},
- {file = "scipy-1.16.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:0c3b4dd3d9b08dbce0f3440032c52e9e2ab9f96ade2d3943313dfe51a7056959"},
- {file = "scipy-1.16.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:7dc1360c06535ea6116a2220f760ae572db9f661aba2d88074fe30ec2aa1ff88"},
- {file = "scipy-1.16.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:663b8d66a8748051c3ee9c96465fb417509315b99c71550fda2591d7dd634234"},
- {file = "scipy-1.16.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:eab43fae33a0c39006a88096cd7b4f4ef545ea0447d250d5ac18202d40b6611d"},
- {file = "scipy-1.16.3-cp313-cp313-win_amd64.whl", hash = "sha256:062246acacbe9f8210de8e751b16fc37458213f124bef161a5a02c7a39284304"},
- {file = "scipy-1.16.3-cp313-cp313-win_arm64.whl", hash = "sha256:50a3dbf286dbc7d84f176f9a1574c705f277cb6565069f88f60db9eafdbe3ee2"},
- {file = "scipy-1.16.3-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:fb4b29f4cf8cc5a8d628bc8d8e26d12d7278cd1f219f22698a378c3d67db5e4b"},
- {file = "scipy-1.16.3-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:8d09d72dc92742988b0e7750bddb8060b0c7079606c0d24a8cc8e9c9c11f9079"},
- {file = "scipy-1.16.3-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:03192a35e661470197556de24e7cb1330d84b35b94ead65c46ad6f16f6b28f2a"},
- {file = "scipy-1.16.3-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:57d01cb6f85e34f0946b33caa66e892aae072b64b034183f3d87c4025802a119"},
- {file = "scipy-1.16.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:96491a6a54e995f00a28a3c3badfff58fd093bf26cd5fb34a2188c8c756a3a2c"},
- {file = "scipy-1.16.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:cd13e354df9938598af2be05822c323e97132d5e6306b83a3b4ee6724c6e522e"},
- {file = "scipy-1.16.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:63d3cdacb8a824a295191a723ee5e4ea7768ca5ca5f2838532d9f2e2b3ce2135"},
- {file = "scipy-1.16.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:e7efa2681ea410b10dde31a52b18b0154d66f2485328830e45fdf183af5aefc6"},
- {file = "scipy-1.16.3-cp313-cp313t-win_amd64.whl", hash = "sha256:2d1ae2cf0c350e7705168ff2429962a89ad90c2d49d1dd300686d8b2a5af22fc"},
- {file = "scipy-1.16.3-cp313-cp313t-win_arm64.whl", hash = "sha256:0c623a54f7b79dd88ef56da19bc2873afec9673a48f3b85b18e4d402bdd29a5a"},
- {file = "scipy-1.16.3-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:875555ce62743e1d54f06cdf22c1e0bc47b91130ac40fe5d783b6dfa114beeb6"},
- {file = "scipy-1.16.3-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:bb61878c18a470021fb515a843dc7a76961a8daceaaaa8bad1332f1bf4b54657"},
- {file = "scipy-1.16.3-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f2622206f5559784fa5c4b53a950c3c7c1cf3e84ca1b9c4b6c03f062f289ca26"},
- {file = "scipy-1.16.3-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:7f68154688c515cdb541a31ef8eb66d8cd1050605be9dcd74199cbd22ac739bc"},
- {file = "scipy-1.16.3-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:8b3c820ddb80029fe9f43d61b81d8b488d3ef8ca010d15122b152db77dc94c22"},
- {file = "scipy-1.16.3-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:d3837938ae715fc0fe3c39c0202de3a8853aff22ca66781ddc2ade7554b7e2cc"},
- {file = "scipy-1.16.3-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:aadd23f98f9cb069b3bd64ddc900c4d277778242e961751f77a8cb5c4b946fb0"},
- {file = "scipy-1.16.3-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:b7c5f1bda1354d6a19bc6af73a649f8285ca63ac6b52e64e658a5a11d4d69800"},
- {file = "scipy-1.16.3-cp314-cp314-win_amd64.whl", hash = "sha256:e5d42a9472e7579e473879a1990327830493a7047506d58d73fc429b84c1d49d"},
- {file = "scipy-1.16.3-cp314-cp314-win_arm64.whl", hash = "sha256:6020470b9d00245926f2d5bb93b119ca0340f0d564eb6fbaad843eaebf9d690f"},
- {file = "scipy-1.16.3-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:e1d27cbcb4602680a49d787d90664fa4974063ac9d4134813332a8c53dbe667c"},
- {file = "scipy-1.16.3-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:9b9c9c07b6d56a35777a1b4cc8966118fb16cfd8daf6743867d17d36cfad2d40"},
- {file = "scipy-1.16.3-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:3a4c460301fb2cffb7f88528f30b3127742cff583603aa7dc964a52c463b385d"},
- {file = "scipy-1.16.3-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:f667a4542cc8917af1db06366d3f78a5c8e83badd56409f94d1eac8d8d9133fa"},
- {file = "scipy-1.16.3-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.whl", hash = "sha256:f379b54b77a597aa7ee5e697df0d66903e41b9c85a6dd7946159e356319158e8"},
- {file = "scipy-1.16.3-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.whl", hash = "sha256:4aff59800a3b7f786b70bfd6ab551001cb553244988d7d6b8299cb1ea653b353"},
- {file = "scipy-1.16.3-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:da7763f55885045036fabcebd80144b757d3db06ab0861415d1c3b7c69042146"},
- {file = "scipy-1.16.3-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:ffa6eea95283b2b8079b821dc11f50a17d0571c92b43e2b5b12764dc5f9b285d"},
- {file = "scipy-1.16.3-cp314-cp314t-win_amd64.whl", hash = "sha256:d9f48cafc7ce94cf9b15c6bffdc443a81a27bf7075cf2dcd5c8b40f85d10c4e7"},
- {file = "scipy-1.16.3-cp314-cp314t-win_arm64.whl", hash = "sha256:21d9d6b197227a12dcbf9633320a4e34c6b0e51c57268df255a0942983bac562"},
- {file = "scipy-1.16.3.tar.gz", hash = "sha256:01e87659402762f43bd2fee13370553a17ada367d42e7487800bf2916535aecb"},
+ {file = "scipy-1.17.0-cp311-cp311-macosx_10_14_x86_64.whl", hash = "sha256:2abd71643797bd8a106dff97894ff7869eeeb0af0f7a5ce02e4227c6a2e9d6fd"},
+ {file = "scipy-1.17.0-cp311-cp311-macosx_12_0_arm64.whl", hash = "sha256:ef28d815f4d2686503e5f4f00edc387ae58dfd7a2f42e348bb53359538f01558"},
+ {file = "scipy-1.17.0-cp311-cp311-macosx_14_0_arm64.whl", hash = "sha256:272a9f16d6bb4667e8b50d25d71eddcc2158a214df1b566319298de0939d2ab7"},
+ {file = "scipy-1.17.0-cp311-cp311-macosx_14_0_x86_64.whl", hash = "sha256:7204fddcbec2fe6598f1c5fdf027e9f259106d05202a959a9f1aecf036adc9f6"},
+ {file = "scipy-1.17.0-cp311-cp311-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fc02c37a5639ee67d8fb646ffded6d793c06c5622d36b35cfa8fe5ececb8f042"},
+ {file = "scipy-1.17.0-cp311-cp311-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:dac97a27520d66c12a34fd90a4fe65f43766c18c0d6e1c0a80f114d2260080e4"},
+ {file = "scipy-1.17.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:ebb7446a39b3ae0fe8f416a9a3fdc6fba3f11c634f680f16a239c5187bc487c0"},
+ {file = "scipy-1.17.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:474da16199f6af66601a01546144922ce402cb17362e07d82f5a6cf8f963e449"},
+ {file = "scipy-1.17.0-cp311-cp311-win_amd64.whl", hash = "sha256:255c0da161bd7b32a6c898e7891509e8a9289f0b1c6c7d96142ee0d2b114c2ea"},
+ {file = "scipy-1.17.0-cp311-cp311-win_arm64.whl", hash = "sha256:85b0ac3ad17fa3be50abd7e69d583d98792d7edc08367e01445a1e2076005379"},
+ {file = "scipy-1.17.0-cp312-cp312-macosx_10_14_x86_64.whl", hash = "sha256:0d5018a57c24cb1dd828bcf51d7b10e65986d549f52ef5adb6b4d1ded3e32a57"},
+ {file = "scipy-1.17.0-cp312-cp312-macosx_12_0_arm64.whl", hash = "sha256:88c22af9e5d5a4f9e027e26772cc7b5922fab8bcc839edb3ae33de404feebd9e"},
+ {file = "scipy-1.17.0-cp312-cp312-macosx_14_0_arm64.whl", hash = "sha256:f3cd947f20fe17013d401b64e857c6b2da83cae567adbb75b9dcba865abc66d8"},
+ {file = "scipy-1.17.0-cp312-cp312-macosx_14_0_x86_64.whl", hash = "sha256:e8c0b331c2c1f531eb51f1b4fc9ba709521a712cce58f1aa627bc007421a5306"},
+ {file = "scipy-1.17.0-cp312-cp312-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5194c445d0a1c7a6c1a4a4681b6b7c71baad98ff66d96b949097e7513c9d6742"},
+ {file = "scipy-1.17.0-cp312-cp312-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9eeb9b5f5997f75507814ed9d298ab23f62cf79f5a3ef90031b1ee2506abdb5b"},
+ {file = "scipy-1.17.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:40052543f7bbe921df4408f46003d6f01c6af109b9e2c8a66dd1cf6cf57f7d5d"},
+ {file = "scipy-1.17.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:0cf46c8013fec9d3694dc572f0b54100c28405d55d3e2cb15e2895b25057996e"},
+ {file = "scipy-1.17.0-cp312-cp312-win_amd64.whl", hash = "sha256:0937a0b0d8d593a198cededd4c439a0ea216a3f36653901ea1f3e4be949056f8"},
+ {file = "scipy-1.17.0-cp312-cp312-win_arm64.whl", hash = "sha256:f603d8a5518c7426414d1d8f82e253e454471de682ce5e39c29adb0df1efb86b"},
+ {file = "scipy-1.17.0-cp313-cp313-macosx_10_14_x86_64.whl", hash = "sha256:65ec32f3d32dfc48c72df4291345dae4f048749bc8d5203ee0a3f347f96c5ce6"},
+ {file = "scipy-1.17.0-cp313-cp313-macosx_12_0_arm64.whl", hash = "sha256:1f9586a58039d7229ce77b52f8472c972448cded5736eaf102d5658bbac4c269"},
+ {file = "scipy-1.17.0-cp313-cp313-macosx_14_0_arm64.whl", hash = "sha256:9fad7d3578c877d606b1150135c2639e9de9cecd3705caa37b66862977cc3e72"},
+ {file = "scipy-1.17.0-cp313-cp313-macosx_14_0_x86_64.whl", hash = "sha256:423ca1f6584fc03936972b5f7c06961670dbba9f234e71676a7c7ccf938a0d61"},
+ {file = "scipy-1.17.0-cp313-cp313-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:fe508b5690e9eaaa9467fc047f833af58f1152ae51a0d0aed67aa5801f4dd7d6"},
+ {file = "scipy-1.17.0-cp313-cp313-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6680f2dfd4f6182e7d6db161344537da644d1cf85cf293f015c60a17ecf08752"},
+ {file = "scipy-1.17.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:eec3842ec9ac9de5917899b277428886042a93db0b227ebbe3a333b64ec7643d"},
+ {file = "scipy-1.17.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:d7425fcafbc09a03731e1bc05581f5fad988e48c6a861f441b7ab729a49a55ea"},
+ {file = "scipy-1.17.0-cp313-cp313-win_amd64.whl", hash = "sha256:87b411e42b425b84777718cc41516b8a7e0795abfa8e8e1d573bf0ef014f0812"},
+ {file = "scipy-1.17.0-cp313-cp313-win_arm64.whl", hash = "sha256:357ca001c6e37601066092e7c89cca2f1ce74e2a520ca78d063a6d2201101df2"},
+ {file = "scipy-1.17.0-cp313-cp313t-macosx_10_14_x86_64.whl", hash = "sha256:ec0827aa4d36cb79ff1b81de898e948a51ac0b9b1c43e4a372c0508c38c0f9a3"},
+ {file = "scipy-1.17.0-cp313-cp313t-macosx_12_0_arm64.whl", hash = "sha256:819fc26862b4b3c73a60d486dbb919202f3d6d98c87cf20c223511429f2d1a97"},
+ {file = "scipy-1.17.0-cp313-cp313t-macosx_14_0_arm64.whl", hash = "sha256:363ad4ae2853d88ebcde3ae6ec46ccca903ea9835ee8ba543f12f575e7b07e4e"},
+ {file = "scipy-1.17.0-cp313-cp313t-macosx_14_0_x86_64.whl", hash = "sha256:979c3a0ff8e5ba254d45d59ebd38cde48fce4f10b5125c680c7a4bfe177aab07"},
+ {file = "scipy-1.17.0-cp313-cp313t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:130d12926ae34399d157de777472bf82e9061c60cc081372b3118edacafe1d00"},
+ {file = "scipy-1.17.0-cp313-cp313t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:6e886000eb4919eae3a44f035e63f0fd8b651234117e8f6f29bad1cd26e7bc45"},
+ {file = "scipy-1.17.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:13c4096ac6bc31d706018f06a49abe0485f96499deb82066b94d19b02f664209"},
+ {file = "scipy-1.17.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:cacbaddd91fcffde703934897c5cd2c7cb0371fac195d383f4e1f1c5d3f3bd04"},
+ {file = "scipy-1.17.0-cp313-cp313t-win_amd64.whl", hash = "sha256:edce1a1cf66298cccdc48a1bdf8fb10a3bf58e8b58d6c3883dd1530e103f87c0"},
+ {file = "scipy-1.17.0-cp313-cp313t-win_arm64.whl", hash = "sha256:30509da9dbec1c2ed8f168b8d8aa853bc6723fede1dbc23c7d43a56f5ab72a67"},
+ {file = "scipy-1.17.0-cp314-cp314-macosx_10_14_x86_64.whl", hash = "sha256:c17514d11b78be8f7e6331b983a65a7f5ca1fd037b95e27b280921fe5606286a"},
+ {file = "scipy-1.17.0-cp314-cp314-macosx_12_0_arm64.whl", hash = "sha256:4e00562e519c09da34c31685f6acc3aa384d4d50604db0f245c14e1b4488bfa2"},
+ {file = "scipy-1.17.0-cp314-cp314-macosx_14_0_arm64.whl", hash = "sha256:f7df7941d71314e60a481e02d5ebcb3f0185b8d799c70d03d8258f6c80f3d467"},
+ {file = "scipy-1.17.0-cp314-cp314-macosx_14_0_x86_64.whl", hash = "sha256:aabf057c632798832f071a8dde013c2e26284043934f53b00489f1773b33527e"},
+ {file = "scipy-1.17.0-cp314-cp314-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a38c3337e00be6fd8a95b4ed66b5d988bac4ec888fd922c2ea9fe5fb1603dd67"},
+ {file = "scipy-1.17.0-cp314-cp314-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:00fb5f8ec8398ad90215008d8b6009c9db9fa924fd4c7d6be307c6f945f9cd73"},
+ {file = "scipy-1.17.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f2a4942b0f5f7c23c7cd641a0ca1955e2ae83dedcff537e3a0259096635e186b"},
+ {file = "scipy-1.17.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:dbf133ced83889583156566d2bdf7a07ff89228fe0c0cb727f777de92092ec6b"},
+ {file = "scipy-1.17.0-cp314-cp314-win_amd64.whl", hash = "sha256:3625c631a7acd7cfd929e4e31d2582cf00f42fcf06011f59281271746d77e061"},
+ {file = "scipy-1.17.0-cp314-cp314-win_arm64.whl", hash = "sha256:9244608d27eafe02b20558523ba57f15c689357c85bdcfe920b1828750aa26eb"},
+ {file = "scipy-1.17.0-cp314-cp314t-macosx_10_14_x86_64.whl", hash = "sha256:2b531f57e09c946f56ad0b4a3b2abee778789097871fc541e267d2eca081cff1"},
+ {file = "scipy-1.17.0-cp314-cp314t-macosx_12_0_arm64.whl", hash = "sha256:13e861634a2c480bd237deb69333ac79ea1941b94568d4b0efa5db5e263d4fd1"},
+ {file = "scipy-1.17.0-cp314-cp314t-macosx_14_0_arm64.whl", hash = "sha256:eb2651271135154aa24f6481cbae5cc8af1f0dd46e6533fb7b56aa9727b6a232"},
+ {file = "scipy-1.17.0-cp314-cp314t-macosx_14_0_x86_64.whl", hash = "sha256:c5e8647f60679790c2f5c76be17e2e9247dc6b98ad0d3b065861e082c56e078d"},
+ {file = "scipy-1.17.0-cp314-cp314t-manylinux_2_27_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5fb10d17e649e1446410895639f3385fd2bf4c3c7dfc9bea937bddcbc3d7b9ba"},
+ {file = "scipy-1.17.0-cp314-cp314t-manylinux_2_27_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8547e7c57f932e7354a2319fab613981cde910631979f74c9b542bb167a8b9db"},
+ {file = "scipy-1.17.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:33af70d040e8af9d5e7a38b5ed3b772adddd281e3062ff23fec49e49681c38cf"},
+ {file = "scipy-1.17.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:f9eb55bb97d00f8b7ab95cb64f873eb0bf54d9446264d9f3609130381233483f"},
+ {file = "scipy-1.17.0-cp314-cp314t-win_amd64.whl", hash = "sha256:1ff269abf702f6c7e67a4b7aad981d42871a11b9dd83c58d2d2ea624efbd1088"},
+ {file = "scipy-1.17.0-cp314-cp314t-win_arm64.whl", hash = "sha256:031121914e295d9791319a1875444d55079885bbae5bdc9c5e0f2ee5f09d34ff"},
+ {file = "scipy-1.17.0.tar.gz", hash = "sha256:2591060c8e648d8b96439e111ac41fd8342fdeff1876be2e19dea3fe8930454e"},
]
[package.dependencies]
-numpy = ">=1.25.2,<2.6"
+numpy = ">=1.26.4,<2.7"
[package.extras]
-dev = ["cython-lint (>=0.12.2)", "doit (>=0.36.0)", "mypy (==1.10.0)", "pycodestyle", "pydevtool", "rich-click", "ruff (>=0.0.292)", "types-psutil", "typing_extensions"]
-doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "linkify-it-py", "matplotlib (>=3.5)", "myst-nb (>=1.2.0)", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.2.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)"]
+dev = ["click (<8.3.0)", "cython-lint (>=0.12.2)", "mypy (==1.10.0)", "pycodestyle", "ruff (>=0.12.0)", "spin", "types-psutil", "typing_extensions"]
+doc = ["intersphinx_registry", "jupyterlite-pyodide-kernel", "jupyterlite-sphinx (>=0.19.1)", "jupytext", "linkify-it-py", "matplotlib (>=3.5)", "myst-nb (>=1.2.0)", "numpydoc", "pooch", "pydata-sphinx-theme (>=0.15.2)", "sphinx (>=5.0.0,<8.2.0)", "sphinx-copybutton", "sphinx-design (>=0.4.0)", "tabulate"]
test = ["Cython", "array-api-strict (>=2.3.1)", "asv", "gmpy2", "hypothesis (>=6.30)", "meson", "mpmath", "ninja ; sys_platform != \"emscripten\"", "pooch", "pytest (>=8.0.0)", "pytest-cov", "pytest-timeout", "pytest-xdist", "scikit-umfpack", "threadpoolctl"]
[[package]]
@@ -3013,14 +3038,14 @@ files = [
[[package]]
name = "sqlparse"
-version = "0.5.4"
+version = "0.5.5"
description = "A non-validating SQL parser."
optional = false
python-versions = ">=3.8"
groups = ["main", "dev"]
files = [
- {file = "sqlparse-0.5.4-py3-none-any.whl", hash = "sha256:99a9f0314977b76d776a0fcb8554de91b9bb8a18560631d6bc48721d07023dcb"},
- {file = "sqlparse-0.5.4.tar.gz", hash = "sha256:4396a7d3cf1cd679c1be976cf3dc6e0a51d0111e87787e7a8d780e7d5a998f9e"},
+ {file = "sqlparse-0.5.5-py3-none-any.whl", hash = "sha256:12a08b3bf3eec877c519589833aed092e2444e68240a3577e8e26148acc7b1ba"},
+ {file = "sqlparse-0.5.5.tar.gz", hash = "sha256:e20d4a9b0b8585fdf63b10d30066c7c94c5d7a7ec47c889a2d83a3caa93ff28e"},
]
[package.extras]
@@ -3102,14 +3127,14 @@ typing-extensions = ">=4.12.0"
[[package]]
name = "tzdata"
-version = "2025.2"
+version = "2025.3"
description = "Provider of IANA time zone data"
optional = false
python-versions = ">=2"
groups = ["main", "dev"]
files = [
- {file = "tzdata-2025.2-py2.py3-none-any.whl", hash = "sha256:1a403fada01ff9221ca8044d701868fa132215d84beb92242d9acd2147f667a8"},
- {file = "tzdata-2025.2.tar.gz", hash = "sha256:b60a638fcc0daffadf82fe0f57e53d06bdec2f36c4df66280ae79bce6bd6f2b9"},
+ {file = "tzdata-2025.3-py2.py3-none-any.whl", hash = "sha256:06a47e5700f3081aab02b2e513160914ff0694bce9947d6b76ebd6bf57cfc5d1"},
+ {file = "tzdata-2025.3.tar.gz", hash = "sha256:de39c2ca5dc7b0344f2eba86f49d614019d29f060fc4ebc8a417896a620b56a7"},
]
markers = {dev = "sys_platform == \"win32\""}
@@ -3133,14 +3158,14 @@ devenv = ["check-manifest", "pytest (>=4.3)", "pytest-cov", "pytest-mock (>=3.3)
[[package]]
name = "urllib3"
-version = "2.6.1"
+version = "2.6.3"
description = "HTTP library with thread-safe connection pooling, file post, and more."
optional = false
python-versions = ">=3.9"
groups = ["main"]
files = [
- {file = "urllib3-2.6.1-py3-none-any.whl", hash = "sha256:e67d06fe947c36a7ca39f4994b08d73922d40e6cca949907be05efa6fd75110b"},
- {file = "urllib3-2.6.1.tar.gz", hash = "sha256:5379eb6e1aba4088bae84f8242960017ec8d8e3decf30480b3a1abdaa9671a3f"},
+ {file = "urllib3-2.6.3-py3-none-any.whl", hash = "sha256:bf272323e553dfb2e87d9bfd225ca7b0f467b919d7bbd355436d3fd37cb0acd4"},
+ {file = "urllib3-2.6.3.tar.gz", hash = "sha256:1b62b6884944a57dbe321509ab94fd4d3b307075e0c2eae991ac71ee15ad38ed"},
]
[package.extras]
@@ -3151,14 +3176,14 @@ zstd = ["backports-zstd (>=1.0.0) ; python_version < \"3.14\""]
[[package]]
name = "uvicorn"
-version = "0.38.0"
+version = "0.40.0"
description = "The lightning-fast ASGI server."
optional = false
-python-versions = ">=3.9"
+python-versions = ">=3.10"
groups = ["main"]
files = [
- {file = "uvicorn-0.38.0-py3-none-any.whl", hash = "sha256:48c0afd214ceb59340075b4a052ea1ee91c16fbc2a9b1469cca0e54566977b02"},
- {file = "uvicorn-0.38.0.tar.gz", hash = "sha256:fd97093bdd120a2609fc0d3afe931d4d4ad688b6e75f0f929fde1bc36fe0e91d"},
+ {file = "uvicorn-0.40.0-py3-none-any.whl", hash = "sha256:c6c8f55bc8bf13eb6fa9ff87ad62308bbbc33d0b67f84293151efe87e0d5f2ee"},
+ {file = "uvicorn-0.40.0.tar.gz", hash = "sha256:839676675e87e73694518b5574fd0f24c9d97b46bea16df7b8c05ea1a51071ea"},
]
[package.dependencies]
@@ -3368,14 +3393,26 @@ anyio = ">=3.0.0"
[[package]]
name = "wcwidth"
-version = "0.2.14"
+version = "0.5.3"
description = "Measures the displayed width of unicode strings in a terminal"
optional = false
-python-versions = ">=3.6"
+python-versions = ">=3.8"
+groups = ["main"]
+files = [
+ {file = "wcwidth-0.5.3-py3-none-any.whl", hash = "sha256:d584eff31cd4753e1e5ff6c12e1edfdb324c995713f75d26c29807bb84bf649e"},
+ {file = "wcwidth-0.5.3.tar.gz", hash = "sha256:53123b7af053c74e9fe2e92ac810301f6139e64379031f7124574212fb3b4091"},
+]
+
+[[package]]
+name = "xlwt"
+version = "1.3.0"
+description = "Library to create spreadsheet files compatible with MS Excel 97/2000/XP/2003 XLS files, on any platform, with Python 2.6, 2.7, 3.3+"
+optional = false
+python-versions = "*"
groups = ["main"]
files = [
- {file = "wcwidth-0.2.14-py2.py3-none-any.whl", hash = "sha256:a7bb560c8aee30f9957e5f9895805edd20602f2d7f720186dfd906e82b4982e1"},
- {file = "wcwidth-0.2.14.tar.gz", hash = "sha256:4d478375d31bc5395a3c55c40ccdf3354688364cd61c4f6adacaa9215d0b3605"},
+ {file = "xlwt-1.3.0-py2.py3-none-any.whl", hash = "sha256:a082260524678ba48a297d922cc385f58278b8aa68741596a87de01a9c628b2e"},
+ {file = "xlwt-1.3.0.tar.gz", hash = "sha256:c59912717a9b28f1a3c2a98fd60741014b06b043936dcecbc113eaaada156c88"},
]
[metadata]
diff --git a/prompts/JNL-G_DMP_full_Opidor.md b/prompts/JNL-G_DMP_full_Opidor.md
new file mode 100644
index 0000000..6811271
--- /dev/null
+++ b/prompts/JNL-G_DMP_full_Opidor.md
@@ -0,0 +1,462 @@
+# Data Management Plan — JNL-G
+
+**Project**: JNL-G — Digital twin of the Laboratoire National des Champs Magnétiques Intenses-Grenoble
+**Funder**: Agence Nationale de la Recherche (ANR) — call AAPG2025
+**Funder template**: ANR structured DMP template on Opidor (Science Europe-based)
+**Project duration**: 48 months
+**Coordinator**: Christophe Trophime (LNCMI, CNRS UPR)
+**Partners**: LNCMI (CNRS UPR) · UNISTRA / CEMOSIS
+**Plan version**: v1.1 — initial version, integrated with EMFL DMP (within 6 months of project start)
+**Next planned versions**: mid-term (T0+24) and final (T0+48)
+**Related plans**: EMFL Data Management Plan — ISABEL deliverable D4.3 / final D4.4 (Horizon 2020 Grant Agreement No 871106). Identifier (HAL/DOI): *to be added*. The EMFL DMP is the parent plan for user experimental data and EMFL administrative data; the present JNL-G DMP only covers operational, simulation, code and modeling data of the LNCMI-G installation, and inherits the EMFL data-policy rules (open-by-default, CC0 default license, 5-year embargo on raw data, 10-year minimum retention).
+
+---
+
+## General information
+
+### Project
+
+- **Acronym / title.** JNL-G — Digital twin of the LNCMI-G.
+- **Funder reference.** ANR AAPG2025, axe E.5 (Calcul Haute Performance, Modèles Numériques, Simulations, Applications).
+- **Coordinator.** Christophe Trophime, Research Engineer, LNCMI (CNRS UPR).
+- **Partner scientific leader (CEMOSIS).** Christophe Prud'homme, Professor, Université de Strasbourg.
+- **Abstract.** The project develops a hierarchical digital twin (DT) of the LNCMI-G high-field magnet installation, integrating systemic models (power and cooling), full-order multiphysics models of resistive and superconducting magnets, reduced-order models, and a data layer based on operational records from the magnet control systems. The deliverables include the DT software, an operational dashboard, predictive maintenance tools, and an extended MagnetDB platform.
+
+### Plan
+
+- **DMP responsible.** Christophe Trophime (coordinator), supported by Kevin Paillot (WP3 LNCMI lead) and Joubine Aghili (WP3 CEMOSIS lead).
+- **Reviewers.** WP4 leads (Cédric GrandClément, Christophe Prud'homme, Vincent Chabannes).
+- **Update schedule.** Annual review aligned with the WP0 yearly advancement reports (T0+12, T0+24, T0+36, T0+48). Mandatory revisions submitted to the ANR at T0+24 and T0+48.
+- **Identifier.** To be filled after Opidor entry.
+
+### Contributors
+
+| Role | Person | Affiliation | Responsibility |
+|---|---|---|---|
+| DMP coordinator | Christophe Trophime | LNCMI | Project-wide DMP, sections 1, 3, 4, 5, 6 |
+| WP3 LNCMI lead | Kevin Paillot | LNCMI | Sections 1, 2, 3 (operational data) |
+| WP3 CEMOSIS lead | Joubine Aghili | UNISTRA / CEMOSIS | Sections 1, 2 (data-driven modeling) |
+| WP4 architecture lead | Christophe Prud'homme | UNISTRA / CEMOSIS | Section 3 (storage architecture) |
+| Data analytics | Christiane Warth-Martin | LNCMI | Section 4 (personal data, anonymization) |
+
+---
+
+## Section 1 — Data description and collection or re-use of existing data
+
+### 1.0 List of datasets
+
+| # | Short name | Type | Origin | Owner |
+|---|---|---|---|---|
+| D1 | Raw operational data | Observational / instrument | Existing + new (continuous acquisition) | LNCMI |
+| D2 | Curated operational data | Derived (processed) | Produced by project (T3.1) | LNCMI |
+| D3 | Derived operational statistics | Derived (analytical) | Produced by project (WP3) | LNCMI |
+| D4 | MagnetDB relational data | Configuration / metadata | Existing + new | LNCMI |
+| D5 | Simulation & computational data | Computational | Produced by project (WP1, WP2) | LNCMI / CEMOSIS |
+| D6 | Source code & software artifacts | Software | Existing + new | LNCMI / CEMOSIS |
+| D7 | System models (Modelica / FMU) | Computational (model) | Produced by project (T1.1) | LNCMI |
+
+**Scope boundary with the EMFL DMP.** This DMP covers **exclusively operational and technical data**: telemetry from the magnet control systems (Pupitre, PigBrother, Hybrid), power and cooling installation data, and energy provider data (RTE/Enedis) used for operational monitoring. It does not cover any scientist-produced measurement data. **User experimental data** (raw measurements collected by external user teams during their access campaigns) and **EMFL administrative data** (user-proposal management, access ranking, contact details of user teams) are **covered by the EMFL Data Management Plan** (ISABEL D4.3, see Related plans above). LNCMI-G inherits and applies the EMFL rules for those data; the JNL-G project does not redefine them. Where a dataset of the present DMP touches the EMFL boundary (typically through a time-window link between an operational run and a user proposal), the EMFL rule prevails on the user-side fields.
+
+The term "data" in this DMP therefore refers to operational data from the monitoring and control systems of the installation and the magnets, archived MCS logs, simulation setup files and results, source code artifacts, and system models.
+
+**Terminology note.** In the EMFL context, the word *experiment* designates the scientific activity of a user team using the magnet installation (governed by the EMFL DMP). In this document, the same time window is referred to as an **operational run** — the set of control-system recordings produced by the installation during that period. In the MagnetDB schema this entity is named `Record`. An operational run and the corresponding EMFL experiment share a time window and possibly a proposal reference, but contain entirely different data and are managed under different data policies. This DMP covers only the operational run (D1–D3) and its configuration metadata (D4). The word *experiment* is not used in this DMP to avoid confusion with EMFL vocabulary.
+
+### 1.1 Re-use of existing data
+
+The project re-uses three pre-existing assets:
+
+- the historical archive of MCS recordings (Pupitre, PigBrother, Hybrid) accumulated by LNCMI-G operations since the deployment of each control system. The pre-existing storage state is described in the EMFL DMP §5.2 (RAID-1, per-proposal organization, technical data stored in a database every second);
+- the existing MagnetDB instance (PostgreSQL + S3 object store, migrated from MinIO to RustFS at project start) and its current schema, which will be migrated to the redesigned schema (Sprint 0) at project start;
+- the existing Feel++ / HiFiMagnet / MagnetTools / `python_magnetrun` codebases, used as the technical foundation for WP1, WP2 and WP4.
+
+JNL-G is the project that **modernizes the LNCMI-G operational data layer** described in EMFL DMP §5.2: the per-second technical database is being re-engineered into the three-layer architecture of D1 / D2 / D3, with explicit curation, S3 publication, provenance, and a structured PostgreSQL backbone (D4).
+
+No external third-party datasets are re-used at project start. External APIs (RTE, Enedis, weather) are referenced in real time during T3.1 — they are not re-distributed by the project.
+
+### 1.2 Datasets — description, formats, expected volume
+
+#### D1 — Raw operational data
+
+- **Description.** Time-series recordings produced by the three control systems of the LNCMI-G installation: Pupitre (resistive magnet operation), PigBrother (cooling and power installation), Hybrid (hybrid magnet system). Acquired continuously during operations.
+- **Origin.** Existing (historical archive, several years of operations) + newly produced throughout the project.
+- **Format.** Native MCS files (vendor-specific binary / text-based formats inherited from each control system). No transformation is applied at this stage.
+- **Sampling rate.** From 1 Hz (slow process variables) to 5 kHz (fast electrical channels).
+- **Estimated volume.** Several TB of historical data + ~hundreds of GB / year of new acquisition.
+- **Re-use status.** Existing format, partly retained for traceability and as fallback for D2.
+
+#### D2 — Curated operational data
+
+- **Description.** Selected and harmonized subset of D1, restricted to the channels relevant to the digital twin and to predictive maintenance work (WP3, WP2). Initial scope: Pupitre. PigBrother and Hybrid extensions are planned (timeline TBD — see open points).
+- **Origin.** Newly produced by the project, generated by the curation pipeline implemented in T3.1.
+- **Format.** Apache Parquet (columnar, compressed, partitioned by operational run / date).
+- **Estimated volume.** ~10–30% of the corresponding raw volume after channel selection and compression.
+- **Justification of format choice.** Parquet is interoperable, language-agnostic, supports schema evolution, and is natively consumable by Python (`pandas`, `pyarrow`, `polars`), Spark and DuckDB. It is the canonical interchange layer between LNCMI and CEMOSIS.
+
+#### D3 — Derived operational statistics
+
+- **Description.** Computed datasets aggregating D2: per-run statistics (`RecordStats`), derived time series (e.g. Rainflow-counted cycles, stitched trend series), cumulative statistics (`CumulativeStats`). Downsampling (LTTB) is applied at display time only; no pre-stored downsampled files.
+- **Origin.** Newly produced by the project (Phase 1–3 pipelines).
+- **Format.** Parquet for derived time-series payloads stored in RustFS S3 + relational rows in PostgreSQL with JSONB columns for per-run summaries.
+- **Estimated volume.** A few % of D2 volume (aggregated and downsampled).
+
+#### D4 — MagnetDB relational data
+
+- **Description.** Configuration and metadata of the LNCMI-G assets and their use:
+ - sites (housing, alimentation, pump configurations), magnets, parts;
+ - geometry references, materials;
+ - operational runs (`Record`) and their lifecycle: raw data file references (`sources` → D1), curated Parquet file references (`curated` → D2 in RustFS S3), run type, time bounds, operator identity;
+ - links to attachments stored in S3 (CAD, mesh, computed data, simulation outputs);
+ - provenance metadata for meshes, CAD and computed results.
+- **Origin.** Existing (current MagnetDB) + newly produced (Sprint 0 schema redesign + ongoing entries).
+- **Format.** PostgreSQL relational tables. Personal data (user identifiers used for booking / planning) are present in the operational instance but are anonymized in any export.
+- **Estimated volume.** Hundreds of MB of relational data; attachments (in S3) reach the GB range.
+
+#### D5 — Simulation and computational data
+
+- **Description.** Inputs and outputs of HiFiMagnet / Feel++ simulations and ROM evaluations:
+ - geometric setup files (CAD: STEP, BREP);
+ - meshes (Gmsh `.msh`, MED, exodus);
+ - field results (CSV, HDF5, EnSight, VTK / VTU);
+ - computed quantities (R(I) tables, inductance matrices) stored as `ComputedData` (relational + StorageAttachment hybrid);
+ - rendering artifacts (PNG plots, vtk.js scenes for the web frontend).
+- **Origin.** Newly produced by the project (WP1, WP2, WP4).
+- **Estimated volume.** From hundreds of MB (per simulation case) to ~100 GB (large 3D non-linear runs, mesh refinements).
+- **Justification of format choice.** All formats are open, well-established standards in scientific computing and supported by the Feel++ ecosystem and ParaView.
+
+#### D6 — Source code and software artifacts
+
+- **Description.** Source code, documentation, container images, CI artifacts, packaged binaries.
+- **Components.**
+ - **MagnetDB GitHub organization** — public, open-source: `python_magnetdb`, `python_magnetgeo`, `python_magnetsetup`, `python_magnetapi`, `python_magnetrun`.
+ - **Feel++ GitHub organization** — public, open-source: framework, toolboxes, HiFiMagnet, Feel++‑HTS.
+ - **Restricted components**: parts of MagnetTools, hosted in private GitHub repositories. Built artifacts are distributed via the LNCMI baremetal apt depot (`.deb` packages) and a DockerHub base image (`feelpp/magnettools`).
+- **Format.** Source code (C++, Python, Modelica, JS / TS), documentation (Markdown, AsciiDoc, Sphinx / Antora), OCI container images, `.deb` packages, Helm charts, Apptainer / Singularity images for HPC deployment.
+- **Estimated volume.** A few GB across repositories; tens of GB for cumulative container image releases.
+
+#### D7 — System models (Modelica / FMU)
+
+- **Description.** Dynamic models of the LNCMI-G power supply (AC/DC converters, DC current source with PID control) and water cooling system (primary and secondary loops), developed in T1.1 for co-simulation in T1.3.
+- **Origin.** Newly produced by the project. Possibly partly derived from existing internal LNCMI models, to be assessed in T1.1.
+- **Format.** Modelica source (`.mo`); compiled models exported as Functional Mockup Units (FMU 2.0 for Co-Simulation).
+- **Estimated volume.** Less than 100 MB of source + a few hundred MB of FMU bundles.
+- **Hosting.** To be decided (open point — see §3.4).
+
+### 1.3 Origin and methodology of new data collection
+
+| Dataset | Method |
+|---|---|
+| D1 | Continuous, automated acquisition by the existing MCS during installation operation. No new instrumentation is required, although a small instrumentation budget (7 k€) covers sensor renewal. |
+| D2 | Automated curation pipeline (T3.1), triggered offline on archived D1 batches and online on streaming D1. |
+| D3 | Asynchronous statistics pipelines (Celery tasks) triggered after curation; shared `trigger_full_stats_pipeline()` helper used by both offline and streaming paths. |
+| D4 | Manual entry through MagnetDB UI for configuration data; automatic creation by Phase 4 ingest for `Record` (operational run) rows. |
+| D5 | Generated by REANA-orchestrated workflows (setup → CAD → mesh → run → archive); attached to MagnetDB through `StorageAttachment`. |
+| D6 | Standard software development lifecycle on GitHub with CI/CD on GitHub Actions and project-internal runners. |
+| D7 | Manual development in OpenModelica / Dymola; FMU export through standard tooling. |
+
+### 1.4 Utility of the data outside the project
+
+- **D1, D2, D3** — primary value to other EMFL laboratories (HFML Nijmegen, HLD Dresden) and to high-field magnet user facilities for benchmarking and predictive-maintenance studies. The FlexRICAN community is identified as a direct consumer of aggregated energy-management data.
+- **D4** — schema and curated demonstration datasets are useful for any group operating instrument-centric facilities, especially those building MagnetDB-like configuration databases.
+- **D5** — relevant to the magnet-design community (CERN, ITER, fusion magnet groups) and to the Feel++ user community as benchmark cases.
+- **D6** — open-source contributions to Feel++, Scimba and the MagnetDB ecosystem, useful to NumPEx Exa-MA, FlexRICAN, the eye2brain project, and the broader scientific-computing community.
+- **D7** — useful as a co-simulation reference for facilities studying the coupled behavior of power-cooling-load systems.
+
+---
+
+## Section 2 — Documentation and data quality
+
+### 2.1 Metadata and documentation accompanying the data
+
+- **D1.** Each raw recording is identified by its MCS-assigned filename, timestamp, and the MagnetDB `Record` (operational run) it is linked to. No external metadata standard applies; the documentation is provided through MagnetDB itself.
+- **D2 / D3.** Each Parquet file carries a schema (column names, units, dtypes) embedded in its footer. Per-run `Record` rows in PostgreSQL hold processing parameters (curation version, channel selection) ensuring traceability from D2 / D3 back to D1.
+- **D4.** The PostgreSQL schema is the authoritative documentation. The schema is published openly in the MagnetDB GitHub organization, version-controlled through Django migrations.
+- **D5.** Meshes, CAD and computed data carry **provenance metadata** (input geometry, material properties, solver version, mesh generator parameters). The current attachment models lack systematic provenance — closing this gap is an explicit project task (`MeshAttachment`, `CadAttachment` provenance enhancement).
+- **D6.** Standard software documentation: README, API reference (Sphinx / Doxygen), user manuals (Antora-based site), CHANGELOG. Releases are tagged with semantic versioning and archived on Software Heritage and Zenodo (DOI).
+- **D7.** FMU `modelDescription.xml` provides interface metadata; complementary documentation describes the physical assumptions, parameters, and validation cases.
+
+### 2.2 Metadata standards and discoverability
+
+The project does not rely on a single external metadata standard; instead, FAIR-compliant identifiers are used wherever publication or release occurs:
+
+- **DOI** for software releases (Zenodo) and demonstration datasets;
+- **HAL** identifiers for publications;
+- **ORCID** for contributors;
+- **ROR** for affiliations;
+- **SWHID** (Software Heritage IDentifier) for source code snapshots.
+
+The MagnetDB schema can be exported to JSON Schema for re-use; the curated dataset bundles will be accompanied by a schema descriptor and a `README.md`.
+
+### 2.3 Data quality control
+
+- **D1.** Quality is assessed at acquisition by the MCS itself (out-of-range alarms, sensor health). Anomalies feed T3.2 (anomaly detection, predictive maintenance).
+- **D2.** Curation pipeline performs schema validation, monotonic timestamp checks, sampling-rate consistency checks. Any rejected file is logged with a reason and made available for manual review.
+- **D3.** Pipelines are deterministic and idempotent; statistical outputs are recomputable from D2. Versioning of the pipeline code is enforced through CI.
+- **D5.** Verification and validation is the explicit object of T1.2 / T1.3 / T4.2 deliverables (test cases + validation reports vs. experimental data from WP3).
+- **D6.** Quality is enforced through the CI/CD pipelines: unit tests, integration tests, performance benchmarks, code-style and security checks, container image scanning. The CEMOSIS-side research engineer requested in the budget is explicitly tasked with CI/CD, verification, validation and benchmarking.
+
+---
+
+## Section 3 — Storage and backup during the research process
+
+### 3.1 Storage during the project — per dataset
+
+| Dataset | Primary storage | Location | Access protocol |
+|---|---|---|---|
+| D1 | LNCMI NAS (sshfs export) | LNCMI-G site, Grenoble | sshfs / SSH — LNCMI internal network only |
+| D2 | RustFS S3 bucket (MagnetDB instance) | LNCMI-G server room | S3 API (HTTPS) via MagnetDB; pre-signed URLs for CEMOSIS direct access |
+| D3 | RustFS S3 bucket + PostgreSQL | LNCMI-G server room | S3 API + SQL via MagnetDB API |
+| D4 | PostgreSQL (MagnetDB primary database) | LNCMI-G server room | MagnetDB REST/API behind LemonLDAP::NG SSO |
+| D5 | RustFS S3 (attachments) referenced from PostgreSQL | LNCMI-G server room | S3 API via MagnetDB |
+| D6 | GitHub (origin) + GitHub Container Registry + LNCMI apt depot + DockerHub | Distributed | git over HTTPS / SSH; OCI; HTTPS |
+| D7 | TBD (see §3.4) | TBD | TBD |
+
+The **curated Parquet layer on RustFS S3 (D2) is the canonical processed-data layer**. The sshfs-mounted raw paths (D1) are retained as fallback only; this design choice is what allows external partners (CEMOSIS) to consume project data without requiring sshfs access to the LNCMI internal network. CEMOSIS accesses D2 directly via pre-signed RustFS URLs (time-limited, read-only), which are also usable in Python notebooks (`pd.read_parquet(url)`) without installing any MagnetDB-specific tooling.
+
+### 3.2 Volume planning
+
+| Layer | End-of-project volume target | Growth assumption |
+|---|---|---|
+| D1 (raw) | 5–10 TB cumulative | ~0.5–1 TB / year of new acquisition |
+| D2 (curated) | 1–3 TB cumulative | proportional to D1 acquisition |
+| D3 (derived) | < 100 GB | small, dominated by aggregates |
+| D4 (relational) | < 10 GB | structural / metadata growth |
+| D5 (sim/comp) | 1–5 TB | dominated by 3D non-linear runs |
+| D6 (code / images) | < 100 GB | container image accumulation |
+| D7 (system models) | < 1 GB | small, model-source dominant |
+
+The 10 k€ "servers / data storage" line in the LNCMI requested budget covers the procurement of additional disk capacity for the MagnetDB RustFS S3 instance to absorb D2 / D3 / D5 growth.
+
+### 3.3 Backup strategy
+
+- **PostgreSQL (D4) and RustFS S3 (D2, D3, D5):** daily backups managed by the LNCMI IT team, following a 3-2-1 strategy (3 copies, 2 different media, 1 offsite). Backup retention follows the LNCMI institutional policy.
+- **Raw operational data (D1):** kept under the existing LNCMI backup policy, unchanged by the project.
+- **Source code (D6):** distributed by design — every clone is a backup; in addition, every release is mirrored on Software Heritage and Zenodo.
+- **System models (D7):** to be aligned with the chosen hosting strategy (open point).
+
+### 3.4 Hosting decisions still open
+
+These items are not yet fixed and will be resolved during the first six months of the project (under Task T0.1 Monitoring and Planning, in coordination with T4.1 Architecture):
+
+1. **D7 (system models)** — choice between hosting in the MagnetDB GitHub organization, a separate Modelica-focused repository, or a partner-only distribution channel. Depends on the open-source clearance of any pre-existing internal LNCMI models that will be re-used.
+2. **Demo / training datasets** (a public subset of D2 + D4) — choice of repository among Girder, data.gouv.fr, Zenodo, or a combination, depending on the size of each bundle and on DOI requirements.
+3. **PigBrother and Hybrid Parquet curation (D2 extension)** — timeline for extending the Pupitre curation pipeline to the other two MCS sources.
+4. **Retention policy** for raw D1 (sshfs) and for intermediate D2 versions, particularly across schema changes of the curation pipeline.
+
+### 3.5 Data security and protection during the research
+
+- **Authentication.** Access to MagnetDB and to the project's DT services is controlled by LemonLDAP::NG (SSO) with OIDC delegation. External partners get federated access through the same gateway.
+- **Authorization.** Role-based scoping at three levels — `own` / `site` / `all` — consistent across the API, the operational dashboard, and the underlying queries.
+- **Network segmentation.** Raw data on sshfs (D1) are reachable only from within the LNCMI internal network. The MagnetDB front-end (Traefik with SSL) and the curated S3 bucket are reachable externally over HTTPS, behind the SSO gateway.
+- **Credentials.** Service accounts and CI tokens are managed through the LNCMI IT secrets store; rotation is performed annually or after any incident.
+- **Distinct service URLs.** Docker-internal URLs (e.g., `http://lemonldap`) are kept distinct from external browser-facing URLs (e.g., `https://auth.lemon.magnetdb-dev.local`) in environment configuration.
+
+---
+
+## Section 4 — Legal and ethical requirements, codes of conduct
+
+### 4.1 Personal data
+
+- **Inheritance from the EMFL DMP.** Personal data of magnet users (user-team contacts, proposal authorship, access procedures) are governed by the **EMFL Data Management Plan** (ISABEL D4.3 §2). The EMFL DMP commits to GDPR, the EU Data Protection Law Enforcement Directive, and applicable national / regional rules; it specifies that user personal data are restricted to consortium members, used only with user consent, and that aggregated statistics are reported anonymously. The JNL-G project does not redefine these rules and complies with them.
+- **JNL-G-specific scope.** The only personal data handled in addition by JNL-G are the user identifiers already present in MagnetDB (D4) — name, affiliation, contact email — used for booking, planning and access control of the LNCMI-G installation. **No experimental data and no data subject to medical, biometric or other sensitive-personal-data regulation are collected by JNL-G.**
+- **GDPR compliance.** Processing is covered by the CNRS general framework and by the EMFL framework above. The project does not introduce any new processing of personal data beyond what is already declared by LNCMI / EMFL.
+- **CNIL registration.** The DT authentication and access architecture (LemonLDAP::NG / OIDC) developed in WP4 — which is the **JNL-G-specific addition** to the EMFL personal-data framework — will be registered as an extension of LNCMI's existing register of processing activities prior to launch, as referred in the proposal.
+- **Anonymization.** Any export of D4 outside the LNCMI internal network is anonymized: personal identifiers are replaced by opaque pseudonyms or removed entirely depending on the use case. Opaque pseudonyms are used where traceability of "user X over time" is required for analytics; full removal is used for public datasets. This is consistent with the EMFL DMP rule that personal information shall not be published.
+- **Right of access / rectification / erasure.** Handled through the existing CNRS / LNCMI / EMFL procedures; the DT does not establish a separate process.
+
+### 4.2 Intellectual property and licensing
+
+- **Source code (D6).**
+ - **Public components** of MagnetDB and Feel++: open-source, released under permissive licenses (Apache-2.0 or LGPL-3.0 depending on the component, in line with the existing licensing of those repositories). New contributions follow the licensing of the parent repository.
+ - **MagnetTools and other restricted components**: kept under their existing private-repository regime; built artifacts are distributed only via the LNCMI apt depot and the `feelpp/magnettools` DockerHub image. Decision on whether parts can be open-sourced is part of the §3.4 open points.
+- **Datasets.**
+ - **EMFL alignment.** The EMFL DMP (ISABEL D4.3) sets **CC0 1.0 Universal** as the default license for shared datasets, on the principle of open re-use. JNL-G adopts CC0 as the default for the datasets listed below; CC-BY-4.0 is used as a fallback when attribution is required by an institutional policy.
+ - **D5 demonstration cases** (a public subset, released as benchmark datasets): CC0 by default; CC-BY-4.0 if attribution is required.
+ - **D2 / D3 curated datasets** released externally: CC0 by default; CC-BY-4.0 fallback. CC-BY-NC-4.0 may be considered exceptionally if the Operating Data Exchange Policy (§4.3) identifies a concern over commercial re-use of operational data of a national infrastructure — this would be a deviation from the EMFL default and must be justified.
+ - **D4 schema descriptors**: CC-BY-4.0 (attribution useful for traceability of the schema itself).
+- **Patentable results.** None expected at project start. Should patentable outcomes arise (e.g., a novel ROM technique or a hardware-related innovation), publication and data release on the relevant items will be delayed until the patent application stage is closed, in accordance with CNRS IP policy.
+- **Database rights.** The MagnetDB instance is a database in the sense of Directive 96/9/EC; sui generis database rights are held by LNCMI. The schema is openly published; the contents follow the access regime described in §5.
+- **Third-party rights.** No third-party copyrighted data are incorporated. References to external APIs (RTE, Enedis) are runtime-only.
+
+### 4.3 Confidentiality and contractual aspects
+
+- **Inter-partner confidentiality agreement.** A confidentiality agreement between LNCMI and UNISTRA / CEMOSIS will be signed before any operational data exchange takes place (as committed in the proposal). The agreement covers the curated subset (D2) provided for verification and validation.
+- **Operating Data Exchange Policy.** A formal policy describing what subset of operational data may be released externally, in what aggregated form, and under which licence will be drafted in year 2 of the project (T0.1 / T4.1). This policy will be appended as an annex to v2 of the DMP.
+- **External collaborators.** Any access by collaborators outside the consortium (e.g., visiting researchers, FlexRICAN partners, EMFL partners) is subject to a written agreement following the CNRS / Université de Strasbourg standard models.
+
+### 4.4 Ethics and codes of conduct
+
+- The project does not involve human subjects, animal experimentation, dual-use research, or sensitive geographic data; **no ethics committee review is required**.
+- The consortium adheres to the CNRS Code of Ethics for Research and to the European Code of Conduct for Research Integrity (ALLEA).
+- The project endorses the CNRS Open Science roadmap and the ANR principle "as open as possible, as closed as necessary".
+- Authorship and contribution of all research outputs follow the CRediT taxonomy where applicable.
+
+---
+
+## Section 5 — Data sharing and long-term preservation
+
+### 5.1 Sharing strategy — per dataset
+
+| Dataset | Will be shared? | When | Where | License | Conditions |
+|---|---|---|---|---|---|
+| D1 (raw) | No | — | — | — | LNCMI-internal only |
+| D2 (curated) | Partial — demo bundles | At project end (T0+48), incremental from T0+24 | Zenodo + Girder / data.gouv.fr (TBD) | CC0 (CC-BY-4.0 fallback) | Subset selected via the Operating Data Exchange Policy |
+| D3 (derived) | Partial — same demo bundles | Same as D2 | Same as D2 | Same as D2 | Same as D2 |
+| D4 (schema + demo content) | Yes — schema + demo contents | T0+12 (schema), T0+24 (demo) | GitHub + Zenodo | CC-BY-4.0 (content) + Apache-2.0 (schema migrations) | Personal data removed per EMFL DMP |
+| D5 (sim / comp) | Partial — benchmark cases | Continuous | Zenodo + GitHub | CC0 (CC-BY-4.0 fallback) + Apache-2.0 (scripts) | Selected representative cases |
+| D6 (code) | Yes — public components | Continuous (releases) | GitHub + Software Heritage + Zenodo | Apache-2.0 / LGPL-3.0 (per component) | Free re-use |
+| D7 (system models) | TBD | TBD | TBD (see §3.4) | TBD | TBD |
+
+### 5.2 Repositories — selection and trustworthiness
+
+The repositories listed above were selected against the Science Europe criteria for trustworthy repositories: they (i) are widely adopted, (ii) provide persistent identifiers, (iii) implement long-term preservation policies, (iv) offer stable access, and (v) are recognized by the French Open Science strategy.
+
+| Repository | Purpose | Identifier | Notes |
+|---|---|---|---|
+| **GitHub** | Source code primary location | URL | Mirrored to Software Heritage |
+| **Software Heritage** | Code archival | SWHID | Continuous archival of public repositories |
+| **Zenodo** | Software releases, demo datasets | DOI | CERN-hosted, recommended by ANR |
+| **HAL** | Publications | HAL ID | French national open archive |
+| **data.gouv.fr** | Public datasets | URL + DOI mirror | Considered for demo bundles, decision pending |
+| **Girder** | Larger demo datasets | URL | LNCMI / community option, decision pending |
+
+### 5.3 Embargo
+
+The project follows the embargo rules of the **EMFL DMP** (ISABEL D4.3):
+
+- **Raw data tied to user campaigns (out of scope here, but referenced for consistency)**: 5 years from the end of the experiment, after which data become openly accessible with the EMFL facility acting as custodian.
+- **D2 / D3 / D5 demo bundles**: a short embargo (up to 12 months from the corresponding publication submission) may apply when the dataset is tied to a paper still under review. This is shorter than the EMFL 5-year rule because the project-side curated bundles are not user data.
+- **D6 (code)** and **publications**: no embargo; immediate open release.
+- **Patents (hypothetical)**: standard embargo until the patent application is filed, in line with CNRS IP policy.
+
+### 5.4 Long-term preservation
+
+The project applies the **EMFL DMP** (ISABEL D4.3) baseline of **10-year minimum retention** for raw, technical and administrative data, with longer retention for code and schema artifacts on community archives:
+
+- **D6 (code)** — preserved indefinitely on Software Heritage and Zenodo (DOI per release).
+- **D5 benchmark cases and demo bundles** — preserved on Zenodo with DOI; minimum guarantee 20 years per Zenodo policy. Exceeds the EMFL minimum.
+- **D4 schema descriptors** — preserved on Zenodo + GitHub. Exceeds the EMFL minimum.
+- **D2 / D3 curated demo bundles** — preserved on Zenodo and / or data.gouv.fr. Exceeds the EMFL minimum.
+- **D1 raw operational data** — kept according to the LNCMI institutional retention policy; the EMFL 10-year minimum applies. A retention review (alignment between LNCMI policy and EMFL 10-year rule, plus deletion notification protocol per EMFL DMP §4) is part of the §3.4 open points.
+- **D7 system models** — preservation policy aligned with the §3.4 hosting decision; minimum 10 years to remain consistent with the EMFL baseline.
+
+After project completion, MagnetDB itself remains operated by LNCMI as part of its normal infrastructure responsibilities. The DT services developed under WP4 are integrated into the LNCMI operational systems (T4.3) and inherit LNCMI's operations and maintenance.
+
+### 5.5 Methods and tools needed to access and re-use the data
+
+- **D2 / D3 / D5 (Parquet, HDF5, VTK, CSV)**: any standard scientific Python (`pyarrow`, `pandas`, `h5py`) or ParaView for VTK. The README of each demo bundle lists exact dependencies and provides an example notebook.
+- **D4 demo bundles**: a Docker Compose snippet shipped with the bundle reconstructs a minimal MagnetDB stack (postgres, redis, rustfs, api, jupyter) so that students and external users can browse the schema and run example queries.
+- **D6 (code)**: standard build instructions in each repository's README; container images on GHCR / DockerHub; Apptainer images for HPC.
+- **D7 (FMU)**: any FMI-compliant tool (OpenModelica, Dymola, Simulink, Feel++ co-simulation runner) following the FMI 2.0 standard.
+
+### 5.6 Data utility and dissemination
+
+The project's dissemination plan (proposal §III) directly supports the sharing strategy:
+
+- publications in international peer-reviewed venues (Magnet Technology Conference, ICOSAHOM, ECCOMAS, ENUMATH, SIAM, IEEE Digital Twin, MAFELAP) with HAL deposit;
+- engagement with the EMFL and FlexRICAN communities for adoption and re-use;
+- demonstrator role within the NumPEx initiative and the Exa-MA targeted project;
+- communication via LinkedIn and the project's open documentation channels.
+
+---
+
+## Section 6 — Data management responsibilities and resources
+
+### 6.1 Responsibilities
+
+| Domain | Lead | Backup | Scope |
+|---|---|---|---|
+| Overall DMP coordination | Christophe Trophime (LNCMI) | Christophe Prud'homme (CEMOSIS) | All datasets, plan updates, ANR liaison |
+| Operational data (D1, D2, D3) | Kevin Paillot (LNCMI) | Joubine Aghili (CEMOSIS, for analytics) | Curation pipeline, statistics, predictive maintenance |
+| MagnetDB platform (D4) | Christophe Trophime (LNCMI) | To-be-hired LNCMI Research Engineer | Schema, ingestion, attachments |
+| Simulation data (D5) | Vincent Chabannes (CEMOSIS) | Christophe Trophime (LNCMI) | FOM / ROM outputs, attachments, provenance |
+| Code & software (D6) | Vincent Chabannes (CEMOSIS) | To-be-hired CEMOSIS Research Engineer | CI/CD, releases, container images |
+| System models (D7) | Benjamin Vincent (LNCMI) | — | Modelica / FMU |
+| Personal data & anonymization | Christiane Warth-Martin (LNCMI) | Christophe Trophime | D4 user identifiers |
+| Security & access control | Cédric GrandClément (LNCMI) | LNCMI IT team | LemonLDAP::NG, MCS interface, network |
+| EMFL DMP liaison | François Debray (LNCMI) | Christophe Trophime | Interface with EMFL DMP coordination (FlexRICAN, EMFL board); alignment of JNL-G data policies with the EMFL DMP; raising deviations (e.g. licensing, retention) to the EMFL coordination team |
+
+### 6.2 Resources allocated
+
+The proposal explicitly budgets resources that contribute to data management:
+
+**LNCMI side**
+
+- *To-be-hired Research Engineer — 36 person-months* (from the 189 463 € staff line). Contributes directly to the curation and analysis pipelines of WP3 and to the DT architecture in T4.1, i.e. to the implementation of D2 / D3 / D4 / D5 management.
+- *Servers / data storage — 10 k€* (within the 17 k€ instruments line). Increases RustFS S3 disk capacity for D2 / D3 / D5.
+- *Subcontracting — 10 k€* covering UX improvements to the MagnetDB platform and the DT operational dashboard, both of which are user-facing components of the data management infrastructure.
+- *Internal staff (permanent personnel)*. Contributions are detailed in the proposal table; the total of 71.5 PM of LNCMI staff over 48 months includes the time of all data-management leads listed in §6.1.
+
+**CEMOSIS side**
+
+- *Funded PhD — 36 person-months* (within the 202 826 € staff line). Develops ROM methodology with direct effect on D3 / D5 (data-driven and reduced-order representations).
+- *Research Engineer — 12 person-months*. In charge of CI / CD, verification, validation and benchmarking — directly responsible for the D6 quality controls and contributes to D2 / D3 / D5 pipelines.
+- *Internal staff (permanent personnel)*. Contributions of C. Prud'homme (9.6 PM), V. Chabannes (9.6 PM) and J. Aghili (7.2 PM).
+
+**Mission and overheads**
+
+- 8 k€ overheads on each side cover travel for project meetings, conferences and training — including DMP-related events and Opidor / NumPEx workshops.
+
+### 6.3 Costs and cost coverage
+
+The resources above cover all data-management activities during the 48 months of the project, including:
+
+- storage hardware and operating costs (covered under LNCMI institutional infrastructure operations);
+- backup and IT maintenance (covered under LNCMI IT services);
+- repository deposit costs (Zenodo, HAL, Software Heritage are free to use);
+- staff time for curation, validation, and documentation (covered under the requested ANR funding).
+
+Long-term preservation costs after T0+48 are absorbed by LNCMI as part of its standard infrastructure responsibilities and by the long-term policies of the chosen public repositories.
+
+### 6.4 DMP review and update
+
+- Mid-term version (T0+24) and final version (T0+48) submitted to the ANR.
+- Internal annual reviews aligned with WP0 yearly advancement reports (T0+12, T0+24, T0+36, T0+48).
+- Triggered updates whenever a §3.4 open point is resolved or a new dataset emerges.
+
+---
+
+## Annex A — Open points to resolve
+
+These items are tracked outside the dataset descriptions because they cut across several sections:
+
+1. **Training datasets** for ML / ROM work (T2.3, T3.2, T3.3): scope, generation, storage — derived from CuratedData (D2) or curated independently.
+2. **System models (D7, T1.1)**: hosting (MagnetDB org? separate repo?), FMU licensing, open or partner-only distribution.
+3. **Demo DB hosting**: choice between Girder, data.gouv.fr, Zenodo, or a combination.
+4. **PigBrother / Hybrid Parquet curation**: timeline for extending the Pupitre curated pipeline to the other two sources.
+5. **Retention policy** for raw D1 and intermediate D2 versions, especially after schema changes.
+
+All five items will be resolved before v2 of the DMP (T0+24).
+
+## Annex B — Cross-reference with the project DMP summary
+
+| DMP summary section | Opidor / Science Europe section | Notes |
+|---|---|---|
+| §1 Data summary | Section 1 | Datasets D1–D7 list |
+| §2 Data sources, formats and storage | Sections 1, 2, 3 | Per-dataset description, documentation, storage |
+| §3 FAIR principles | Sections 1, 2, 5 | Findability, accessibility, interoperability, re-usability addressed across the three sections |
+| §4 Legal, ethical and security | Sections 3, 4 | Security in §3.5; legal & ethical in §4 |
+| §5 Sharing and preservation | Section 5 | Sharing & long-term preservation |
+| §6 Open points to resolve | Annex A | Tracked separately for visibility |
+
+## Annex C — Relationship with the EMFL DMP (parent plan)
+
+The JNL-G DMP is a **child plan** of the EMFL Data Management Plan (ISABEL deliverable D4.3, final version D4.4). The EMFL DMP covers the four EMFL facilities (LNCMI-Toulouse, LNCMI-Grenoble, HFML-RU/FOM Nijmegen, HLD-HZDR Dresden) and applies to all data produced under EMFL access campaigns.
+
+The table below maps each DMP topic to the authoritative source — EMFL parent plan, JNL-G child plan, or both:
+
+| Topic | Authoritative source | JNL-G addition |
+|---|---|---|
+| User experimental data | EMFL DMP §3, §4, §5 | None — out of scope for JNL-G |
+| EMFL administrative data (proposals, user contacts) | EMFL DMP §2 | None — out of scope for JNL-G |
+| User personal data (GDPR) | EMFL DMP §2 | DT auth architecture (LemonLDAP::NG / OIDC) — JNL-G specific |
+| Default dataset license | EMFL DMP (CC0) | JNL-G aligns; CC-BY-4.0 fallback documented |
+| Embargo on raw data | EMFL DMP (5 years) | JNL-G aligns |
+| Minimum retention | EMFL DMP (10 years) | JNL-G aligns; longer where Zenodo / Software Heritage apply |
+| Operational technical data of LNCMI-G | JNL-G DMP §1, §3 (D1, D2, D3, D4) | The whole project re-engineers this layer |
+| Simulation and computational data | JNL-G DMP (D5) | Project-specific |
+| Source code, software, system models | JNL-G DMP (D6, D7) | Project-specific |
+| MagnetDB platform | JNL-G DMP §1 (D4) | Project-specific |
+
+**Deviation policy.** Where a JNL-G choice deviates from the EMFL DMP (for instance, considering a more restrictive license such as CC-BY-NC-4.0 for a specific operational dataset under §4.2), the deviation is escalated to the EMFL coordination team (§6.1, EMFL DMP liaison) and documented in v2 of the present plan.
+
+**Update synchronization.** Updates to the EMFL DMP (foreseen periodically beyond ISABEL) are reviewed by the JNL-G DMP coordinator at each annual revision; any change relevant to JNL-G is reflected in the next DMP version.
diff --git a/prompts/MagnetDB_profile_README.md b/prompts/MagnetDB_profile_README.md
new file mode 100644
index 0000000..02e593a
--- /dev/null
+++ b/prompts/MagnetDB_profile_README.md
@@ -0,0 +1,169 @@
+
+
+
+
+
+
+
+
+
+
+
+# MagnetDB
+
+**A scientific data management and simulation platform for high-field magnet research.**
+
+MagnetDB centralizes the configurations, operational data, simulation workflows and analytics of the high-field magnets operated at the [Laboratoire National des Champs Magnétiques Intenses](https://lncmi.cnrs.fr) (LNCMI), CNRS. LNCMI is the french magnet user facility located on 2 sites -- Grenoble (LNCMI-G) and Toulouse (LNCMI-T).
+
+It is the foundation for the digital-twin work being carried out under the ANR JNL-G project (2026–2030) and integrates with the Feel++ scientific computing framework developed at [CEMOSIS](https://cemosis.fr).
+
+The platform serves researchers, magnet designers, operators and lab directors with a single view of magnet configurations, real-time and historical operational data, simulation results, and predictive-maintenance signals.
+
+---
+
+## What's in this organization
+
+The MagnetDB organization hosts the open-source components of the platform. Restricted components (in particular parts of MagnetTools) are kept in private repositories; built artifacts for those are distributed via the LNCMI internal apt depot and the `feelpp/magnettools` DockerHub image.
+
+### Core platform
+
+| Repository | Purpose |
+|---|---|
+| **`python_magnetdb`** | Django + FastAPI backend, PostgreSQL schema, REST API, background workers, S3/MinIO integration |
+| **`magnetdb-frontend`** | Web frontend — currently migrating from Vue 2 to React 18 + TypeScript + Vite |
+| **`python_magnetapi`** | Lightweight client library for the MagnetDB API |
+
+### Geometry, mesh and CAD
+
+| Repository | Purpose |
+|---|---|
+| **`python_magnetgeo`** | Polymorphic geometry definitions for LNCMI-G resistive and superconductor magnets |
+| **`python_magnetgmsh`** | Mesh generation from `python_magnetgeo` definitions via Gmsh |
+| **`hifimagnet-salome`** | CAD and Mesh Generation with [SALOME](https://www.salome-platform.org) tools (requires a valid **MeshGems** license) |
+
+### Simulation setup and execution
+
+| Repository | Purpose |
+|---|---|
+| **`python_magnetsetup`** | Templating engine that turns a MagnetDB configuration into a Feel++ / HiFiMagnet simulation case |
+| **`python_magnetworkflow`** | Orchestrated workflow: setup → CAD → mesh → run → archive |
+| **`hifimagnet-paraview`** | ParaView plugins and post-processing scripts |
+
+### Operational data and analysis
+
+| Repository | Purpose |
+|---|---|
+| **`python_magnetrun`** | Parsing, curation and analysis of magnets operational data from the different control and monitoring systems -- namely Pupitre, PigBrother and Hybrid MCS recordings following internal LNCMI nomenclature |
+| **`magnet-scipy`** | SciPy-based analytics for magnet operational data |
+| **`python_magnetcooling`** | Cooling-loop and thermal-hydraulic modelling helpers |
+
+### C++ tools (with Python bindings)
+
+| Repository | Purpose |
+|---|---|
+| **`python_magnettools`** | Python bindings to the C++ MagnetTools library (analytical magnet calculations) |
+
+---
+
+## How the pieces fit together
+
+```
+ ┌───────────────────────────────────────────────────┐
+ │ MagnetDB (Django + FastAPI) │
+ │ PostgreSQL · MinIO (S3) · Celery · LemonLDAP SSO │
+ └───────────────────────────────────────────────────┘
+ ▲ ▲
+ ┌──────────────────┘ └──────────────────┐
+ │ │
+operational data simulation pipeline
+ │ │
+python_magnetrun python_magnetsetup
+ │ │ │
+ curation Feel++ │ HiFiMagnet
+ ETL │ │
+ stats Orchestrated workflows
+ anomaly │ │
+ detection │ python_magnetgmsh
+ │ │ │
+ ▼ ▼ ▼
+Pupitre · PigBrother · Hybrid CAD · mesh · results · provenance
+(MCS recordings, sshfs) (attachments in MinIO)
+```
+
+The platform follows a three-layer operational data architecture:
+
+- **Raw** (sshfs, LNCMI-internal) → **Curated Parquet on S3** (canonical interchange layer) → **Derived statistics in PostgreSQL + S3**.
+
+---
+
+## Getting started
+
+- **Documentation**: see the docs site of the relevant repository (each component ships its own Sphinx / Antora site)
+- **Demo stack**: a minimal Docker Compose setup (postgres + redis + minio + api + jupyter) is available in `python_magnetdb` for students and external evaluators
+- **Container images**: published to GitHub Container Registry (`ghcr.io//...`)
+- **HPC**: Apptainer / Singularity images are available for SLURM / PBS / SGE clusters
+
+If you are joining the project as a student or contributor, start with `python_magnetdb` and the demo Docker Compose stack — it gives you a working MagnetDB instance with a curated seed dataset in under five minutes.
+
+> [!NOTE] The demo stack is intended for evaluation and development purposes. It is not production-ready and should not be used to deploy a real MagnetDB instance.
+
+> [!NOTE] Container images may not be actually published to GHCR until the first stable release (v1.0.0) is tagged.
+
+---
+
+## Related projects
+
+- **[Feel++](https://github.com/feelpp/feelpp)** — finite-element framework used by HiFiMagnet for non-linear multiphysics magnet simulation
+- **Scimba** — scientific machine-learning framework used in the JNL-G project for ROM and Neural Galerkin methods
+- **JNL-G (ANR AAPG2025)** — Digital twin of the LNCMI-G installation; the project under which MagnetDB is being extended into a full digital-twin platform
+- **FASUM (ANR Equipex+)** — 40 T all-superconducting user magnet at LNCMI-G; MagnetDB ingests its operational data
+- **EMFL** — European Magnetic Field Laboratory; LNCMI-G is one of three EMFL member facilities
+
+---
+
+## Contributing
+
+Contributions are welcome. Each repository has its own `CONTRIBUTING.md` describing coding standards, testing, and the pull-request workflow.
+
+- Issues and pull requests are tracked per repository
+- Larger architectural discussions happen in `python_magnetdb` Discussions
+- Releases follow [semantic versioning](https://semver.org/)
+- Tagged releases are archived on [Software Heritage](https://www.softwareheritage.org/) and [Zenodo](https://zenodo.org/) with a DOI
+
+---
+
+## Data management
+
+The data managed by MagnetDB in the context of the JNL-G project is described in the project's Data Management Plan. **JNL-G's data are operational data of the LNCMI-G installation — recordings produced by the magnet, power and cooling control systems** while a magnet is energized. User experimental data (measurements performed by external user teams on their own samples) are out of scope and are governed by the [EMFL DMP](https://emfl.eu/).
+
+---
+
+## Funding and acknowledgments
+
+MagnetDB is developed at LNCMI (CNRS UPR 3228) in collaboration with CEMOSIS (Université de Strasbourg). Its development has received support from:
+
+- **ANR AAPG2025 JNL-G** — *Digital twin of the LNCMI-G*
+- **H2020 ISABEL** (Grant Agreement No 871106) — *Improving the sustainability of the European Magnetic Field Laboratory*
+- **ANR Equipex+ FASUM** (ANR-21-ESRE-0027) — *Forty Tesla Superconducting User Magnet*
+- **CNRS** institutional support to LNCMI as a national research infrastructure
+
+
+
+
+
+
+
+---
+
+## Contact
+
+- **Lead developer**: Christophe Trophime — *christophe.trophime@lncmi.cnrs.fr*
+- **LNCMI Grenoble**: 25 avenue des Martyrs, 38000 Grenoble, France — [lncmi.cnrs.fr](https://lncmi.cnrs.fr)
+- **Issues**: please open them in the relevant repository of this organization
+
+---
+
+MagnetDB is open-source software. Public components are released under the Apache-2.0 or LGPL-3.0 license (see each repository for its exact terms). Documentation and demonstration datasets are released under CC0 or CC-BY-4.0.
diff --git a/prompts/django-database-routing.md b/prompts/django-database-routing.md
new file mode 100644
index 0000000..f77cd2f
--- /dev/null
+++ b/prompts/django-database-routing.md
@@ -0,0 +1,338 @@
+# Django Database Routing — MagnetDB
+
+**Status:** Reference note
+**Context:** `python_magnetdb` Django app — Django 5.0, PostgreSQL primary, optional MySQL operational databases
+
+---
+
+## 1. Current state
+
+`python_magnetdb/settings.py` declares a single database:
+
+```python
+DATABASES = {
+ 'default': {
+ "ENGINE": "django.db.backends.postgresql",
+ 'HOST': getenv('DATABASE_HOST') or 'localhost',
+ 'NAME': getenv('DATABASE_NAME') or 'magnetdb',
+ 'USER': getenv('DATABASE_USER') or 'magnetdb',
+ 'PASSWORD': getenv('DATABASE_PASSWORD') or 'magnetdb',
+ }
+}
+```
+
+Since there is only one key (`"default"`), **every model** in `python_magnetdb` uses it automatically. No router is needed and none is configured. This covers all core models:
+
+- `Site`, `Magnet`, `Part`, `Material`, `User`, `Server`
+- `Experiment`, `PupitreData`, `PigBrotherData`, `HybridData`, `CuratedData`
+- `ExperimentStats`, `ProcessedTimeSeries`, `CumulativeStats`
+- `StorageAttachment`, `MeshAttachment`, `CadAttachment`, `Simulation`
+
+---
+
+## 2. How Django picks a database (default behaviour)
+
+When no `DATABASE_ROUTERS` is set:
+
+| Operation | Database used |
+|---|---|
+| `Model.objects.all()` | `"default"` |
+| `Model.objects.using("default").all()` | explicit, same result |
+| `manage.py migrate` | `"default"` |
+| `manage.py migrate --database=other` | explicit target |
+
+The `"default"` key is Django's built-in fallback for every queryset, migration, and raw SQL call that does not specify a target explicitly.
+
+---
+
+## 3. When would a router be needed in MagnetDB?
+
+The most likely scenario is connecting to the **external operational MySQL databases** at LNCMI as read-only sources. For example:
+
+| Alias | Source system | Data |
+|---|---|---|
+| `supervision` | SUPERVISION MySQL DB | Pupitre run files metadata |
+| `pigbrother` | PIG_BROTHER MySQL DB | PigBrother acquisition data |
+| `hybrid` | HYBRIDE MySQL DB | Hybrid magnet data |
+
+These are **read-only reference sources** — MagnetDB never writes to them. All writes go to `"default"` (PostgreSQL).
+
+---
+
+## 4. Adding the MySQL backends
+
+### 4.1 Install drivers (with fallback)
+
+```python
+# manage.py — top of file, before django.setup()
+try:
+ import MySQLdb # preferred: mysqlclient (C extension, faster)
+except ImportError:
+ import pymysql
+ pymysql.install_as_MySQLdb() # pure-Python fallback
+```
+
+```bash
+pip install mysqlclient # preferred
+# or
+pip install pymysql # fallback if mysqlclient won't compile
+```
+
+### 4.2 Extend `settings.py`
+
+```python
+DATABASES = {
+ # --- Primary store (all writes, all MagnetDB models) ---
+ 'default': {
+ 'ENGINE': 'django.db.backends.postgresql',
+ 'HOST': getenv('DATABASE_HOST') or 'localhost',
+ 'NAME': getenv('DATABASE_NAME') or 'magnetdb',
+ 'USER': getenv('DATABASE_USER') or 'magnetdb',
+ 'PASSWORD': getenv('DATABASE_PASSWORD') or 'magnetdb',
+ },
+
+ # --- External operational sources (read-only) ---
+ 'supervision': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'HOST': getenv('SUPERVISION_DB_HOST') or 'localhost',
+ 'NAME': getenv('SUPERVISION_DB_NAME') or 'SUPERVISION',
+ 'USER': getenv('SUPERVISION_DB_USER') or 'readonly',
+ 'PASSWORD': getenv('SUPERVISION_DB_PASSWORD') or '',
+ 'PORT': getenv('SUPERVISION_DB_PORT') or '3306',
+ 'OPTIONS': {'charset': 'utf8mb4'},
+ },
+
+ 'pigbrother': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'HOST': getenv('PIGBROTHER_DB_HOST') or 'localhost',
+ 'NAME': getenv('PIGBROTHER_DB_NAME') or 'PIG_BROTHER',
+ 'USER': getenv('PIGBROTHER_DB_USER') or 'readonly',
+ 'PASSWORD': getenv('PIGBROTHER_DB_PASSWORD') or '',
+ 'OPTIONS': {'charset': 'utf8mb4'},
+ },
+
+ 'hybrid': {
+ 'ENGINE': 'django.db.backends.mysql',
+ 'HOST': getenv('HYBRID_DB_HOST') or 'localhost',
+ 'NAME': getenv('HYBRID_DB_NAME') or 'HYBRIDE',
+ 'USER': getenv('HYBRID_DB_USER') or 'readonly',
+ 'PASSWORD': getenv('HYBRID_DB_PASSWORD') or '',
+ 'OPTIONS': {'charset': 'utf8mb4'},
+ },
+}
+```
+
+Add the corresponding env vars to `.envrc.example`:
+
+```bash
+export SUPERVISION_DB_HOST=supervision-db.lncmi.local
+export SUPERVISION_DB_NAME=SUPERVISION
+export SUPERVISION_DB_USER=readonly
+export SUPERVISION_DB_PASSWORD=
+```
+
+---
+
+## 5. Router implementation
+
+### 5.1 Create `python_magnetdb/routers.py`
+
+```python
+# python_magnetdb/routers.py
+
+OPERATIONAL_DB_APPS = {
+ 'supervision': 'supervision',
+ 'pigbrother': 'pigbrother',
+ 'hybrid': 'hybrid',
+}
+
+
+class MagnetDBRouter:
+ """
+ Route queries for operational MySQL models to their respective databases.
+ All writes and all core MagnetDB models always go to 'default' (PostgreSQL).
+ """
+
+ def db_for_read(self, model, **hints):
+ db = OPERATIONAL_DB_APPS.get(model._meta.app_label)
+ return db if db else 'default'
+
+ def db_for_write(self, model, **hints):
+ # Operational databases are read-only from MagnetDB's perspective.
+ if model._meta.app_label in OPERATIONAL_DB_APPS:
+ raise ValueError(
+ f"Write to operational database '{model._meta.app_label}' is not allowed."
+ )
+ return 'default'
+
+ def allow_relation(self, obj1, obj2, **hints):
+ # Allow relations only within the same database family.
+ db1 = OPERATIONAL_DB_APPS.get(obj1._meta.app_label, 'default')
+ db2 = OPERATIONAL_DB_APPS.get(obj2._meta.app_label, 'default')
+ return db1 == db2
+
+ def allow_migrate(self, db, app_label, model_name=None, **hints):
+ if app_label in OPERATIONAL_DB_APPS:
+ # Never run migrations on the external operational databases.
+ return False
+ # Only run MagnetDB migrations on the default PostgreSQL database.
+ return db == 'default'
+```
+
+### 5.2 Register the router in `settings.py`
+
+```python
+DATABASE_ROUTERS = ['python_magnetdb.routers.MagnetDBRouter']
+```
+
+---
+
+## 6. Django apps layout for operational models
+
+Each operational database needs its own Django app so the `app_label` routing works.
+
+```
+python_magnetdb/ ← app_label = 'python_magnetdb' → 'default' (PostgreSQL)
+operational/
+ supervision/ ← app_label = 'supervision' → 'supervision' (MySQL)
+ apps.py
+ models.py ← read-only mirror models, db_table = existing table names
+ pigbrother/ ← app_label = 'pigbrother' → 'pigbrother' (MySQL)
+ apps.py
+ models.py
+ hybrid/ ← app_label = 'hybrid' → 'hybrid' (MySQL)
+ apps.py
+ models.py
+```
+
+Example `apps.py`:
+
+```python
+# operational/supervision/apps.py
+from django.apps import AppConfig
+
+class SupervisionConfig(AppConfig):
+ name = 'operational.supervision'
+ label = 'supervision' # must match key in OPERATIONAL_DB_APPS
+ managed = False # Django will not create/alter these tables
+```
+
+Example model (mirrors an existing MySQL table):
+
+```python
+# operational/supervision/models.py
+from django.db import models
+
+class SupervisionRun(models.Model):
+ """Read-only mirror of the SUPERVISION.runs table."""
+ run_id = models.IntegerField(primary_key=True)
+ site_name = models.CharField(max_length=128)
+ started = models.DateTimeField()
+ stopped = models.DateTimeField(null=True)
+
+ class Meta:
+ app_label = 'supervision'
+ db_table = 'runs'
+ managed = False # never touch the real schema
+```
+
+Register them in `INSTALLED_APPS`:
+
+```python
+INSTALLED_APPS = [
+ 'django.contrib.postgres',
+ 'django.contrib.contenttypes',
+ 'python_magnetdb',
+ 'operational.supervision',
+ 'operational.pigbrother',
+ 'operational.hybrid',
+]
+```
+
+---
+
+## 7. Querying across databases
+
+The router makes everything transparent. No `.using()` is needed in normal code:
+
+```python
+# Routed automatically to PostgreSQL via router
+experiments = Experiment.objects.filter(site__name="M10")
+
+# Routed automatically to MySQL SUPERVISION via router
+runs = SupervisionRun.objects.filter(site_name="M10")
+```
+
+Use `.using()` only when you need to override explicitly:
+
+```python
+# Force a specific database regardless of routing
+SupervisionRun.objects.using('supervision').filter(site_name="M10")
+```
+
+Cross-database joins are **not possible** via ORM (different servers). Combine in Python:
+
+```python
+experiment_names = set(Experiment.objects.values_list('name', flat=True))
+matching_runs = SupervisionRun.objects.filter(site_name__in=experiment_names)
+```
+
+---
+
+## 8. Migration behaviour with the router
+
+| Command | Effect |
+|---|---|
+| `manage.py migrate` | Runs only on `"default"` (PostgreSQL) — operational DBs blocked by `allow_migrate` |
+| `manage.py migrate --database=supervision` | Still blocked by `allow_migrate` returning `False` for that app |
+| `manage.py inspectdb --database=supervision` | Generates model stubs from the live MySQL schema — useful to bootstrap operational models |
+
+To bootstrap models from the real MySQL schema:
+
+```bash
+python manage.py inspectdb --database=supervision > operational/supervision/models.py
+```
+
+Then clean up the generated file: add `managed = False`, set correct `app_label`, remove unwanted fields.
+
+---
+
+## 9. Environment variables summary
+
+Add to `.envrc.example` (team reference) and `.envrc` (local values):
+
+```bash
+# PostgreSQL — primary MagnetDB store
+export DATABASE_HOST=postgres
+export DATABASE_NAME=magnetdb
+export DATABASE_USER=magnetdb
+export DATABASE_PASSWORD=magnetdb
+
+# MySQL — SUPERVISION (read-only)
+export SUPERVISION_DB_HOST=supervision-db.lncmi.local
+export SUPERVISION_DB_NAME=SUPERVISION
+export SUPERVISION_DB_USER=readonly
+export SUPERVISION_DB_PASSWORD=
+
+# MySQL — PIGBROTHER (read-only)
+export PIGBROTHER_DB_HOST=pigbrother-db.lncmi.local
+export PIGBROTHER_DB_NAME=PIG_BROTHER
+export PIGBROTHER_DB_USER=readonly
+export PIGBROTHER_DB_PASSWORD=
+
+# MySQL — HYBRIDE (read-only)
+export HYBRID_DB_HOST=hybrid-db.lncmi.local
+export HYBRID_DB_NAME=HYBRIDE
+export HYBRID_DB_USER=readonly
+export HYBRID_DB_PASSWORD=
+```
+
+---
+
+## 10. Key design decisions
+
+- **`python_magnetdb` always uses `default`** — no change to existing models or queries.
+- **Operational databases are read-only** — the router raises on write attempts as a safety guard.
+- **`managed = False` on all operational models** — Django never touches the MySQL schemas.
+- **`allow_migrate` returns `False` for operational apps** — `manage.py migrate` is safe to run with no risk of touching SUPERVISION/PIGBROTHER/HYBRID.
+- **`mysqlclient` preferred over `PyMySQL`** — the try/except in `manage.py` provides a silent fallback with no code changes elsewhere.
diff --git a/prompts/generate-ecosystem-visual.md b/prompts/generate-ecosystem-visual.md
new file mode 100644
index 0000000..f6ce91d
--- /dev/null
+++ b/prompts/generate-ecosystem-visual.md
@@ -0,0 +1,136 @@
+# Prompt: Generate HiFiMagnet Ecosystem Status Visual
+
+## Goal
+
+Write a self-contained Python script that produces a publication-quality figure
+summarising the **pre-requisites assessment** of the HiFiMagnet package ecosystem.
+The figure must convey two things at a glance:
+
+1. **Current readiness** of each package (overall quality / maturity).
+2. **Required dev effort** to bring it to a production-ready state.
+
+Save the output as `hifimagnet-ecosystem-status.png` (300 dpi) and, if plotly is
+available, also as `hifimagnet-ecosystem-status.html` for interactive inspection.
+
+---
+
+## Input Data
+
+Use the following dataset verbatim. All scores are integers on a 1–5 scale.
+
+```python
+packages = [
+ # name, category, overall_readiness, readability, has_ci, coverage_pct, dev_effort
+ # overall_readiness: 1=prototype … 5=production-ready
+ # readability: 1=unreadable … 5=exemplary
+ # has_ci: True / False
+ # coverage_pct: integer 0-100 (use midpoint of ranges; 0 if unknown)
+ # dev_effort: 1=minimal … 5=very high
+ dict(name="python_magnetgeo", category="geometry", overall=3, readability=3, has_ci=True, coverage=57, effort=2),
+ dict(name="python_magnetgmsh", category="geometry", overall=2, readability=3, has_ci=False, coverage=0, effort=3),
+ dict(name="hifimagnet-salome", category="geometry", overall=2, readability=3, has_ci=False, coverage=0, effort=5),
+ dict(name="python_magnetsetup", category="simulation", overall=2, readability=3, has_ci=False, coverage=15, effort=4),
+ dict(name="python_magnetworkflows", category="simulation", overall=3, readability=3, has_ci=True, coverage=0, effort=3),
+ dict(name="hifimagnet-paraview", category="postproc", overall=3, readability=2, has_ci=True, coverage=20, effort=4),
+ dict(name="python_magnetrun", category="data", overall=3, readability=3, has_ci=True, coverage=30, effort=3),
+ dict(name="python_magnetcooling", category="data", overall=3, readability=3, has_ci=True, coverage=30, effort=3),
+ dict(name="magnet_scipy", category="simulation", overall=2, readability=3, has_ci=False, coverage=21, effort=3),
+ dict(name="python-magnettools", category="field", overall=3, readability=4, has_ci=False, coverage=50, effort=4),
+ dict(name="magnettools-cpp", category="field", overall=3, readability=2, has_ci=False, coverage=10, effort=5),
+]
+```
+
+Category colour palette (use consistently across all sub-plots):
+
+| Category | Colour |
+|---|---|
+| geometry | `#4C72B0` (steel blue) |
+| simulation | `#DD8452` (orange) |
+| postproc | `#55A868` (green) |
+| data | `#C44E52` (red) |
+| field | `#8172B2` (purple) |
+
+---
+
+## Required Layout
+
+Produce a **single figure** with three panels arranged horizontally
+(`figsize=(18, 7)`):
+
+### Panel 1 — Bubble chart: Readiness vs Dev Effort
+
+- X-axis: `dev_effort` (1–5, label "Dev Effort → more work")
+- Y-axis: `overall_readiness` (1–5, label "Overall Readiness → more mature")
+- Bubble size: proportional to `coverage_pct` (min visible size even at 0%)
+- Bubble colour: by `category` using the palette above
+- Marker shape: filled circle if `has_ci=True`, open circle (unfilled) if `has_ci=False`
+- Label each bubble with the short package name (strip `python_` prefix for brevity;
+ use `magnettools-py` for `python-magnettools`)
+- Add light grey dashed grid lines at every integer tick
+- Add a light-red shaded rectangle covering effort ≥ 4 AND readiness ≤ 2
+ (high-effort / low-readiness danger zone), with a small "⚠ danger zone" label
+- Legend entries: categories (colour) + CI status (filled vs open marker)
+
+### Panel 2 — Horizontal stacked bar: Score breakdown per package
+
+Sort packages by `overall_readiness` descending, then `dev_effort` ascending.
+
+Draw a horizontal stacked bar for each package with three segments:
+
+| Segment | Value | Colour |
+|---|---|---|
+| Readiness | `overall_readiness` | `#2ca02c` (green) |
+| Readability | `readability` | `#1f77b4` (blue) |
+| Effort (inverse) | `6 - dev_effort` | `#d62728` (red, so longer = less effort) |
+
+Normalise each bar to a 0–15 total width so bars are comparable.
+Add a small vertical dashed line at x=9 (mid-point, score 3 on each dimension).
+Label the right end of each bar with the package's `coverage_pct` value
+(e.g. `"57 %"`) so coverage is visible without a separate axis.
+
+### Panel 3 — CI / packaging status matrix (heatmap-style)
+
+Rows = packages (same sort order as Panel 2).
+Columns = the following boolean attributes (derive from the input data and the
+notes below):
+
+| Column | Source |
+|---|---|
+| Has CI | `has_ci` |
+| CI auto-triggers | False for python_magnetworkflows (triggers disabled), else same as has_ci |
+| Coverage > 30 % | `coverage > 30` |
+| pip-installable | False for hifimagnet-salome, hifimagnet-paraview, python_magnetworkflows, python_magnetgmsh; True otherwise |
+| Published to PyPI | False for all packages |
+| Solo bus-factor | True for python_magnetgeo, python_magnetrun, python_magnetcooling, magnet_scipy, python-magnettools, magnettools-cpp, hifimagnet-salome |
+
+Use a two-colour scheme: ✅ green cell for True / ❌ red cell for False.
+Display the emoji (or equivalent coloured rectangle + text) inside each cell.
+Add column labels rotated 45°.
+
+---
+
+## Implementation requirements
+
+- Use **matplotlib** as the primary library (always available).
+- Optionally use **plotly** for the HTML export (guard with `try/except ImportError`).
+- No hard-coded absolute paths — save outputs next to the script.
+- Use `matplotlib.rcParams` to set a clean style:
+ `plt.style.use("seaborn-v0_8-whitegrid")` (fall back to `"seaborn-whitegrid"`
+ if the versioned name is unavailable).
+- Add a figure-level title:
+ `"HiFiMagnet Ecosystem — Package Readiness & Dev Effort Assessment (2026-04-27)"`
+- Add a footer note:
+ `"Bubble size ∝ test coverage (%). Open circles = no CI. Effort: 1 = minimal, 5 = very high."`
+- The script must be runnable with `python generate_ecosystem_visual.py` with no
+ arguments and no interactive prompts.
+
+---
+
+## Output files expected
+
+| File | Description |
+|---|---|
+| `hifimagnet-ecosystem-status.png` | 300 dpi static figure |
+| `hifimagnet-ecosystem-status.html` | Interactive plotly version (if plotly installed) |
+
+Place both files in the same directory as the script.
diff --git a/prompts/global-dev-plan.md b/prompts/global-dev-plan.md
new file mode 100644
index 0000000..15cdb69
--- /dev/null
+++ b/prompts/global-dev-plan.md
@@ -0,0 +1,865 @@
+# MagnetDB — Global Development Plan
+
+**Version 1.0 · May 2026**
+LNCMI — Laboratoire National des Champs Magnétiques Intenses
+
+**Team**: Christophe + Rémi (1.5 FTE effective)
+**Horizon**: ~12–14 months of calendar time
+
+---
+
+## Overview
+
+This document consolidates four parallel workstreams into a single coordinated plan:
+
+| Track | Scope | Est. effort |
+|-------|-------|-------------|
+| **A — Infrastructure & Distribution** | Private PyPI, apt depot, Docker CI/CD | 7 days |
+| **B — Core Data Model** | Lifecycle status overhaul + standalone Mesh model + standalone CAD model | ~11 days |
+| **C — Authentication & Access** | LemonLDAP Combination auth, user scoping, OIDC claims | ~5 days |
+| **D — Operational Statistics** | RecordStats, ETL pipeline, streaming | 24–31 weeks |
+| **E — Frontend Migration** | Vue 2 → Vue 3 (recommended path) | 6–10 weeks |
+
+Tracks A and B are largely independent and can begin immediately in parallel.
+Track C is a prerequisite for the data-scoping features in Track D (Phase D0.2–D0.4).
+Track E interleaves with Track D — see the suggested cadence in Section 5.
+
+---
+
+## Track A — Infrastructure & Distribution
+
+> Source: `roadmap.md`
+> Goal: Replace manual packaging and deployment with a fully automated CI/CD pipeline.
+
+### A0 — Prerequisites (1 day)
+
+**A0.1 — Self-hosted GitHub runner (½ day)**
+- [ ] Choose host machine (existing LNCMI server or VM)
+- [ ] Install runner deps: Docker, `dpkg-dev`, `devscripts`, `dupload`
+- [ ] Register runner at org level with labels `self-hosted,lncmi,trixie`
+- [ ] Install as systemd service; set up weekly Docker prune cron
+- [ ] Smoke-test: workflow with `runs-on: [self-hosted, lncmi, trixie]` reaches `apt.lncmi.cnrs.fr`
+
+**A0.2 — GPG subkey for CI signing (½ day)**
+- [ ] Create a signing-only subkey of the DD key (4096-bit RSA, 2y expiry)
+- [ ] Export only the subkey private material; add as `APT_SIGNING_KEY` GitHub org secret
+- [ ] Verify import on a clean machine; set calendar reminder for rotation
+
+**A0.3 — SSH deploy key for depot (1 hour)**
+- [ ] Generate dedicated ed25519 key pair `magnettools-ci-deploy`
+- [ ] Create `apt-ci` system user on the baremetal depot; grant write access to pool/dists
+- [ ] Add public key to `apt-ci`'s `authorized_keys` with `command=` restriction
+- [ ] Add `APT_DEPLOY_KEY`, `APT_DEPOT_HOST`, `APT_DEPOT_INCOMING` as org secrets
+
+### A1 — magnettools C++ packaging (2 days)
+
+**A1.1 — Debian package structure (1 day)**
+- [ ] Verify or create `debian/` directory: `control`, `rules`, `changelog`, `copyright`, `install`
+- [ ] Test manual build: `dpkg-buildpackage -us -uc -b`
+- [ ] Test manual `dupload --to lncmi magnettools_*.changes`
+- [ ] Verify `apt-ftparchive` index rebuild and GPG re-signing via `postupload` hook
+
+**A1.2 — Multistage Docker + auditwheel wheel (1 day)**
+- [ ] Extend Dockerfile into multistage: manylinux_2_28 builder → auditwheel repair → export
+- [ ] Verify tag `manylinux_2_28_x86_64` with `auditwheel show`
+- [ ] Smoke test: install wheel on clean `debian:trixie` container; `import magnettools`
+- [ ] Add `make wheel` target
+
+**A1.3 — CI workflows for magnettools (½ day)**
+- [ ] Add `publish-deb.yml` (self-hosted runner, `dpkg-buildpackage` + `dupload`)
+- [ ] Add `publish-wheel.yml` (GitHub-hosted, multistage Docker, publish to GitHub Packages)
+- [ ] Test both with `workflow_dispatch` + `dry_run: true`, then with a real tag
+
+### A2 — Private PyPI server (1 day)
+
+- [ ] Add `pypiserver` container to `docker-compose.yml` with RustFS S3 backend
+- [ ] Traefik labels: `https://pypi.magnetdb-dev.local`; htpasswd auth for write
+- [ ] Add `publish.yml` to `python_magnetgeo`, `python_magnetsetup`, `python_magnetapi`, `python_magnetrun`
+- [ ] Test: `pip install --extra-index-url https://nuget.pkg.github.com/MagnetDB/simple/ python-magnetgeo`
+
+### A3 — pyproject.toml migration (½ day)
+
+- [ ] Replace local `{path = ...}` deps with versioned package refs
+- [ ] Add `[[tool.poetry.source]]` for GitHub Packages
+- [ ] Note in `pyproject.toml` that `magnettools` is a system `.deb`, not a Poetry dep
+- [ ] `poetry lock` + full test suite pass
+
+### A4 — Docker image pipeline (1½ days)
+
+- [ ] Add `publish-image-base.yml` to `magnettools` repo: push `feelpp/magnettools:X.Y.Z` to DockerHub
+- [ ] Update `python_magnetdb` Dockerfile to `FROM feelpp/magnettools:X.Y.Z`
+- [ ] Add `publish-image.yml`: build api + jupyter images; push to GHCR
+- [ ] Update student `docker-compose.yml`: `image: ghcr.io/magnetdb/...`, no `build:` sections
+
+### A5 — Documentation & integration tests (1 day)
+
+- [ ] Write `DEPLOYMENT.md` covering: external deps, first-time setup (dev + student), runner maintenance, GPG rotation
+- [ ] Add `integration-check.yml`: pull GHCR images, run `docker compose -f docker-compose.test.yml up`
+- [ ] Full end-to-end smoke test: tag `magnettools`, `python_magnetgeo`, `python_magnetdb` in sequence
+
+### A6 — MinIO → RustFS migration (1–2 days)
+
+> Reference: `rustfs-parquet-frontend-display.md` §1
+> Goal: Replace the MinIO S3 container with RustFS. RustFS exposes the same S3-compatible API so
+> all application code (`boto3`, `django-storages`, `StorageAttachment`) is unchanged — only
+> environment variables and the docker-compose service block are updated.
+
+**A6.1 — Stand up RustFS alongside MinIO (½ day)**
+- [ ] Add `rustfs` service to `docker-compose.yml` (e.g. `ghcr.io/rustfs/rustfs:latest`); keep `minio` running in parallel during migration
+- [ ] Recreate the same bucket structure in RustFS (`magnetdb-attachments`, `magnetdb-parquet`, etc.)
+- [ ] Configure CORS on the curated-data bucket — expose `Content-Range` for client-side Parquet columnar reads:
+ ```json
+ { "AllowedOrigins": ["https://magnetdb.lncmi.cnrs.fr"],
+ "AllowedMethods": ["GET"],
+ "AllowedHeaders": ["*"],
+ "ExposeHeaders": ["Content-Length", "Content-Range"],
+ "MaxAgeSeconds": 3600 }
+ ```
+
+**A6.2 — Mirror data and flip credentials (½ day)**
+- [ ] Mirror all objects from MinIO to RustFS using `mc mirror`:
+ ```bash
+ mc alias set src http://minio:9000 $MINIO_ACCESS_KEY $MINIO_SECRET_KEY
+ mc alias set dst http://rustfs:9000 $RUSTFS_ACCESS_KEY $RUSTFS_SECRET_KEY
+ mc mirror src/magnetdb-attachments dst/magnetdb-attachments
+ mc mirror src/magnetdb-parquet dst/magnetdb-parquet
+ ```
+- [ ] Update `.envrc.example`: replace `MINIO_ENDPOINT` / `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY` with `S3_ENDPOINT_URL` / `S3_ACCESS_KEY` / `S3_SECRET_KEY` pointing to RustFS
+- [ ] Update `settings.py` / `django-storages` config to read the new env var names
+- [ ] Remove the `minio` service from `docker-compose.yml` once all services are verified
+
+**A6.3 — Smoke test (½ day)**
+- [ ] Restart API + worker containers; run the existing attachment upload/download test
+- [ ] Verify pre-signed URL generation works (needed for client-side Parquet reads in Track E)
+- [ ] Add A6 to `DEPLOYMENT.md` and `integration-check.yml`
+
+**Track A dependency graph:**
+```
+A0 → A1 → A4.1 → A4.2
+ A6 (can run after A2 — RustFS must be up before D2 Parquet ETL)
+A0 → A2 → A3
+A0 → A5 (capstone, depends on all above)
+```
+A1 and A2 are independent and can be parallelised.
+
+---
+
+## Track B — Core Data Model
+
+> Sources: `magnetdb_lifecycle_migration_guide.md`, `MESH_MODEL_CREATION.md`, `CAD_MODEL_CREATION.md`
+> Goal: Modernise the status lifecycle and introduce first-class Mesh and CAD models. All three can proceed in parallel.
+
+### B1 — Lifecycle Status Overhaul (~5 days)
+
+> Source: `magnetdb_lifecycle_migration_guide.md`
+
+#### Revised status model
+
+| Entity | Added statuses | Terminal state |
+|--------|---------------|----------------|
+| Site | `stopped` | `stopped` (never `defunct`) |
+| Magnet | `retired` | `retired` or `defunct` |
+| Part | `retired` | `retired` or `defunct` |
+
+#### Cascade rules (summary)
+- `PUT /sites/{id}/put_in_operation`: accepts magnets in `in_study` **or** `in_stock` (not just `in_stock`)
+- `POST /sites/{id}/shutdown`: site → `stopped`; per-magnet decision in request payload; at least 1 part must share the terminal status for `retired`/`defunct` magnets
+- `POST /magnets/{id}/retire`: new standalone endpoint
+- `POST /magnets/{id}/defunct`: updated to accept `defunct_parts` list (≥1 required)
+
+#### Implementation phases
+
+**B1.1 — Backend model & DB (~½ day)**
+- [ ] `python_magnetdb/models/status.py`: add `RETIRED = 'retired'`, `STOPPED = 'stopped'`
+- [ ] `python manage.py makemigrations` — only `choices` altered, no data migration yet
+- [ ] Run migration in test env; confirm existing rows unaffected
+
+**B1.2 — API endpoint updates (~1 day)**
+- [ ] Rewrite `POST /sites/{id}/shutdown` with `ShutdownPayload` Pydantic model; wrap in `transaction.atomic()`
+- [ ] Update `POST /sites/{id}/put_in_operation` guard to accept `in_study` magnets
+- [ ] Add `POST /magnets/{id}/retire`
+- [ ] Update `POST /magnets/{id}/defunct` (select `defunct_parts` list, rest → `in_stock`)
+
+**B1.3 — Frontend: status display (~½ day)**
+- [ ] `StatusBadge.vue`: `stopped` → amber/warning, `retired` → neutral amber
+- [ ] `main.js`: add `stopped: 'Stopped'`, `retired: 'Retired'` to `statusName` filter
+- [ ] Update filter dropdowns and table columns in site/magnet list views
+
+**B1.4 — Frontend: shutdown workflow (~2 days)**
+- [ ] Multi-step dialog: Step 1 — per-magnet status selector; Step 2 — per-part selector for `retired`/`defunct` magnets
+- [ ] Enforce ≥1 part selection in UI before submit is enabled
+- [ ] Confirmation summary before POST to `/sites/{id}/shutdown`
+- [ ] Add **Reactivate** action on magnet detail view (`retired` → `in_stock`)
+
+**B1.5 — Testing & data validation (~1 day)**
+- [ ] Backend unit tests: all valid transitions, cascade correctness, payload validation errors, rollback
+- [ ] Data audit: query for sites marked `defunct` (may need normalisation to `stopped`)
+- [ ] Integration test in staging: mixed shutdown (in_stock + retired + defunct in one call)
+
+### B2 — Standalone Mesh Model (~3 days)
+
+> Source: `MESH_MODEL_CREATION.md`
+
+**Goal**: Introduce a `Mesh` model with M2M ownership (Part, Magnet, Site), provenance metadata, and mesh sharing — while leaving `MeshAttachment` fully intact.
+
+**B2.1 — Model & migration**
+- [ ] Create `python_magnetdb/models/mesh.py` with `Mesh` and `MeshType` (axi/3d)
+- [ ] Fields: `type`, `attachment` (FK StorageAttachment), `mesh_config` (JSON), `command`, `provenance` (JSON), `comment`, M2M to Part/Magnet/Site, timestamps
+- [ ] Register in `python_magnetdb/models/__init__.py`
+- [ ] `python manage.py makemigrations` → creates `meshes` table + M2M through tables
+- [ ] Second data migration: backfill all existing `MeshAttachment` rows into `Mesh`
+
+**B2.2 — FastAPI routes**
+- [ ] `POST /api/meshes` — upload file, parse JSON fields, link to owner
+- [ ] `GET /api/meshes/{id}` — single mesh with attachment
+- [ ] `PATCH /api/meshes/{id}` — update `mesh_config`, `command`, `provenance`, `comment`
+- [ ] `DELETE /api/meshes/{id}` — cascade-deletes `StorageAttachment`
+- [ ] `POST /api/meshes/{id}/link` — add second owner
+- [ ] `DELETE /api/meshes/{id}/unlink` — remove owner; delete row if no owners remain
+- [ ] Register router in `web.py`
+
+**B2.3 — Serializer & show endpoint updates**
+- [ ] Verify `model_serializer` handles M2M reverse accessors correctly
+- [ ] Add `'meshes__attachment'` to `prefetch_related` in `magnets.show`, `sites.show`, `parts.show`
+- [ ] Expose both `meshes` (new) and `mesh_attachments` (old) in serialized responses
+- [ ] Deferred: migrate `Simulation.mesh_attachment` FK to `Mesh` once new model is stable
+
+**What must NOT be changed**: `mesh_attachment.py`, `mesh_attachments.py` router, `MeshAttachmentEditor.vue`, existing `meshattachment_set` prefetch calls.
+
+### B3 — Standalone CAD Model (~3 days)
+
+> Source: `CAD_MODEL_CREATION.md`
+
+**Goal**: Introduce a `Cad` model with M2M ownership (Part, Magnet, Site), provenance metadata, and CAD file sharing — while leaving `CadAttachment` fully intact. Follows the same additive pattern as B2.
+
+**B3.1 — Model & migration**
+- [ ] Create `python_magnetdb/models/cad.py` with `Cad` and `CadType` (axi/3d)
+- [ ] Fields: `type`, `attachment` (FK StorageAttachment), `cad_config` (JSON), `command`, `provenance` (JSON), `comment`, M2M to Part/Magnet/Site (`related_name='cad_set'`), timestamps
+- [ ] Register in `python_magnetdb/models/__init__.py`: `from .cad import Cad, CadType`
+- [ ] `python manage.py makemigrations` → creates `cad` table + M2M through tables (`cad_parts`, `cad_magnets`, `cad_sites`)
+- [ ] Second data migration: backfill all existing `CadAttachment` rows into `Cad` (type + attachment + owner links; `cad_config`/`command`/`provenance`/`comment` left NULL — that information was never captured)
+
+**B3.2 — FastAPI routes** (`python_magnetdb/routes/api/cad.py`)
+- [ ] `POST /api/cad` — upload file (`.xao`, `.brep`, or other), parse JSON fields, link to one owner (`resource_type`/`resource_id`)
+- [ ] `GET /api/cad/{id}` — single cad with attachment
+- [ ] `PATCH /api/cad/{id}` — update `cad_config`, `command`, `provenance`, `comment` (type and attachment are immutable)
+- [ ] `DELETE /api/cad/{id}` — cascade-deletes `StorageAttachment`
+- [ ] `POST /api/cad/{id}/link` — add second owner
+- [ ] `DELETE /api/cad/{id}/unlink` — remove owner; delete row if no owners remain
+- [ ] Register router in `web.py`
+
+**B3.3 — Serializer & show endpoint updates**
+- [ ] Add `'cad_set__attachment'` to `prefetch_related` in `parts.show`, `magnets.show`, `sites.show` alongside existing `cadattachment_set` prefetch calls
+- [ ] In `_part_post_processor`, `_magnet_post_processor`, `_site_post_processor`: rename `cad_set` → `cad_new`; keep `cadattachment_set` → `cad` (existing key, unchanged) so both old and new CAD relations are exposed
+- [ ] Deferred: retire `CadAttachment` FK once `Cad` model is stable and frontend has been updated
+
+**Note on CAD file pairs**: `.xao` + `.brep` produced by the same geometry invocation remain separate `Cad` rows (matching current `CadAttachment` behaviour). They are implicitly related by sharing the same owners and `command`/`provenance` fields. Explicit pairing via a `group_id` UUID is out of scope.
+
+**What must NOT be changed**: `cad_attachment.py`, `cad_attachments.py` router, all existing `cadattachment_set` prefetch calls, frontend `CadAttachment` components.
+
+---
+
+## Track C — Authentication & Access
+
+> Sources: `lemonldap-dbusers-gemini.md`, `roadmap-operational-stats.md` (Phase 0.2–0.4)
+> Goal: Enable multi-source authentication in LemonLDAP and map external identities to MagnetDB users for data scoping.
+
+### C1 — LemonLDAP Combination Auth
+
+**Use case**: Researchers log in via LDAP; external monitoring system users may log in via a DBI (database) module, or a future SAML provider. A single rule chain unifies these.
+
+**C1.1 — Enable Combination module in Manager**
+- [ ] Manager → General Parameters → Authentication modules → set Auth, UserDB, Password to **Combination**
+- [ ] Define combination modules: `LDAP` (existing), `DBI` or `SAML` (new external)
+- [ ] Set combination rule, e.g.:
+ ```perl
+ $_authChoice eq "LDAP" ? LDAP : ExternalDB
+ ```
+ or IP-based:
+ ```perl
+ inSubnet($ip, '192.168.x.0/24') ? LDAP : ExternalDB
+ ```
+
+**C1.2 — OIDC claim export**
+- [ ] Configure LemonLDAP Manager to export the relevant LDAP attribute (e.g., `monitoring_id`) as a custom OIDC claim
+- [ ] Validate with `lemonldap-ng-cli` or Manager test tool before applying to production
+
+**C1.3 — Testing**
+- [ ] Validate each auth path (LDAP user, external user) logs in and receives correct claims
+- [ ] Verify OIDC token contains `monitoring_id` claim for users who have it in LDAP
+
+### C2 — User Model & OIDC Claim Mapping (from Track D Phase 0.2–0.4)
+
+These steps are logically part of Track D Phase 0 but depend on C1 being operational:
+
+- [ ] Add `data_scope` field to User model (`own` / `site` / `all`, default `all`)
+- [ ] Add `accessible_sites` M2M to Site
+- [ ] Create `ExternalIdentity` model (`user`, `provider`, `external_id`)
+- [ ] Extend role choices: `experimenter` (read-only, own data), `exploit` (read+update, all operational)
+- [ ] Update `routes/api/sessions.py`: auto-create `ExternalIdentity` on login if `monitoring_id` claim present
+- [ ] Implement `get_user_record_queryset(user)`, `get_user_site_queryset(user)` in `dependencies.py`
+- [ ] Wire scoped queries into `GET /api/records`, `GET /api/sites/{id}/records`, `GET /api/parts/{id}/records`
+
+---
+
+## Track D — Operational Statistics Backend
+
+> Sources: `roadmap-operational-stats.md`, `django-database-routing.md`, `rustfs-parquet-frontend-display.md`
+> ~12 months; interleaves with Track E. See detailed descriptions in `roadmap-operational-stats.md`.
+>
+> **Terminology.** The MagnetDB entity `Record` represents an **operational run** — the control-system recordings from a magnet operation period. This is distinct from what the EMFL/ISABEL DMP calls an "experiment" (the scientist's user campaign, governed by a separate DMP). The word "experiment" is not used in this track to avoid confusion. The `experimenter` field on `Record` is the *operator* identity from the control system, not the scientist.
+>
+> **UserDB**: term used in this plan for the external read-only operational databases at LNCMI (SUPERVISION, PIGBROTHER, HYBRID MySQL instances). These are the upstream data sources for the ingestion pipeline. See `django-database-routing.md` for the full implementation reference.
+
+### D0 — Foundation: Model Evolution (3–4 weeks)
+
+Extends Record, User models; implements scoped query layer; OIDC claim mapping.
+**Depends on**: Track C (C2 overlaps with D0.2–D0.4)
+
+| Sub-phase | Deliverable |
+|-----------|-------------|
+| D0.0 | External DB connectivity — UserDB router (prerequisite for D1 ingestion) |
+| D0.1 | Record model redesign (`record_type`, `sources`, `curated`, `experimenter`, time bounds, `stream_id`) |
+| D0.2 | User model + `ExternalIdentity` model + new roles ← covered in Track C |
+| D0.3 | Scoped query layer in `dependencies.py` |
+| D0.4 | OIDC claim mapping in `sessions.py` ← covered in Track C |
+
+#### D0.0 — External DB Connectivity / UserDB Router
+
+> Reference: `django-database-routing.md`
+> Goal: Give MagnetDB read-only ORM access to the three operational MySQL databases so that D1–D4 ingest tasks can query them directly without bespoke connection code.
+
+**D0.0.1 — Driver & settings (~½ day)**
+- [ ] Add `mysqlclient` (or `pymysql` fallback) to `pyproject.toml`
+- [ ] Extend `python_magnetdb/settings.py`: add `supervision`, `pigbrother`, `hybrid` database entries (all read-only MySQL; credentials via env vars)
+- [ ] Add corresponding env vars to `.envrc.example` (`SUPERVISION_DB_HOST`, `PIGBROTHER_DB_HOST`, `HYBRID_DB_HOST`, …)
+
+**D0.0.2 — Router (~½ day)**
+- [ ] Create `python_magnetdb/routers.py` with `MagnetDBRouter`:
+ - `db_for_read`: routes `supervision`/`pigbrother`/`hybrid` app_label to their MySQL DB; everything else → `default`
+ - `db_for_write`: raises on any write attempt to operational DBs
+ - `allow_migrate`: blocks migrations on operational DBs entirely
+- [ ] Register in `settings.py`: `DATABASE_ROUTERS = ['python_magnetdb.routers.MagnetDBRouter']`
+
+**D0.0.3 — Operational app skeletons (~1 day)**
+- [ ] Create `operational/supervision/`, `operational/pigbrother/`, `operational/hybrid/` Django apps (each with `apps.py` setting `managed = False` and correct `label`)
+- [ ] Bootstrap initial models via `manage.py inspectdb --database=`; clean up: set `managed = False`, correct `app_label`, drop unwanted fields
+- [ ] Register apps in `INSTALLED_APPS`
+- [ ] Smoke-test: `SupervisionRun.objects.using('supervision').count()` returns without error
+
+**D0.0.4 — Verify migration safety (~15 min)**
+- [ ] Confirm `manage.py migrate` (no `--database` flag) does not touch MySQL schemas
+- [ ] Confirm `manage.py migrate --database=supervision` is also blocked by router
+
+### D1 — Per-Record Statistics (4–5 weeks)
+
+**Depends on**: D0
+Creates `RecordStats` model; raw and computed (MagnetTools) stats as Celery tasks; per-record and per-entity API endpoints; backfill management command.
+
+Key models: `RecordStats(record, magnet, part, category, data JSON, computed_at)`
+Key tasks: `compute_record_raw_stats`, `compute_record_computed_stats`
+Key endpoints: `GET /api/records/{id}/stats`, `GET /api/magnets/{id}/record-stats`, `GET /api/parts/{id}/record-stats`
+
+### D2 — Curated Parquet ETL (3–4 weeks)
+
+> Reference: `rustfs-parquet-frontend-display.md` §2–3; `python-magnetrun-parquet-save-load.plan.md`
+> **Prerequisite**: python_magnetrun parquet Phases 1–6 (FieldMeta category, PandasMagnetData
+> saveParquet/loadParquet, MagnetRun.fromparquet) must be complete or in active progress.
+> **Prerequisite**: Track A A6 (RustFS up and running).
+
+**Depends on**: D1
+Replaces on-the-fly `/visualize` with curated Parquet files stored in RustFS. The `ProcessedTimeSeries`
+model is dropped — curated file references live directly on the redesigned `Record` model.
+
+**Data layer mapping**:
+- `Record.sources` → D1: list of raw MCS filenames / NAS paths (immutable)
+- `Record.curated` → D2: list of `StorageAttachment` FKs pointing to full-resolution Parquet files in RustFS
+- One Parquet per `(source_type, group)`: Pupitre → one file; PigBrother/TDMS → one per group; Hybrid → one per stream
+- S3 key convention: `curated/{housing}/{record_id}/{source_type}-{group}.parquet`
+
+**Downsampling policy**: LTTB is applied **at display time only** — no pre-stored downsampled files.
+The `max_points` query parameter is the single control knob. If future profiling shows on-the-fly
+LTTB is too slow for large PigBrother kHz records, the backend can serve a pre-stored artifact
+transparently without any API or frontend change (add a `downsampled_attachments` field).
+
+**Derived columns** (hoop stress per part per timestep via MagnetTools): still pre-computed and
+stored as a separate derived Parquet in RustFS, referenced via an additional `StorageAttachment`.
+
+Key tasks: `process_record_raw(record_id)` — parse via python_magnetrun → `mdata.saveParquet()` →
+attach to `Record.curated`; `process_record_derived(record_id)` — MagnetTools computation → store
+derived Parquet.
+
+Key endpoints:
+- `GET /api/records/{id}/timeseries/data?columns=B,t&max_points=1000&t_min=…&t_max=…` — server-side
+ LTTB from full-res Parquet (Option A, replaces `/visualize`; zero frontend change)
+- `GET /api/records/{id}/timeseries/presigned-url` — returns a pre-signed RustFS URL + column catalog
+ (Option B, used by `TimeseriesViewer` component and CEMOSIS Python notebooks)
+
+Old `/visualize` kept functional (deprecated header added).
+
+**Initial scope (Pupitre only)**: PigBrother and Hybrid Parquet curation follows when
+`python_magnetrun` TDMS parquet (Phase 5) is complete (DMP Annex A open point 4).
+
+### D3 — Cumulative Stats & Lifetime Views (3–4 weeks)
+
+**Depends on**: D1
+`CumulativeStats` model aggregates per-record stats into lifetime summaries; stitched time series for trend plots; auto-refresh wired into ingest chain.
+
+Key endpoints: `GET /api/sites/{id}/stats`, `GET /api/magnets/{id}/stats/history?field=…`
+
+### D4 — Automated Offline Ingestion (3–4 weeks)
+
+**Depends on**: D2, D3
+Celery Beat directory scanner; full ingest pipeline chain: file → Record (with curated Parquet) → RecordStats → CumulativeStats; `IngestLog`; admin status endpoint.
+
+### D5 — Streaming Readiness & Online Data (6–8 weeks)
+
+**Depends on**: D4 (can be deferred until NI/DB integration is concretely planned)
+Redis Streams buffer; `BaseStreamAdapter` + `DatabasePollAdapter` + `NIStreamAdapter` skeleton; window manager; optional WebSocket live endpoint; stream management admin API.
+
+---
+
+## Track E — Frontend Migration
+
+> Sources: `vue-cli-4-to-5-migration.md`, `node-image-migration-bookworm-to-trixie.md`, `roadmap-operational-stats.md`
+
+### E0 — Current baseline (complete on `node22` branch ✅)
+
+The `node22` branch already delivers the following, ready to merge to `main`:
+
+| Task | Details | Status |
+|------|---------|--------|
+| Node 18-bookworm → 22-trixie | Two-step via Node 20-trixie; both Dockerfiles updated | ✅ |
+| Vue CLI 4 → 5 (Webpack 4 → 5) | `@vue/cli-*` bumped to `~5.0.0`; `--openssl-legacy-provider` removed | ✅ |
+| TailwindCSS 2 → 3 (PostCSS 8) | `purge` → `content`; `@tailwindcss/forms` 0.3 → 0.5 | ✅ |
+| `babel-eslint` → `@babel/eslint-parser` | Peer-dep forced ESLint 6 → 8 in the same step | ✅ |
+| ESLint 8 → 9 flat config | `eslint.config.js`; `eslint-plugin-vue ^10`; `lint` script → `eslint src/` | ✅ |
+| `Vue.filter` → `Vue.prototype.$filters` | `main.js` + all 12 templates updated | ✅ |
+| Webpack 5 Node polyfill fallbacks | `resolve.fallback: { stream: false, assert: false }` in `vue.config.js` | ✅ |
+| Full smoke test | All views, forms, charts, Monaco editor verified on Node 22 | ✅ |
+
+**Immediate action**: merge `node22` → `main` before starting E1 on either path.
+
+---
+
+### Decision: Vue 3 vs React
+
+The current frontend is **Vue 2** (Options API SFCs, Vuex 3, Vue Router 3, TailwindCSS 3, chart.js, plotly.js, Monaco editor). Vue 2 reached end-of-life on **2023-12-31**.
+
+| Factor | Vue 3 | React |
+|--------|-------|-------|
+| Migration strategy | Incremental (`@vue/compat`) | Full rewrite |
+| Existing code reuse | ~80% of template logic | ~20% (logic only) |
+| Time to first deployable result | 2–3 weeks | 6–8 weeks |
+| Total effort (1.5 FTE part-time) | 6–10 weeks | 4–6 months |
+| Risk to production stability | Low | Medium–High |
+| Team ramp-up | None (team already knows Vue) | Medium (JSX, hooks, different model) |
+| Ecosystem breadth | Medium | Large |
+| Hiring pool | Medium | Large |
+| Long-term community momentum | Good (Vue 3 actively developed) | Excellent |
+
+**Recommended path**: **Vue 3** — incremental migration, low production risk, work already done on the `node22` branch gives a meaningful head start. Choose React only if there is a concrete plan to grow the team beyond 3–4 people or to consolidate with other React-based internal tools.
+
+Both paths are documented below so either can be started from the same E0 baseline.
+
+---
+
+### Path A — Vue 3 Migration (recommended, ~6–10 weeks)
+
+#### E-A1 — Compatibility build & audit (1–2 weeks)
+
+**Goal**: Get the app booting under `@vue/compat` without any functional regressions.
+
+- [ ] Install `@vue/compat` (drop-in replacement for `vue`):
+ ```bash
+ npm install vue@^3 @vue/compat
+ npm install -D @vue/compiler-sfc
+ ```
+- [ ] Configure `vue.config.js` to alias `vue` → `@vue/compat`:
+ ```js
+ config.resolve.alias.set('vue', '@vue/compat')
+ ```
+- [ ] Set global compat config in `main.js`:
+ ```js
+ import { createApp, configureCompat } from 'vue'
+ configureCompat({ MODE: 2 }) // Vue 2 mode with Vue 3 warnings
+ ```
+- [ ] Boot the app; collect all `[Vue warn]: COMPAT` messages in the console
+- [ ] Triage warnings into three buckets:
+ - **Already fixed**: `Vue.filter` removal (done ✅)
+ - **Breaking**: `v-model` argument change, `$attrs/$listeners` merge, slot unification, `Vue.set`/`Vue.delete`, `$children`
+ - **Non-breaking / gradual**: `Vue.use` → `app.use`, global component registration
+
+Exit criterion: app boots and all major routes are navigable without console errors.
+
+#### E-A2 — Core infrastructure migration (1–2 weeks)
+
+**Vue Router 3 → 4**
+
+- [ ] `npm install vue-router@^4`
+- [ ] Replace `new Router({...})` → `createRouter({ history: createWebHistory(), routes })`
+- [ ] Replace `router.beforeEach` callback signature: `(to, from, next)` → `(to, from)` returning a value
+- [ ] Update dynamic import syntax if using string-based lazy loading
+
+**Vuex 3 → Pinia**
+
+- [ ] `npm install pinia`
+- [ ] Create one Pinia store per Vuex module (auth, magnets, sites, parts, records, visualisation)
+- [ ] Each store: `defineStore('name', { state: () => ({...}), getters: {}, actions: {} })`
+- [ ] Replace `this.$store.commit/dispatch` in components with store action calls
+- [ ] Remove Vuex entirely once all modules are migrated
+
+**Global API changes**
+
+- [ ] Replace `new Vue({...}).$mount('#app')` → `createApp(App).use(router).use(pinia).mount('#app')`
+- [ ] Replace `Vue.component(...)` (global) → `app.component(...)`
+- [ ] Replace `Vue.use(...)` → `app.use(...)`
+- [ ] Replace `Vue.prototype.$x = y` → `app.config.globalProperties.$x = y`
+
+Exit criterion: app boots with Vue 3 proper (no `@vue/compat`), routing works, Pinia stores initialise.
+
+#### E-A3 — Component migration (3–5 weeks)
+
+Migrate one SFC at a time, starting with leaf components (no children) and working up to layout/page components.
+
+**v-model changes** (most common breaking change)
+
+- [ ] `v-model` on native inputs: unchanged
+- [ ] `v-model` on custom components: `value` prop + `input` event → `modelValue` prop + `update:modelValue` event
+- [ ] `v-model:propName` syntax for multiple bindings
+
+**Slots**
+
+- [ ] Replace `slot="name"` attribute → `v-slot:name` directive
+- [ ] Replace `$slots.default` → `$slots.default()`
+- [ ] Replace scoped slots `slot-scope` → `v-slot:name="{ prop }"`
+
+**$attrs and $listeners**
+
+- [ ] `$listeners` is removed; merged into `$attrs` in Vue 3
+- [ ] Components using `v-bind="$listeners"` → `v-bind="$attrs"` (now includes event listeners)
+- [ ] Components that use `inheritAttrs: false` may need `useAttrs()` composable
+
+**Lifecycle hooks** (minimal changes in Options API)
+
+- [ ] `beforeDestroy` → `beforeUnmount`
+- [ ] `destroyed` → `unmounted`
+- [ ] All other hooks unchanged in Options API
+
+**Transition names**
+
+- [ ] `v-enter` → `v-enter-from`
+- [ ] `v-leave` → `v-leave-from`
+
+**Priority order for migration (component categories)**:
+
+1. Pure presentational components: `StatusBadge`, `Button`, `Card`, `Alert`, `Modal`, `Popover`
+2. Form components: `Form`, field wrappers, `MeshAttachmentEditor`
+3. Chart/visualisation components: `BmapChart`, `StressMapChart`, `TimeseriesChart`
+4. List views: `Sites/Index`, `Magnets/Index`, `Parts/Index`, `Records/Index`
+5. Detail/show views: `Sites/Show`, `Magnets/Show`, `Parts/Show`
+6. Layout: `App.vue`, `Nav`, `Sidebar`
+
+Exit criterion: all routes render without Vue compat warnings; ESLint `eslint-plugin-vue` v10 rules pass.
+
+#### E-A4 — New feature components (1–2 weeks)
+
+Build the new frontend components for Track D stats/timeseries endpoints (available from D1 onward):
+
+- [ ] `RecordStatsCard.vue` — displays per-record stats (min/max/mean/std) for a given scope
+- [ ] `CumulativeStatsPanel.vue` — lifetime summary for a site/magnet/part
+- [ ] `TrendChart.vue` — per-record stats over time (stitched series, using existing chart.js or plotly.js)
+- [ ] `TimeseriesViewer.vue` — replaces current `VisualisationCard`; two display modes:
+ - **Phase D2 initial (Option A)**: calls `GET /api/records/{id}/timeseries/data?columns=…&max_points=1000` — server-side LTTB, no new JS dep
+ - **Upgraded (Option B)**: calls `GET /api/records/{id}/timeseries/presigned-url`, then uses `hyparquet` (`npm install hyparquet`) for client-side columnar reads + LTTB; the same pre-signed URL is usable by CEMOSIS in Python notebooks (`pd.read_parquet(url)`)
+- [ ] `ExperimenterRecordList.vue` — scoped record list for `experimenter` role
+- [ ] Admin UI: `UserScopeEditor.vue` — manage `data_scope` and `accessible_sites` per user
+
+#### E-A5 — Vue CLI → Vite (optional, 1 week)
+
+Vue CLI 5 is fully functional and not end-of-life, but Vite offers substantially faster dev-server startup and HMR. This step is optional and can be deferred.
+
+- [ ] `npm install -D vite @vitejs/plugin-vue`
+- [ ] Create `vite.config.js` replacing `vue.config.js`
+- [ ] Update `index.html` to be at the project root (Vite convention)
+- [ ] Replace `process.env.VUE_APP_*` → `import.meta.env.VITE_*`
+- [ ] Update `web/Dockerfile` build step: `npm run build` still works (Vite outputs to `dist/`)
+- [ ] Remove `@vue/cli-service`, `webpack`, `@vue/cli-plugin-*`
+
+Exit criterion: `vite build` and `vite dev` replace `vue-cli-service build/serve`; Docker images unchanged.
+
+---
+
+### Path B — React Migration (full rewrite, ~4–6 months)
+
+> Choose this path only if the team plans to grow beyond 3–4 people or to consolidate with other React-based internal tools. All phases are sequential; no incremental deployment until E-B3.
+
+#### E-B0 — Decision prerequisites
+
+Before committing to React, resolve:
+- [ ] Confirm team will learn React (JSX, hooks, `useEffect`, `useContext`) — budget 2–3 weeks ramp-up
+- [ ] Choose state management: **TanStack Query** (server state, recommended for this API-heavy app) + **Zustand** (client state) — avoids Redux boilerplate
+- [ ] Choose routing: **React Router v6** (file-based routing via `createBrowserRouter`)
+- [ ] Confirm build tool: **Vite + React** (`@vitejs/plugin-react`) — replaces Vue CLI 5
+- [ ] Decide on TypeScript: strongly recommended for a full rewrite (enables gradual adoption)
+
+#### E-B1 — Parallel app skeleton (2–3 weeks)
+
+Run in a separate directory (`web-react/`) until ready to cut over.
+
+- [ ] `npm create vite@latest web-react -- --template react-ts`
+- [ ] Install core deps:
+ ```bash
+ npm install @tanstack/react-query react-router-dom zustand axios
+ npm install -D tailwindcss @tailwindcss/forms autoprefixer
+ ```
+- [ ] Configure TailwindCSS (same design tokens as current app — reuse `tailwind.config.js`)
+- [ ] Set up `QueryClient`, `BrowserRouter`, and `ZustandStore` in `main.tsx`
+- [ ] Implement the API client layer (`src/api/`) matching the existing FastAPI endpoints
+- [ ] Set up `react-router-dom` routes matching the current Vue Router routes
+
+#### E-B2 — Auth & layout shell (1–2 weeks)
+
+- [ ] Implement OIDC login flow (replace `routes/api/sessions.py` integration):
+ - Use `@tanstack/react-query` to fetch `/api/sessions/me`
+ - Store auth state in Zustand
+ - `` wrapper for role-gated pages
+- [ ] Implement the main layout: nav bar, sidebar, content area (reuse TailwindCSS classes)
+- [ ] Implement `StatusBadge` component (port colour mapping from `StatusBadge.vue`)
+- [ ] Implement shared UI primitives: `Button`, `Card`, `Modal`, `Alert`, `Form`
+
+#### E-B3 — Feature pages (6–10 weeks)
+
+One route group at a time. Each group below is independently deployable behind a feature flag once complete.
+
+**Sites** (1–1.5 weeks)
+- [ ] `SiteList` — `useQuery(['sites'], fetchSites)` + table + status filter
+- [ ] `SiteShow` — detail view with magnet list, mesh list, record list
+- [ ] `SiteForm` — create/edit
+- [ ] Shutdown workflow: multi-step dialog (reuse the B1 lifecycle model)
+
+**Magnets** (1–1.5 weeks)
+- [ ] `MagnetList`, `MagnetShow`, `MagnetForm`
+- [ ] Retire / defunct actions (B1 lifecycle)
+
+**Parts** (1 week)
+- [ ] `PartList`, `PartShow`, `PartForm`
+- [ ] Mesh attachment editor: `` using `react-dropzone` for file upload
+
+**Records & Visualisation** (2–3 weeks)
+- [ ] `RecordList` (with server-side pagination via TanStack Query)
+- [ ] `RecordShow` with stats cards and time series viewer
+- [ ] `TimeseriesChart` component — two display modes (mirror Vue path):
+ - **Option A** (initial): `useQuery` → `GET /api/records/{id}/timeseries/data?columns=…&max_points=1000` → `react-plotly.js`
+ - **Option B** (upgraded): `useQuery` → pre-signed URL → `hyparquet` columnar read + client-side LTTB → `react-plotly.js`; install: `npm install hyparquet`
+- [ ] `BmapChart` and `StressMapChart`: wrap existing chart.js or plotly.js calls in React components
+- [ ] Monaco editor: use `@monaco-editor/react` package
+
+**Admin UI** (1–2 weeks)
+- [ ] `UserList`, `UserShow`, `UserScopeEditor` (data_scope, accessible_sites, ExternalIdentity)
+- [ ] `IngestStatusPage` — admin ingestion log (Track D Phase D4)
+- [ ] `StreamStatusPage` — stream management (Track D Phase D5, deferred)
+
+#### E-B4 — Cutover & cleanup (1–2 weeks)
+
+- [ ] Move `web-react/` → `web/`; archive `web/src/` (keep in git history)
+- [ ] Update `web/Dockerfile` and `web/Dockerfile-dev` to use the Vite build
+- [ ] Update nginx config (`web/config/nginx.conf`) — path rewriting for SPA (same as current)
+- [ ] Remove Vue CLI, Vue 2, Vuex, Vue Router 3 deps
+- [ ] Update `docker-compose*.yml` — no `web/Dockerfile` changes needed (same `dist/` output path)
+
+#### Library equivalences (Vue 2 → React)
+
+| Vue 2 (current) | React equivalent |
+|----------------|-----------------|
+| Vuex 3 | Zustand (client state) + TanStack Query (server state) |
+| Vue Router 3 | React Router v6 |
+| `axios` + manual loading state | TanStack Query (`useQuery`, `useMutation`) |
+| `chart.js` | `react-chartjs-2` wrapper |
+| `plotly.js` | `react-plotly.js` wrapper |
+| Monaco editor (CDN) | `@monaco-editor/react` |
+| TailwindCSS 3 | TailwindCSS 3 (unchanged) |
+| `vue-final-modal` | `headlessui` or custom portal |
+| `@vue/compat` warnings | TypeScript strict mode |
+| *(new)* client-side Parquet reads | `hyparquet` (pure JS, no WASM; HTTP range requests for columnar projection) |
+
+---
+
+### Shared considerations (both paths)
+
+**Build tooling baseline** (already established on `node22` branch)
+
+| Item | Current state |
+|------|--------------|
+| Node | 22-trixie ✅ |
+| Base Docker image | `node:22-trixie` ✅ |
+| ESLint | 9 flat config ✅ |
+| TailwindCSS | 3.x ✅ |
+| Build output | `web/dist/` served by `nginx:alpine` ✅ |
+
+**nginx config** (`web/config/nginx.conf`) — keep as-is for both paths; it already handles SPA routing with `try_files $uri $uri/ /index.html`.
+
+**API contract** — the FastAPI backend is path-stable. Both paths use the same endpoints. No backend changes are needed for E1–E5.
+
+**Testing**
+- Vue 3 path: add `@vue/test-utils@^2` + `vitest` (replaces Jest + `@vue/test-utils@^1`)
+- React path: `@testing-library/react` + `vitest` (or Jest)
+- Both: keep the existing backend pytest suite unchanged
+
+---
+
+## Section 5 — Interleaving & Recommended Cadence
+
+```
+Month 1: Track A (A0–A1): runner, GPG, magnettools packaging
+ Track B (B1.1–B1.2): lifecycle status backend
+ Track C (C1): LemonLDAP Combination auth
+
+Month 2: Track A (A2–A3): PyPI server (RustFS backend), pyproject.toml
+ Track A (A6): MinIO → RustFS migration (can run in parallel with A2)
+ Track B (B1.3–B1.5): lifecycle frontend + tests
+ Track B (B2): standalone Mesh model
+ Track B (B3): standalone CAD model
+
+Month 3: Track A (A4–A5): Docker pipeline, integration tests
+ Track D (D0.0): UserDB router — external DB connectivity (no C dependency)
+ Track C (C2) / Track D (D0.1–D0.4): User model, OIDC mapping, scoped queries
+ [Vue 3] Track E (E-A1): merge node22 branch; install @vue/compat; collect warnings
+ [React] Track E (E-B1): scaffold Vite+React app in web-react/; API client layer
+
+Month 4: Track D (D1): RecordStats — API-only, test via Swagger/curl
+ [Vue 3] Track E (E-A2): Vue Router 4 + Pinia migration
+ [React] Track E (E-B2): Auth + layout shell; StatusBadge; shared UI primitives
+
+Month 5–6: Track D (D2): Curated Parquet ETL (replaces /visualize; RustFS must be live)
+ [Vue 3] Track E (E-A3): component migration (leaf → layout)
+ [React] Track E (E-B3 start): Sites, Magnets, Parts pages
+ → New frontend components can consume new stats/timeseries endpoints
+
+Month 7–8: Track D (D3): CumulativeStats
+ [Vue 3] Track E (E-A3–E-A4): trend charts, experimenter views, admin UI
+ [React] Track E (E-B3 cont.): Records, Visualisation, Admin pages
+
+Month 9: Track D (D4): automated offline ingestion (pure backend)
+ [Vue 3] Track E (E-A5): polish + optional Vue CLI → Vite
+ [React] Track E (E-B4): cutover; archive Vue source; update Dockerfiles
+
+Month 10–12: Track D (D5): streaming (when NI/DB integration is ready)
+ → Real-time dashboard components (WebSocket) whichever path was chosen
+```
+
+**Key sequencing rules:**
+- A0 must complete before A1 and A2 (they share the runner and org secrets)
+- A6 (RustFS migration) must complete before D2 Parquet ETL writes curated files; can run in parallel with A2–A3
+- B1 backend phases (B1.1–B1.2) must deploy before frontend phases (B1.3–B1.4)
+- C1 must be stable before C2/D0.4 (OIDC claim mapping depends on LemonLDAP exporting the claim)
+- D0.0 (UserDB router) has no external dependency and can start in Month 2 alongside B/C work
+- D0 must complete before D1; D1 before D2 and D3; D2+D3 before D4
+- E-A1 / E-B1 can start as soon as `node22` branch merges; largely independent from D0–D2
+- TimeseriesViewer Option B (`hyparquet`) requires A6 (RustFS CORS) and D2 (presigned-url endpoint)
+- **Frontend path decision must be made before Month 3** — the two paths diverge immediately
+
+---
+
+## Section 6 — Effort Summary
+
+| Track | Phase | Effort | Assignee |
+|-------|-------|--------|----------|
+| A | A0 Prerequisites | 1 day | Christophe (GPG), Rémi (runner) |
+| A | A1 magnettools | 2 days | Christophe |
+| A | A2 PyPI server | 1 day | Rémi |
+| A | A3 pyproject.toml | ½ day | Rémi |
+| A | A4 Docker pipeline | 1½ days | Both |
+| A | A5 Docs + integration | 1 day | Both |
+| A | A6 MinIO → RustFS migration | 1–2 days | Christophe |
+| **A total** | | **~8–9 days** | |
+| B | B1 Lifecycle status | 5 days | Both |
+| B | B2 Mesh model | 3 days | Christophe |
+| B | B3 CAD model | 3 days | Christophe |
+| **B total** | | **~11 days** | |
+| C | C1 LemonLDAP | 1–2 days | Christophe |
+| C | C2 User/OIDC mapping | 2–3 days | Christophe |
+| **C total** | | **~5 days** | |
+| D | D0.0 UserDB router (ext. DB connectivity) | 2 days | Christophe |
+| D | D0.1–D0.4 Foundation (model, scoped queries, OIDC) | 3–4 weeks | Both |
+| D | D1 RecordStats | 4–5 weeks | Both |
+| D | D2 Curated Parquet ETL | 3–4 weeks | Both |
+| D | D3 CumulativeStats | 3–4 weeks | Both |
+| D | D4 Ingestion | 3–4 weeks | Rémi |
+| D | D5 Streaming | 6–8 weeks | Both |
+| **D total** | | **~22–29 weeks** | |
+| E (Vue 3 path) | E-A1 Compat build + audit | 1–2 weeks | Rémi |
+| E (Vue 3 path) | E-A2 Router 4 + Pinia | 1–2 weeks | Rémi |
+| E (Vue 3 path) | E-A3 Component migration | 3–5 weeks | Rémi |
+| E (Vue 3 path) | E-A4 New stats/timeseries components | 1–2 weeks | Rémi |
+| E (Vue 3 path) | E-A5 Vite (optional) | 1 week | Rémi |
+| **E total (Vue 3)** | | **~6–10 weeks** | |
+| — or — | | | |
+| E (React path) | E-B1 Vite + React skeleton | 2–3 weeks | Both |
+| E (React path) | E-B2 Auth + layout shell | 1–2 weeks | Both |
+| E (React path) | E-B3 Feature pages | 6–10 weeks | Both |
+| E (React path) | E-B4 Cutover + cleanup | 1–2 weeks | Both |
+| **E total (React)** | | **~4–6 months** | |
+| **Grand total (Vue 3 path)** | | **~11–13 months** | |
+| **Grand total (React path)** | | **~15–19 months** | |
+
+---
+
+## Section 7 — Risk Register
+
+| Risk | Likelihood | Impact | Mitigation |
+|------|-----------|--------|------------|
+| manylinux_2_28 base can't build magnettools C++ deps | Medium | A1.2 blocked | Fall back to `debian:bookworm` base |
+| Baremetal depot `postupload` hook not yet configured | Unknown | A1.3 blocked | Clarify before A1.1 |
+| LemonLDAP Combination module breaks existing LDAP login | Medium | C1 rollback | Test in staging with a shadow rule first |
+| `monitoring_id` LDAP attribute not consistently populated | Medium | C2/D0.4 blocked | Make ExternalIdentity creation optional; log missing claims |
+| MagnetTools fails for certain magnet configs | Medium | D1/D2 degraded | Degrade gracefully: keep raw stats, skip computed, log error |
+| RustFS migration data loss or service interruption | Low | A6 blocked | Run `mc mirror` with `--overwrite=false`; keep MinIO live until full smoke-test passes |
+| Parquet storage growth in RustFS | Low | D2 storage | Full-res D2 files are 200 KB–2 MB each; monitor bucket size; use zstd compression in `saveParquet()` |
+| python_magnetrun parquet Phases 1–6 not ready when D2 starts | Medium | D2 delayed | Fall back to MagnetDB-internal pyarrow conversion for Pupitre; reprocess when python_magnetrun lands |
+| RustFS CORS misconfiguration blocks client-side Parquet reads | Low | Option B unavailable | Start with Option A (server-side); Option B is an upgrade, not a blocker |
+| Existing `defunct` site records need manual normalisation to `stopped` | Unknown | B1.5 audit | Run audit query before deploying B1; prepare targeted data migration |
+| NI streaming hardware integration delayed | High | D5 deferred | D5 is designed to be deferrable — D0–D4 deliver full value without it |
+| Vue 3 → Vite migration adds scope to Track E | Low | E-A5 extended | Keep Vite as optional; Vue CLI 5 is fully functional |
+| Vue 3 compat warnings reveal hidden `$children`/`$listeners` usage | Low | E-A1 extended | Audit all components for `$children`; replace with `ref` or slot pattern |
+| React rewrite scope creep (TypeScript, new test suite, full redesign) | High | E-B delayed | Timebox each feature page strictly; no design overhaul in E-B3 |
+| React: plotly.js / chart.js wrapper libraries add indirection | Low | E-B3 rework | Evaluate `react-plotly.js` and `react-chartjs-2` early in E-B1 |
+
+---
+
+## Section 8 — Immediate Next Steps (Month 1)
+
+1. **A0**: Provision GitHub runner; create GPG subkey; generate SSH deploy key
+2. **B1.1**: Add `RETIRED`, `STOPPED` to `status.py`; generate and review migration; deploy to test env
+3. **B2**: Create `mesh.py` model; generate migration; write backfill data migration
+4. **B3**: Create `cad.py` model; generate migration; write backfill data migration (same pattern as B2, can run in parallel)
+5. **C1**: Enable Combination module in LemonLDAP staging; validate existing LDAP login still works
+6. **Decision**: Confirm Vue 3 or React path (see Track E decision matrix); communicate to Rémi; merge `node22` → `main` as the shared starting point for either path
+
+**Quick-start for B1.1 (can start today):**
+```bash
+git checkout -b feature/lifecycle-status-retired-stopped
+# Edit python_magnetdb/models/status.py — add RETIRED, STOPPED
+python manage.py makemigrations
+# Review generated migration
+python manage.py migrate
+# Run test suite
+```
+
+**Quick-start for B2 (parallel branch):**
+```bash
+git checkout -b feature/mesh-model
+# Create python_magnetdb/models/mesh.py
+# Register in __init__.py
+python manage.py makemigrations
+# Write backfill data migration
+```
+
+**Quick-start for B3 (parallel branch):**
+```bash
+git checkout -b feature/cad-model
+# Create python_magnetdb/models/cad.py
+# Register in __init__.py
+python manage.py makemigrations
+# Write backfill data migration (CadAttachment → Cad)
+```
diff --git a/prompts/hifimagnet-ecosystem-assessment.md b/prompts/hifimagnet-ecosystem-assessment.md
new file mode 100644
index 0000000..9a998bb
--- /dev/null
+++ b/prompts/hifimagnet-ecosystem-assessment.md
@@ -0,0 +1,103 @@
+# HiFiMagnet Ecosystem — Pre-requisites Assessment Summary
+
+> Generated: 2026-04-27
+> Sources: per-package `*-assessment.yaml` files in each repository's `prompts/` directory.
+> **Dev Effort score: 1 = minimal work needed, 5 = very high effort required**
+
+## Summary Table
+
+| Package | Overall Readiness | CI | Tests / Coverage | Installability | API Stability | Readability | Maintenance | Dev Effort |
+|---|---|---|---|---|---|---|---|---|
+| **python_magnetgeo** | 3 — usable w/ caveats | ✅ GHA (active) | pytest+cov / **57 %** | `pip install -e .` works | mostly stable (v1.0.1, Beta) | 3/5 | active, solo | **2** |
+| **python_magnetrun** | 3 — usable w/ caveats | ✅ GHA (4 Pythons + Debian) | pytest+cov / **~30 %** | manual step (local dep) | unstable, Pre-Alpha | 3/5 | active, solo | **3** |
+| **python_magnetworkflows** | 3 — usable w/ caveats | ⚠️ GHA (push triggers **disabled**) | pytest / unknown | system packages (Feel++) | unstable | 3/5 | active, small team | **3** |
+| **hifimagnet-paraview** | 3 — usable w/ caveats | ✅ GHA (unit + integration) | pytest / **<30 %** | system ParaView required | unstable, Pre-Alpha | 2/5 | active, small team | **4** |
+| **python-magnettools** | 3 — usable w/ caveats | ❌ none | pytest / **30–70 %** | C++ build + system pkgs | experimental | 4/5 | active, solo | **4** |
+| **python_magnetgmsh** | 2 — early-stage | ❌ none | shell scripts (no pytest) | manual + system gmsh | experimental, Alpha | 3/5 | active, small team | **3** |
+| **python_magnetsetup** | 2 — early-stage | ❌ none | pytest / **<30 %** (logging only) | pip works, system pkgs | unstable | 3/5 | active, small team | **4** |
+| **magnet_scipy** | 2 — early-stage | ❌ none | pytest / **~21 %** (stubbed) | pip works (pure Python) | experimental, Alpha | 3/5 | inactive (~7 mo) | **3** |
+| **hifimagnet-salome** | 2 — early-stage | ❌ none | manual scripts / unknown | SALOME + proprietary MeshGems | unstable | 3/5 | active, solo | **5** |
+| **magnettools-cpp** | 3 — usable w/ caveats | ❌ none | manual scripts / **<30 %** | complex (NAG, CADNA, etc.) | mostly stable | 2/5 | active, solo | **5** |
+
+---
+
+## Per-package Notes
+
+### python_magnetgeo
+- Root dependency of the whole stack; best positioned overall.
+- Active CI (GitHub Actions, Python 3.11/3.12/3.13), 57% coverage.
+- Not published to PyPI — all dependents require a git-install.
+- Code concerns: 124 `isinstance` guards, files up to 887 lines (`Insert.py`), inconsistent file naming (PascalCase vs snake_case), 10 TODO/FIXME in core code.
+
+### python_magnetrun
+- CI green on 4 Python versions + Debian Trixie; Codecov integrated.
+- `python_magnetcooling` is a local non-PyPI dependency requiring a manual pre-install step.
+- Coverage at 30% with several modules at 0% (e.g. `BandH.py`).
+- Active refactoring (`rework_analysis` branch); API breaking changes documented in CHANGELOG.
+
+### python_magnetworkflows
+- CI file exists but push/PR triggers are **commented out** — only runs on `workflow_dispatch`.
+- Core dependency Feel++ must be installed as Debian system packages; standard venv requires `--system-site-packages`.
+- Leftover artefacts (`.bak`, `.old`, `~` files) committed inside the package directory.
+
+### hifimagnet-paraview
+- CI present but meaningful tests require a non-pip-installable ParaView OSMesa binary + Git LFS data.
+- Readability 2/5: 40+ commented-out `print()` calls in `stats.py` alone; 20+ functions exceed 50 lines.
+- Maintainability 2/5: the 3D/2D/Axi module triplets (`stats`/`statsAxi`, `histo`/`histoAxi`, `meshinfo`/`meshinfoAxi`) duplicate large swaths of logic with no shared base class.
+
+### python-magnettools
+- Python pybind11 bindings for the `magnettools-cpp` C++ library.
+- Highest readability in the ecosystem (4/5): Google-style docstrings, type annotations, clean module separation.
+- No CI; build requires CMake + system C++ libraries; not published to PyPI.
+
+### python_magnetgmsh
+- `tests/` directory exists but is empty; pytest is configured but no `test_*.py` files written.
+- Shell-script test suite requires external geometry data at `/data/geometries` — not reproducible by new contributors.
+- Gmsh ≥ 4.13.1 may require the dev channel (`gmsh.info/python-packages-dev`).
+
+### python_magnetsetup
+- No CI — the only existing tests cover the logging module; core simulation-setup logic is untested.
+- `jsonmodel.py` (1294 lines) and `setup.py` (1048 lines) are severely oversized.
+- Mixed `print()`/`logger` usage, heavy commented-out blocks, and a broken f-string in `jsonmodel.py`.
+
+### magnet_scipy
+- Pure Python (scipy/numpy/pandas), so the simplest install in the ecosystem.
+- Inactive: last commit ~7 months ago (September 2025).
+- Multiple refactor variants coexist (`main.py`, `main_refactor.py`, `coupled_main_refactor.py`) with no clear canonical entry point.
+- README Quick Start examples are stubbed out with no actual runnable code.
+
+### hifimagnet-salome
+- Requires a full SALOME platform environment (9.9–9.15) and a proprietary MeshGems licence.
+- No standard Python packaging (`setup.py`/`pyproject.toml` absent).
+- 36 TODO/FIXME markers; `print()` used throughout instead of `logging`.
+- Highest dev effort in the ecosystem alongside `magnettools-cpp`.
+
+### magnettools-cpp
+- C++ library underpinning most field calculations; very large optional dependency matrix (NAG, CADNA, MATHEVAL, SUNDIALS, SPHEREPACK, EXPOKIT).
+- Readability 2/5: pre-C++11 idioms (`NULL`, raw pointers, `using namespace std` in 15 headers), 430-line fat header (`MagnetType.h`).
+- Empty `ChangeLog`; no semantic version tags in git; commit messages are terse and sometimes typo-ridden.
+
+---
+
+## Key Findings
+
+| Priority | Finding |
+|---|---|
+| **Highest leverage** | `python_magnetgeo` is the root dependency of the whole stack and the best positioned. Publishing it to PyPI would unblock all downstream packages. |
+| **Missing CI (critical)** | `python_magnetgmsh`, `python_magnetsetup`, `magnet_scipy`, `python-magnettools`, `magnettools-cpp`, and `hifimagnet-salome` have **no CI at all** — regressions are invisible. |
+| **System-dep blockers** | `hifimagnet-salome` (SALOME + MeshGems), `hifimagnet-paraview` (ParaView OSMesa), `python_magnetworkflows` (Feel++) cannot be installed with plain `pip install` and cannot be tested in standard CI runners without significant extra work. |
+| **Coverage gap** | Only `python_magnetgeo` exceeds 50% coverage. Everything else is ≤30%, meaning regressions in core logic would go undetected. |
+| **Structural debt** | `hifimagnet-paraview` (3D/2D/Axi duplication) and `python_magnetsetup` (1000+ line modules) are the worst offenders for long-term maintainability. |
+| **Bus-factor risk** | Most packages have a solo maintainer (Christophe Trophime); `python_magnetworkflows` and `hifimagnet-paraview` are the only ones with a meaningful second contributor. |
+| **Mislabeled assessment** | `python_magnetcooling/prompts/python_magnetrun-assessment.yaml` contains a `python_magnetrun` assessment — `python_magnetcooling` has no dedicated pre-requisites analysis yet. |
+
+---
+
+## Score Legend
+
+| Dimension | 1 | 3 | 5 |
+|---|---|---|---|
+| Overall Readiness | prototype | usable with caveats | production-ready |
+| Readability | unreadable | average | exemplary |
+| Maintenance | unmaintained | actively maintained solo | full governance |
+| Dev Effort | minimal | moderate | very high |
diff --git a/prompts/hifimagnet-paraview-assessment.yaml b/prompts/hifimagnet-paraview-assessment.yaml
new file mode 100644
index 0000000..22406b8
--- /dev/null
+++ b/prompts/hifimagnet-paraview-assessment.yaml
@@ -0,0 +1,43 @@
+package: hifimagnet-paraview
+description: Python post-processing toolkit for HiFiMagnet/Feel++ simulation results via ParaView, supporting statistics, histograms, visualization, and CSV export for 3D, 2D, and axisymmetric geometries.
+tests:
+ present: true
+ kind: pytest
+ coverage_estimate: low (<30%) # unit tests cover helpers only; integration tests cover 2D/3D/Axi workflows but require ParaView + LFS data
+documentation:
+ readme: comprehensive
+ api_docs: sphinx/mkdocs # Sphinx config with .rst files present in docs/
+ usage_examples: dedicated docs # docs/QUICKSTART.md, docs/examples.rst
+ci:
+ present: true
+ runs_tests: true
+ builds_package: false # no build/publish job; only unit + integration test jobs
+ platform: GitHub Actions
+installability:
+ pip_install: requires manual steps # needs ParaView system install + --system-site-packages venv
+ extra_dependencies: system packages # libglu1-mesa, libglapi-mesa, ParaView OSMesa binary (not on PyPI)
+ packaging: pyproject.toml
+api_stability:
+ status: unstable # pyproject.toml classifies as "Pre-Alpha" (Development Status :: 2)
+ breaking_changes_risk: high
+maintenance:
+ active: true
+ last_commit_approx: "9 weeks ago"
+ bus_factor: small team # 2 primary humans (Muzet 60 commits, Trophime 48 commits)
+code_quality:
+ readability:
+ score: 2 # 1=unreadable, 3=average, 5=exemplary
+ type_hints: partial # consistent in method.py; absent in histo/stats/view modules
+ docstrings: partial # good coverage in method.py; sparse elsewhere
+ function_length: poor # 20+ functions exceed 50 lines; several exceed 100
+ commented_out_code: high # 40+ commented-out print() calls in stats.py alone; many more across codebase
+ notes: "Naming conventions are clear and ruff is configured, but long functions, pervasive debug prints, and inconsistent type annotations reduce readability."
+ maintainability:
+ score: 2 # 1=unmaintainable, 3=average, 5=easily maintained
+ code_duplication: high # stats/statsAxi, histo/histoAxi, meshinfo/meshinfoAxi share near-identical logic with no shared base
+ linter_configured: true # ruff with E/W/F/I/N/UP/B rules in pyproject.toml
+ coverage_enforced: false # no --cov threshold in CI
+ notes: "The 3D/2D/Axi module triplets duplicate large swaths of logic; extracting a shared base would significantly reduce the maintenance surface."
+overall_readiness:
+ score: 3
+ blocker: "Requires a non-pip-installable ParaView binary for all meaningful functionality, making automated installation and reproducibility non-trivial outside the HiFiMagnet infrastructure."
diff --git a/prompts/hifimagnet-salome-assessment.yaml b/prompts/hifimagnet-salome-assessment.yaml
new file mode 100644
index 0000000..c3cbe26
--- /dev/null
+++ b/prompts/hifimagnet-salome-assessment.yaml
@@ -0,0 +1,32 @@
+package: hifimagnet-salome
+description: A SALOME platform plugin for generating CAD geometry and meshes for PolyHelix and Bitter magnet inserts used in high-field magnet design.
+tests:
+ present: true
+ kind: manual scripts
+ coverage_estimate: unknown
+documentation:
+ readme: decent
+ api_docs: sphinx/mkdocs
+ usage_examples: inline in readme
+ci:
+ present: false
+ runs_tests: false
+ builds_package: false
+ platform: none
+installability:
+ pip_install: requires manual steps
+ extra_dependencies: complex
+ packaging: none
+api_stability:
+ status: unstable
+ breaking_changes_risk: medium
+maintenance:
+ active: true
+ last_commit_approx: 7 weeks ago
+ bus_factor: solo
+ score: 3 # active solo maintainer covering SALOME 9.9–9.15, but no CI safety net and high bus-factor risk
+readability:
+ score: 3 # consistent class-based structure with docstrings, but large monolithic files (up to 1554 lines), 36 TODO/FIXME markers, and print() used throughout instead of logging
+overall_readiness:
+ score: 2
+ blocker: no CI and no standard Python packaging — installation requires a full SALOME platform environment and a proprietary MeshGems licence, making automated testing and reproducible installs very difficult
diff --git a/prompts/license-audit.md b/prompts/license-audit.md
new file mode 100644
index 0000000..04cb5db
--- /dev/null
+++ b/prompts/license-audit.md
@@ -0,0 +1,205 @@
+# License Audit
+
+**Date**: 2026-05-13
+**Project license**: MIT (all internal components: `python_magnetdb`, `python_magnetgeo`, `magnettools`, `python_magnetgmsh`)
+
+---
+
+## Findings by severity
+
+### Requires attention: LGPL dependencies
+
+| Package | Version | License | Used via |
+|---|---|---|---|
+| `psycopg` | 3.3.2 | **LGPL-3.0-only** | direct |
+| `psycopg-binary` | 3.3.2 | **LGPL-3.0-only** | direct (binary extra) |
+| `paramiko` | 3.5.1 | **LGPL** (unversioned) | `fabric` → `python-magnetsetup` |
+
+**Are these a conflict?** No hard conflict with MIT, but LGPL imposes an obligation: users must be able to replace/relink the LGPL library with a modified version.
+
+- For `psycopg` (pure Python + C extension loaded dynamically), Python's import mechanism satisfies the "relinking" requirement — this is a well-established, accepted position.
+- For **`psycopg-binary`**, the pre-compiled wheel bundles libpq **statically**. This is the more nuanced case: under strict LGPL-3.0, users should be able to relink against a modified libpq. Most projects accept this in practice, but it's worth knowing. If strict compliance matters, switch to `psycopg[c]` (dynamically links to the system's libpq) and remove the `[binary]` extra.
+- For `paramiko`, the LGPL version is not specified in METADATA. The `fabric` dependency only uses it for SSH — same analysis applies.
+
+### Benign: MPL-2.0 dependencies
+
+| Package | License | Used via |
+|---|---|---|
+| `certifi` | MPL-2.0 | `requests` (transitive) |
+| `pathspec` | MPL-2.0 | `black` (dev only) |
+
+MPL-2.0 is **file-level** copyleft: modifications to MPL source files must be released under MPL, but using MPL libraries does not propagate to your code. No conflict.
+
+### Missing license declaration
+
+**`python-magnetsetup`** (`python_magnetsetup/pyproject.toml`) has no `license` field and no `LICENSE` file. Since it is in-tree and authored by the same team, there is no third-party conflict — but it should declare `license = "MIT"` for consistency.
+
+### Requires documentation: `gmsh` GPL-2+ with API exception (`python_magnetgmsh`)
+
+The `gmsh` Python package (4.13.1) is declared **GPL-2+** in its PyPI metadata. At face value this would require any code linking against it to also be GPL. However, the Gmsh project grants an **explicit API exception**:
+
+> Use of the Gmsh API (all language bindings, including Python) is permitted in programs that are not GPL, without those programs being required to be GPL themselves.
+
+`python_magnetgmsh` only ever calls published Gmsh API functions via `ctypes` dynamic loading of `libgmsh.so` — exactly the usage covered by the exception. Its MIT license is therefore valid, and both planned licenses (Apache-2.0, LGPL-3.0) are equally permitted under the exception.
+
+Caveats:
+- The PyPI METADATA does not mention the exception. Any downstream auditor will see "GPL" and may be alarmed. The `python_magnetgmsh` README should explicitly document this.
+- The exception covers only the API surface. Any future code accessing Gmsh internals beyond the published API would lose this protection.
+- GPL-2+ is strictly incompatible with Apache-2.0 in the FSF sense (patent termination clause). The API exception bypasses this, but only for API consumers — worth noting if `python_magnetgmsh` is ever statically bundled with Gmsh.
+
+### Unmaintained dependency (not a license conflict, but a risk)
+
+`xlwt` in `python_magnetgeo/pyproject.toml`: BSD-licensed, no conflict, but the package has been abandoned since 2019. Its recommended replacement is `openpyxl` (MIT).
+
+---
+
+## Full dependency license table
+
+### Python backend (`pyproject.toml`)
+
+| Package | License | Notes |
+|---|---|---|
+| django | BSD-3-Clause | |
+| psycopg | LGPL-3.0-only | See above |
+| psycopg-binary | LGPL-3.0-only | Static libpq — see above |
+| jsonfield | MIT | |
+| pyjwt | MIT | |
+| uvicorn | BSD-3-Clause | |
+| uvloop | MIT | |
+| fastapi | MIT | |
+| pydantic | MIT | |
+| python-multipart | Apache-2.0 | |
+| minio | Apache-2.0 | |
+| requests | Apache-2.0 | |
+| cryptography | Apache-2.0 OR BSD-3-Clause | |
+| celery | BSD-3-Clause | |
+| pandas | BSD-3-Clause | |
+| pyarrow | Apache-2.0 | |
+| numpy | BSD-3-Clause | |
+| scipy | BSD-3-Clause | |
+| tabulate | MIT | |
+| pyyaml | MIT | |
+| pint | BSD-3-Clause | |
+| watchfiles | MIT | |
+| pytz | MIT | |
+| matplotlib | PSF/BSD-compatible | |
+| mplcursors | MIT | |
+| magnettools | MIT | from github.com/feelpp/magnettools |
+| python-magnetgeo | MIT | in-tree submodule |
+| python-magnetsetup | **undeclared** | in-tree submodule — should be MIT |
+
+### Transitive dependencies (notable)
+
+| Package | License | Used via |
+|---|---|---|
+| paramiko | LGPL (unversioned) | fabric |
+| certifi | MPL-2.0 | requests |
+| pathspec | MPL-2.0 | black (dev) |
+| bcrypt | Apache-2.0 | paramiko |
+| pynacl | Apache-2.0 | paramiko |
+| pycryptodome | BSD + Public Domain | |
+| python-dateutil | BSD + Apache-2.0 (dual) | |
+
+### python_magnetgeo (`python_magnetgeo/pyproject.toml`)
+
+| Package | License | Notes |
+|---|---|---|
+| pyyaml | MIT | |
+| pandas | BSD-3-Clause | |
+| xlwt | BSD | unmaintained since 2019 |
+
+### python_magnetsetup (`python_magnetsetup/pyproject.toml`)
+
+| Package | License | Notes |
+|---|---|---|
+| python-magnetgeo | MIT | |
+| fabric | BSD-2-Clause | |
+| pint | BSD-3-Clause | |
+| python-decouple | MIT | |
+| requests | Apache-2.0 | |
+| chevron | MIT | |
+| pyyaml | MIT | |
+
+### Web frontend (`web/package.json`)
+
+| Package | License | Notes |
+|---|---|---|
+| vue / vue-router / vuex | MIT | |
+| axios | MIT | |
+| plotly.js | MIT | |
+| chart.js | MIT | |
+| mathjs | Apache-2.0 | |
+| lodash | MIT | |
+| tailwindcss | MIT | |
+| nouislider | MIT | |
+| yup | MIT | |
+| @guolao/vue-monaco-editor | MIT | |
+
+### Salome Platform and MeshGems (external tools)
+
+#### Salome Platform — LGPL-2.1
+
+All core Salome modules (KERNEL, GEOM, SMESH, SHAPER) from https://github.com/SalomePlatform are **LGPL-2.1** (not "or later").
+
+| Usage pattern | Location | Implication |
+|---|---|---|
+| External subprocess call (`salome -w1 -t ...`) | `python_magnetsetup/setup.py` | No obligation — external process is not linking |
+| Singularity container wrapping Salome | `python_magnetsetup/setup.py` | Salome remains separate inside container |
+| Direct API import (`import salome`, `from salome.geom ...`) | `python_magnetgeo/examples/salome_export.py` | Script runs *inside* Salome's own Python — Salome is the host, not a dependency |
+| XAO file format reading | `python_magnetgmsh/xao2msh.py` | File format only, no Salome library involved |
+
+No license obligation arises in any of these patterns. Salome is never linked into distributed code.
+
+**Caveat for Apache-2.0 relicensing**: Apache-2.0 and LGPL-2.1-only are technically incompatible per FSF (patent termination clause is an extra restriction under GPL-2). This only matters if MagnetDB code were ever distributed as a combined linked work with Salome — which it is not. Not a practical blocker, but worth noting if the deployment model changes.
+
+#### MeshGems (BLSurf / GHS3D / Hexotic) — Proprietary commercial
+
+MeshGems is owned by **Spatial/Dassault Systèmes** and requires a paid commercial license. The Salome FAQ explicitly states these plugins are not distributed via the internet.
+
+The project correctly treats MeshGems as a user-supplied external tool:
+- Algorithm names (`"BLSURF"`, `"GHS3D"`) appear only as config strings — not linked code
+- `mgkeydir: str = r"/opt/MeshGems"` in `python_magnetsetup/node.py` is a user-configured path
+- `mesh_gems_directory` in `python_magnetdb/models/server.py` is a configuration field only
+
+**Distribution risk**: Any Docker or Singularity image distributed publicly (Docker Hub, GHCR, etc.) that **bundles MeshGems binaries** would violate the MeshGems commercial license. Images may include Salome (LGPL), but MeshGems must be absent or injected at runtime by users who hold a valid commercial license.
+
+### python_magnetgmsh (`../python_magnetgmsh/pyproject.toml`)
+
+| Package | License | Notes |
+|---|---|---|
+| gmsh | **GPL-2+** (with API exception) | API exception permits MIT/Apache-2.0/LGPL-3.0 use — must be documented |
+| xmltodict | MIT | |
+| pyyaml | MIT | |
+| python-magnetgeo | MIT | |
+| numpy | BSD-3-Clause | |
+
+### to_duckdb (`to_duckdb/requirements.txt`)
+
+| Package | License | Notes |
+|---|---|---|
+| duckdb | MIT | |
+| pyyaml | MIT | |
+| python-magnetgeo | MIT | |
+| pytest | MIT | dev |
+
+---
+
+## Summary
+
+| Category | Verdict |
+|---|---|
+| GPL packages | `gmsh` is GPL-2+, but covered by Gmsh API exception — must be documented |
+| LGPL (psycopg, paramiko) | Compatible in practice; `psycopg[binary]` has a nuanced static-linking caveat |
+| MPL-2.0 (certifi, pathspec) | No conflict — file-level copyleft only |
+| Apache-2.0 packages | Fully compatible with MIT |
+| Internal packages | `python_magnetsetup` should declare its license |
+
+## Recommended actions
+
+1. **`python_magnetsetup/pyproject.toml`**: add `license = {text = "MIT"}` and a `LICENSE` file.
+2. **`psycopg[binary]`**: if strict LGPL-3.0 compliance is required, switch to `psycopg[c]` (dynamic linking to system libpq). Otherwise document the accepted risk.
+3. **`xlwt`** in `python_magnetgeo`: plan migration to `openpyxl` (MIT) to drop an unmaintained dependency.
+4. **`paramiko`**: confirm LGPL version (likely 2.1+) — no action needed, but worth documenting.
+5. **`gmsh` API exception**: add a note to the `python_magnetgmsh` README explicitly stating that `gmsh` is used solely through its published API under the Gmsh API exception, and that this permits the MIT (and planned Apache-2.0/LGPL-3.0) licensing of `python_magnetgmsh`.
+6. **MeshGems in containers**: ensure no publicly distributed Docker or Singularity image bundles MeshGems binaries. MeshGems must be absent or user-injected at runtime.
+7. **`python_magnetgeo/examples/salome_export.py`**: add a header comment stating it requires a separate Salome Platform installation (LGPL-2.1) and is not part of the installable package API.
diff --git a/prompts/magnet-scipy-assessment.yaml b/prompts/magnet-scipy-assessment.yaml
new file mode 100644
index 0000000..fad6269
--- /dev/null
+++ b/prompts/magnet-scipy-assessment.yaml
@@ -0,0 +1,37 @@
+package: magnet-scipy
+description: Simulates RL circuits with adaptive PID control, variable resistance R(I,T), and magnetic coupling between multiple circuits using SciPy.
+tests:
+ present: true
+ kind: pytest+coverage
+ coverage_estimate: low (<30%) # measured line-rate ≈ 21.5% in coverage.xml
+documentation:
+ readme: decent
+ api_docs: docstrings only
+ usage_examples: inline in readme # Quick Start section present but code examples are incomplete/stubbed
+ci:
+ present: false
+ runs_tests: false
+ builds_package: false
+ platform: none
+installability:
+ pip_install: works # pyproject.toml, pip install -e . documented and straightforward
+ extra_dependencies: none # pure Python; scipy/numpy/pandas/matplotlib are standard
+ packaging: pyproject.toml # not published to PyPI
+api_stability:
+ status: experimental # classifier "Development Status :: 3 - Alpha"; active refactoring visible in file names
+ breaking_changes_risk: high
+maintenance:
+ active: unknown # last commit ~7 months ago; no further activity visible
+ last_commit_approx: "7 months ago (Sept 2025)"
+ bus_factor: solo
+code_readability:
+ score: 3 # 1=unreadable, 3=acceptable, 5=exemplary
+ notes: >
+ Module names and function names are descriptive. Some docstrings present in key modules
+ (pid_controller.py, coupled_circuits.py, csv_utils.py). However, several refactor variants
+ coexist (main.py / main_refactor.py, coupled_main_refactor.py, single_circuit_adapter.py),
+ which creates confusion about the canonical entry points. Inline comments are sparse in
+ complex numerical sections (ODE integration, PID tuning logic).
+overall_readiness:
+ score: 2
+ blocker: "No CI pipeline, test coverage is only ~21%, and the README Quick Start examples are stubbed out with no actual code."
diff --git a/prompts/mysql-to-duckdb.md b/prompts/mysql-to-duckdb.md
new file mode 100644
index 0000000..e2cf9af
--- /dev/null
+++ b/prompts/mysql-to-duckdb.md
@@ -0,0 +1,130 @@
+# Task: Create a MySQL-to-DuckDB connection script
+
+## Context
+
+Working directory: `~/github/python_magnetdb/to_duckdb`
+Virtualenv to use for testing: `~/github/python_magnetdb/to_duckdb/venv-systempackages`
+
+Before writing any code, read the existing files in `to_duckdb/` to understand
+the conventions in use (schema, config, populate, crud patterns, requirements.txt).
+
+## Goal
+
+Create a new script `mysql_connect.py` in `~/github/python_magnetdb/to_duckdb/`
+that connects DuckDB to a **remote MySQL server** and supports three modes,
+selectable via a CLI flag:
+
+1. **`--mode live`** (default)
+ Use DuckDB's `mysql_scanner` extension to attach the remote MySQL database
+ directly and print the full schema (tables + columns). No local copy is made.
+ This is also the mode to use for inspecting an unknown MySQL schema before
+ deciding on export strategy or poll watermark column.
+
+2. **`--mode export`**
+ Read every table (or a user-specified subset via `--tables`) from the remote
+ MySQL server and persist them into a local file. Output format is selectable:
+ - `--format csv` (default): one `.csv` file per table in `--output-dir`
+ - `--format parquet`: one `.parquet` file per table in `--output-dir`
+ - `--format duckdb`: all tables into a single `.duckdb` file (`--output`,
+ default: `magnetdb_mysql.duckdb`, created if it does not exist)
+ Tables are always created fresh (`CREATE OR REPLACE`) — no pre-creation needed.
+
+3. **`--mode poll`** *(not yet implemented — pending MySQL schema inspection)*
+ Periodic incremental pull of new/updated rows, mimicking streaming data.
+ See "Mode 3 design decisions" section below.
+
+## MySQL connection parameters
+
+Accept all connection parameters via CLI arguments **and** via environment
+variables (env vars take precedence over defaults, CLI flags take precedence
+over env vars). The parameters are:
+
+| CLI flag | Env var | Default |
+|-----------------|------------------|--------------|
+| `--host` | `MYSQL_HOST` | `localhost` |
+| `--port` | `MYSQL_PORT` | `3306` |
+| `--user` | `MYSQL_USER` | *(required)* |
+| `--password` | `MYSQL_PASSWORD` | *(required)* |
+| `--database` | `MYSQL_DB` | *(required)* |
+
+## Detailed requirements (modes live + export)
+
+- Use `argparse` for the CLI.
+- Use the `duckdb` Python package (already installed in the venv).
+- For the `mysql_scanner` extension: load it with
+ `INSTALL mysql; LOAD mysql;` then use
+ `ATTACH 'host=... user=... password=... database=...' AS mysqldb (TYPE mysql_scanner);`
+- For `live` mode: list all tables and print column names + types for each.
+ Use `SELECT table_name FROM information_schema.tables WHERE table_catalog = 'mysqldb'`
+ and `DESCRIBE mysqldb.`.
+- For `export` mode:
+ - CSV/Parquet: `COPY (SELECT * FROM mysqldb.) TO '' (...)`
+ - DuckDB: `CREATE OR REPLACE TABLE AS SELECT * FROM mysqldb.`
+ - Log row counts per table when `--verbose`.
+- Add a `--verbose` / `-v` flag that logs each step (tables found, rows copied, etc.).
+- Handle connection errors gracefully with a clear error message (no stack trace
+ for expected errors like wrong credentials or host unreachable).
+- Follow the existing code style in `to_duckdb/` (PEP 8, NumPy-style docstrings
+ on public functions, type annotations).
+
+## Mode 3 design decisions (pending MySQL schema inspection)
+
+### Use case
+Periodic pull of new/updated rows from MySQL — a lightweight alternative to the
+full Kafka/TimescaleDB streaming architecture described in
+`to_duckdb/streaming-data-extension.md`.
+
+### Watermark strategy
+The poll loop needs a column to track "last seen value" so it only fetches new rows.
+
+| Column type | Example | Catches inserts? | Catches updates? |
+|----------------------|----------------|------------------|------------------|
+| Auto-increment int | `id` | Yes | No |
+| Insertion timestamp | `created_at` | Yes | No |
+| Update timestamp | `updated_at` | Yes | Yes |
+| None | — | No (full scan) | No |
+
+**Decision needed:** which column exists in the MySQL tables to be polled?
+Use `--mode live` to inspect the schema first, then come back here.
+
+If no suitable watermark column exists, the fallback is "re-export on a timer"
+(just run `--mode export` on a cron schedule).
+
+### Watermark persistence
+| Option | Works for duckdb format? | Works for csv/parquet? |
+|-------------------------------------|--------------------------|------------------------|
+| `_poll_state` table in output .duckdb | Yes | No |
+| Sidecar `.state.json` file | Yes | Yes |
+
+**Recommended approach:** use DuckDB table when `--format duckdb`, JSON file otherwise.
+
+### New CLI flags for poll mode
+```
+--watermark-col COLUMN column to track progress (required for poll mode)
+--interval N seconds between polls (default: 30)
+--output accumulation store (DuckDB file)
+--format {duckdb,csv,parquet}
+```
+
+### Key open questions before implementing mode 3
+1. Which tables need to be polled?
+2. Do those tables have an `updated_at`, `created_at`, or auto-increment `id` column?
+3. Should new rows be appended to the same file used by `--mode export`, or a
+ separate accumulation file?
+4. Is there a maximum look-back window (e.g. "only last 24 h") or should the
+ watermark go back to the beginning of time on first run?
+
+## Verification
+
+After writing the script:
+1. Run `venv-systempackages/bin/python mysql_connect.py --help` and confirm the
+ help text is correct.
+2. Check that `duckdb` and the `mysql_scanner` extension are available:
+ `venv-systempackages/bin/python -c "import duckdb; c=duckdb.connect(); c.execute('INSTALL mysql; LOAD mysql;'); print('ok')"`.
+3. Report which packages are missing if the extension install fails.
+
+## Implementation status
+
+- [x] `--mode live` — implemented in `to_duckdb/mysql_connect.py`
+- [x] `--mode export` — implemented in `to_duckdb/mysql_connect.py`
+- [ ] `--mode poll` — pending MySQL schema inspection (see design decisions above)
diff --git a/prompts/python-magnetrun-parquet-save-load.plan.md b/prompts/python-magnetrun-parquet-save-load.plan.md
new file mode 100644
index 0000000..b2a1336
--- /dev/null
+++ b/prompts/python-magnetrun-parquet-save-load.plan.md
@@ -0,0 +1,600 @@
+# Parquet save/load with rich metadata — design plan
+
+*Created: 2026-04-25 — captures the design discussion before implementation begins*
+
+## Context
+
+`python_magnetrun` data containers (`PandasMagnetData`, `TdmsMagnetData`, future
+`HybridData`) need a persistent format that survives the round-trip from raw
+acquisition file → ETL → S3 storage (RustFS) → downstream analysis. CSV, the
+current `saveData` target, drops type information, unit metadata, group
+structure, and timing anchors. Parquet is the right target: columnar, compressed,
+typed, and supports both file-level and per-column metadata via PyArrow.
+
+The `rustfs/magnetfs` package was a demonstrator. The intended workflow is:
+
+```
+raw file (.txt / .tdms / hybrid)
+ ↓
+load_magnetdata() / HybridRun.fromdir()
+ ↓
+ETL via prepareData(), addData(), Units(), analysis pipelines
+ ↓
+saveParquet() — bytes
+ ↓
+S3 upload (RustFS or other) — orthogonal layer
+```
+
+The goal is for the Parquet artifact to be *self-describing enough* that it can
+be loaded back into a working `MagnetDataBase` instance without the original
+raw file or defs JSON.
+
+---
+
+## Design decisions
+
+The following decisions were made during discussion. Each is paired with the
+rationale so future readers don't need to rediscover the reasoning.
+
+### D1 — `pint.Unit` is stored as a string in Parquet metadata
+
+`pint.Unit` cannot be embedded in Parquet metadata (which is `bytes`-only) and
+is not self-contained: a `Unit` references its `UnitRegistry`, and registries
+don't round-trip through serialization.
+
+**Convention:** store `str(pint_unit)` (pint's long form, e.g. `"tesla"`,
+`"meter ** 3 / second"`) as UTF-8. Empty string represents `None`. Never store
+the pretty-printed `f"{unit:~P}"` form — it's for display, not parsing.
+
+**Load:** call `_make_ureg()` fresh inside `loadParquet`, then
+`ureg.parse_expression(s)`, taking `.units` if the result is a `Quantity`.
+Calling `_make_ureg()` per-load guarantees project-specific units (`percent`,
+`ppm`, `var`) are registered regardless of what the rest of the process did.
+
+**Known limitation:** `Unit` identity is per-registry. Cross-file pint
+arithmetic between two separately-loaded Parquet files will fail unless callers
+adopt `pint.set_application_registry(ureg)`. Flag, don't fix speculatively.
+
+### D2 — Add `category` to `FieldMeta`, do **not** add `Groups` to `PandasMagnetData`
+
+The asymmetry between TDMS (`Groups[group][channel]` carrying `wf_start_time`,
+`wf_increment`) and pandas (no Groups) is deliberate — TDMS Groups carries
+*timing structure*, not just categorization. Adding a degenerate Groups dict
+to `PandasMagnetData` would unify the name without unifying the contract.
+
+The thing actually wanted for the Parquet saver is a per-channel category tag.
+That's a per-field property, not a structural one. Extend `FieldMeta`:
+
+```python
+class FieldMeta(NamedTuple):
+ symbol: str
+ unit: Any # pint.Unit | None
+ label: str
+ description: str
+ category: str = "" # NEW — TDMS group name, or pupitre bucket
+```
+
+For TDMS the category is `key.split("/")[0]`. For pupitre it comes from JSON
+defs (`"Currents"`, `"Voltages"`, `"Flows"`, `"Temperatures"`, `"Pressures"`,
+`"Field"`). For HybridData it's the prefix (`"kHz"`, `"rms"`, `"trigger"`).
+
+Round-trip on load: bucket fields by category to rebuild `Groups` for TDMS;
+ignore for pandas.
+
+**Prerequisite work:** `pupitre-defs.json`, `pigbrother-defs.json`, and
+`hybrid-defs.json` need a `"category"` field added. Default to `""` for forward
+compatibility on older Parquet files.
+
+### D3 — Drop the `timestamp` column from saved data; keep only `t`
+
+`timestamp` is fully reconstructible from `start_timestamp + t * 1s`, and for
+high-rate data (pigbrother kHz, hybrid kHz) the 8 bytes/row of `datetime64[ns]`
+is non-trivial.
+
+**Implication:** add a lazy `getTimestamp()` (or `materializeTimestamp()`)
+method that computes the column on demand from `t` plus file-level
+`start_timestamp`. `extractTimeData` and cross-source alignment call it lazily;
+everything else operates on `t`.
+
+### D4 — Sub-second precision in `start_timestamp` requires care
+
+ISO-8601 strings lose nanosecond precision unless explicitly formatted. TDMS
+`wf_start_time` is `numpy.datetime64[ns]`. For pupitre at 1 Hz this doesn't
+matter; for pigbrother and hybrid kHz streams it does.
+
+**Convention:** store two keys to be unambiguous:
+
+```
+magnetrun.start_timestamp_seconds : "1715271243" # epoch seconds
+magnetrun.start_timestamp_nanos : "123456789" # remainder
+```
+
+Same for `end_timestamp`. Document that the timestamp is naive UTC by storing:
+
+```
+magnetrun.timestamp_tz : "UTC-naive"
+```
+
+### D5 — Properties are caller-populated, not computed at save time
+
+`saveParquet` should be cheap and have no surprise side effects. Plateau
+detection needs thresholds; signature extraction needs a key and a threshold;
+energy needs an integration window. The saver doesn't know these.
+
+**API:** add `self.properties: dict` on `MagnetDataBase`. Analysis code attaches
+results via `setProperty(name, value)`. `saveParquet` serializes whatever is
+there, no computation.
+
+```python
+mdata.setProperty("plateaux", nplateaus(mdata, ...))
+mdata.setProperty("signature", asdict(Signature.from_mdata(mdata, ...)))
+mdata.saveParquet("run.parquet")
+```
+
+This matches how `field_meta` already works (populated by `Units()` / `addData`,
+consumed at use time).
+
+### D6 — TDMS / HybridRun multi-rate: save one group/stream per file initially
+
+A single Parquet file assumes one time grid. Pupitre, single TDMS group, and a
+single HybridRun stream all fit. Multi-group TDMS and full HybridRun do not.
+
+**Initial implementation:** `saveParquet(path, group=None)`. For pupitre, `group`
+must be `None`. For TDMS, `group` must be specified. For HybridRun, `group` is
+the stream identifier.
+
+**Future:** directory layout — `run.parquet/` containing one Parquet per
+group plus a top-level `_manifest.json`. Defer until the single-group case is
+proven.
+
+### D7 — S3 layer is orthogonal to `python_magnetrun`
+
+`saveParquet` accepts a path *or* a writable binary file-like. No boto3 import
+in `python_magnetrun`. The RustFS / S3 wrapper composes:
+
+```python
+buf = BytesIO()
+mdata.saveParquet(buf, group=group)
+buf.seek(0)
+s3.upload_fileobj(buf, bucket, key)
+```
+
+Keep `pyarrow.fs.S3FileSystem` off the table for now — it complicates RustFS
+endpoint/credential handling and ties pyarrow to the storage backend.
+
+### D8 — `pyarrow` for the saver, not `polars`
+
+`rustfs/magnetfs/conversion.py` uses polars, which has weaker control over
+Parquet metadata. The core saver in `python_magnetrun` uses pyarrow
+(`pa.Table.from_pandas(df, preserve_index=False)` then
+`table.replace_schema_metadata(...)`). Polars stays fine for the RustFS upload
+path if it's already there, but new code uses pyarrow.
+
+---
+
+## Metadata schema — version 1
+
+### File-level (`schema.metadata`)
+
+```
+magnetrun.schema_version : "1"
+magnetrun.source_file : "M9_2024.05.09---16_34_03.txt"
+magnetrun.source_type : "pupitre" | "pigbrother" | "ensight" | "hybrid"
+magnetrun.housing : "M9"
+magnetrun.site : "M9"
+magnetrun.group : "" # empty for pupitre, group name for TDMS
+magnetrun.start_timestamp_seconds : "1715271243"
+magnetrun.start_timestamp_nanos : "123456789"
+magnetrun.end_timestamp_seconds : "..."
+magnetrun.end_timestamp_nanos : "..."
+magnetrun.timestamp_tz : "UTC-naive"
+magnetrun.defs_file : "pupitre-defs.json" # if any, for traceability only
+magnetrun.properties : { ...JSON... } # see below
+```
+
+### Field-level (per `pa.field` in the schema)
+
+```
+magnetrun.symbol : "B"
+magnetrun.unit : "tesla" # pint-parseable; "" → None
+magnetrun.label : "B" # may be ""
+magnetrun.description : "..." # may be ""
+magnetrun.category : "Field" # TDMS group, pupitre bucket, hybrid prefix
+```
+
+### Properties blob (file-level, JSON-encoded)
+
+```json
+{
+ "B": {"min": 0.0, "max": 24.1, "unit": "tesla"},
+ "energy": {"value": 3.42e8, "unit": "joule"},
+ "plateaux": [
+ {"key": "Field", "start": 1234.5, "end": 1300.0,
+ "value": 24.0, "duration": 65.5, "unit": "tesla"}
+ ],
+ "signature": {
+ "key": "Référence_GR1",
+ "regimes": ["U", "P", "D"],
+ "times": [0.0, 12.3, 78.0, 90.5],
+ "values": [0.0, 31200.0, 31200.0, 0.0],
+ "threshold": 1e-2
+ }
+}
+```
+
+These map directly onto `nplateaus()` output and `Signature.from_mdata()` —
+serialization is `dataclasses.asdict()` / `dict(...)`.
+
+### Forward compatibility
+
+- Required keys: `schema_version`, `source_type`, `start_timestamp_*`,
+ `timestamp_tz`. Loaders raise on missing.
+- Optional keys: everything else. Loaders use `.get(..., b"")` and tolerate
+ absence.
+- Version bump: increment `schema_version` whenever a new top-level key has
+ non-default semantics. Loaders warn (not fail) on unknown versions.
+
+---
+
+## API
+
+### `MagnetDataBase` additions
+
+```python
+# magnetdata_base.py
+from typing import IO
+import os
+
+@abstractmethod
+def saveParquet(
+ self,
+ target: str | os.PathLike | IO[bytes],
+ group: str | None = None,
+) -> None:
+ """Write data + metadata to Parquet.
+
+ For TDMS data, *group* must be specified (one group per file). For
+ pandas data, *group* must be None. *target* may be a filesystem path
+ or an open binary stream.
+ """
+
+@classmethod
+@abstractmethod
+def loadParquet(
+ cls,
+ source: str | os.PathLike | IO[bytes],
+) -> "MagnetDataBase":
+ """Reconstruct a data container from a Parquet file written by saveParquet."""
+
+def setProperty(self, name: str, value: Any) -> None:
+ """Attach a JSON-serializable property for later inclusion in saveParquet."""
+ self.properties[name] = value
+
+def getProperty(self, name: str, default: Any = None) -> Any:
+ return self.properties.get(name, default)
+```
+
+`MagnetDataBase.__init__` gains `self.properties: dict = {}`.
+
+### Top-level factory
+
+```python
+# python_magnetrun/io/parquet.py (new module)
+def load_magnetrun_parquet(source) -> MagnetDataBase:
+ """Read magnetrun.source_type from metadata and dispatch to the right subclass."""
+
+# MagnetRun.py
+@classmethod
+def fromparquet(cls, source) -> "MagnetRun":
+ """Restore Housing/Site from file-level metadata, wrap MagnetDataBase."""
+```
+
+### Unit serialization helpers
+
+```python
+# python_magnetrun/io/parquet.py
+
+def _serialize_unit(unit) -> bytes:
+ return (str(unit) if unit is not None else "").encode("utf-8")
+
+def _deserialize_unit(unit_bytes: bytes, ureg) -> "pint.Unit | None":
+ s = unit_bytes.decode("utf-8")
+ if not s:
+ return None
+ parsed = ureg.parse_expression(s)
+ return parsed.units if hasattr(parsed, "units") else parsed
+
+def _serialize_field_meta(meta: FieldMeta) -> dict[bytes, bytes]:
+ return {
+ b"magnetrun.symbol": meta.symbol.encode("utf-8"),
+ b"magnetrun.unit": _serialize_unit(meta.unit),
+ b"magnetrun.label": meta.label.encode("utf-8"),
+ b"magnetrun.description": meta.description.encode("utf-8"),
+ b"magnetrun.category": meta.category.encode("utf-8"),
+ }
+
+def _deserialize_field_meta(field_metadata: dict[bytes, bytes], ureg) -> FieldMeta:
+ return FieldMeta(
+ symbol = field_metadata[b"magnetrun.symbol"].decode("utf-8"),
+ unit = _deserialize_unit(field_metadata[b"magnetrun.unit"], ureg),
+ label = field_metadata.get(b"magnetrun.label", b"").decode("utf-8"),
+ description = field_metadata.get(b"magnetrun.description", b"").decode("utf-8"),
+ category = field_metadata.get(b"magnetrun.category", b"").decode("utf-8"),
+ )
+```
+
+### Timestamp helpers
+
+```python
+def _serialize_timestamp(ts: datetime) -> tuple[bytes, bytes]:
+ """Split naive UTC datetime into (seconds, nanos) byte-strings."""
+ pts = pd.Timestamp(ts)
+ seconds = pts.value // 1_000_000_000
+ nanos = pts.value % 1_000_000_000
+ return str(seconds).encode("utf-8"), str(nanos).encode("utf-8")
+
+def _deserialize_timestamp(seconds_bytes: bytes, nanos_bytes: bytes) -> datetime:
+ seconds = int(seconds_bytes.decode("utf-8"))
+ nanos = int(nanos_bytes.decode("utf-8"))
+ return pd.Timestamp(seconds * 1_000_000_000 + nanos, unit="ns").to_pydatetime()
+```
+
+### S3 wrapper (separate package)
+
+```python
+# rustfs/magnetfs/parquet_io.py or python_magnetrun/io/s3.py
+def save_to_s3(
+ mdata: MagnetDataBase,
+ bucket: str,
+ key: str,
+ group: str | None = None,
+ s3_client = None,
+) -> None:
+ buf = BytesIO()
+ mdata.saveParquet(buf, group=group)
+ buf.seek(0)
+ s3 = s3_client or get_s3_client()
+ s3.upload_fileobj(buf, bucket, key)
+
+def load_from_s3(bucket: str, key: str, s3_client = None) -> MagnetDataBase:
+ s3 = s3_client or get_s3_client()
+ buf = BytesIO()
+ s3.download_fileobj(bucket, key, buf)
+ buf.seek(0)
+ return load_magnetrun_parquet(buf)
+```
+
+---
+
+## Implementation phases
+
+### Phase 1 — `category` on `FieldMeta` *(prerequisite)*
+
+Independently useful even if Parquet work is deferred. Status: **⏳ todo**.
+
+- Add `category: str = ""` to `FieldMeta` in `magnetdata_base.py`.
+- `load_units_from_json` reads `defn.get("category", "")` and stores it.
+- `addData` / `computeData` gain a `category=""` kwarg; default for derived
+ fields is the source field's category (or `""`).
+- TDMS-specific: `addData` derives category from `key.split("/")[0]` if not
+ explicitly given.
+- HybridData: category from prefix (`kHz`, `rms`, `trigger`).
+- `field_defs.add_field_def`/`update_field_def`/`list_field_defs` gain `category`
+ kwarg; CLI gains `--category`.
+- Editorial: add `"category"` to entries in `pupitre-defs.json`,
+ `pigbrother-defs.json`, `hybrid-defs.json`. Categories: `Currents`,
+ `Voltages`, `Flows`, `Temperatures`, `Pressures`, `Field`, `Power`, `Misc`.
+
+**Validate:**
+```bash
+pytest tests/ -k "field_meta or category"
+magnetrun-field-defs python_magnetrun/pupitre-defs.json list # shows category column
+```
+
+### Phase 2 — `properties` dict on `MagnetDataBase`
+
+Status: **⏳ todo**.
+
+- Add `self.properties: dict = {}` in `MagnetDataBase.__init__`.
+- Add `setProperty(name, value)` and `getProperty(name, default)` methods.
+- No change to existing analysis code yet — opt-in.
+
+**Validate:**
+```bash
+pytest tests/test_magnetdata_base.py -k "properties"
+```
+
+### Phase 3 — `saveParquet` / `loadParquet` for `PandasMagnetData`
+
+Status: **⏳ todo**. The simpler case; lands first.
+
+- New module `python_magnetrun/io/parquet.py` with serialization helpers.
+- `PandasMagnetData.saveParquet(target, group=None)`:
+ - If `group is not None`: raise `ValueError`.
+ - Build `pa.Table` with `preserve_index=False`.
+ - Drop `timestamp` column if present (D3); keep `t`.
+ - Replace schema metadata with file-level keys (D4 timestamps, source info,
+ properties JSON).
+ - Replace each field's metadata with `_serialize_field_meta(...)`.
+ - Write via `pq.write_table`.
+- `PandasMagnetData.loadParquet(source)`:
+ - Read with `pq.read_table`.
+ - Validate `schema_version`.
+ - Reconstruct `start_timestamp` / `end_timestamp` from split-nanos keys.
+ - Convert table to pandas DataFrame.
+ - Walk schema fields, populate `self.units` and `self.field_meta` via
+ `_deserialize_field_meta`.
+ - Restore `self.properties` from JSON blob.
+ - Do *not* materialize `timestamp` column — leave to lazy
+ `getTimestamp()`.
+
+**Validate:**
+```bash
+pytest tests/io/test_parquet_pandas.py -v
+# round-trip test: load .txt → saveParquet → loadParquet → assert field_meta,
+# units, properties, start_timestamp, t column all match
+```
+
+### Phase 4 — `getTimestamp()` lazy materializer
+
+Status: **⏳ todo**.
+
+- Concrete method on `MagnetDataBase`:
+ ```python
+ def getTimestamp(self) -> pd.Series:
+ if "timestamp" in self.Data.columns:
+ return self.Data["timestamp"]
+ return pd.Timestamp(self.start_timestamp) + pd.to_timedelta(self.Data["t"], unit="s")
+ ```
+- Audit `extractTimeData` and any cross-source alignment code to call it
+ instead of assuming the column exists.
+
+**Validate:**
+```bash
+pytest tests/ -k "extract_time or timestamp"
+```
+
+### Phase 5 — `saveParquet` / `loadParquet` for `TdmsMagnetData`
+
+Status: **⏳ todo**. Multi-group split.
+
+- `TdmsMagnetData.saveParquet(target, group=None)`:
+ - If `group is None`: raise `ValueError("TDMS requires a group")`.
+ - Extract DataFrame for that group via `getData(group)`.
+ - File-level `magnetrun.group` = group name.
+ - File-level `magnetrun.start_timestamp_*` = group's `wf_start_time`.
+ - Same field-level treatment as pandas, with category derived from key prefix.
+- `TdmsMagnetData.loadParquet`:
+ - Read `magnetrun.group` from metadata.
+ - Reconstruct `self.Groups[group][channel]` with `wf_start_time`,
+ `wf_increment` derived from `t` column spacing.
+ - Field meta same as pandas.
+
+**Note:** loaded TDMS-from-Parquet has only one group populated. That's by
+design — multi-group save is deferred to Phase 8 (manifest layout).
+
+**Validate:**
+```bash
+pytest tests/io/test_parquet_tdms.py -v
+```
+
+### Phase 6 — Top-level factory + `MagnetRun.fromparquet`
+
+Status: **⏳ todo**.
+
+- `python_magnetrun/io/parquet.py::load_magnetrun_parquet(source)` reads
+ `magnetrun.source_type` and dispatches.
+- `MagnetRun.fromparquet(source)` reads `magnetrun.housing` / `magnetrun.site`
+ and wraps the loaded `MagnetDataBase`.
+- Symmetric `MagnetRun.saveParquet(path, group=None)` delegates to the
+ contained data object.
+
+**Validate:**
+```bash
+pytest tests/test_magnetrun.py -k "parquet"
+```
+
+### Phase 7 — S3 thin wrapper
+
+Status: **⏳ todo**. Lives in `rustfs/magnetfs` *or* a new
+`python_magnetrun/io/s3.py` (decide based on whether boto3 should be a hard
+dependency of `python_magnetrun` — recommendation: keep it in `rustfs/magnetfs`
+to avoid the dependency).
+
+- `save_to_s3(mdata, bucket, key, group=None)`.
+- `load_from_s3(bucket, key) -> MagnetDataBase`.
+- `magnetfs` CLI gains `magnetrun-save` / `magnetrun-load` subcommands using
+ the new path (in addition to the existing demo-only `convert`).
+
+### Phase 8 — Multi-group manifest layout *(future, deferred)*
+
+Directory of Parquet files + top-level `_manifest.json`. Pursue when a concrete
+need surfaces (e.g. shipping a complete TDMS run as one artifact, or HybridRun's
+three streams together).
+
+---
+
+## Open questions
+
+### Q1 — S3 key convention
+
+Current demo: `M10_2020.10.23---20_10_41.parquet`. Insufficient when the same
+run has pupitre, pigbrother, and hybrid versions. Options:
+
+- `{source_type}/{housing}/{run_id}.parquet`
+- `{housing}/{run_id}/{source_type}.parquet`
+- `{housing}/{run_id}/{source_type}-{group_or_stream}.parquet` (handles
+ multi-group TDMS naturally)
+
+Whatever is chosen should be derivable from the file's metadata so the key
+itself can be opaque if needed. Decide before Phase 7.
+
+### Q2 — boto3 as a `python_magnetrun` dependency?
+
+If S3 helpers live in `python_magnetrun/io/s3.py`, boto3 becomes a runtime
+dependency. If they live in `rustfs/magnetfs`, `python_magnetrun` stays
+S3-agnostic but users need a second package for the S3 path.
+
+**Recommendation:** keep S3 in `rustfs/magnetfs` (or a new sibling `magnetfs-s3`
+package). `python_magnetrun.saveParquet` accepts `IO[bytes]`, so any storage
+backend composes externally.
+
+### Q3 — Compression
+
+Pyarrow defaults to snappy. zstd gives 2-3× better compression at modest CPU
+cost and is well-supported. For pigbrother kHz data the saving is significant.
+
+**Recommendation:** default to `compression="zstd"` with `compression_level=3`,
+expose `compression=` kwarg on `saveParquet` for callers who want to override.
+
+### Q4 — Properties shape — flat dict vs typed object?
+
+Currently `dict[str, Any]`. Could become a `RunProperties` dataclass with
+known fields (`b_min`, `b_max`, `energy`, `plateaux`, `signature`).
+
+**Recommendation:** stay with `dict` for v1. The flexibility matches the
+"caller populates whatever they computed" model. Promote to a typed object
+only if a clear consumption pattern emerges.
+
+### Q5 — HybridRun integration
+
+`HybridRun` has its own `saveData` (CSV-only, single key). The Parquet
+equivalent needs to pick: one stream per file (matches D6) or one Parquet
+per (system, signal) pair. Address in a follow-up plan once Phases 1-6 land.
+
+---
+
+## File change summary
+
+| File | Phase | Status | Change |
+|---|---|---|---|
+| `python_magnetrun/magnetdata_base.py` | 1, 2 | ⏳ todo | `category` on `FieldMeta`; `properties` dict; `setProperty`/`getProperty`; abstract `saveParquet`/`loadParquet`; concrete `getTimestamp` |
+| `python_magnetrun/magnetdata_pandas.py` | 3 | ⏳ todo | implement `saveParquet`/`loadParquet`; `addData` accepts `category=` |
+| `python_magnetrun/magnetdata_tdms.py` | 5 | ⏳ todo | implement `saveParquet`/`loadParquet` (group-required); category from prefix |
+| `python_magnetrun/hybrid/hybrid_data.py` | 1 | ⏳ todo | `category` from prefix; load_units override populates it |
+| `python_magnetrun/field_defs.py` | 1 | ⏳ todo | `add/update/list_field_def` gain `category=` kwarg; CLI `--category` |
+| `python_magnetrun/io/parquet.py` | 3 | ⏳ todo | new — serialization helpers, `load_magnetrun_parquet` factory |
+| `python_magnetrun/MagnetRun.py` | 6 | ⏳ todo | `fromparquet` classmethod; `saveParquet` delegating method |
+| `python_magnetrun/pupitre-defs.json` | 1 | ⏳ editorial | add `"category"` to all entries |
+| `python_magnetrun/pigbrother-defs.json` | 1 | ⏳ editorial | add `"category"` to all entries |
+| `python_magnetrun/hybrid-defs.json` | 1 | ⏳ editorial | add `"category"` to all entries |
+| `tests/io/test_parquet_pandas.py` | 3 | ⏳ todo | new — round-trip tests |
+| `tests/io/test_parquet_tdms.py` | 5 | ⏳ todo | new — round-trip tests, multi-group |
+| `rustfs/magnetfs/parquet_io.py` | 7 | ⏳ todo | new — `save_to_s3`/`load_from_s3` thin wrappers |
+| `rustfs/magnetfs/cli.py` | 7 | ⏳ todo | new subcommands using the magnetrun saver |
+
+---
+
+## Execution order
+
+1. **Phase 1** (`category` on `FieldMeta` + JSON-defs editorial) — independently
+ useful, unblocks 3 and 5.
+2. **Phase 2** (`properties` dict) — tiny, no risk, unblocks 3.
+3. **Phase 3** (`PandasMagnetData` Parquet) — first real Parquet code; pupitre
+ round-trip working end to end.
+4. **Phase 4** (`getTimestamp` lazy) — needed before 5 because TDMS tests will
+ exercise extractTimeData.
+5. **Phase 5** (`TdmsMagnetData` Parquet).
+6. **Phase 6** (factory + `MagnetRun.fromparquet`).
+7. **Phase 7** (S3 wrapper) — usable end-to-end pipeline.
+8. **Phase 8** (manifest layout) and HybridRun integration — defer.
diff --git a/prompts/python_magnetgeo-assessment.yaml b/prompts/python_magnetgeo-assessment.yaml
new file mode 100644
index 0000000..027e865
--- /dev/null
+++ b/prompts/python_magnetgeo-assessment.yaml
@@ -0,0 +1,55 @@
+package: python_magnetgeo
+description: Python helpers to define, load, and manipulate high-field magnet geometry
+ (helices, inserts, magnets, rings, HTS stacks) expressed as YAML data structures,
+ for use in HiFiMagnet CAD/mesh pipelines.
+tests:
+ present: true
+ kind: pytest+coverage
+ coverage_estimate: medium # 57.4% line-rate per coverage.xml
+documentation:
+ readme: comprehensive # 1566-line README.md
+ api_docs: sphinx/mkdocs # docs/ with Sphinx conf.py + RTD URL registered
+ usage_examples: dedicated docs # examples/ scripts + data/ with annotated YAML fixtures
+ci:
+ present: true
+ runs_tests: true
+ builds_package: false # no publish/build step in workflow
+ platform: GitHub Actions # .github/workflows/pytest.yml; matrix py3.11/3.12/3.13
+installability:
+ pip_install: works # pip install -e ".[dev]" used in CI
+ extra_dependencies: none # only pyyaml + pandas
+ packaging: pyproject.toml # setuptools backend; PyPI badge commented out — not published
+api_stability:
+ status: mostly stable # v1.0.1, Beta classifier, BREAKING_CHANGES.md present
+ breaking_changes_risk: medium
+maintenance:
+ active: true
+ last_commit_approx: "5 weeks ago" # as of 2026-04-27
+ bus_factor: solo # ~393 commits Christophe Trophime vs 2-63 others
+code_readability:
+ score: 3 # 1=unreadable, 3=readable with caveats, 5=exemplary
+ positives:
+ - comprehensive docstrings on all public classes and methods
+ - type hints throughout (args, return types)
+ - clean base class (YAMLObjectBase) centralising serialisation — no duplication
+ - flake8 passes cleanly at max-line-length=100
+ - dedicated modules for enums, validation, logging, and visualisation
+ concerns:
+ - inconsistent file naming: PascalCase (Helix.py) vs snake_case (coolingslit.py, tierod.py)
+ - 124 isinstance/type() guards spread across the codebase suggests structural complexity
+ - some methods are very long (Insert.py is 887 lines, base.py 783 lines)
+code_maintainability:
+ score: 3 # 1=hard to change safely, 3=manageable, 5=easy to extend
+ positives:
+ - shared base class eliminates ~95% of serialisation duplication
+ - validation.py and logging_config.py properly separated
+ - enums.py for shared constants
+ - tox matrix (py311/py312) and mypy configured
+ concerns:
+ - 10 TODO/FIXME comments in core code (Leads, Screens, Mandrin, Chamfer validation)
+ - Shape.py.new present in repo (work-in-progress artefact)
+ - solo bus factor makes long-term maintenance fragile
+overall_readiness:
+ score: 3
+ blocker: "Not published to PyPI (git-install only) and test coverage at ~57% leaves
+ several core geometry classes under-tested."
diff --git a/prompts/python_magnetgmsh-assessment.yaml b/prompts/python_magnetgmsh-assessment.yaml
new file mode 100644
index 0000000..33ad344
--- /dev/null
+++ b/prompts/python_magnetgmsh-assessment.yaml
@@ -0,0 +1,78 @@
+package: python_magnetgmsh
+description: Python helpers to create CAD and mesh files using Gmsh for high-field magnet geometries defined by python_magnetgeo YAML configurations.
+
+tests:
+ present: true
+ kind: manual scripts
+ coverage_estimate: none
+ notes: >
+ tests/ directory exists but is empty; pytest is fully configured in pyproject.toml
+ but no test_*.py files have been written. Actual validation relies on shell scripts
+ (testsuite.sh, testsuite-xao.sh, testsuite2D.sh) that invoke the CLI against
+ geometry data at /data/geometries — not reproducible without that external dataset.
+
+documentation:
+ readme: comprehensive
+ api_docs: docstrings only
+ usage_examples: inline in readme
+ notes: >
+ README covers installation, CLI usage, four worked examples, a migration guide for
+ breaking changes, and a TODO list. Docstrings found in 32/34 source files (274
+ occurrences). readthedocs URL is declared in pyproject.toml but may not be live.
+
+ci:
+ present: false
+ runs_tests: false
+ builds_package: false
+ platform: none
+ notes: No .github/workflows or .gitlab-ci.yml found.
+
+installability:
+ pip_install: requires manual steps
+ extra_dependencies: system packages
+ packaging: pyproject.toml
+ notes: >
+ python-magnetgeo is sourced from git (not PyPI), so a plain `pip install .`
+ requires the [tool.uv.sources] redirect or a manual pre-install step.
+ Gmsh >= 4.13.1 may need the dev channel (gmsh.info/python-packages-dev).
+ Package is not published to PyPI (badges are commented out in README).
+
+readability:
+ score: 3 # 1=unreadable, 3=adequate conventions present, 5=exemplary
+ tools_configured: [black, flake8, mypy]
+ docstring_coverage: high # 32/34 source files contain docstrings
+ type_annotations: partial # encouraged in README/contrib guide, not universally applied
+ ci_enforced: false
+ notes: >
+ Tooling (Black line-length 100, flake8, mypy) is declared in pyproject.toml but
+ not enforced by CI. Docstring density is good; type-hint coverage is partial —
+ mypy is set to disallow_untyped_defs=false. Shell scripts (testsuite*.sh) are
+ lightly commented and lack set -euo pipefail enforcement.
+
+api_stability:
+ status: experimental
+ breaking_changes_risk: high
+ notes: >
+ PyPI classifier is "3 - Alpha". README documents multiple breaking changes in
+ v0.1.0: return types changed to GeometryLoadResult objects, new ValidationError
+ contract, strict dependency pin on python_magnetgeo >=1.0.0,<2.0.0, minimum
+ Python bumped to 3.9.
+
+maintenance:
+ active: true
+ last_commit_approx: "3 months ago"
+ bus_factor: small team
+ score: 2 # 1=abandoned, 3=steady small team+CI, 5=well-staffed+automated
+ contributors: 3 # Christophe Trophime (~180/218 commits), jermuzet, Romain Vallet
+ notes: >
+ Development is ongoing but heavily concentrated on a single author (~82% of commits).
+ No CI means regressions are caught manually. No release cadence or changelog beyond
+ the README migration section. Score penalised for missing automation and high
+ bus-factor risk.
+
+overall_readiness:
+ score: 2 # 1=prototype, 3=usable with caveats, 5=production-ready
+ blocker: >
+ No CI pipeline and no pytest test suite — the only tests are shell scripts that
+ require external geometry data at /data/geometries, making automated verification
+ impossible for new contributors.
diff --git a/prompts/python_magnetrun-assessment.yaml b/prompts/python_magnetrun-assessment.yaml
new file mode 100644
index 0000000..80cc198
--- /dev/null
+++ b/prompts/python_magnetrun-assessment.yaml
@@ -0,0 +1,63 @@
+package: python_magnetrun
+description: >
+ Utilities to view and analyse magnet runs from LNCMI control/monitoring
+ systems (Pupitre, PigBrother, and hybrid FEPC acquisition systems).
+
+tests:
+ present: true
+ kind: pytest+coverage
+ coverage_estimate: medium # line-rate=0.30 from coverage.xml (just above 30%)
+
+documentation:
+ readme: comprehensive # 1207-line README with ToC, install, usage, analysis, ETL sections
+ api_docs: sphinx/mkdocs # Sphinx source in docs/source, deployed to GitHub Pages
+ usage_examples: notebooks # notebooks/01_getting_started.ipynb + inline README examples
+
+ci:
+ present: true
+ runs_tests: true # test.yml: pytest on Python 3.11–3.14, Ubuntu & Debian Trixie, Codecov upload
+ builds_package: false # docs.yml builds Sphinx docs; no wheel/sdist build step
+ platform: GitHub Actions
+
+installability:
+ pip_install: requires manual steps # python_magnetcooling must be pip-installed from the local subdir first
+ extra_dependencies: system packages # nlopt C library; optional extras pull in clawpack, scikit-learn, etc.
+ packaging: pyproject.toml # not published to PyPI
+
+api_stability:
+ status: unstable # Pre-Alpha classifier; active rework_analysis branch; BREAKING_CHANGES.md present
+ breaking_changes_risk: high
+
+maintenance:
+ active: true
+ last_commit_approx: "3 days ago"
+ bus_factor: solo
+
+readability:
+ score: 3 # decent overall, uneven across modules
+ linting: near-clean # ruff configured with E/F/W/I/UP/B/SIM/BLE; only 1 fixable import-sort violation
+ type_annotations: partial # ~60% of methods annotated in newer modules (magnetdata_pandas, MagnetRun,
+ # waterflow_pipeline); older modules (BandH.py) have none
+ docstrings: inconsistent # newer modules have module + method docstrings with param/return docs;
+ # several older files have no docstrings at all
+ module_structure: good # 14 subpackages with clear responsibility boundaries; logging via getLogger throughout
+ todo_debt: low # 14 TODO/FIXME markers across the whole codebase
+ notes: >
+ Clear quality gap between recently written modules and older ones. The active refactor
+ is gradually lifting the floor, but callers of lower-level modules still encounter
+ inconsistent naming conventions and missing type hints.
+
+maintenance_practice:
+ score: 3 # good habits, one-person risk
+ changelog: good # CHANGELOG.md documents breaking changes per version with before/after tables
+ breaking_changes_doc: good # dedicated BREAKING_CHANGES.md (superseded by CHANGELOG from v0.3.0 onward)
+ contributing_guide: present # CONTRIBUTING.rst (128 lines), but still references old GitHub URL (Trophime/ not MagnetDB/)
+ dependency_pinning: good # ranges specified in pyproject.toml; local dep (python_magnetcooling) unversioned
+ tooling: good # ruff + mypy + pre-commit configured; tox.ini present; Codecov integrated
+ bus_factor_risk: high # single maintainer; no evidence of a second reviewer on any PR
+
+overall_readiness:
+ score: 3 # installable, functional, CI green, decent docs — manual install step, ~30% coverage, API in active rework
+ blocker: >
+ python_magnetcooling is a local (non-PyPI) dependency that must be manually
+ installed before the main package, blocking a one-step pip install.
diff --git a/prompts/python_magnetsetup-assessment.yaml b/prompts/python_magnetsetup-assessment.yaml
new file mode 100644
index 0000000..1111b3a
--- /dev/null
+++ b/prompts/python_magnetsetup-assessment.yaml
@@ -0,0 +1,32 @@
+package: python_magnetsetup
+description: Generates configuration and input files required to set up and run HiFiMagnet magnet simulations, callable from the magnetdb web interface or the python_magnetapi CLI.
+tests:
+ present: true
+ kind: pytest
+ coverage_estimate: low (<30%)
+documentation:
+ readme: decent
+ api_docs: sphinx/mkdocs
+ usage_examples: inline in readme
+ci:
+ present: false
+ runs_tests: false
+ builds_package: false
+ platform: none
+installability:
+ pip_install: works
+ extra_dependencies: system packages
+ packaging: pyproject.toml
+api_stability:
+ status: unstable
+ breaking_changes_risk: medium
+maintenance:
+ active: true
+ last_commit_approx: "6 weeks ago"
+ bus_factor: small team
+code_readability:
+ score: 3 # out of 5
+ notes: "Type annotations and docstrings present; ruff configured. Pulled down by oversized modules (jsonmodel.py 1294 lines, setup.py 1048 lines), heavy commented-out code, and mixed print()/logger usage (including a broken f-string in jsonmodel.py)."
+overall_readiness:
+ score: 2
+ blocker: "No CI pipeline — tests (covering only the logging module) are never run automatically, leaving the core simulation-setup logic untested."
diff --git a/prompts/python_magnetworkflows-assessment.yaml b/prompts/python_magnetworkflows-assessment.yaml
new file mode 100644
index 0000000..bf5b09a
--- /dev/null
+++ b/prompts/python_magnetworkflows-assessment.yaml
@@ -0,0 +1,56 @@
+package: python_magnetworkflows
+description: >
+ Orchestrates coupled electromagnetic-thermal-hydraulic simulation workflows
+ for high-field magnets using the Feel++ finite-element library.
+
+tests:
+ present: true
+ kind: pytest
+ coverage_estimate: unknown # pytest configured but no coverage plugin or report present
+
+documentation:
+ readme: decent
+ api_docs: docstrings only
+ usage_examples: inline in readme
+
+ci:
+ present: true
+ runs_tests: true
+ builds_package: false
+ platform: GitHub Actions
+ # Note: push/PR triggers are commented out in ci.yml — CI only runs on workflow_dispatch
+
+installability:
+ pip_install: requires manual steps
+ extra_dependencies: system packages # Feel++ must be installed as Debian system packages; venv requires --system-site-packages
+ packaging: pyproject.toml
+
+api_stability:
+ status: unstable
+ breaking_changes_risk: medium
+
+readability:
+ score: 3 # 1=unreadable, 3=readable with caveats, 5=exemplary
+ notes: >
+ Code is split into focused modules (cli, solver, oneconfig, commissioning, run, params, error)
+ and ruff is configured for linting/formatting. However, several large modules (measures.py=552 lines,
+ error.py=491 lines, solver.py=463 lines) have sparse docstrings (10 docstring markers across 5 functions
+ in solver.py), 8 TODO/FIXME markers remain in the source, and leftover artefacts (.bak, .old, ~files)
+ are committed inside the package directory.
+
+maintenance:
+ active: true
+ last_commit_approx: "9 weeks ago"
+ bus_factor: small team # Christophe Trophime + jermuzet (+ AI-assisted commits)
+ score: 3 # 1=abandoned, 3=active but fragile, 5=well-governed
+ notes: >
+ Actively developed with modern tooling (pyproject.toml, ruff, mypy, pre-commit, Sphinx docs).
+ However, automatic CI triggers are disabled (push/PR hooks commented out in ci.yml), the project
+ classifier is still "2 - Pre-Alpha" at version 0.1.0, and the bus factor is effectively 2 humans.
+
+overall_readiness:
+ score: 3
+ blocker: >
+ Core dependency (Feel++) cannot be installed via pip and requires system-level Debian packages;
+ combined with no coverage measurement and automatic CI triggers disabled, the package is usable
+ but not reliably reproducible outside the authors' environment.
diff --git a/prompts/rename-site-to-assembly.md b/prompts/rename-site-to-assembly.md
new file mode 100644
index 0000000..e4c9735
--- /dev/null
+++ b/prompts/rename-site-to-assembly.md
@@ -0,0 +1,172 @@
+# Migration Plan: Rename `site` → `assembly`
+
+## Motivation
+
+The name "site" is ambiguous — it conflates a physical installation location with a logical grouping of magnets. "Assembly" more accurately describes the concept: a named configuration of one or more magnets that can be put in operation, shut down, and simulated as a unit.
+
+---
+
+## Scope
+
+This rename touches: Python model layer, database schema, API routes, frontend, CLI, actions, seeds, and tests. It should be done in a single branch to avoid drift.
+
+---
+
+## Phase 1 — Python Model Layer
+
+**Files to rename:**
+
+| Old | New |
+|-----|-----|
+| `python_magnetdb/models/site.py` | `assembly.py` |
+| `python_magnetdb/models/site_magnet.py` | `assembly_magnet.py` |
+
+**Changes inside those files:**
+- `class Site` → `class Assembly`, `db_table = "assemblies"`
+- `class SiteMagnet` → `class AssemblyMagnet`, `db_table = "assembly_magnets"`
+- FK field name on `AssemblyMagnet`: `site` → `assembly`
+
+**`python_magnetdb/models/__init__.py`:**
+- Import `Assembly` from `assembly`, `AssemblyMagnet` from `assembly_magnet`; remove old imports.
+
+**Models with foreign keys to Site** — update field name `site` → `assembly` and string ref `'Site'` → `'Assembly'` in:
+- `python_magnetdb/models/record.py`
+- `python_magnetdb/models/simulation.py`
+- `python_magnetdb/models/cad_attachment.py`
+- `python_magnetdb/models/mesh_attachment.py`
+
+---
+
+## Phase 2 — Database Migration
+
+Create a new migration file (e.g. `0010_rename_site_to_assembly.py`) that:
+1. Renames table `sites` → `assemblies`
+2. Renames table `site_magnets` → `assembly_magnets`
+3. Renames FK columns `site_id` → `assembly_id` on Record, Simulation, CadAttachment, MeshAttachment
+
+Do **not** modify existing migrations — only add a new one.
+
+---
+
+## Phase 3 — API Routes
+
+**Files to rename:**
+
+| Old | New |
+|-----|-----|
+| `python_magnetdb/routes/api/sites.py` | `assemblies.py` |
+| `python_magnetdb/routes/api/site_magnets.py` | `assembly_magnets.py` |
+
+**URL paths:** `/api/sites` → `/api/assemblies`, `/api/site_magnets` → `/api/assembly_magnets`
+
+**`python_magnetdb/routes/api/serializers.py`:**
+- `_site_post_processor` → `_assembly_post_processor`
+- `sitemagnet_set` → `assemblymagnet_set`
+- Update the post-processor mapping key.
+
+**`python_magnetdb/routes/api/home.py`:**
+- Update `Site` import and any `"site"` resource-type string.
+
+**`python_magnetdb/routes/api/visualisations.py`:**
+- `resource_type == "site"` → `resource_type == "assembly"` (3 occurrences).
+
+Register the new route files in the app router; remove old registrations.
+
+---
+
+## Phase 4 — Actions & Business Logic
+
+**Files to rename:**
+
+| Old | New |
+|-----|-----|
+| `python_magnetdb/actions/generate_site_directory.py` | `generate_assembly_directory.py` |
+
+**Function renames:**
+- `generate_site_directory` → `generate_assembly_directory`
+- `generate_site_config` → `generate_assembly_config`
+- `get_site_data` → `get_assembly_data`
+- All `site_id` parameter names → `assembly_id`
+
+**Update call sites in:**
+- `python_magnetdb/actions/generate_simulation_config.py`
+- `python_magnetdb/actions/object_geometries.py`
+- `python_magnetdb/actions/run_simulation_setup.py`
+
+---
+
+## Phase 5 — Seeds & CRUD
+
+**`python_magnetdb/seeds/crud.py`:**
+- `create_site` → `create_assembly`, `query_site` → `query_assembly`
+- Update `Site` import.
+
+**All seed files** (`seed-Hybrid.py`, `seed-M*.py`, `seeds.py`):
+- Update import of `create_site` → `create_assembly`
+- Rename all call sites.
+
+---
+
+## Phase 6 — Frontend
+
+**Files/directories to rename:**
+
+| Old | New |
+|-----|-----|
+| `web/src/services/siteService.js` | `assemblyService.js` |
+| `web/src/views/sites/` | `assemblies/` |
+| `AttachMagnetToSiteModal.vue` | `AttachMagnetToAssemblyModal.vue` |
+
+**`web/src/router.js`:**
+- Route names: `'sites'` → `'assemblies'`, `'new_site'` → `'new_assembly'`, `'site'` → `'assembly'`
+- Route paths: `/sites` → `/assemblies`
+
+**`web/src/App.vue`:**
+- Update nav link text and route name.
+
+**Inside all Vue components:**
+- Update all references to `siteService` → `assemblyService`, API URLs, route names.
+
+---
+
+## Phase 7 — CLI (`python_magnetapi`)
+
+**`python_magnetapi/python_magnetapi/site.py`** → rename to `assembly.py`:
+- Update internal API URL strings (`/api/sites` → `/api/assemblies`)
+- `site_create` → `assembly_create`
+
+**`python_magnetapi/python_magnetapi/cli.py`:**
+- Import `assembly_create` instead of `site_create`
+- Update `--site` CLI arguments and help strings.
+
+**`python_magnetapi/python_magnetapi/utils.py`:**
+- Update `"site"` resource type strings → `"assembly"`.
+
+---
+
+## Phase 8 — Tests
+
+| Old | New |
+|-----|-----|
+| `tests/test_site_geometry_config.py` | `test_assembly_geometry_config.py` |
+
+- Update all imports (`Site` → `Assembly`) and variable names.
+- Update `python_magnetapi/tests/test_list.py` for new CLI command names.
+
+---
+
+## Phase 9 — Verification
+
+1. Run `python manage.py migrate` — confirm migration applies cleanly.
+2. Run the full test suite.
+3. Start the dev server and manually verify: list assemblies, create, attach magnet, run simulation.
+4. Check the CLI: `magnetapi assembly create ...`
+
+---
+
+## Key Risks
+
+- **String literals for `resource_type`** — `"site"` appears as a runtime string in visualisations and migrations; missing even one will silently break queries.
+- **Existing data** — if the DB has live data, the rename migration must be tested on a snapshot first.
+- **Frontend route-name references** — any `router.push({ name: 'site' })` call not caught by search will 404 silently.
+- **`python_magnetapi` submodule** — it is a separate package (possibly a git submodule); changes there need their own commit.
diff --git a/prompts/roadmap-operational-stats.md b/prompts/roadmap-operational-stats.md
index 15932a3..b24f4c9 100644
--- a/prompts/roadmap-operational-stats.md
+++ b/prompts/roadmap-operational-stats.md
@@ -3,11 +3,82 @@
## Context & Constraints
- **Team**: Christophe (lead) + Rémi, effectively 1.5 FTE on MagnetDB
-- **Parallel work**: React migration (5 phases) is already planned
+- **Parallel work**: Frontend migration (5 phases) is planned — **Vue 3 or React, decision pending** (see comparison below)
- **Production stability**: LNCMI research operations depend on the platform
- **Principle**: Incremental delivery — each phase delivers standalone value
-This roadmap covers the backend evolution for operational data statistics, pre-processed time series, ingestion automation, streaming readiness, and user role/access refinements. It is designed to interleave with the React migration without blocking it.
+### Frontend prerequisite status (as of 2026-05-06) ✅
+
+The following build tooling work is complete on the `eslint` branch. It is a prerequisite for both migration paths:
+
+| Task | Status | Relevance |
+|------|--------|-----------|
+| Vue CLI 4 → 5 (Webpack 4 → 5) | ✅ Done | Vue 3: unblocks compat build; React: useful if keeping Webpack, but Vite is preferred |
+| Node 18 → 22 (`node:22-trixie`) | ✅ Done | Both paths |
+| ESLint 6 → 9 with flat config | ✅ Done | Both paths |
+| `Vue.filter` → `Vue.prototype.$filters` | ✅ Done | Vue 3: required (Vue.filter removed); React: irrelevant |
+
+---
+
+## Frontend Migration Decision: Vue 3 vs React
+
+The current frontend is **Vue 2** (Options API SFCs, Vuex 3, Vue Router 3, TailwindCSS, chart.js, plotly.js, Monaco editor). Vue 2 reached end-of-life on **2023-12-31**.
+
+### Vue 3 migration
+
+**Approach**: Incremental upgrade using the [Vue 2 migration build](https://v3-migration.vuejs.org/migration-build.html) (`@vue/compat`), then progressively opt components into Vue 3 mode. Vuex → Pinia, Vue Router 3 → 4.
+
+| Pros | Cons |
+|------|------|
+| Most existing Options API SFCs are Vue 3-compatible with minimal changes | Vue ecosystem is smaller than React — fewer community packages, fewer developers available |
+| Incremental migration: one component at a time, no big-bang rewrite | Vue 2 → 3 still has breaking changes: `v-model`, slots, `$attrs/$listeners`, global API (`Vue.use`, `Vue.set`) all changed |
+| Vuex → Pinia is a simple, mechanical migration | Vetur IDE plugin must be replaced by Volar |
+| Vue Router 3 → 4 requires minimal changes | Vue CLI 5 should be replaced by Vite for the full benefit of Vue 3 (separate effort) |
+| TailwindCSS, chart.js, plotly.js, axios, Monaco editor: all unchanged | Long-term: smaller hiring pool |
+| No paradigm shift — team already knows Vue | |
+| `Vue.filter` already removed (one blocker already cleared) | |
+| **Estimated effort**: 6–10 weeks (Christophe + Rémi part-time) | |
+
+**Recommended if**: production stability and migration speed are the top priorities, and the team plans to stay primarily Vue-oriented.
+
+---
+
+### React migration
+
+**Approach**: Full rewrite. All Vue SFCs become React components (JSX/TSX). Vuex → Zustand or TanStack Query. Vue Router → React Router v6. Build tool: Vite + React.
+
+| Pros | Cons |
+|------|------|
+| Largest frontend ecosystem — most packages have React-first support | **Complete rewrite** — every `.vue` file must be reimplemented |
+| Largest hiring pool — easier to onboard new developers | No incremental path: requires a parallel app or a big-bang cutover |
+| React 18+ concurrent features (Suspense, transitions) | Team must learn React (JSX, hooks, different component model) — steep ramp for 1.5 FTE |
+| First-class TypeScript support across the ecosystem | Much higher risk to production stability during migration |
+| TanStack Query / React Query is excellent for the API-heavy data patterns in MagnetDB | chart.js, plotly.js, Monaco editor need React wrapper components (exist, but add indirection) |
+| Vite + React is a very modern, fast build stack | Vuex mental model does not map directly to React — Redux/Zustand/Jotai are different paradigms |
+| Better long-term community momentum | **Estimated effort**: 4–6 months (Christophe + Rémi part-time) |
+
+**Recommended if**: long-term maintainability, team growth, and ecosystem breadth outweigh migration cost.
+
+---
+
+### Decision matrix
+
+| Factor | Vue 3 | React |
+|--------|-------|-------|
+| Migration effort | Low–Medium (incremental) | High (full rewrite) |
+| Risk to production | Low | Medium–High |
+| Team ramp-up | None | Medium (JSX, hooks) |
+| Ecosystem breadth | Medium | Large |
+| Hiring pool | Medium | Large |
+| Existing code reuse | High (~80% of template logic reusable) | Low (~20% logic reusable) |
+| Time to first deployable result | 2–3 weeks | 6–8 weeks |
+| Long-term community momentum | Good (Vue 3 is actively developed) | Excellent |
+
+**Recommended path for this team and codebase**: **Vue 3**, unless there is a specific long-term plan to grow the team beyond 3–4 people or to consolidate with other React-based internal tools. The incremental migration approach and the work already done (Vue.filter removal, Vue CLI 5) give a meaningful head start that would be discarded in a React rewrite.
+
+`Vue.filter` is removed from `src/main.js` and all 12 template files updated. The codebase now has no Vue 3 blockers in the build or filter layer.
+
+This roadmap covers the backend evolution for operational data statistics, pre-processed time series, ingestion automation, streaming readiness, and user role/access refinements. It is designed to interleave with the Vue 3 migration without blocking it.
---
@@ -24,7 +95,7 @@ This roadmap covers the backend evolution for operational data statistics, pre-p
**Total estimated effort**: 24–31 working weeks (~6–8 months of calendar time, accounting for parallel React migration work and operational duties).
-**Recommended cadence**: Alternate between backend phases (this roadmap) and React migration phases. For example: React Phase 1 → Stats Phase 0 → React Phase 2 → Stats Phase 1 → etc.
+**Recommended cadence**: Alternate between backend phases (this roadmap) and Vue 3 migration phases. For example: Vue 3 Phase 1 → Stats Phase 0 → Vue 3 Phase 2 → Stats Phase 1 → etc.
---
@@ -34,13 +105,17 @@ This roadmap covers the backend evolution for operational data statistics, pre-p
**Why first**: Every subsequent phase depends on these model changes. They are low-risk (additive fields, backward-compatible) and can be deployed immediately.
-### 0.1 Record model extension (Week 1)
+> **Terminology note.** The MagnetDB entity called `Record` represents an **operational run** — the set of control-system recordings produced during a magnet operation period (Pupitre, PigBrother, or Hybrid). This is *not* what the EMFL/ISABEL DMP calls an "experiment" (which is the scientist's user campaign and is governed by a separate DMP). The two share a time window and possibly a proposal reference, but contain different data under different policies. The `Record` name is kept throughout this roadmap; the word "experiment" is reserved for the EMFL context.
+
+### 0.1 Record model redesign (Week 1)
-Add fields to the existing Record model:
+Add fields to the existing Record model and introduce the D1/D2 data layer split:
- `record_type` (CharField with choices: monitoring, transient, calibration, maintenance) — default "monitoring" for all existing records
- `source` (CharField: offline, stream, database) — default "offline"
-- `experimenter` (CharField, nullable, indexed) — the external user ID from the operational system
+- `sources` (JSONField) — list of raw MCS filenames / NAS paths (D1 references, immutable after acquisition)
+- `curated` (M2M to StorageAttachment) — curated full-resolution Parquet files in RustFS S3 (D2 layer); one per `(source_type, group)` pair
+- `experimenter` (CharField, nullable, indexed) — the operator identity from the control system (not the scientist — see terminology note above)
- `experimenter_user` (FK to User, nullable) — resolved MagnetDB user link
- `started_at`, `ended_at` (DateTimeField, nullable) — time bounds
- `duration_seconds` (FloatField, nullable)
@@ -431,37 +506,37 @@ Add Celery Beat schedule entry for each active stream (configurable window durat
---
-## Interleaving with the React Migration
+## Interleaving with the Frontend Migration
-The React migration and this backend roadmap are largely independent, but some frontend work is needed to expose new features. Suggested interleaving:
+The frontend migration (Vue 3 or React) and this backend roadmap are largely independent. The suggested interleaving below is the same regardless of which path is chosen — only the effort column differs.
```
-Month 1–2: React Phase 1 (preparation/audit)
- Stats Phase 0 (model foundations) ← backend, no UI needed
+Month 1–2: Frontend Phase 1 (preparation/audit) ← build tooling prereqs already done
+ Stats Phase 0 (model foundations) ← backend, no UI needed
-Month 3–4: React Phase 2 (core infrastructure)
- Stats Phase 1 (RecordStats) ← API-only, test via Swagger/curl
+Month 3–4: Frontend Phase 2 (core infrastructure)
+ Stats Phase 1 (RecordStats) ← API-only, test via Swagger/curl
-Month 4–5: Stats Phase 2 (ETL/time series) ← replaces existing /visualize
+Month 4–5: Stats Phase 2 (ETL/time series) ← replaces existing /visualize
-Month 5–7: React Phase 3 (component migration)
+Month 5–7: Frontend Phase 3 (component migration)
Stats Phase 3 (cumulative stats)
- → React components can consume new stats/timeseries endpoints
+ → New frontend components can consume new stats/timeseries endpoints
-Month 7–8: Stats Phase 4 (automated ingestion) ← pure backend
+Month 7–8: Stats Phase 4 (automated ingestion) ← pure backend
-Month 8–10: React Phase 4–5 (polish, cleanup)
+Month 8–10: Frontend Phase 4–5 (polish, cleanup)
→ Build stats dashboard, trend charts, experimenter views
→ Admin UI for user roles, data scoping, external identities
-Month 10–12: Stats Phase 5 (streaming) ← when NI/DB integration is ready
+Month 10–12: Stats Phase 5 (streaming) ← when NI/DB integration is ready
→ Real-time dashboard components (if WebSocket path chosen)
```
This interleaving ensures:
-- Backend APIs are stable before React components consume them
-- The `/visualize` replacement (Phase 2) is ready before the React VisualisationCard is migrated
+- Backend APIs are stable before new frontend components consume them
+- The `/visualize` replacement (Phase 2) is ready before the VisualisationCard is migrated
- The user role/scoping system (Phase 0) is in place before external access is enabled
- Streaming (Phase 5) is deferred until actually needed
diff --git a/prompts/rustfs-parquet-frontend-display.md b/prompts/rustfs-parquet-frontend-display.md
new file mode 100644
index 0000000..725c74c
--- /dev/null
+++ b/prompts/rustfs-parquet-frontend-display.md
@@ -0,0 +1,255 @@
+# RustFS Migration, Parquet Storage & Frontend Display
+
+*Created: 2026-05-06 — architectural decisions made during Track D / DMP review*
+
+---
+
+## 1. MinIO → RustFS migration
+
+### Why
+
+RustFS is the planned replacement for MinIO as the S3 object store backing MagnetDB (curated
+data D2, derived statistics D3, simulation outputs D5, mesh attachments). The switch is
+motivated by operational and licensing considerations; it is transparent to all application code.
+
+### What does not change
+
+RustFS exposes the **same S3-compatible API** as MinIO. Consequently:
+
+| Component | Status |
+|-----------|--------|
+| `boto3` / `botocore` client code | Unchanged |
+| `django-storages` S3 backend | Unchanged — only `AWS_S3_ENDPOINT_URL` env var updated |
+| Pre-signed URL generation | Unchanged |
+| `StorageAttachment` model | Unchanged |
+| `python_magnetrun` S3 helpers (`save_to_s3` / `load_from_s3`) | Unchanged |
+| CI/CD workflows that push artifacts to S3 | Unchanged — only endpoint/credentials rotated |
+
+### What changes
+
+| Item | Change |
+|------|--------|
+| `MINIO_ENDPOINT` env var | Renamed / replaced by `S3_ENDPOINT_URL` pointing to RustFS |
+| `MINIO_ACCESS_KEY` / `MINIO_SECRET_KEY` | Replaced by RustFS service-account credentials |
+| CORS configuration | Reconfigured in RustFS admin UI (same rules as MinIO) |
+| Bucket creation / lifecycle policies | Recreated in RustFS |
+| `docker-compose*.yml` | Replace `minio:` service block with `rustfs:` (or `ghcr.io/rustfs/rustfs:latest`) |
+| `pypiserver` backend (Track A, A2) | Update to use RustFS endpoint instead of MinIO |
+
+### Migration procedure (one-time)
+
+1. Stand up the RustFS container alongside the existing MinIO instance.
+2. Create the same bucket structure in RustFS (`magnetdb-attachments`, `magnetdb-parquet`, etc.).
+3. Use `mc mirror` (MinIO client, compatible with any S3 endpoint) to copy all objects:
+ ```bash
+ mc alias set src http://minio:9000 MINIO_ACCESS_KEY MINIO_SECRET_KEY
+ mc alias set dst http://rustfs:9000 RUSTFS_ACCESS_KEY RUSTFS_SECRET_KEY
+ mc mirror src/magnetdb-attachments dst/magnetdb-attachments
+ mc mirror src/magnetdb-parquet dst/magnetdb-parquet
+ ```
+4. Flip the environment variables in `.envrc` / Docker secrets.
+5. Restart the API and worker containers; run the smoke-test suite.
+6. Decommission the MinIO container once all services are verified.
+
+### CORS configuration in RustFS
+
+The curated data bucket must allow cross-origin `GET` requests so that the frontend can fetch
+Parquet files via pre-signed URLs. Set the following CORS rule on the bucket (equivalent to the
+current MinIO policy):
+
+```json
+{
+ "CORSRules": [{
+ "AllowedOrigins": ["https://magnetdb.lncmi.cnrs.fr", "https://magnetdb-dev.local"],
+ "AllowedMethods": ["GET"],
+ "AllowedHeaders": ["*"],
+ "ExposeHeaders": ["Content-Length", "Content-Range"],
+ "MaxAgeSeconds": 3600
+ }]
+}
+```
+
+`Content-Range` must be exposed because HTTP range requests are used by client-side Parquet
+readers for columnar projection (reading only the columns the user selected without downloading
+the full file).
+
+---
+
+## 2. Parquet in the data architecture
+
+### Layer mapping
+
+| DMP label | Format | Location | Description |
+|-----------|--------|----------|-------------|
+| D1 | Native MCS binary / text | NAS (sshfs, LNCMI-internal only) | Raw acquisition files — immutable after capture |
+| D2 | **Apache Parquet** | **RustFS S3** | Curated, full-resolution — the canonical processed layer |
+| D3 | PostgreSQL JSONB + tiny Parquet | RustFS S3 + PostgreSQL | Derived statistics; stitched trend series (one point per record) |
+
+### Record model redesign
+
+The `Record` model (or its successor `Experiment`) carries:
+
+```
+sources : list of raw filenames / NAS paths → D1 references
+curated : list of StorageAttachment FKs → D2 Parquet files in RustFS
+```
+
+One curated Parquet per `(source_type, group)` pair:
+- Pupitre → one file (single group)
+- PigBrother (TDMS) → one file per TDMS group
+- Hybrid → one file per stream identifier
+
+The S3 key convention for curated files:
+
+```
+curated/{housing}/{record_id}/{source_type}-{group_or_stream}.parquet
+```
+
+This key is derivable from the Parquet file-level metadata (`magnetrun.housing`,
+`magnetrun.source_type`, `magnetrun.group`) enabling orphan recovery without a DB query.
+
+### Derived columns (hoop stress, etc.)
+
+Physics-computed columns (hoop stress per part per timestep via MagnetTools) do not exist in the
+raw data and are expensive to recompute. They are stored as a separate derived Parquet, also in
+RustFS, referenced from the redesigned Record / a `DerivedTimeSeries` attachment:
+
+```
+derived/{housing}/{record_id}/{magnet_id}-computed.parquet
+```
+
+These derived Parquet files follow the same `python_magnetrun` metadata schema (field-level
+`magnetrun.category`, `magnetrun.unit`, etc.) so they are self-describing.
+
+### Downsampling policy
+
+**Downsampling (LTTB) is applied at display time only. No pre-stored downsampled files.**
+
+Rationale:
+- D2 files at typical Pupitre 1 Hz / 60 min are 200 KB–2 MB — small enough that on-the-fly
+ LTTB from the full-res Parquet is fast (pyarrow columnar read + in-memory LTTB).
+- Pre-storing downsampled artifacts adds storage management overhead (invalidation on reprocess,
+ multiple resolution tiers) for no current gain.
+- The API contract is already forward-compatible: if a future profiling run shows that on-the-fly
+ LTTB on large PigBrother kHz records is too slow, the backend can transparently switch to
+ serving a pre-stored downsampled Parquet without any frontend or API signature change.
+
+The `max_points` query parameter on the data endpoint acts as the single control knob:
+
+```
+GET /api/records/{id}/timeseries/data?columns=B,t&max_points=1000&t_min=0&t_max=600
+```
+
+- `max_points` absent or 0 → return full-resolution data (for export / CEMOSIS notebooks)
+- `max_points` set → apply LTTB server-side before returning JSON
+
+---
+
+## 3. Parquet display in the JS frontend
+
+The plotly.js and chart.js libraries used in the frontend consume JSON arrays. Neither reads
+Parquet natively. An intermediary layer is always needed: either the backend converts Parquet →
+JSON (server-side), or a JS library does it in the browser (client-side).
+
+### Option A — Server-side (recommended for initial implementation)
+
+```
+frontend → GET /api/records/{id}/timeseries/data?columns=B,t&max_points=1000
+backend → opens D2 Parquet from RustFS (pyarrow, columnar projection)
+ → applies LTTB if max_points set
+ → returns JSON
+frontend → plotly.js / chart.js (unchanged)
+```
+
+**Pros**: zero frontend change; works immediately in both Vue 3 and React paths.
+**Cons**: server CPU and memory for every visualization request.
+
+This is the right choice for Track D Phase D2 — it replaces the current `/visualize` endpoint
+with no frontend migration cost.
+
+### Option B — Client-side with pre-signed URL (recommended for the new TimeseriesViewer component)
+
+```
+frontend → GET /api/records/{id}/timeseries/presigned-url
+backend → generates pre-signed RustFS URL (boto3, unchanged from MinIO)
+ → returns { url, columns_catalog, started_at, ... }
+frontend → hyparquet.parquetRead(url, { columns: ['B', 't'] })
+ → applies LTTB in JS if needed
+ → plotly.js / chart.js (unchanged)
+```
+
+**Pros**:
+- Zero server load for visualization after the pre-signed URL is issued.
+- Columnar projection via HTTP range requests: only the requested columns are downloaded,
+ not the full file. Critical for wide PigBrother files.
+- The **same pre-signed URL** can be handed to CEMOSIS researchers for direct use in
+ Python notebooks (`pd.read_parquet(url)` or `pyarrow.parquet.read_table(url)`).
+- Works in any browser without a backend change when columns or time range change.
+
+**Cons**: requires CORS configuration on the RustFS bucket (see Section 1).
+
+**Library**: [`hyparquet`](https://github.com/hyparam/hyparquet) — pure JS, no WebAssembly,
+~10 KB, supports HTTP range requests and async column projection. Suitable for browser use.
+No additional bundler configuration needed.
+
+```js
+import { parquetRead, parquetMetadata } from 'hyparquet'
+
+// fetch metadata to get column catalog (cheap — reads only the Parquet footer)
+const meta = await parquetMetadata(presignedUrl)
+
+// read only the columns needed for display
+await parquetRead({
+ url: presignedUrl,
+ columns: ['t', 'B'],
+ onComplete: (rows) => {
+ // rows is an array of objects [{ t: 0.0, B: 0.0 }, ...]
+ // apply LTTB here if needed, then feed to plotly.js
+ }
+})
+```
+
+### Option C — DuckDB-WASM (future, interactive exploration)
+
+[DuckDB-WASM](https://duckdb.org/docs/api/wasm/overview.html) can execute SQL against a Parquet
+file via HTTPS URL, including pre-signed S3 URLs, with columnar projection and predicate
+pushdown running in the browser via WebAssembly. Suitable for a future interactive query panel.
+Not needed for the standard timeseries viewer.
+
+```js
+import * as duckdb from '@duckdb/duckdb-wasm'
+// SELECT t, B FROM read_parquet('presigned-url') WHERE t BETWEEN 100 AND 600
+```
+
+### Recommended rollout
+
+| Phase | Approach | Rationale |
+|-------|----------|-----------|
+| Track D Phase D2 (short term) | Option A (server-side) | Drop-in replacement for `/visualize`; no frontend change |
+| New `TimeseriesViewer` component (Vue 3 E-A4 / React E-B3) | Option B (`hyparquet` + pre-signed URL) | Columnar projection; same URL usable in CEMOSIS notebooks |
+| Future interactive exploration panel | Option C (DuckDB-WASM) | Only if SQL-style querying is needed |
+
+---
+
+## 4. Impact on Track D Phase D2 scope
+
+The combination of (a) downsampling at display time only and (b) curated refs living directly on
+`Record` rather than in a separate `ProcessedTimeSeries` model simplifies Phase D2:
+
+| Sub-phase | Original scope | Revised scope |
+|-----------|----------------|---------------|
+| D2.1 ProcessedTimeSeries model | Full model (scope, origin, columns catalog, Parquet FK) | **Drops** — curated ref lives on `Record.curated` |
+| D2.2 Parquet infrastructure | `store_as_parquet` helper + `read_parquet_columns` + LTTB storage | `read_parquet_columns` (pyarrow) + LTTB at query time; write via `python_magnetrun.saveParquet()` |
+| D2.3 Raw ETL | parse → clean → write Parquet → create ProcessedTimeSeries row | parse → `mdata.saveParquet()` → `Record.curated.add(attachment)` |
+| D2.4 Derived ETL | hoop stress → separate Parquet per scope | Unchanged — derived columns still worth pre-computing |
+| D2.5 API endpoints | catalog endpoints + data endpoint | Data endpoint only; catalog is `Record.curated` list via existing Record show endpoint |
+| D2.6 Backfill + validation | management command + deprecate `/visualize` | Unchanged |
+
+**Revised D2 duration estimate**: 3–4 weeks (down from 5–6 weeks).
+
+### Forward-compatibility note
+
+When (if) pre-stored downsampled Parquet becomes worth it:
+- Add a `downsampled_attachments` field to Record (or a small `DownsampledCache` model).
+- The data endpoint checks for a cached artifact before running LTTB.
+- No API signature change, no frontend change.
diff --git a/prompts/scalable-dataset-management-architecture-with-workflows-orchestration.md b/prompts/scalable-dataset-management-architecture-with-workflows-orchestration.md
new file mode 100644
index 0000000..2e49b6c
Binary files /dev/null and b/prompts/scalable-dataset-management-architecture-with-workflows-orchestration.md differ
diff --git a/prompts/vue-cli-4-to-5-migration.md b/prompts/vue-cli-4-to-5-migration.md
new file mode 100644
index 0000000..65b89ac
--- /dev/null
+++ b/prompts/vue-cli-4-to-5-migration.md
@@ -0,0 +1,285 @@
+# Migration Plan: Vue CLI 4 → Vue CLI 5 (Webpack 4 → 5)
+
+**Date:** 2026-05-05
+**Branch:** `node22`
+**Scope:** `web/` frontend only
+
+---
+
+## Context
+
+Vue CLI 5 is primarily a **Webpack 4 → Webpack 5** upgrade plus modernised
+tooling wrappers. Vue itself does not change — Vue CLI 5 fully supports Vue
+2.x, so all `.vue` components, the Vuex store, and VueRouter 3 are untouched.
+
+This upgrade eliminates the root causes of the `--openssl-legacy-provider`
+workaround, unlocks Node 22 support, and unblocks a future Vue 2 → 3 migration.
+
+---
+
+## Affected Files
+
+| File | Nature of change | Status |
+|------|-----------------|--------|
+| `web/package.json` | Bump `@vue/cli-*`, swap TailwindCSS, replace `babel-eslint`, bump ESLint | ✅ Done |
+| `web/tailwind.config.js` | `purge` → `content`, remove `darkMode`/`variants` | ✅ Done |
+| `web/vue.config.js` | Add webpack `resolve.fallback` for Node built-ins | ✅ Done |
+| `web/postcss.config.js` | No change (same structure, PostCSS 8 is a drop-in) | ✅ Done |
+| `web/Dockerfile` | Remove `ENV NODE_OPTIONS=--openssl-legacy-provider` | ✅ Done |
+| `web/Dockerfile-dev` | Remove `ENV NODE_OPTIONS=--openssl-legacy-provider` | ✅ Done |
+| `web/package-lock.json` | Regenerated by `npm install` inside `node:20-trixie` container | ✅ Done |
+
+**Not changed:** all `src/` Vue components, `babel.config.js`, runtime
+dependencies (`vue`, `vue-router`, `vuex`, `axios`, `chart.js`, `plotly.js`, …).
+
+---
+
+## Deviations from Original Plan
+
+### ESLint 6 → 8 (forced, not originally planned)
+
+`@babel/eslint-parser@^7.x` requires `eslint@^7.5.0 || ^8.0.0 || ^9.0.0`.
+`@vue/cli-plugin-eslint@~5.0.0` also requires `eslint>=7.28.0` and
+`eslint-plugin-vue>=8.0.0`. Both packages refused to install with ESLint 6.
+
+Bumped in `package.json`:
+```diff
+-"eslint": "^6.7.2",
+-"eslint-plugin-vue": "^6.2.2",
++"eslint": "^8.0.0",
++"eslint-plugin-vue": "^8.0.0",
+```
+
+`eslint-plugin-vue@^8` enforces two rules that the existing `src/` code
+violates. Rather than renaming components or restructuring templates, both
+rules are disabled in `eslintConfig`:
+
+```diff
+-"rules": {}
++"rules": {
++ "vue/multi-word-component-names": "off",
++ "vue/valid-v-slot": "off"
++}
+```
+
+- `vue/multi-word-component-names`: `Alert`, `Button`, `Card`, `Form`, `Modal`, `Popover`, etc. are single-word component names — established UI components, not worth renaming.
+- `vue/valid-v-slot`: multiple list views use `v-slot:header.name` dot-modifier syntax that eslint-plugin-vue v8 rejects; the templates work correctly at runtime.
+
+### Webpack 5 Node.js polyfill fallbacks (not in original pre-migration audit)
+
+The original plan stated "No Node.js built-ins (`Buffer`, `process`, `crypto`)
+in `src/`" — correct for app code. However, two **transitive dependencies**
+(`probe-image-size` via `plotly.js`, `stream-parser`) reference `stream` and
+`assert`, which Webpack 5 no longer polyfills automatically.
+
+`vue.config.js` was updated to add empty fallbacks (the code paths that
+reference these modules are never reached in the browser):
+
+```diff
+ module.exports = {
+ devServer: { allowedHosts: ['lncmig.local', 'magnetdb-dev.local'] },
++ configureWebpack: {
++ resolve: {
++ fallback: { stream: false, assert: false },
++ },
++ },
+ }
+```
+
+---
+
+## Migration Steps
+
+### Phase 1 — Core CLI packages ✅
+
+`@vue/cli-plugin-babel`, `@vue/cli-plugin-eslint`, `@vue/cli-service` bumped
+to `~5.0.0` in `web/package.json`.
+
+### Phase 2 — Remove `--openssl-legacy-provider` ✅
+
+Removed from `scripts` in `package.json` and from `ENV` in both Dockerfiles.
+
+### Phase 3 — Replace `babel-eslint` ✅
+
+Replaced `babel-eslint: ^10.1.0` with `@babel/eslint-parser: ^7.x`.
+Updated `eslintConfig.parserOptions`:
+```json
+"parser": "@babel/eslint-parser",
+"requireConfigFile": false
+```
+
+Also bumped `eslint` to `^8.0.0` and `eslint-plugin-vue` to `^8.0.0` (forced
+by peer dependency requirements — see Deviations above).
+
+### Phase 4 — PostCSS 8 + TailwindCSS 3 ✅
+
+- Removed `@tailwindcss/postcss7-compat`, `postcss: ^7`, `autoprefixer: ^9`
+- Added `tailwindcss: ^3.x`, `autoprefixer: ^10`
+- `@tailwindcss/forms` bumped from `^0.3.4` → `^0.5.x`
+- `tailwind.config.js`: `purge` → `content`, removed `darkMode`/`variants`
+
+> **Visual check still required:** load each main view in a browser and compare
+> layout against the v4 build.
+
+### Phase 5 — Audit and trim the `overrides` block ✅
+
+Removed entries for packages no longer in the Webpack 5 dep tree:
+`cipher-base`, `pbkdf2`, `sha.js`.
+
+Kept: all remaining entries (still present via other dependencies).
+
+### Phase 6 — Full build and smoke test ✅
+
+All three CLI checks pass inside a `node:22-trixie` container:
+
+| Command | Result |
+|---------|--------|
+| `npm run build` | ✅ Compiled — only bundle-size warnings (expected) |
+| `npm run lint` | ✅ No lint errors found |
+| `npm run serve` | ✅ Compiled successfully in ~21s, serving on :8080 |
+
+Browser smoke test via `docker compose -f docker-compose-dev-traefik-ssl.yml up`:
+
+- [x] App loads and sign-in works
+- [x] Sites / Magnets / Parts / Records list views render correctly
+- [x] Forms (new site, new magnet, etc.) submit without errors
+- [x] Visualisation views (bmap, stress-map) render charts
+- [x] Monaco editor loads (CDN)
+- [x] No console errors related to missing polyfills or chunk loading
+
+### Phase 7 — Docker builds ✅
+
+Both images built successfully:
+
+| Image | Tag | Result |
+|-------|-----|--------|
+| `magnetdb-web` | `vuecli5` | ✅ Built — nginx:alpine serving compiled `dist/` |
+| `magnetdb-web-dev` | `vuecli5` | ✅ Built — node:22-trixie with deps installed |
+
+```bash
+# Dev image
+docker build -f web/Dockerfile-dev \
+ --build-arg USERNAME=feelpp \
+ --build-arg USER_UID=$(id -u) \
+ --build-arg USER_GID=$(id -g) \
+ -t magnetdb-web-dev:vuecli5 web/
+
+# Production image
+docker build -f web/Dockerfile \
+ --build-arg NODE_ENV=production \
+ --build-arg API_ENDPOINT=http://localhost:5000 \
+ -t magnetdb-web:vuecli5 web/
+```
+
+### Phase 8 — ESLint 8 → 9 with flat config ✅
+
+`@vue/cli-plugin-eslint@5` passes removed ESLint 8 options to ESLint 9's
+constructor, so `vue-cli-service lint` is bypassed in favour of calling ESLint
+directly.
+
+Changes:
+- `eslint` bumped to `^9.0.0`
+- `eslint-plugin-vue` bumped to `^10.0.0` (adds flat config, keeps vue2-* presets)
+- `globals: ^16.0.0` added to devDependencies
+- `eslint-webpack-plugin: ^4.0.0` added to overrides (v3 doesn't support ESLint 9)
+- `eslintConfig` section removed from `package.json`
+- `web/eslint.config.js` created (flat config)
+- `lint` script changed from `vue-cli-service lint` to `eslint src/`
+- `lintOnSave: false` added to `vue.config.js` (webpack build no longer runs ESLint)
+- `vue/no-reserved-component-names: off` added (new rule in v10, flags `Button`/`Form`)
+- `catch (e)` → `catch` in `Form.vue` (optional catch binding, fixes `no-unused-vars`)
+
+### Phase 9 — Switch to `node:22-trixie` ✅
+
+```diff
+-FROM node:20-trixie AS builder
++FROM node:22-trixie AS builder
+```
+
+Applied to both `web/Dockerfile` and `web/Dockerfile-dev`. Build and lint
+verified clean on Node 22.
+
+---
+
+## What Changes vs What Stays the Same
+
+### Removed entirely
+
+| Item | Reason |
+|------|--------|
+| `--openssl-legacy-provider` flag | Webpack 5 uses Web Crypto API natively |
+| `@tailwindcss/postcss7-compat` | Vue CLI 5 uses PostCSS 8 |
+| `postcss: ^7` explicit dep | Owned by Vue CLI 5 |
+| `autoprefixer: ^9` | Incompatible with PostCSS 8 |
+| `babel-eslint` | Superseded by `@babel/eslint-parser` |
+| `purge`/`darkMode`/`variants` in tailwind config | TailwindCSS 3 API change |
+| `cipher-base`, `pbkdf2`, `sha.js` overrides | No longer in dep tree with Webpack 5 |
+
+### Unchanged
+
+| Item | Note |
+|------|------|
+| All `src/` Vue components | No Webpack 5 breakage for this codebase |
+| `vue`, `vue-router`, `vuex` | Runtime — unrelated to build tooling |
+| `axios`, `chart.js`, `plotly.js`, `mathjs` | Runtime — unrelated |
+| `babel.config.js` | No change |
+| `postcss.config.js` | Same structure, PostCSS 8 is a drop-in |
+
+---
+
+## What This Unlocks
+
+- **Node 22 support** — Webpack 5 has no OpenSSL compatibility issues
+- **Cleaner Dockerfiles** — no legacy flags or workarounds
+- **Faster builds** — Webpack 5 persistent cache and better tree-shaking
+- **Smaller bundles** — improved module concatenation
+- **PostCSS 8** — compatible with the entire modern CSS tooling ecosystem
+- **Path to Vue 3** — Vue CLI 5 is the recommended bridge before a Vue 2 → 3
+ migration; the Options API SFCs in this project require no changes for Vue 3
+ compatibility (no `Vue.filter`, no class components, no `$listeners`)
+
+---
+
+## Rollback
+
+If a phase fails and cannot be fixed quickly, restore from git:
+
+```bash
+git checkout -- web/package.json web/package-lock.json \
+ web/tailwind.config.js web/vue.config.js \
+ web/Dockerfile web/Dockerfile-dev
+rm -rf web/node_modules
+docker run --rm -v $(pwd)/web:/app -w /app node:20-trixie npm install
+```
+
+---
+
+## Effort Summary
+
+| Phase | Task | Effort | Status |
+|-------|------|--------|--------|
+| 1 | Bump `@vue/cli-*` to v5 | ~30 min | ✅ Done |
+| 2 | Remove `--openssl-legacy-provider` | ~10 min | ✅ Done |
+| 3 | Replace `babel-eslint` → `@babel/eslint-parser` (+ ESLint 6→8) | ~30 min | ✅ Done |
+| 4 | PostCSS 8 + TailwindCSS 3 | ~1 hour | ✅ Done |
+| 5 | Audit and trim `overrides` | ~30 min | ✅ Done |
+| 6 | Full build + smoke test | ~1 hour | ✅ Done |
+| 7 | Docker builds | ~30 min | ✅ Done |
+| 8 | ESLint 8 → 9 with flat config | ~1 hour | ✅ Done |
+| 9 | Switch to `node:22-trixie` | ~15 min | ✅ Done |
+
+---
+
+## Long-Term Recommendations
+
+| Item | Priority | Status |
+|------|----------|--------|
+| Replace `Vue.filter` with global properties (Vue 3 prep) | Medium | ✅ Done |
+| Vue 2 → Vue 3 migration | Low (long-term) | 🔲 Pending |
+| Consider Vite as an alternative to Vue CLI 5 | Low | 🔲 Pending |
+
+---
+
+## Next Steps
+
+1. **Commit** all changed files on `node22` and **open a PR** to `main`.
diff --git a/python_magnetdb/actions/generate_magnet_directory.py b/python_magnetdb/actions/generate_magnet_directory.py
index 31a51cc..60fe961 100644
--- a/python_magnetdb/actions/generate_magnet_directory.py
+++ b/python_magnetdb/actions/generate_magnet_directory.py
@@ -70,4 +70,5 @@ def generate_magnet_directory(magnet_id, directory):
with open(f"{directory}/config.json", "w+") as file:
config = generate_magnet_config(magnet_id)
file.write(json.dumps(config))
+ print(f"generate_magnet_directory: config={config}")
return config
diff --git a/python_magnetdb/actions/generate_simulation_config.py b/python_magnetdb/actions/generate_simulation_config.py
index 6f20eab..c06eaec 100755
--- a/python_magnetdb/actions/generate_simulation_config.py
+++ b/python_magnetdb/actions/generate_simulation_config.py
@@ -22,15 +22,13 @@ def format_material(material):
def generate_magnet_config(magnet_id):
magnet = Magnet.objects.prefetch_related(
- 'magnetpart_set__part',
- 'magnetpart_set__part__material',
- 'sitemagnet_set__site',
+ "magnetpart_set__part",
+ "magnetpart_set__part__material",
+ "sitemagnet_set__site",
).get(id=magnet_id)
- print(
- f"generate_magnet_config[{magnet_id}]: magnet={magnet.name}"
- )
+ print(f"generate_magnet_config[{magnet_id}]: magnet={magnet.name}")
payload = {"geom": f"{magnet.name}.yaml"}
-
+
try:
insulator_payload = format_material(Material.objects.get(name="MAT_ISOLANT"))
except Material.DoesNotExist:
@@ -38,7 +36,7 @@ def generate_magnet_config(magnet_id):
"Material 'MAT_ISOLANT' is not defined in the database. "
"Please create this material before generating magnet configurations."
)
-
+
for magnet_part in magnet.magnetpart_set.all():
# if not magnet_part.active:
# continue
@@ -65,7 +63,7 @@ def generate_site_config(site_id):
# if not site_magnet.active:
# continue
payload["magnets"].append(generate_magnet_config(site_magnet.magnet_id))
- # print(f'generate_site_config: {payload}')
+ print(f"generate_site_config: {payload}")
return payload
diff --git a/python_magnetdb/actions/generate_site_directory.py b/python_magnetdb/actions/generate_site_directory.py
index 66c63f9..adfb169 100644
--- a/python_magnetdb/actions/generate_site_directory.py
+++ b/python_magnetdb/actions/generate_site_directory.py
@@ -16,10 +16,10 @@ def mkdir(dir):
def generate_site_directory(site_id, directory):
site = Site.objects.prefetch_related(
- 'sitemagnet_set__magnet',
- 'sitemagnet_set__magnet__magnetpart_set__part__cadattachment_set__attachment',
- 'sitemagnet_set__magnet__magnetpart_set__part__material',
- 'sitemagnet_set__magnet__cadattachment_set__attachment',
+ "sitemagnet_set__magnet",
+ "sitemagnet_set__magnet__magnetpart_set__part__cadattachment_set__attachment",
+ "sitemagnet_set__magnet__magnetpart_set__part__material",
+ "sitemagnet_set__magnet__cadattachment_set__attachment",
).get(id=site_id)
mkdir(f"{directory}/data")
mkdir(f"{directory}/data/geometries")
@@ -39,7 +39,7 @@ def generate_site_directory(site_id, directory):
# add flow_params per magnet
generate_flow_params(magnet, directory, magnet.name)
-
+
for magnet_part in magnet.magnetpart_set.all():
print(f"magnet_part: name={magnet_part.part.name}")
# if not magnet_part.active:
@@ -49,13 +49,11 @@ def generate_site_directory(site_id, directory):
if magnet_part.part.shape_attachment:
magnet_part.part.shape_attachment.download(
f"{directory}/data/cad/{magnet_part.part.shape_attachment.attachment.filename}"
- )
+ )
if magnet_part.part.cadattachment_set.all():
for cad in magnet_part.part.cadattachment_set.all():
- cad.attachment.download(
- f"{directory}/data/cad/{cad.attachment.filename}"
- )
-
+ cad.attachment.download(f"{directory}/data/cad/{cad.attachment.filename}")
+
for probe in magnet.probe_set.all():
with open(f"{directory}/data/geometries/{probe.name}.yaml", "w") as f:
f.write(probe.geometry_config_to_yaml)
@@ -64,7 +62,7 @@ def generate_site_directory(site_id, directory):
magnet_config = generate_magnet_config(magnet.id)
file.write(json.dumps(magnet_config))
site_config["magnets"].append({magnet.name: magnet_config})
- # print(f'generate_site_directory: site_config={site_config}')
+ print(f"generate_site_directory: site_config={site_config}")
with open(f"{directory}/config.json", "w+") as file:
file.write(json.dumps(site_config))
diff --git a/python_magnetdb/models/magnet.py b/python_magnetdb/models/magnet.py
index 2279922..6c1d41c 100644
--- a/python_magnetdb/models/magnet.py
+++ b/python_magnetdb/models/magnet.py
@@ -48,339 +48,101 @@ class Meta:
metadata = models.JSONField(default=dict, null=False)
flow_params = models.JSONField(null=True)
- @property
- def geometry_config_to_json(self):
- """
- Convert magnet to python_magnetgeo object and serialize to JSON.
-
- Uses python_magnetgeo classes (Insert, Supras, Bitters) to create
- geometry objects with proper validation, then serializes using their
- built-in to_json() method.
-
- Returns:
- str: JSON string representation with __classname__ format
- """
+ def to_geometry_object(self):
+ """Build and return the python_magnetgeo object for this magnet."""
from python_magnetgeo.deserialize import unserialize_object
import copy
- # Collect probe names
- probes = []
- for probe in self.probe_set.all():
- config = probe.geometry_config_to_json
- # Deserialize to get a magnetgeo object
- probe_obj = unserialize_object(config)
- probes.append(probe_obj)
+ eps = 0.9 # clearance in mm for bore fallback calculations
- if self.type == MagnetType.INSERT:
- # Collect helices, rings, and current leads as objects
- helices = []
- hangles = []
- rings = []
- rangles = []
- currentleads = []
-
- for magnet_part in self.magnetpart_set.all():
- if magnet_part.part.type == PartType.HELIX:
- # Deserialize geometry_config to get Helix object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Ensure __classname__ is set for proper deserialization
- if "__classname__" not in config:
- config["__classname__"] = "Helix"
- helix_obj = unserialize_object(config)
- helices.append(helix_obj)
- hangles.append(magnet_part.angle if magnet_part.angle is not None else 0)
- elif magnet_part.part.type == PartType.RING:
- # Deserialize geometry_config to get Ring object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Ensure __classname__ is set for proper deserialization
- if "__classname__" not in config:
- config["__classname__"] = "Ring"
- ring_obj = unserialize_object(config)
- rings.append(ring_obj)
- rangles.append(magnet_part.angle if magnet_part.angle is not None else 0)
- elif magnet_part.part.type == PartType.LEAD:
- # Deserialize geometry_config to get CurrentLead object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Ensure __classname__ is set for proper deserialization
- if "__classname__" not in config:
- config["__classname__"] = "InnerCurrentLead"
- lead_obj = unserialize_object(config)
- currentleads.append(lead_obj)
+ probes = [unserialize_object(p.geometry_config_to_json) for p in self.probe_set.all()]
- # Create Insert object with validation
- insert = Insert(
+ if self.type == MagnetType.INSERT:
+ helices, hangles, rings, rangles, currentleads = [], [], [], [], []
+ for mp in self.magnetpart_set.all():
+ config = copy.deepcopy(mp.part.geometry_config)
+ config["name"] = mp.part.name
+ if mp.part.type == PartType.HELIX:
+ config.setdefault("__classname__", "Helix")
+ helices.append(unserialize_object(config))
+ hangles.append(mp.angle if mp.angle is not None else 0)
+ elif mp.part.type == PartType.RING:
+ config.setdefault("__classname__", "Ring")
+ rings.append(unserialize_object(config))
+ rangles.append(mp.angle if mp.angle is not None else 0)
+ elif mp.part.type == PartType.LEAD:
+ config.setdefault("__classname__", "InnerCurrentLead")
+ currentleads.append(unserialize_object(config))
+ return Insert(
name=self.name,
helices=helices,
rings=rings,
currentleads=currentleads,
hangles=hangles,
rangles=rangles,
- innerbore=self.inner_bore if self.inner_bore is not None else 0,
- outerbore=self.outer_bore if self.outer_bore is not None else 0,
+ innerbore=self.inner_bore if self.inner_bore is not None else (helices[0].r[0] - eps if helices else 0),
+ outerbore=self.outer_bore if self.outer_bore is not None else (helices[-1].r[1] + eps if helices else 0),
probes=probes,
)
- return insert.to_json()
elif self.type == MagnetType.SUPRAS:
- # Collect supra magnets and current leads as objects
- magnets = []
- currentleads = []
-
- for magnet_part in self.magnetpart_set.all():
- if magnet_part.part.type == PartType.SUPRA:
- # Deserialize geometry_config to get Supra object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- supra_obj = unserialize_object(config)
- magnets.append(supra_obj)
- elif magnet_part.part.type == PartType.LEAD:
- # Deserialize geometry_config to get CurrentLead object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- lead_obj = unserialize_object(config)
- currentleads.append(lead_obj)
-
- # Create Supras object with validation
- supras = Supras(
+ magnets, currentleads = [], []
+ for mp in self.magnetpart_set.all():
+ config = copy.deepcopy(mp.part.geometry_config)
+ config["name"] = mp.part.name
+ if mp.part.type == PartType.SUPRA:
+ magnets.append(unserialize_object(config))
+ elif mp.part.type == PartType.LEAD:
+ currentleads.append(unserialize_object(config))
+ return Supras(
name=self.name,
magnets=magnets,
- innerbore=self.inner_bore if self.inner_bore is not None else 0,
- outerbore=self.outer_bore if self.outer_bore is not None else 0,
+ innerbore=self.inner_bore if self.inner_bore is not None else (magnets[0].r[0] - eps if magnets else 0),
+ outerbore=self.outer_bore if self.outer_bore is not None else (magnets[-1].r[1] + eps if magnets else 0),
probes=probes,
)
- return supras.to_json()
elif self.type == MagnetType.BITTERS:
- # Collect bitter magnets and current leads as objects
- magnets = []
- currentleads = []
-
- for magnet_part in self.magnetpart_set.all():
- if magnet_part.part.type == PartType.BITTER:
- # Deserialize geometry_config to get Bitter object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- bitter_obj = unserialize_object(config)
- magnets.append(bitter_obj)
- elif magnet_part.part.type == PartType.LEAD:
- # Deserialize geometry_config to get CurrentLead object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- lead_obj = unserialize_object(config)
- currentleads.append(lead_obj)
-
- # Create Bitters object with validation
- bitters = Bitters(
+ magnets, currentleads = [], []
+ for mp in self.magnetpart_set.all():
+ config = copy.deepcopy(mp.part.geometry_config)
+ config["name"] = mp.part.name
+ if mp.part.type == PartType.BITTER:
+ magnets.append(unserialize_object(config))
+ elif mp.part.type == PartType.LEAD:
+ currentleads.append(unserialize_object(config))
+ return Bitters(
name=self.name,
magnets=magnets,
- innerbore=self.inner_bore if self.inner_bore is not None else 0,
- outerbore=self.outer_bore if self.outer_bore is not None else 0,
+ innerbore=self.inner_bore if self.inner_bore is not None else (magnets[0].r[0] - eps if magnets else 0),
+ outerbore=self.outer_bore if self.outer_bore is not None else (magnets[-1].r[1] + eps if magnets else 0),
probes=probes,
)
- return bitters.to_json()
- # Fallback for unknown types
- return json.dumps(
- {
- "__tag__": "Unknown",
- "__value__": {
- "name": self.name,
- "innerbore": self.inner_bore if self.inner_bore is not None else 0,
- "outerbore": self.outer_bore if self.outer_bore is not None else 0,
- },
- }
- )
+ return None
- @property
- def geometry_config_to_yaml(self):
- """
- Convert magnet to python_magnetgeo object and serialize to YAML.
+ def _fallback_geo_dict(self):
+ return {
+ "name": self.name,
+ "innerbore": self.inner_bore if self.inner_bore is not None else 0,
+ "outerbore": self.outer_bore if self.outer_bore is not None else 0,
+ }
- Uses python_magnetgeo classes (Insert, Supras, Bitters) to create
- geometry objects with proper validation, then serializes using yaml.dump().
+ @property
+ def geometry_config_to_json(self):
+ geo = self.to_geometry_object()
+ if geo is not None:
+ return geo.to_json()
+ return json.dumps({"__tag__": "Unknown", "__value__": self._fallback_geo_dict()})
- Returns:
- str: YAML string representation with proper YAML tags
- """
- from python_magnetgeo.deserialize import unserialize_object
- import copy
+ @property
+ def geometry_config_to_yaml(self):
import yaml
-
print(
f"Generating geometry_config_to_yaml for magnet {self.name} of type {self.type} ...",
flush=True,
)
- # Collect probe names
- probes = []
- for probe in self.probe_set.all():
- config = probe.geometry_config_to_json
- # Deserialize to get a magnetgeo object
- probe_obj = unserialize_object(config)
- probes.append(probe_obj)
-
- if self.type == MagnetType.INSERT:
- print(
- f"Processing INSERT magnet {self.name} with {len(self.magnetpart_set.all())} parts ...",
- flush=True,
- )
- # Collect helices, rings, and current leads as objects
- helices = []
- hangles = []
- rings = []
- rangles = []
- currentleads = []
-
- for magnet_part in self.magnetpart_set.all():
- if magnet_part.part.type == PartType.HELIX:
- # Deserialize geometry_config to get Helix object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Deserialize to get a magnetgeo object
- helix_obj = unserialize_object(config)
- helices.append(helix_obj)
- hangles.append(magnet_part.angle if magnet_part.angle is not None else 0)
- elif magnet_part.part.type == PartType.RING:
- # Deserialize geometry_config to get Ring object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Deserialize to get a magnetgeo object
- ring_obj = unserialize_object(config)
- rings.append(ring_obj)
- rangles.append(magnet_part.angle if magnet_part.angle is not None else 0)
- elif magnet_part.part.type == PartType.LEAD:
- # Deserialize geometry_config to get CurrentLead object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Deserialize to get a magnetgeo object
- lead_obj = unserialize_object(config)
- currentleads.append(lead_obj)
-
- # Create Insert object with validation
- # Epsilon in mm - clearance for bore calculations
- eps = 0.9
- insert = Insert(
- name=self.name,
- helices=helices,
- rings=rings,
- currentleads=currentleads,
- hangles=hangles,
- rangles=rangles,
- innerbore=(
- self.inner_bore
- if self.inner_bore is not None or self.inner_bore == 0
- else helices[0].r[0] - eps
- ),
- outerbore=(
- self.outer_bore
- if self.outer_bore is not None or self.outer_bore == 0
- else helices[-1].r[1] + eps
- ),
- probes=probes,
- )
- return insert.to_yaml()
-
- elif self.type == MagnetType.SUPRAS:
- print(
- f"Processing SUPRAS magnet {self.name} with {len(self.magnetpart_set.all())} parts ...",
- flush=True,
- )
- # Collect supra magnets and current leads as objects
- magnets = []
- currentleads = []
-
- for magnet_part in self.magnetpart_set.all():
- if magnet_part.part.type == PartType.SUPRA:
- # Deserialize geometry_config to get Supra object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Deserialize to get a magnetgeo object
- supra_obj = unserialize_object(config)
- magnets.append(supra_obj)
- elif magnet_part.part.type == PartType.LEAD:
- # Deserialize geometry_config to get CurrentLead object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Deserialize to get a magnetgeo object
- lead_obj = unserialize_object(config)
- currentleads.append(lead_obj)
-
- # Create Supras object with validation
- # Handle empty magnets list (e.g., fresh database with no parts)
- if not magnets:
- innerbore_val = self.inner_bore if self.inner_bore is not None else 0
- outerbore_val = self.outer_bore if self.outer_bore is not None else 0
- else:
- innerbore_val = (
- self.inner_bore if self.inner_bore is not None else magnets[0].r[0] - eps
- )
- outerbore_val = (
- self.outer_bore if self.outer_bore is not None else magnets[-1].r[1] + eps
- )
-
- supras = Supras(
- name=self.name,
- magnets=magnets,
- innerbore=innerbore_val,
- outerbore=outerbore_val,
- probes=probes,
- )
- return supras.to_yaml()
-
- elif self.type == MagnetType.BITTERS:
- print(
- f"Processing BITTERS magnet {self.name} with {len(self.magnetpart_set.all())} parts ...",
- flush=True,
- )
- # Collect bitter magnets and current leads as objects
- magnets = []
- currentleads = []
-
- for magnet_part in self.magnetpart_set.all():
- if magnet_part.part.type == PartType.BITTER:
- # Deserialize geometry_config to get Bitter object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Deserialize to get a magnetgeo object
- bitter_obj = unserialize_object(config)
- magnets.append(bitter_obj)
- elif magnet_part.part.type == PartType.LEAD:
- # Deserialize geometry_config to get CurrentLead object
- config = copy.deepcopy(magnet_part.part.geometry_config)
- config["name"] = magnet_part.part.name
- # Deserialize to get a magnetgeo object
-
- lead_obj = unserialize_object(config)
- currentleads.append(lead_obj)
-
- # Create Bitters object with validation
- # Handle empty magnets list (e.g., fresh database with no parts)
- if not magnets:
- innerbore_val = self.inner_bore if self.inner_bore is not None else 0
- outerbore_val = self.outer_bore if self.outer_bore is not None else 0
- else:
- innerbore_val = (
- self.inner_bore if self.inner_bore is not None else magnets[0].r[0] - eps
- )
- outerbore_val = (
- self.outer_bore if self.outer_bore is not None else magnets[-1].r[1] + eps
- )
-
- bitters = Bitters(
- name=self.name,
- magnets=magnets,
- innerbore=innerbore_val,
- outerbore=outerbore_val,
- probes=probes,
- )
- return bitters.to_yaml()
-
- # Fallback for unknown types - return simple YAML
- fallback_data = {
- "name": self.name,
- "innerbore": self.inner_bore if self.inner_bore is not None else 0,
- "outerbore": self.outer_bore if self.outer_bore is not None else 0,
- }
- return yaml.dump(fallback_data, default_flow_style=False)
+ geo = self.to_geometry_object()
+ if geo is not None:
+ return geo.to_yaml()
+ return yaml.dump(self._fallback_geo_dict(), default_flow_style=False)
diff --git a/python_magnetdb/models/part.py b/python_magnetdb/models/part.py
index c7de60d..95734a9 100644
--- a/python_magnetdb/models/part.py
+++ b/python_magnetdb/models/part.py
@@ -55,59 +55,31 @@ def allow_shape_file(self):
def allow_modelaxi_file(self):
return self.type == PartType.HELIX or self.type == PartType.BITTER
- @property
- def geometry_config_to_json(self):
- """
- Convert geometry_config to JSON string.
-
- Creates a python_magnetgeo object from geometry_config, updates the name,
- and returns the JSON representation using the object's to_json() method.
-
- Returns:
- str: JSON string or None if geometry_config is empty
- """
+ def to_geometry_object(self):
+ """Build and return the python_magnetgeo object for this part, or None if geometry_config is empty."""
if self.geometry_config is None or self.geometry_config == {}:
return None
-
- # Create python_magnetgeo object from geometry_config
from python_magnetgeo.deserialize import unserialize_object
-
config = copy.deepcopy(self.geometry_config)
config["name"] = self.name
+ return unserialize_object(config)
- # Deserialize to get a magnetgeo object
- obj = unserialize_object(config)
-
- # Use object's native to_json() method
- print(f"geometry_config_to_json[{obj.name}]:", obj.to_json())
- return obj.to_json()
+ @property
+ def geometry_config_to_json(self):
+ obj = self.to_geometry_object()
+ if obj is None:
+ return None
+ result = obj.to_json()
+ print(f"geometry_config_to_json[{obj.name}]:", result)
+ return result
@property
def geometry_config_to_yaml(self):
- """
- Convert geometry_config to YAML string.
-
- Creates a python_magnetgeo object from geometry_config, updates the name,
- and returns the YAML representation using yaml.dump().
-
- Returns:
- str: YAML string or None if geometry_config is empty
- """
- if self.geometry_config is None or self.geometry_config == {}:
+ obj = self.to_geometry_object()
+ if obj is None:
return None
-
- # Create python_magnetgeo object from geometry_config
- from python_magnetgeo.deserialize import unserialize_object
- import yaml
-
- config = copy.deepcopy(self.geometry_config)
- config["name"] = self.name
-
- # Deserialize to get a magnetgeo object
- obj = unserialize_object(config)
-
- # Use object's to_yaml() method for proper YAML serialization
- print(f"geometry_config_to_yaml[{obj.name}]:", config)
+ result = obj.to_yaml()
+ print(f"geometry_config_to_yaml[{obj.name}]:", self.geometry_config)
print("object:\n", obj)
- print("yaml:\n", obj.to_yaml())
- return obj.to_yaml()
+ print("yaml:\n", result)
+ return result
diff --git a/python_magnetdb/models/site.py b/python_magnetdb/models/site.py
index 6d537f4..f563162 100644
--- a/python_magnetdb/models/site.py
+++ b/python_magnetdb/models/site.py
@@ -17,17 +17,8 @@ class Meta:
created_at = models.DateTimeField(auto_now_add=True, null=False)
updated_at = models.DateTimeField(auto_now=True, null=False)
- @property
- def geometry_config_to_json(self):
- """
- Convert site configuration to JSON string.
-
- Creates a python_magnetgeo MSite object from the site data,
- and returns the JSON representation using the object's to_json() method.
-
- Returns:
- str: JSON string representation of the MSite
- """
+ def to_geometry_object(self):
+ """Build and return the MSite object for this site."""
from python_magnetgeo.deserialize import unserialize_object
import json
@@ -37,19 +28,15 @@ def geometry_config_to_json(self):
r_offset = []
paralax = []
- # Populate from related sitemagnet objects
for site_magnet in self.sitemagnet_set.all():
- # Get the magnet's geometry as JSON, then deserialize to object
magnet_json = site_magnet.magnet.geometry_config_to_json
print("magnet_json:", magnet_json)
- magnet_obj = unserialize_object(json.loads(magnet_json))
- magnets.append(magnet_obj)
+ magnets.append(unserialize_object(json.loads(magnet_json)))
z_offset.append(site_magnet.z_offset)
r_offset.append(site_magnet.r_offset)
paralax.append(site_magnet.parallax)
- # Create MSite object and use its to_json() method
- obj = MSite(
+ return MSite(
name=self.name,
magnets=magnets,
screens=screens,
@@ -57,46 +44,11 @@ def geometry_config_to_json(self):
r_offset=r_offset,
paralax=paralax,
)
- return obj.to_json()
@property
- def geometry_config_to_yaml(self):
- """
- Convert site configuration to YAML string.
-
- Creates a python_magnetgeo MSite object from the site data,
- and returns the YAML representation using yaml.dump().
-
- Returns:
- str: YAML string representation of the MSite
- """
- from python_magnetgeo.deserialize import unserialize_object
- import json
-
- magnets = []
- screens = []
- z_offset = []
- r_offset = []
- paralax = []
-
- # Populate from related sitemagnet objects
- for site_magnet in self.sitemagnet_set.all():
- # Get the magnet's geometry as JSON, then deserialize to object
- magnet_json = site_magnet.magnet.geometry_config_to_json
- print("magnet_json:", magnet_json)
- magnet_obj = unserialize_object(json.loads(magnet_json))
- magnets.append(magnet_obj)
- z_offset.append(site_magnet.z_offset)
- r_offset.append(site_magnet.r_offset)
- paralax.append(site_magnet.parallax)
+ def geometry_config_to_json(self):
+ return self.to_geometry_object().to_json()
- # Create MSite object and use its to_json() method
- obj = MSite(
- name=self.name,
- magnets=magnets,
- screens=screens,
- z_offset=z_offset,
- r_offset=r_offset,
- paralax=paralax,
- )
- return obj.to_yaml()
+ @property
+ def geometry_config_to_yaml(self):
+ return self.to_geometry_object().to_yaml()
diff --git a/python_magnetgeo b/python_magnetgeo
index 3252251..85de128 160000
--- a/python_magnetgeo
+++ b/python_magnetgeo
@@ -1 +1 @@
-Subproject commit 325225135e8071dafc0773ff0898281a998e91c8
+Subproject commit 85de12851589366f6e870af4071da019786e5261
diff --git a/python_magnetsetup b/python_magnetsetup
index 04a721e..da2cfbb 160000
--- a/python_magnetsetup
+++ b/python_magnetsetup
@@ -1 +1 @@
-Subproject commit 04a721e1fea340be49a38be620fe386206f78f00
+Subproject commit da2cfbb7c053020a656fbe13bd7664802ccd67c0
diff --git a/to_duckdb/.gitignore b/to_duckdb/.gitignore
new file mode 100644
index 0000000..dc04ae0
--- /dev/null
+++ b/to_duckdb/.gitignore
@@ -0,0 +1,8 @@
+*.png
+*.json
+*.duckdb
+
+deprecated/
+
+# direnv — contains credentials, never commit
+.envrc
diff --git a/to_duckdb/M25032101.json b/to_duckdb/M25032101.json
new file mode 100644
index 0000000..63fa174
--- /dev/null
+++ b/to_duckdb/M25032101.json
@@ -0,0 +1,656 @@
+{
+ "name": "M25032101",
+ "status": "in_operation",
+ "design_office_reference": "",
+ "description": "14 Helices, Phi = 34 mm",
+ "parts": [
+ {
+ "name": "H24110501",
+ "description": "H1",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-021-B",
+ "material": {
+ "name": "MA24032701",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 52900000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 490000000.0,
+ "nuance": "CuAg2,75"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H1.yaml"
+ },
+ {
+ "name": "H24101801",
+ "description": "H2",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-023-B",
+ "material": {
+ "name": "MA24032501",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 52500000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 500000000.0,
+ "nuance": "CuAg2,75"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H2.yaml"
+ },
+ {
+ "name": "H24073101",
+ "description": "H3",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-025-B",
+ "material": {
+ "name": "MA24020201",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53200000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 530000000.0,
+ "nuance": "CuAg5,5"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H3.yaml"
+ },
+ {
+ "name": "H24071901",
+ "description": "H4",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-027-B",
+ "material": {
+ "name": "MA24020501",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53300000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 530000000.0,
+ "nuance": "CuAg5,5"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H4.yaml"
+ },
+ {
+ "name": "H25011501",
+ "description": "H5",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-029-B",
+ "material": {
+ "name": "MA24020601",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53800000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 510000000.0,
+ "nuance": "CuAg5,5"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H5.yaml"
+ },
+ {
+ "name": "H25011502",
+ "description": "H6",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-031-B",
+ "material": {
+ "name": "MA24020701",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53400000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 510000000.0,
+ "nuance": "CuAg5,5"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H6.yaml"
+ },
+ {
+ "name": "H25010701",
+ "description": "H7",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-033-A",
+ "material": {
+ "name": "MA24021501",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53100000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 510000000.0,
+ "nuance": "CuAg5,5"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H7.yaml"
+ },
+ {
+ "name": "H25010702",
+ "description": "H8",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-035-A",
+ "material": {
+ "name": "MA24021401",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53300000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 510000000.0,
+ "nuance": "CuAg5,5"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H8.yaml"
+ },
+ {
+ "name": "H25010703",
+ "description": "H9",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-037-A",
+ "material": {
+ "name": "MA24021901",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53200000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 510000000.0,
+ "nuance": "CuAg5,5"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H9.yaml"
+ },
+ {
+ "name": "H25011503",
+ "description": "H10",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-039-A",
+ "material": {
+ "name": "MA24022101",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53200000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 500000000.0,
+ "nuance": "CuAg5,5"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H10.yaml"
+ },
+ {
+ "name": "H25010704",
+ "description": "H11",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-041-A",
+ "material": {
+ "name": "MA24022301",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 52600000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 500000000.0,
+ "nuance": "CuAg2,75"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H11.yaml"
+ },
+ {
+ "name": "H25022101",
+ "description": "H12",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-043-A",
+ "material": {
+ "name": "MA24040301",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53600000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 500000000.0,
+ "nuance": "CuAg2,75"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H12.yaml"
+ },
+ {
+ "name": "H24022201",
+ "description": "H13",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-045-A",
+ "material": {
+ "name": "MA23033001",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 53600000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 495000000.0,
+ "nuance": "CuAg2,75"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H13.yaml"
+ },
+ {
+ "name": "H23110801",
+ "description": "H14",
+ "status": "in_operation",
+ "type": "helix",
+ "design_office_reference": "HL-37-047-A",
+ "material": {
+ "name": "MA23032201",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 55000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 420000000.0,
+ "nuance": "CuAg2,75"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37_H14.yaml"
+ },
+ {
+ "name": "B26021101",
+ "description": "R1",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-049-A",
+ "material": {
+ "name": "MA26021001",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 40000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 678000000.0,
+ "nuance": "CuNiBe"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R1.yaml"
+ },
+ {
+ "name": "B26021102",
+ "description": "R2",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-050-A",
+ "material": {
+ "name": "MA26021001",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 40000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 678000000.0,
+ "nuance": "CuNiBe"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R2.yaml"
+ },
+ {
+ "name": "B26021103",
+ "description": "R3",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-051-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R3.yaml"
+ },
+ {
+ "name": "B26021104",
+ "description": "R4",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-052-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R4.yaml"
+ },
+ {
+ "name": "B26021105",
+ "description": "R5",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-053-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R5.yaml"
+ },
+ {
+ "name": "B26021106",
+ "description": "R6",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-054-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R6.yaml"
+ },
+ {
+ "name": "B26021107",
+ "description": "R7",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-055-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R7.yaml"
+ },
+ {
+ "name": "B26021108",
+ "description": "R8",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-056-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R8.yaml"
+ },
+ {
+ "name": "B26021109",
+ "description": "R9",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-057-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R9.yaml"
+ },
+ {
+ "name": "B26021110",
+ "description": "R10",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-058-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R10.yaml"
+ },
+ {
+ "name": "B26021111",
+ "description": "R11",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-059-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R11.yaml"
+ },
+ {
+ "name": "B26021112",
+ "description": "R12",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-060-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R12.yaml"
+ },
+ {
+ "name": "B26021113",
+ "description": "R13",
+ "status": "in_stock",
+ "type": "ring",
+ "design_office_reference": "HL-37-061-A",
+ "material": {
+ "name": "MA26021002",
+ "description": "",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47000000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 350000000.0,
+ "nuance": "CuCrZr"
+ },
+ "geometry": "/home/LNCMI-G/christophe.trophime/github/hifimagnet-projects/HL-37/HL-37-R13.yaml"
+ }
+ ]
+}
diff --git a/to_duckdb/MIGRATION_EXPERIMENTS_FILE_RELPATH.md b/to_duckdb/MIGRATION_EXPERIMENTS_FILE_RELPATH.md
new file mode 100644
index 0000000..2ca7bb9
--- /dev/null
+++ b/to_duckdb/MIGRATION_EXPERIMENTS_FILE_RELPATH.md
@@ -0,0 +1,84 @@
+# Migration — `experiments.file` relative path
+
+## Context
+
+`experiments.file` previously stored the **absolute path** to the pupitre TXT
+file (e.g. `/mnt/LNCMIG-Data/records/srv-data-install/M10/2025.04.30 - 13:06:03.txt`).
+
+This makes the database non-portable: if the mount point changes, every path in
+the table breaks.
+
+The new convention stores **only the filename**
+(e.g. `2025.04.30 - 13:06:03.txt`). The full path is reconstructed at
+runtime as:
+
+```
+records_base / srv_subdir / housing / filename
+```
+
+where `housing` is read from `sites.housing` for the experiment's site, and
+`records_base` / `srv_subdir` default to the constants in `populate.py`
+(`/mnt/LNCMIG-Data/records` and `srv-data-install`).
+
+---
+
+## What changed in the code
+
+| File | Change |
+|------|--------|
+| `magnetdb.py` | `populate experiments` now stores `fpath.name` instead of `str(fpath)` |
+| `compute_exp_stats.py` | Joins `sites` to get `housing`; reconstructs full path from `records_base / srv_subdir / housing / filename`; added `--records-base` / `--srv-subdir` CLI flags |
+| `compute_hoop_stats.py` | Reconstructs `exp_file` from `pupitre_datadir / housing / filename` when the stored value is not absolute |
+| `stress_map.py` | No change needed — `_expand_pupitre_pattern` already handles relative filenames |
+
+Both `compute_exp_stats.py` and `compute_hoop_stats.py` accept absolute paths
+unchanged (backward compatibility during and after migration).
+
+---
+
+## Migration script
+
+Run **once** against any database that was populated before this change.
+The UPDATE is idempotent: rows that already contain only a filename (no `/`)
+are not touched by the `WHERE` clause.
+
+```bash
+cd to_duckdb
+source venv-systempackages/bin/activate
+python3 migrate_experiments_file_relpath.py --db magnetdb.duckdb
+```
+
+Or as a one-liner:
+
+```bash
+python3 - <<'EOF'
+import duckdb, sys
+db = sys.argv[1] if len(sys.argv) > 1 else "magnetdb.duckdb"
+con = duckdb.connect(db)
+n = con.execute(
+ "UPDATE experiments "
+ "SET file = regexp_extract(file, '[^/]+$', 0) "
+ "WHERE file LIKE '/%'"
+).rowcount
+print(f"Migrated {n} row(s).")
+con.close()
+EOF
+```
+
+---
+
+## Verification
+
+```sql
+-- All values should now be bare filenames (no leading slash)
+SELECT COUNT(*) AS still_absolute
+FROM experiments
+WHERE file LIKE '/%';
+-- Expected: 0
+
+-- Spot-check a few rows
+SELECT id, site_name, file
+FROM experiments
+ORDER BY id
+LIMIT 5;
+```
diff --git a/to_duckdb/MIGRATION_HOUSING_FK.md b/to_duckdb/MIGRATION_HOUSING_FK.md
new file mode 100644
index 0000000..f85b79c
--- /dev/null
+++ b/to_duckdb/MIGRATION_HOUSING_FK.md
@@ -0,0 +1,209 @@
+# Migration plan — `housing_config` foreign key in `sites`
+
+## Context
+
+`housing` in every Python script and JSON file is the **name of a
+`housing_config` row** (e.g. `"M8"`, `"M9"`, `"M10"`). It is **not** a
+free-form label. The goal is to enforce this at the database level by making
+`sites.housing` a proper foreign key into `housing_config.name`.
+
+Because the database is a demonstrator that can be rebuilt from scratch, we
+can rewrite the schema instead of writing an ALTER TABLE migration.
+
+---
+
+## Step 1 — Reorder tables in `schema.py`
+
+`housing_config` must be declared **before** `sites` so DuckDB can resolve the
+foreign key at CREATE TABLE time.
+
+Move the `housing_config` block from the end of `SCHEMA_SQL` to just before
+the `sites` table. Then add `REFERENCES housing_config(name)` to the
+`housing` column of `sites`:
+
+```sql
+-- housing_config (new position, before sites)
+CREATE TABLE IF NOT EXISTS housing_config (
+ name VARCHAR PRIMARY KEY,
+ coil_assignment MAP(VARCHAR, VARCHAR),
+ formats VARCHAR[],
+ extra_config JSON
+);
+
+CREATE TABLE IF NOT EXISTS sites (
+ name VARCHAR PRIMARY KEY,
+ description VARCHAR,
+ status VARCHAR,
+ housing VARCHAR REFERENCES housing_config(name), -- FK added
+ commissioned_at TIMESTAMP,
+ decommissioned_at TIMESTAMP
+);
+```
+
+Remove the old `housing_config` block that was appended at the end of
+`SCHEMA_SQL`.
+
+---
+
+## Step 2 — Seed `housing_config` before `sites`
+
+Any code path that calls `ensure_schema` and then inserts sites must
+populate `housing_config` first.
+
+### 2a — `seeds_to_duckdb.py` (`_write_to_duckdb`)
+
+Add a call to `insert_housing_config` for each known housing **before**
+`insert_site` is called:
+
+```python
+from crud import insert_housing_config # add to existing imports
+from housing_defaults import HOUSING_SEED_DATA # see Step 3
+
+def _write_to_duckdb(output_path):
+ con = duckdb.connect(str(output_path))
+ ensure_schema(con)
+
+ # ① housing configs — must come before sites (FK constraint)
+ for row in HOUSING_SEED_DATA:
+ insert_housing_config(con, row, verbose=False)
+
+ for m in _materials.values(): ... # unchanged
+ for s in _sites.values():
+ insert_site(con, s, verbose=False) # FK now enforced
+ ...
+```
+
+### 2b — `add_site.py` / `magnetdb.py site add`
+
+Before inserting a site, check that its `housing` value exists in
+`housing_config`. If it does not, abort with a clear message:
+
+```
+Error: housing 'M10' not found in housing_config.
+Load it first with: python magnetdb.py housing add M10
+```
+
+---
+
+## Step 3 — `housing_defaults.py` (new file)
+
+Create a small helper module that holds the seed data for all known housings
+so it can be imported by both `seeds_to_duckdb.py` and the new CLI command.
+
+```python
+# housing_defaults.py
+from pathlib import Path
+import json
+
+_MAGNETRUN_PKG = Path(__file__).parent.parent / "python_magnetrun" / "python_magnetrun"
+
+def _load(name):
+ ref = json.loads((_MAGNETRUN_PKG / f"{name}-housing-config.json").read_text())
+ suffix_to_coil = {"H": "Insert", "B": "Bitter"}
+ s1 = ref["reference_gr1_current"][-1]
+ s2 = ref["reference_gr2_current"][-1]
+ ca = {suffix_to_coil[s1]: "GR1", suffix_to_coil[s2]: "GR2"}
+ extra_keys = [
+ "reference_gr1_hybrid", "reference_gr2_hybrid",
+ "hybrid_formula_map", "hybrid_voltage_mask_map",
+ ]
+ extra = {k: ref[k] for k in extra_keys if k in ref and ref[k]} or None
+ return {"name": name, "coil_assignment": ca, "formats": ref["formats"], "extra_config": extra}
+
+HOUSING_SEED_DATA = [_load(n) for n in ("M8", "M9", "M10")]
+```
+
+---
+
+## Step 4 — `crud.py` — guard in `insert_site`
+
+Add a FK pre-check to give a clear error rather than a raw DuckDB constraint
+violation:
+
+```python
+def insert_site(con, data: dict, verbose: bool = True) -> None:
+ housing = data.get("housing")
+ if housing:
+ row = con.execute(
+ "SELECT 1 FROM housing_config WHERE name = ?", [housing]
+ ).fetchone()
+ if row is None:
+ raise ValueError(
+ f"insert_site: housing '{housing}' not found in housing_config. "
+ f"Insert it first with insert_housing_config()."
+ )
+ # ... rest of existing insert unchanged
+```
+
+---
+
+## Step 5 — `magnetdb.py` — add `housing` subcommand
+
+Extend the unified CLI with a new `housing` entity so students can manage
+housing configs without touching Python:
+
+```
+python magnetdb.py housing list
+python magnetdb.py housing add M9
+python magnetdb.py housing view M9
+python magnetdb.py housing export M9 [--output-dir .]
+```
+
+`housing add ` loads the row from `HOUSING_SEED_DATA` (Step 3).
+`housing export ` calls `export_housing_config_json` (already in
+`crud.py`).
+
+---
+
+## Step 6 — `crud.py` — `view_housing_configs` helper
+
+Add a simple display helper consistent with `view_sites` / `view_magnets`:
+
+```python
+def view_housing_configs(con) -> None:
+ rows = con.execute(
+ "SELECT name, coil_assignment FROM housing_config ORDER BY name"
+ ).fetchall()
+ for name, ca in rows:
+ print(f" {name:<6} {dict(ca)}")
+```
+
+---
+
+## Step 7 — Update tests
+
+Update `test_housing_config_db.py`:
+
+- Verify the FK is enforced: inserting a site with an unknown housing must
+ raise an error.
+- Verify the happy path: after inserting a housing config, inserting a site
+ with that housing succeeds.
+
+```python
+def test_fk_enforced_on_site_insert(con):
+ with pytest.raises(Exception): # duckdb ConstraintException or ValueError
+ insert_site(con, {"name": "S1", "housing": "UNKNOWN"}, verbose=False)
+
+def test_site_insert_after_housing(con):
+ insert_housing_config(con, {"name": "M9", "coil_assignment": {"Insert": "GR1", "Bitter": "GR2"},
+ "formats": ["pupitre"], "extra_config": None}, verbose=False)
+ insert_site(con, {"name": "S1", "housing": "M9"}, verbose=False)
+ row = con.execute("SELECT housing FROM sites WHERE name = 'S1'").fetchone()
+ assert row[0] == "M9"
+```
+
+---
+
+## Execution order
+
+| # | File | Change |
+|---|------|--------|
+| 1 | `schema.py` | Move `housing_config` before `sites`; add `REFERENCES housing_config(name)` |
+| 2 | `housing_defaults.py` | Create new file with `HOUSING_SEED_DATA` |
+| 3 | `crud.py` | Guard in `insert_site`; add `view_housing_configs` |
+| 4 | `seeds_to_duckdb.py` | Seed `housing_config` rows before sites |
+| 5 | `magnetdb.py` | Add `housing` subcommand (`list`, `add`, `view`, `export`) |
+| 6 | `test_housing_config_db.py` | Add FK and happy-path tests |
+
+Steps 1–4 are required for correctness. Steps 5–6 improve usability and
+coverage.
diff --git a/to_duckdb/README.md b/to_duckdb/README.md
index 8c1a614..e768016 100644
--- a/to_duckdb/README.md
+++ b/to_duckdb/README.md
@@ -1,248 +1,220 @@
-# Student DuckDB Tooling
+# MagnetDB DuckDB Tooling
-Helper scripts for building and populating a standalone [DuckDB](https://duckdb.org/) database from MagnetDB data, intended for M1 student project work.
+Helper scripts for building and populating a standalone [DuckDB](https://duckdb.org/) database from MagnetDB data.
-No Django, PostgreSQL, MinIO, or any other MagnetDB service needs to be running. The result is a single portable `.duckdb` file that students can query directly from Python or Jupyter notebooks.
+No Django, PostgreSQL, MinIO, or any other MagnetDB service needs to be running. The result is a single portable `magnetdb.duckdb` file that can be queried directly from Python or Jupyter notebooks.
-These scripts are **teacher/admin tools** — they are not part of `python_magnetdb` and do not need to be shipped to students. Only the generated `.duckdb` file (and the TSV record files) are distributed.
+These scripts are **admin tools** — they are not part of `python_magnetdb`. Only the generated `.duckdb` file (and the TSV record files) need to be distributed to end users.
---
-## Location in the repository
+## Directory layout
```
-magnetdb/ ← repo root
-├── python_magnetdb/ ← Django application (not needed here)
-│ └── seeds/
-│ ├── seed-M19061901.py
-│ ├── seeds-Bitters.py
-│ └── ...
-└── to_duckdb/ ← this directory
- ├── README.md
- ├── seeds_to_duckdb.py
- ├── add_site.py
- └── student_queries.py
+to_duckdb/
+├── README.md ← this file
+├── schema.py ← canonical DDL (single source of truth)
+├── schema_diagram.py ← text summary + graphical ER diagram
+├── crud.py ← low-level CRUD helpers
+├── populate.py ← filesystem scanning for TDMS / pupitre files
+├── magnetdb.py ← unified CLI entry point (use this)
+├── compute_op_stats.py ← ingest per-file operational statistics
+├── compute_hoop_stats.py ← ingest per-file hoop-stress statistics
+├── query_cumstats.py ← query cumulative stats by site / magnet / part
+├── stress_map.py ← hoop-stress analysis library (geometry, plots)
+├── conftest.py ← pytest fixtures
+├── docs/
+│ ├── loading.md ← adding magnets, sites, materials
+│ ├── populate.md ← populate subcommands
+│ ├── statistics.md ← operational statistics (compute + query)
+│ ├── query_cumstats.md ← query_cumstats.py full CLI + API reference
+│ ├── hoop-stress.md ← hoop-stress compute and visualisation
+│ └── schema.md ← database schema reference + JSON formats
+├── tests/
+│ ├── test_schema.py
+│ ├── test_crud.py
+│ ├── test_add_magnet.py
+│ ├── test_add_site.py
+│ ├── test_magnetdb.py
+│ ├── test_material_db.py
+│ └── test_housing_config_db.py
+├── tutorials/ ← standalone demo scripts
+│ ├── README.md
+│ ├── queries.py ← ready-to-run DuckDB query examples
+│ ├── statheures_demo.py ← field-time histogram demo
+│ ├── stress_map.py ← shim → magnetdb.py hoop-stress
+│ ├── student_statheures_note.md
+│ └── README_student_stress_map.md
+├── marimo/
+│ ├── select_site.py ← interactive Marimo site browser
+│ └── select_site_note.md
+└── deprecated/ ← superseded standalone scripts
+ └── DEPRECATED.md
```
---
-## Files
-
-| File | Purpose |
-|------|---------|
-| `seeds_to_duckdb.py` | Build the DB from `python_magnetdb/seeds/` — creates materials, parts, and magnets |
-| `add_magnet.py` | Add a magnet (with its parts and materials) from a MagnetDB magnet JSON export |
-| `add_site.py` | Add a site (with magnet links and experiment records) from a MagnetDB JSON export |
-| `student_queries.py` | Example queries to explore the DB — can be used as a notebook starting point |
-
----
-
## Requirements
```bash
-pip install duckdb
+cd to_duckdb/
+python3 -m venv venv
+source venv/bin/activate # Windows: venv\Scripts\activate
+pip install -r requirements.txt
```
-No other dependencies. Both scripts use only the Python standard library plus `duckdb`.
-
---
-## Workflow
-
-### Step 1 — Build the structural data
+## Unified CLI — `magnetdb.py`
-Run `seeds_to_duckdb.py` from the `to_duckdb/` directory. It reads the seed files in `../python_magnetdb/seeds/` and populates the DB with materials, parts, and magnets.
-
-```bash
-cd to_duckdb/
-
-# Load all available seeds (repo root inferred as ../)
-python seeds_to_duckdb.py --repo ..
-
-# Load specific seeds only
-python seeds_to_duckdb.py --repo .. --seeds bitters,M19061901,M19071101
-
-# Custom output path
-python seeds_to_duckdb.py --repo .. --output /path/to/student.duckdb
+```
+python magnetdb.py [arguments] [--db PATH]
```
-Available seed keys:
-
-| Key | Seed file | Content |
-|-----|-----------|---------|
-| `bitters` | `seeds-Bitters.py` | M8, M9, M10 Bitter magnets |
-| `M19061901` | `seed-M19061901.py` | HL-31 insert, 14 helices + rings |
-| `M19071101` | `seed-M19071101.py` | H12-phi50 insert, 12 helices + rings |
-| `M18110501` | `seed-M18110501.py` | Earlier HL-31 configuration |
-| `M20022001` | `seed-M20022001.py` | Insert configuration |
-| `M22011801` | `seed-M22011801.py` | Insert configuration |
-| `records` | `seed-records.py` | Experiment records for M9/M10 sites |
-
-The output is printed to the terminal, including a summary table and the full `coil_index → part` mapping for each magnet.
+Default DB: `magnetdb.duckdb` in the current directory.
+
+### Quick reference
+
+| Command | Description | Detail |
+|---------|-------------|--------|
+| `list` | List all objects in the DB | — |
+| `db create` | Create DB and initialise schema | [loading.md](docs/loading.md) |
+| `db delete [--yes]` | Delete DB file | [loading.md](docs/loading.md) |
+| `material add/view/delete` | Manage materials | [loading.md](docs/loading.md) |
+| `magnet add/view/delete` | Manage magnets | [loading.md](docs/loading.md) |
+| `site add/view/delete` | Manage sites + experiment records | [loading.md](docs/loading.md) |
+| `site update-magnet` | Patch positional/temporal SiteMagnet fields | [loading.md](docs/loading.md) |
+| `housing view` | List housing configs | [loading.md](docs/loading.md#housing-configs) |
+| `experiments view` | List experiment records | [populate.md](docs/populate.md#experiments-view) |
+| `operationaldata view` | List operationaldata records | [populate.md](docs/populate.md#operationaldata-view) |
+| `overview-records view` | List overview_records | [populate.md](docs/populate.md#overview-records-view) |
+| `populate operationaldata` | Register TDMS/pupitre files from filesystem | [populate.md](docs/populate.md) |
+| `populate experiments` | Discover additional pupitre TXT files | [populate.md](docs/populate.md) |
+| `populate overview-records` | Process Overview TDMS via python_magnetrun | [populate.md](docs/populate.md) |
+| `populate overview-records-from-json` | Load overview_records from a summary JSON | [populate.md](docs/populate.md) |
+| `hoop-stress compute` | Compute and persist hoop-stress bin stats + fatigue | [hoop-stress.md](docs/hoop-stress.md) |
+| `hoop-stress barchart` | Bar chart: stress at given currents vs Rpe | [hoop-stress.md](docs/hoop-stress.md) |
+| `hoop-stress history` | Normalised stress vs time from pupitre file | [hoop-stress.md](docs/hoop-stress.md) |
+| `hoop-stress stats` | Descriptive statistics of stress time series | [hoop-stress.md](docs/hoop-stress.md) |
+| `hoop-stress fatigue` | Rainflow cycle counting | [hoop-stress.md](docs/hoop-stress.md) |
-### Step 1b — Add a magnet from a JSON export (alternative to seeds)
+---
-When a magnet is not covered by a seed file, use `add_magnet.py` with a MagnetDB magnet JSON export. The JSON embeds all part and material definitions, so no prior data in the DB is needed.
+## Typical full setup
```bash
cd to_duckdb/
-
-# Preview without writing
-python add_magnet.py /path/to/M25032101.json --dry-run
-
-# Write to the default DB (student_magnetdb.duckdb in current directory)
-python add_magnet.py /path/to/M25032101.json
-
-# Write to a specific DB
-python add_magnet.py /path/to/M25032101.json --db /path/to/student.duckdb
+DB=magnetdb.duckdb
+JSON=/home/myuser/hifimagnet-projects/magnetdb.json
+RECORDS=/mnt/LNCMIG-Data/records
```
-The magnet type (`insert`, `bitters`, `hybrid`) is inferred automatically from the part types. The operation is **idempotent**: running it twice with the same JSON is safe — existing materials, parts, and magnets are skipped.
-
-Appending to an existing DB works the same way — just point `--db` at it:
+> [!NOTE]
+> The default variables `$DB`, `$JSON`, and `$RECORDS` need to be adjusted to point to your local JSON and record directories.
```bash
-python add_magnet.py /path/to/M25032101.json --db student.duckdb
-```
-
----
-
-### Step 2 — Add sites
-
-Sites reference magnets by name, so Step 1 (or Step 1b) must be completed first. Use a MagnetDB site JSON export (as produced by `python_magnetapi`) to add a site with its magnet links and experiment records.
+# 0. Create the database
+python magnetdb.py db create --db $DB
-```bash
-cd to_duckdb/
+# 1. Load sites (magnets auto-resolved from the same JSON directory)
+for f in $JSON/M9_A19061901_*.json $JSON/M10_A19071101_*.json; do
+ python magnetdb.py site add "$f" --db $DB
+done
-# Preview without writing
-python add_site.py /path/to/M10_M19071101_13.json --dry-run
+# 2. Verify
+python magnetdb.py list --db $DB
-# Write to the default DB (student_magnetdb.duckdb in current directory)
-python add_site.py /path/to/M10_M19071101_13.json
+# 3. Populate operationaldata from the filesystem
+python magnetdb.py populate operationaldata --all --db $DB \
+ --records-base $RECORDS --type Archive Overview Pupitre
-# Write to a specific DB
-python add_site.py /path/to/M10_M19071101_13.json --db /path/to/student.duckdb
+# 4. Ingest per-file operational statistics (idempotent)
+python -c "
+import duckdb
+con = duckdb.connect('$DB', read_only=True)
+for (s,) in con.execute('SELECT name FROM sites ORDER BY name').fetchall():
+ print(s)
+" | while read SITE; do
+ python compute_op_stats.py --db $DB \
+ --records $RECORDS/srv-data-install \
+ --site "$SITE" --type Pupitre
+done
+
+# 5. Ingest hoop-stress statistics (idempotent)
+python magnetdb.py hoop-stress compute --all --db $DB
+
+# 6. Query
+python tutorials/queries.py
+python tutorials/query_cumstats.py --db $DB --site M9_A19061901_00 scalars
+python tutorials/query_cumstats.py --db $DB --site M9_A19061901_00 site-bins \
+ --channels Ptot,tsb --plot
+python magnetdb.py hoop-stress barchart M9_A19061901_00 --db $DB
+python magnetdb.py hoop-stress fatigue M9_A19061901_00 --db $DB
+
+# 7. Distribute magnetdb.duckdb + raw record files
```
-The script validates that all magnets referenced in the JSON already exist in the DB and fails with a clear message if any are missing.
-
-The operation is **idempotent**: running it twice with the same JSON is safe — existing sites, magnet links, and experiment records are skipped.
-
---
-## Database schema
-
-```
-materials physical properties of conductor alloys (rpe in Pa)
-parts individual physical components (helix, ring, bitter, lead)
-magnets magnet assemblies (insert, bitters, hybrid, …)
-magnet_parts ordered parts within a magnet, with coil_index
-sites operational configurations (housing, commissioning dates)
-site_magnets which magnets are active in a site (many-to-many)
-experiments operational records (TSV files) attached to a site
-```
+## Detailed documentation
-### coil_index
+| Topic | File |
+|-------|------|
+| Adding magnets, sites, materials | [docs/loading.md](docs/loading.md) |
+| Populating TDMS / pupitre / overview tables | [docs/populate.md](docs/populate.md) |
+| Operational statistics (compute + query) | [docs/statistics.md](docs/statistics.md) |
+| Cumulative query CLI + Python API | [docs/query_cumstats.md](docs/query_cumstats.md) |
+| Hoop-stress analysis | [docs/hoop-stress.md](docs/hoop-stress.md) |
+| Database schema + JSON formats | [docs/schema.md](docs/schema.md) |
+| MySQL bridge (live / export / view / poll + plots) | [docs/mysql_connect.md](docs/mysql_connect.md) |
+| Deprecated scripts migration guide | [deprecated/DEPRECATED.md](deprecated/DEPRECATED.md) |
+| Tutorials | [tutorials/README.md](tutorials/README.md) |
-The `magnet_parts.coil_index` column maps each helix or bitter part to its `Icoil_N` column in the operational TSV records:
+---
-- Assigned 1-based, in the order parts appear in the magnet definition
-- Only `helix` and `bitter` parts receive a coil_index
-- `ring` and `lead` parts get `NULL`
+## Viewing the database structure
-Example query to retrieve the mapping:
+`schema_diagram.py` introspects a live `.duckdb` file (or falls back to
+`schema.py` if no file is found) and produces either a plain-text schema
+summary or a graphical ER diagram (PNG / SVG / PDF).
-```python
-import duckdb
-con = duckdb.connect("student_magnetdb.duckdb", read_only=True)
-
-con.execute("""
- SELECT 'Icoil' || mp.coil_index AS column,
- p.name AS part,
- p.type,
- mat.nuance,
- mat.rpe / 1e6 AS rpe_MPa
- FROM magnet_parts mp
- JOIN parts p ON p.name = mp.part_name
- JOIN magnets m ON m.name = mp.magnet_name
- LEFT JOIN materials mat ON mat.name = p.material_name
- WHERE m.name = 'M19061901'
- AND mp.coil_index IS NOT NULL
- ORDER BY mp.coil_index
-""").df()
-```
+```bash
+# Text summary — all 21 tables with columns, types, and PK/FK markers
+python schema_diagram.py --text
----
+# Graphical ER diagram saved to schema_diagram.png (default)
+python schema_diagram.py
-## Site JSON format
-
-The JSON expected by `add_site.py` matches the format produced by `python_magnetapi`. The minimal required fields are:
-
-```json
-{
- "name": "M10_M19071101_13",
- "status": "in_operation",
- "housing": "M10",
- "commissioned_at": "2025-11-12 00:00:00",
- "decommissioned_at": "None",
- "magnets": [
- "M19071101",
- "M10Bitters"
- ],
- "records": [
- {
- "name": "M10_2025.11.13---09:14:21.txt",
- "description": "",
- "file": "M10_2025.11.13---09:14:21.txt"
- }
- ]
-}
+# Custom DB file and output path
+python schema_diagram.py --db /path/to/magnetdb.duckdb --output er.svg
```
-Notes:
-- `magnets` contains magnet **names only** — no part or material definitions. The magnets must already be in the DB.
-- `decommissioned_at` can be `"None"` or omitted for active sites.
-- `records` can be an empty list `[]` if no experiment files are available yet.
+The diagram colour-codes tables by role:
+
+| Colour | Group |
+|--------|-------|
+| Green | Reference tables (`materials`, `housing_config`) |
+| Blue | Assembly tables (`parts`, `magnets`, `sites`, junction tables) |
+| Yellow | Data tables (`experiments`, `operationaldata`, `overview_records`) |
+| Red | Statistics tables (`*_processed`, `*_scalars`, `*_bin_stats`, `*_fatigue`) |
---
## Example queries
-`student_queries.py` contains ready-to-run examples covering:
+`tutorials/queries.py` contains ready-to-run examples covering:
1. Full site hierarchy (site → magnet → parts → materials)
2. `Icoil_N → part` mapping for a specific magnet
3. Experiment records for a site
4. Material comparison across all helices
5. Coil channel count per magnet
-6. Parts shared across multiple magnets (reused helices/rings)
-
-Run it directly or copy cells into a Jupyter notebook:
+6. Parts shared across multiple magnets
+7. All sites in which a magnet has been used
+8. Sites and magnets in which a given part has been used
```bash
-python student_queries.py
+python tutorials/queries.py
```
----
-
-## Typical full setup
-
-```bash
-cd to_duckdb/
-
-# 1a. Build structural data from seeds (when seed files are available)
-python seeds_to_duckdb.py --repo .. --seeds bitters,M19061901,M19071101
-
-# 1b. Or load a magnet directly from a MagnetDB JSON export (no seeds needed)
-python add_magnet.py /path/to/M25032101.json
-python add_magnet.py /path/to/M25032101.json --dry-run # preview first
-
-# 2. Add one or more operational sites from their JSON exports
-python add_site.py /path/to/M10_M19071101_13.json
-python add_site.py /path/to/M9_M19061901_xx.json # repeat for each site
-
-# 3. Verify the result
-python student_queries.py
-
-# 4. Ship student_magnetdb.duckdb + TSV record files to students
-```
+When copying cells into Jupyter, paste the connection block (`DB_PATH` + `con = …`) first. `DB_PATH` falls back to `"magnetdb.duckdb"` (cwd-relative) when `__file__` is not defined in a notebook context.
diff --git a/to_duckdb/add_magnet.py b/to_duckdb/add_magnet.py
deleted file mode 100644
index a4caac9..0000000
--- a/to_duckdb/add_magnet.py
+++ /dev/null
@@ -1,426 +0,0 @@
-"""
-add_magnet.py
-=============
-Add a magnet (with its parts and materials) to an existing student DuckDB
-database from a MagnetDB magnet JSON export.
-
-Unlike add_site.py, the JSON here is a *magnet* export: it contains the full
-definition of every part, including embedded material objects. No prior data
-in the DB is required — materials and parts are created on the fly.
-
-JSON format (as exported from MagnetDB)
-----------------------------------------
-{
- "name": "M25032101",
- "status": "in_operation",
- "design_office_reference": "",
- "description": "14 Helices, Phi = 34 mm",
- "parts": [
- {
- "name": "H24110501",
- "description": "H1",
- "status": "in_operation",
- "type": "helix",
- "design_office_reference": "HL-37-021-B",
- "geometry": "/path/to/HL-37_H1.yaml",
- "material": {
- "name": "MA24032701",
- "description": "",
- "t_ref": 293,
- "volumic_mass": 9000.0,
- "specific_heat": 385,
- "alpha": 0.0036,
- "electrical_conductivity": 52900000.0,
- "thermal_conductivity": 380,
- "magnet_permeability": 1,
- "young": 117000000000.0,
- "poisson": 0.33,
- "expansion_coefficient": 1.8e-05,
- "rpe": 490000000.0,
- "nuance": "CuAg2,75"
- }
- },
- ...
- ]
-}
-
-Usage
------
- python add_magnet.py M25032101.json
- python add_magnet.py M25032101.json --db path/to/student.duckdb
- python add_magnet.py M25032101.json --dry-run
-"""
-
-import argparse
-import json
-import sys
-from pathlib import Path
-
-import duckdb
-
-# ---------------------------------------------------------------------------
-# Schema DDL (same tables as add_site.py — idempotent on existing DBs)
-# ---------------------------------------------------------------------------
-
-SCHEMA_SQL = """
-CREATE TABLE IF NOT EXISTS materials (
- name VARCHAR PRIMARY KEY,
- description VARCHAR,
- nuance VARCHAR,
- t_ref DOUBLE,
- volumic_mass DOUBLE,
- specific_heat DOUBLE,
- alpha DOUBLE,
- electrical_conductivity DOUBLE,
- thermal_conductivity DOUBLE,
- magnet_permeability DOUBLE,
- young DOUBLE,
- poisson DOUBLE,
- expansion_coefficient DOUBLE,
- rpe DOUBLE
-);
-
-CREATE TABLE IF NOT EXISTS parts (
- name VARCHAR PRIMARY KEY,
- type VARCHAR,
- status VARCHAR,
- material_name VARCHAR REFERENCES materials(name),
- geometry VARCHAR,
- geometry_data JSON,
- cad VARCHAR,
- design_office_reference VARCHAR
-);
-
-CREATE TABLE IF NOT EXISTS magnets (
- name VARCHAR PRIMARY KEY,
- type VARCHAR,
- status VARCHAR,
- geometry VARCHAR,
- geometry_data JSON,
- design_office_reference VARCHAR
-);
-
--- Migration: add geometry_data to existing databases (no-op if already present)
-ALTER TABLE parts ADD COLUMN IF NOT EXISTS geometry_data JSON;
-ALTER TABLE magnets ADD COLUMN IF NOT EXISTS geometry_data JSON;
-
-CREATE TABLE IF NOT EXISTS magnet_parts (
- magnet_name VARCHAR REFERENCES magnets(name),
- part_name VARCHAR REFERENCES parts(name),
- rank INTEGER,
- coil_index INTEGER,
- PRIMARY KEY (magnet_name, part_name)
-);
-
-CREATE TABLE IF NOT EXISTS sites (
- name VARCHAR PRIMARY KEY,
- description VARCHAR,
- status VARCHAR,
- housing VARCHAR,
- commissioned_at TIMESTAMP,
- decommissioned_at TIMESTAMP
-);
-
-CREATE TABLE IF NOT EXISTS site_magnets (
- site_name VARCHAR REFERENCES sites(name),
- magnet_name VARCHAR REFERENCES magnets(name),
- PRIMARY KEY (site_name, magnet_name)
-);
-
-CREATE TABLE IF NOT EXISTS experiments (
- id INTEGER PRIMARY KEY,
- name VARCHAR,
- description VARCHAR,
- file VARCHAR,
- site_name VARCHAR REFERENCES sites(name),
- status VARCHAR DEFAULT 'pending'
-);
-"""
-
-# Part types that receive a coil_index (i.e. map to an Icoil_N column)
-COIL_TYPES = {"helix", "bitter"}
-
-
-# ---------------------------------------------------------------------------
-# Helpers
-# ---------------------------------------------------------------------------
-
-
-def _load_geometry_json(geometry_path) -> str | None:
- """
- Load a geometry YAML file via python_magnetgeo and return a JSON string
- (with ``__classname__`` annotations) suitable for storing in DuckDB.
- Returns None if the file is absent or python_magnetgeo is not available.
- """
- if not geometry_path:
- return None
- path = Path(geometry_path)
- if not path.exists():
- return None
- try:
- import json as _json
- import yaml as _yaml
- from python_magnetgeo.deserialize import serialize_instance
- with open(path) as f:
- obj = _yaml.load(f, Loader=_yaml.FullLoader)
- return _json.dumps(obj, default=serialize_instance)
- except Exception as exc:
- print(f" [WARN] Could not serialize geometry '{geometry_path}': {exc}")
- return None
-
-
-def _exists(con, table, name):
- return con.execute(f"SELECT 1 FROM {table} WHERE name = ?", [name]).fetchone() is not None
-
-
-def _infer_magnet_type(parts):
- """Infer magnet assembly type from the types of its constituent parts."""
- coil_types = {p["type"] for p in parts if p["type"] in COIL_TYPES}
- if coil_types == {"helix"}:
- return "insert"
- if coil_types == {"bitter"}:
- return "bitters"
- if len(coil_types) > 1:
- return "hybrid"
- return "unknown"
-
-
-# ---------------------------------------------------------------------------
-# Validation
-# ---------------------------------------------------------------------------
-
-
-def _validate(data):
- errors = []
- if not data.get("name"):
- errors.append("Missing top-level 'name'")
- if not data.get("parts"):
- errors.append("'parts' list is empty or missing")
- for i, part in enumerate(data.get("parts", [])):
- if not part.get("name"):
- errors.append(f"Part[{i}] is missing 'name'")
- if not part.get("type"):
- errors.append(f"Part '{part.get('name', i)}' is missing 'type'")
- if not part.get("material") or not part["material"].get("name"):
- errors.append(f"Part '{part.get('name', i)}' is missing 'material.name'")
- return errors
-
-
-# ---------------------------------------------------------------------------
-# Insertion
-# ---------------------------------------------------------------------------
-
-
-def _insert_material(con, mat):
- name = mat["name"]
- if _exists(con, "materials", name):
- print(f" ~ material {name} (already exists, skipped)")
- return
- con.execute(
- "INSERT INTO materials VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
- [
- name,
- mat.get("description") or None,
- mat.get("nuance") or None,
- mat.get("t_ref"),
- mat.get("volumic_mass"),
- mat.get("specific_heat"),
- mat.get("alpha"),
- mat.get("electrical_conductivity"),
- mat.get("thermal_conductivity"),
- mat.get("magnet_permeability"),
- mat.get("young"),
- mat.get("poisson"),
- mat.get("expansion_coefficient"),
- mat.get("rpe"),
- ],
- )
- print(f" + material {name} [{mat.get('nuance', '?')}]")
-
-
-def _insert_part(con, part):
- name = part["name"]
- if _exists(con, "parts", name):
- print(f" ~ part {name} (already exists, skipped)")
- return
- con.execute(
- """
- INSERT INTO parts
- (name, type, status, material_name, geometry, geometry_data, cad, design_office_reference)
- VALUES (?,?,?,?,?,?,?,?)
- """,
- [
- name,
- part.get("type"),
- part.get("status"),
- part["material"]["name"],
- part.get("geometry") or None,
- _load_geometry_json(part.get("geometry")),
- part.get("cad") or None,
- part.get("design_office_reference") or None,
- ],
- )
- print(f" + part {name} [{part.get('type', '?')}]")
-
-
-def _insert_magnet(con, data, magnet_type):
- name = data["name"]
- if _exists(con, "magnets", name):
- print(f" ~ magnet {name} (already exists, skipped)")
- return
- con.execute(
- """
- INSERT INTO magnets
- (name, type, status, geometry, geometry_data, design_office_reference)
- VALUES (?,?,?,?,?,?)
- """,
- [
- name,
- magnet_type,
- data.get("status"),
- data.get("geometry") or None,
- _load_geometry_json(data.get("geometry")),
- data.get("design_office_reference") or None,
- ],
- )
- print(f" + magnet {name} [{magnet_type}] {data.get('status', '')}")
-
-
-def _insert_magnet_parts(con, magnet_name, parts):
- coil_counter = 0
- inserted = 0
- skipped = 0
- for rank, part in enumerate(parts):
- part_name = part["name"]
- part_type = part.get("type", "")
-
- coil_index = None
- if part_type in COIL_TYPES:
- coil_counter += 1
- coil_index = coil_counter
-
- existing = con.execute(
- "SELECT 1 FROM magnet_parts WHERE magnet_name = ? AND part_name = ?",
- [magnet_name, part_name],
- ).fetchone()
- if existing:
- skipped += 1
- continue
-
- con.execute(
- "INSERT INTO magnet_parts VALUES (?,?,?,?)",
- [magnet_name, part_name, rank, coil_index],
- )
- inserted += 1
-
- print(
- f" + magnet_parts {inserted} inserted, {skipped} already present"
- f" ({coil_counter} coil channel(s))"
- )
-
-
-# ---------------------------------------------------------------------------
-# Public entry point
-# ---------------------------------------------------------------------------
-
-
-def add_magnet(data, db_path, dry_run=False):
- """
- Insert a magnet (and its parts and materials) into the student DuckDB.
-
- Parameters
- ----------
- data : dict matching the MagnetDB magnet JSON export format
- db_path : path to the .duckdb file (created if it does not exist)
- dry_run : if True, validate only — do not write
- """
- db_path = Path(db_path)
-
- errors = _validate(data)
- if errors:
- print("Validation errors:")
- for e in errors:
- print(f" • {e}")
- sys.exit(1)
-
- parts = data["parts"]
- magnet_type = _infer_magnet_type(parts)
-
- if dry_run:
- coil_parts = [p for p in parts if p.get("type") in COIL_TYPES]
- print("[dry-run] Validation passed. Would insert:")
- print(f" magnet : {data['name']} [{magnet_type}] {data.get('status', '')}")
- print(f" parts : {len(parts)} ({len(coil_parts)} coil channel(s))")
- mats = {p["material"]["name"] for p in parts if p.get("material")}
- print(f" materials: {len(mats)}")
- return
-
- con = duckdb.connect(str(db_path))
- con.execute(SCHEMA_SQL)
-
- print(f"\nAdding magnet '{data['name']}' to {db_path.name} …\n")
-
- # 1. Materials (deduplicated — multiple parts may share one)
- seen_materials = set()
- for part in parts:
- mat = part.get("material", {})
- mat_name = mat.get("name")
- if mat_name and mat_name not in seen_materials:
- _insert_material(con, mat)
- seen_materials.add(mat_name)
-
- print()
-
- # 2. Parts
- for part in parts:
- _insert_part(con, part)
-
- print()
-
- # 3. Magnet
- _insert_magnet(con, data, magnet_type)
-
- print()
-
- # 4. Magnet–part links with coil_index
- _insert_magnet_parts(con, data["name"], parts)
-
- con.close()
- print("\nDone.")
-
-
-# ---------------------------------------------------------------------------
-# CLI
-# ---------------------------------------------------------------------------
-
-
-def main():
- parser = argparse.ArgumentParser(
- description="Add a magnet to the student DuckDB from a MagnetDB JSON export.",
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog=__doc__,
- )
- parser.add_argument("json_file", help="Path to the magnet JSON file")
- parser.add_argument(
- "--db",
- default="student_magnetdb.duckdb",
- help="Target DuckDB file (default: student_magnetdb.duckdb; created if absent)",
- )
- parser.add_argument(
- "--dry-run",
- action="store_true",
- help="Validate and preview without writing to the DB",
- )
- args = parser.parse_args()
-
- json_path = Path(args.json_file)
- if not json_path.exists():
- print(f"Error: '{json_path}' not found.")
- sys.exit(1)
-
- data = json.loads(json_path.read_text())
- add_magnet(data, args.db, dry_run=args.dry_run)
-
-
-if __name__ == "__main__":
- main()
diff --git a/to_duckdb/add_site.py b/to_duckdb/add_site.py
deleted file mode 100644
index 9cbb6f5..0000000
--- a/to_duckdb/add_site.py
+++ /dev/null
@@ -1,387 +0,0 @@
-"""
-add_site.py
-===========
-Add a site to an existing student DuckDB database from a JSON file
-matching the MagnetDB site export format.
-
-Magnets referenced in the JSON that are not yet in the database are loaded
-automatically from a same-named JSON file (e.g. M19071101.json) found in the
-same directory as the site JSON (or the directory given by --magnet-dir).
-If no such file is found the script fails with a clear message.
-
-JSON format (as exported from MagnetDB)
-----------------------------------------
-{
- "name": "M10_M19071101_13",
- "description": "",
- "status": "in_operation",
- "housing": "M10",
- "commissioned_at": "2025-11-12 00:00:00",
- "decommissioned_at": "None",
- "magnets": [
- "M19071101",
- "M10Bitters"
- ],
- "records": [
- {
- "name": "M10_2025.11.13---09:14:21.txt",
- "description": "",
- "file": "M10_2025.11.13---09:14:21.txt"
- },
- ...
- ]
-}
-
-Usage
------
- python add_site.py M10_M19071101_13.json
- python add_site.py M10_M19071101_13.json --db path/to/student.duckdb
- python add_site.py M10_M19071101_13.json --dry-run
- python add_site.py M10_M19071101_13.json --magnet-dir /path/to/magnet/jsons
-"""
-
-import argparse
-import json
-import sys
-from pathlib import Path
-
-import duckdb
-
-from add_magnet import add_magnet
-
-# ---------------------------------------------------------------------------
-# Schema DDL
-# ---------------------------------------------------------------------------
-
-SCHEMA_SQL = """
-CREATE TABLE IF NOT EXISTS materials (
- name VARCHAR PRIMARY KEY,
- description VARCHAR,
- nuance VARCHAR,
- t_ref DOUBLE,
- volumic_mass DOUBLE,
- specific_heat DOUBLE,
- alpha DOUBLE,
- electrical_conductivity DOUBLE,
- thermal_conductivity DOUBLE,
- magnet_permeability DOUBLE,
- young DOUBLE,
- poisson DOUBLE,
- expansion_coefficient DOUBLE,
- rpe DOUBLE
-);
-
-CREATE TABLE IF NOT EXISTS parts (
- name VARCHAR PRIMARY KEY,
- type VARCHAR,
- status VARCHAR,
- material_name VARCHAR REFERENCES materials(name),
- geometry VARCHAR,
- geometry_data JSON,
- cad VARCHAR,
- design_office_reference VARCHAR
-);
-
-CREATE TABLE IF NOT EXISTS magnets (
- name VARCHAR PRIMARY KEY,
- type VARCHAR,
- status VARCHAR,
- geometry VARCHAR,
- geometry_data JSON,
- design_office_reference VARCHAR
-);
-
--- Migration: add geometry_data to existing databases (no-op if already present)
-ALTER TABLE parts ADD COLUMN IF NOT EXISTS geometry_data JSON;
-ALTER TABLE magnets ADD COLUMN IF NOT EXISTS geometry_data JSON;
-
-CREATE TABLE IF NOT EXISTS magnet_parts (
- magnet_name VARCHAR REFERENCES magnets(name),
- part_name VARCHAR REFERENCES parts(name),
- rank INTEGER,
- coil_index INTEGER,
- PRIMARY KEY (magnet_name, part_name)
-);
-
-CREATE TABLE IF NOT EXISTS sites (
- name VARCHAR PRIMARY KEY,
- description VARCHAR,
- status VARCHAR,
- housing VARCHAR,
- commissioned_at TIMESTAMP,
- decommissioned_at TIMESTAMP
-);
-
-CREATE TABLE IF NOT EXISTS site_magnets (
- site_name VARCHAR REFERENCES sites(name),
- magnet_name VARCHAR REFERENCES magnets(name),
- PRIMARY KEY (site_name, magnet_name)
-);
-
-CREATE TABLE IF NOT EXISTS experiments (
- id INTEGER PRIMARY KEY,
- name VARCHAR,
- description VARCHAR,
- file VARCHAR,
- site_name VARCHAR REFERENCES sites(name),
- status VARCHAR DEFAULT 'pending'
-);
-"""
-
-# ---------------------------------------------------------------------------
-# Helpers
-# ---------------------------------------------------------------------------
-
-
-def _parse_timestamp(value):
- if not value or str(value).lower() in ("none", "null", ""):
- return None
- return str(value)
-
-
-def _exists(con, table, name):
- return con.execute(f"SELECT 1 FROM {table} WHERE name = ?", [name]).fetchone() is not None
-
-
-def _next_experiment_id(con):
- row = con.execute("SELECT COALESCE(MAX(id), 0) FROM experiments").fetchone()
- return (row[0] or 0) + 1
-
-
-# ---------------------------------------------------------------------------
-# Auto-load missing magnets
-# ---------------------------------------------------------------------------
-
-
-def _ensure_magnets(magnet_names, db_path, magnet_dir, dry_run=False):
- """
- For every magnet in *magnet_names* that is absent from the DB, try to
- load it from ``/.json`` using add_magnet.
- Returns a list of error strings for magnets that cannot be resolved.
- Each call to add_magnet opens and closes its own connection, so we
- check existence with a short-lived connection per iteration.
- """
- errors = []
- for name in magnet_names:
- # Check with a fresh read-only connection to avoid lock conflicts
- with duckdb.connect(str(db_path)) as chk:
- found = (
- chk.execute("SELECT 1 FROM magnets WHERE name = ?", [name]).fetchone() is not None
- )
- if found:
- continue
- json_path = Path(magnet_dir) / f"{name}.json"
- if not json_path.exists():
- errors.append(
- f"Magnet '{name}' not in DB and '{json_path}' not found. "
- f"Load it manually with: python add_magnet.py {name}.json"
- )
- continue
- print(f" ~ magnet '{name}' not in DB — loading from {json_path.name} …")
- magnet_data = json.loads(json_path.read_text())
- add_magnet(magnet_data, db_path, dry_run=dry_run)
- return errors
-
-
-# ---------------------------------------------------------------------------
-# Validation
-# ---------------------------------------------------------------------------
-
-
-def _validate(data):
- errors = []
-
- if not data.get("name"):
- errors.append("Missing 'name'")
- if not data.get("magnets"):
- errors.append("'magnets' list is empty or missing")
-
- return errors
-
-
-# ---------------------------------------------------------------------------
-# Insertion
-# ---------------------------------------------------------------------------
-
-
-def _insert_site(con, data):
- name = data["name"]
- if _exists(con, "sites", name):
- print(f" ~ site {name} (already exists, skipped)")
- return
-
- con.execute(
- "INSERT INTO sites VALUES (?,?,?,?,?,?)",
- [
- name,
- data.get("description") or None,
- data.get("status", "in_study"),
- data.get("housing") or None,
- _parse_timestamp(data.get("commissioned_at")),
- _parse_timestamp(data.get("decommissioned_at")),
- ],
- )
- print(f" + site {name} [{data.get('housing', '?')}] {data.get('status', '')}")
-
-
-def _insert_site_magnets(con, site_name, magnet_names):
- for magnet_name in magnet_names:
- existing = con.execute(
- "SELECT 1 FROM site_magnets WHERE site_name = ? AND magnet_name = ?",
- [site_name, magnet_name],
- ).fetchone()
- if existing:
- print(f" ~ magnet {magnet_name} (already linked, skipped)")
- continue
-
- con.execute("INSERT INTO site_magnets VALUES (?,?)", [site_name, magnet_name])
- row = con.execute("SELECT type FROM magnets WHERE name = ?", [magnet_name]).fetchone()
- mag_type = row[0] if row else "?"
- print(f" + magnet {magnet_name} ({mag_type})")
-
-
-def _insert_experiments(con, site_name, records):
- next_id = _next_experiment_id(con)
- inserted = 0
- skipped = 0
-
- for i, rec in enumerate(records):
- file_name = rec.get("file") or rec.get("name")
- existing = con.execute(
- "SELECT 1 FROM experiments WHERE site_name = ? AND file = ?",
- [site_name, file_name],
- ).fetchone()
- if existing:
- skipped += 1
- continue
-
- con.execute(
- "INSERT INTO experiments VALUES (?,?,?,?,?,'pending')",
- [
- next_id + i,
- rec.get("name") or file_name,
- rec.get("description") or None,
- file_name,
- site_name,
- ],
- )
- inserted += 1
-
- print(f" + records {inserted} inserted, {skipped} already present")
-
-
-# ---------------------------------------------------------------------------
-# Public entry point
-# ---------------------------------------------------------------------------
-
-
-def add_site(data, db_path, dry_run=False, magnet_dir=None):
- """
- Insert a site and its records into the student DuckDB.
-
- Parameters
- ----------
- data : dict matching the MagnetDB site JSON export format
- db_path : path to the .duckdb file
- dry_run : if True, validate only — do not write
- magnet_dir : directory to search for .json files when a
- magnet is missing from the DB (default: current directory)
- """
- db_path = Path(db_path)
- if magnet_dir is None:
- magnet_dir = Path(".")
- else:
- magnet_dir = Path(magnet_dir)
-
- if not db_path.exists():
- print(f"Error: '{db_path}' does not exist.")
- print("Create it first with: python seeds_to_duckdb.py or python add_magnet.py")
- sys.exit(1)
-
- con = duckdb.connect(str(db_path))
- # Ensure schema is current (idempotent — safe on existing DBs)
- con.execute(SCHEMA_SQL)
-
- errors = _validate(data)
- if errors:
- print("Validation errors:")
- for e in errors:
- print(f" • {e}")
- con.close()
- sys.exit(1)
-
- # Auto-load any magnets that are missing from the DB.
- # Close our connection first so add_magnet can open its own without
- # hitting a lock on platforms that restrict concurrent writers.
- con.close()
- missing_errors = _ensure_magnets(data.get("magnets", []), db_path, magnet_dir, dry_run=dry_run)
- if missing_errors:
- print("Errors resolving magnets:")
- for e in missing_errors:
- print(f" • {e}")
- sys.exit(1)
-
- if dry_run:
- print("[dry-run] Validation passed. Would insert:")
- print(f" site : {data['name']} [{data.get('housing', '?')}]")
- print(f" magnets : {data.get('magnets', [])}")
- print(f" records : {len(data.get('records', []))}")
- return
-
- # Reopen for the actual inserts
- site_name = data["name"]
- con = duckdb.connect(str(db_path))
- print(f"\nAdding site '{site_name}' to {db_path.name} …\n")
-
- _insert_site(con, data)
- _insert_site_magnets(con, site_name, data.get("magnets", []))
- _insert_experiments(con, site_name, data.get("records", []))
-
- con.close()
- print("\nDone.")
-
-
-# ---------------------------------------------------------------------------
-# CLI
-# ---------------------------------------------------------------------------
-
-
-def main():
- parser = argparse.ArgumentParser(
- description="Add a site to the student DuckDB from a MagnetDB JSON export.",
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog=__doc__,
- )
- parser.add_argument("json_file", help="Path to the site JSON file")
- parser.add_argument(
- "--db",
- default="student_magnetdb.duckdb",
- help="Target DuckDB file (default: student_magnetdb.duckdb)",
- )
- parser.add_argument(
- "--magnet-dir",
- default=None,
- help=(
- "Directory to search for .json files when a magnet is "
- "missing from the DB (default: same directory as the site JSON file)"
- ),
- )
- parser.add_argument(
- "--dry-run",
- action="store_true",
- help="Validate and preview without writing to the DB",
- )
- args = parser.parse_args()
-
- json_path = Path(args.json_file)
- if not json_path.exists():
- print(f"Error: '{json_path}' not found.")
- sys.exit(1)
-
- magnet_dir = args.magnet_dir if args.magnet_dir else json_path.parent
- data = json.loads(json_path.read_text())
- add_site(data, args.db, dry_run=args.dry_run, magnet_dir=magnet_dir)
-
-
-if __name__ == "__main__":
- main()
diff --git a/to_duckdb/compute_exp_stats.py b/to_duckdb/compute_exp_stats.py
new file mode 100644
index 0000000..2016665
--- /dev/null
+++ b/to_duckdb/compute_exp_stats.py
@@ -0,0 +1,482 @@
+"""
+compute_exp_stats.py
+====================
+Ingest per-file experiment statistics into DuckDB.
+
+For each experiments file not yet processed this script:
+ 1. Loads the record file (via python_magnetrun or pandas fallback).
+ 2. Computes per-run scalar stats → exp_run_scalars
+ 'energy_j' = sum(Ptot * dt)
+ 'heat_extracted_j' = sum((tsb - teb) * Q_m3s * rho_cp * dt)
+ 'duration_s' = sum(dt)
+ 'duration_field_on_s' = sum(dt) where Field > field_threshold
+ 3. Computes site-level field-bin stats → exp_site_bin_stats
+ channels: Pmagnet, Ptot, tsb, teb, debitbrut (configurable)
+ 4. Computes per-part field-bin stats → exp_part_bin_stats
+ channels: Icoil, Ucoil, hoop_stress_proxy (= I^2)
+ only rows where |Icoil| > current_threshold are counted
+ 5. Marks the file as processed in exp_stats_processed (idempotent).
+
+Usage
+-----
+ python compute_exp_stats.py --db magnetdb.duckdb --site M10_A250429_00
+ python compute_exp_stats.py --db magnetdb.duckdb --site M10_A250429_00 --reprocess
+
+Physical constants
+------------------
+ debitbrut is assumed to be in m³/h.
+ Override with --flow-to-m3s if your data uses different units.
+ Water: rho = 1000 kg/m³, cp = 4186 J/(kg·K) → rho_cp = 4 186 000 J/(m³·K)
+"""
+
+import argparse
+import json
+import sys
+from pathlib import Path
+
+import duckdb
+import numpy as np
+import pandas as pd
+
+sys.path.insert(0, str(Path(__file__).parent))
+from config import DEFAULT_DB
+from populate import _RECORDS_BASE as _DEFAULT_RECORDS_BASE, _SRV_SUBDIR as _DEFAULT_SRV_SUBDIR
+from schema import ensure_schema
+
+DEFAULT_RECORDS_BASE = str(_DEFAULT_RECORDS_BASE)
+DEFAULT_SRV_SUBDIR = _DEFAULT_SRV_SUBDIR
+
+# ---------------------------------------------------------------------------
+# Defaults (same as compute_op_stats)
+# ---------------------------------------------------------------------------
+
+FIELD_COL = "Field"
+FIELD_THRESHOLD = 0.1 # T — minimum field to count as "field on"
+CURRENT_THRESHOLD = 0.1 # A — minimum |Icoil| to count as "coil on"
+FLOW_TO_M3S = 1.0 / 3600.0 # m³/h → m³/s
+RHO_CP = 1_000.0 * 4_186.0 # J / (m³·K) water
+
+DEFAULT_BINS: list[tuple[float, float]] = [
+ (0.0, 0.1),
+ (0.1, 5.0),
+ (5.0, 10.0),
+ (10.0, 15.0),
+ (15.0, 20.0),
+ (20.0, 25.0),
+ (25.0, 30.0),
+ (30.0, 35.0),
+ (35.0, 40.0),
+ (40.0, 45.0),
+]
+
+SITE_CHANNELS = ["Pmagnet", "Ptot", "tsb", "teb", "debitbrut"]
+
+# ---------------------------------------------------------------------------
+# File loading (identical logic to compute_op_stats)
+# ---------------------------------------------------------------------------
+
+
+def _compute_dt(df: pd.DataFrame) -> pd.Series:
+ if "Date" in df.columns and "Time" in df.columns:
+ try:
+ ts = pd.to_datetime(
+ df["Date"].astype(str) + " " + df["Time"].astype(str),
+ format="%Y.%m.%d %H:%M:%S",
+ )
+ dt = ts.diff().dt.total_seconds().fillna(0.0)
+ return dt.clip(lower=0.0)
+ except Exception:
+ pass
+ if "t" in df.columns:
+ return df["t"].diff().fillna(0.0).clip(lower=0.0)
+ return pd.Series(1.0, index=df.index)
+
+
+def load_file(path: Path) -> pd.DataFrame | None:
+ if not path.exists():
+ print(f" [SKIP] not found: {path}")
+ return None
+ try:
+ from python_magnetrun.magnetdata import load_magnetdata
+ md = load_magnetdata(str(path))
+ df = md.Data.copy()
+ except Exception:
+ try:
+ df = pd.read_csv(path, sep="\t", low_memory=False)
+ except Exception as exc:
+ print(f" [ERROR] cannot read {path.name}: {exc}")
+ return None
+
+ if FIELD_COL not in df.columns:
+ print(f" [SKIP] no '{FIELD_COL}' column in {path.name}")
+ return None
+
+ df["dt"] = _compute_dt(df)
+ return df
+
+
+# ---------------------------------------------------------------------------
+# Database helpers
+# ---------------------------------------------------------------------------
+
+
+def get_experiments(con, site_name: str) -> pd.DataFrame:
+ return con.execute(
+ """
+ SELECT e.id, e.name, e.file, s.housing
+ FROM experiments e
+ JOIN sites s ON s.name = e.site_name
+ WHERE e.site_name = ?
+ ORDER BY e.name
+ """,
+ [site_name],
+ ).df()
+
+
+def get_site_parts(con, site_name: str) -> pd.DataFrame:
+ return con.execute(
+ """
+ SELECT p.name AS part_name, mp.coil_index, mp.magnet_name
+ FROM site_magnets sm
+ JOIN magnet_parts mp ON mp.magnet_name = sm.magnet_name
+ JOIN parts p ON p.name = mp.part_name
+ WHERE sm.site_name = ?
+ AND mp.coil_index IS NOT NULL
+ ORDER BY mp.coil_index
+ """,
+ [site_name],
+ ).df()
+
+
+def is_processed(con, exp_id: int) -> bool:
+ return (
+ con.execute(
+ "SELECT 1 FROM exp_stats_processed WHERE experiment_id = ?", [exp_id]
+ ).fetchone()
+ is not None
+ )
+
+
+def mark_processed(con, exp_id: int, df: pd.DataFrame, bins: list[tuple]) -> None:
+ dt_median = float(df["dt"][df["dt"] > 0].median()) if (df["dt"] > 0).any() else 0.0
+ con.execute(
+ """
+ INSERT OR REPLACE INTO exp_stats_processed
+ (experiment_id, n_rows, dt_median, bin_config)
+ VALUES (?, ?, ?, ?)
+ """,
+ [exp_id, len(df), dt_median, json.dumps(bins)],
+ )
+
+
+# ---------------------------------------------------------------------------
+# Stat computation (same helpers as compute_op_stats)
+# ---------------------------------------------------------------------------
+
+
+def _assign_bins(field: pd.Series, bins: list[tuple]) -> pd.Series:
+ out = pd.Series(np.nan, index=field.index)
+ for low, high in bins:
+ mask = (field >= low) & (field < high)
+ out[mask] = low
+ return out
+
+
+def _bin_agg(x: pd.Series, dt: pd.Series) -> dict:
+ x = x.astype(float)
+ dt = dt.astype(float)
+ return {
+ "n_samples": len(x),
+ "sum_dt": float(dt.sum()),
+ "sum_x_dt": float((x * dt).sum()),
+ "sum_x2_dt": float((x**2 * dt).sum()),
+ "min_x": float(x.min()),
+ "max_x": float(x.max()),
+ }
+
+
+def compute_scalars(
+ df: pd.DataFrame,
+ flow_to_m3s: float = FLOW_TO_M3S,
+ rho_cp: float = RHO_CP,
+) -> dict[str, float]:
+ dt = df["dt"].astype(float)
+ scalars: dict[str, float] = {}
+
+ scalars["duration_s"] = float(dt.sum())
+
+ field_on = df[FIELD_COL].astype(float) > FIELD_THRESHOLD
+ scalars["duration_field_on_s"] = float(dt[field_on].sum())
+
+ if "Ptot" in df.columns:
+ scalars["energy_j"] = float((df["Ptot"].astype(float) * dt).sum())
+
+ if all(c in df.columns for c in ("tsb", "teb", "debitbrut")):
+ delta_t = df["tsb"].astype(float) - df["teb"].astype(float)
+ flow_m3s = df["debitbrut"].astype(float) * flow_to_m3s
+ scalars["heat_extracted_j"] = float((delta_t * flow_m3s * rho_cp * dt).sum())
+
+ return scalars
+
+
+def insert_scalars(con, exp_id: int, scalars: dict[str, float]) -> None:
+ for channel, value in scalars.items():
+ con.execute(
+ "INSERT OR REPLACE INTO exp_run_scalars VALUES (?, ?, ?)",
+ [exp_id, channel, value],
+ )
+
+
+def compute_site_bin_stats(
+ df: pd.DataFrame, bins: list[tuple], channels: list[str]
+) -> list[dict]:
+ field = df[FIELD_COL].astype(float)
+ bin_low = _assign_bins(field, bins)
+ rows = []
+ for low, high in bins:
+ mask = bin_low == low
+ sub = df[mask]
+ if sub.empty:
+ continue
+ for ch in channels:
+ if ch not in sub.columns:
+ continue
+ agg = _bin_agg(sub[ch], sub["dt"])
+ rows.append({"field_bin_low": low, "field_bin_high": high, "channel": ch, **agg})
+ return rows
+
+
+def insert_site_bin_stats(con, exp_id: int, rows: list[dict]) -> None:
+ for r in rows:
+ con.execute(
+ """
+ INSERT OR REPLACE INTO exp_site_bin_stats
+ (experiment_id, field_bin_low, field_bin_high, channel,
+ n_samples, sum_dt, sum_x_dt, sum_x2_dt, min_x, max_x)
+ VALUES (?,?,?,?,?,?,?,?,?,?)
+ """,
+ [
+ exp_id,
+ r["field_bin_low"], r["field_bin_high"], r["channel"],
+ r["n_samples"], r["sum_dt"], r["sum_x_dt"], r["sum_x2_dt"],
+ r["min_x"], r["max_x"],
+ ],
+ )
+
+
+def compute_part_bin_stats(
+ df: pd.DataFrame, bins: list[tuple], part_name: str, coil_index: int
+) -> list[dict]:
+ i_col = f"Icoil{coil_index}"
+ u_col = f"Ucoil{coil_index}"
+ if i_col not in df.columns:
+ return []
+
+ field = df[FIELD_COL].astype(float)
+ icoil = df[i_col].astype(float)
+ active = icoil.abs() > CURRENT_THRESHOLD
+ bin_low = _assign_bins(field, bins)
+
+ rows = []
+ for low, high in bins:
+ mask = (bin_low == low) & active
+ sub = df[mask]
+ if sub.empty:
+ continue
+
+ i_sub = sub[i_col].astype(float)
+ dt_sub = sub["dt"]
+
+ rows.append({
+ "part_name": part_name, "field_bin_low": low, "field_bin_high": high,
+ "channel": "Icoil", **_bin_agg(i_sub, dt_sub),
+ })
+
+ if u_col in sub.columns:
+ rows.append({
+ "part_name": part_name, "field_bin_low": low, "field_bin_high": high,
+ "channel": "Ucoil", **_bin_agg(sub[u_col].astype(float), dt_sub),
+ })
+
+ rows.append({
+ "part_name": part_name, "field_bin_low": low, "field_bin_high": high,
+ "channel": "hoop_stress_proxy", **_bin_agg(i_sub**2, dt_sub),
+ })
+
+ return rows
+
+
+def insert_part_bin_stats(con, exp_id: int, rows: list[dict]) -> None:
+ for r in rows:
+ con.execute(
+ """
+ INSERT OR REPLACE INTO exp_part_bin_stats
+ (experiment_id, part_name, field_bin_low, field_bin_high, channel,
+ n_samples, sum_dt, sum_x_dt, sum_x2_dt, min_x, max_x)
+ VALUES (?,?,?,?,?,?,?,?,?,?,?)
+ """,
+ [
+ exp_id,
+ r["part_name"], r["field_bin_low"], r["field_bin_high"], r["channel"],
+ r["n_samples"], r["sum_dt"], r["sum_x_dt"], r["sum_x2_dt"],
+ r["min_x"], r["max_x"],
+ ],
+ )
+
+
+# ---------------------------------------------------------------------------
+# Top-level ingestion
+# ---------------------------------------------------------------------------
+
+
+def ingest_site(
+ site_name: str,
+ db_path: str,
+ records_base: str = DEFAULT_RECORDS_BASE,
+ srv_subdir: str = DEFAULT_SRV_SUBDIR,
+ bins: list[tuple] = DEFAULT_BINS,
+ site_channels: list[str] = SITE_CHANNELS,
+ flow_to_m3s: float = FLOW_TO_M3S,
+ rho_cp: float = RHO_CP,
+ reprocess: bool = False,
+ verbose: bool = True,
+) -> dict:
+ """Process all experiment files for *site_name* and persist stats.
+
+ experiments.file stores only the filename; the full path is reconstructed
+ as records_base / srv_subdir / housing / filename.
+ If experiments.file is already an absolute path it is used as-is (migration
+ backward-compatibility).
+ """
+ con = duckdb.connect(db_path)
+ ensure_schema(con)
+
+ exp_df = get_experiments(con, site_name)
+ parts = get_site_parts(con, site_name)
+
+ results = {"new": 0, "skipped": 0, "errors": []}
+
+ for _, row in exp_df.iterrows():
+ exp_id = int(row["id"])
+ filename = row["file"]
+ housing = row["housing"]
+
+ if not reprocess and is_processed(con, exp_id):
+ results["skipped"] += 1
+ continue
+
+ f = Path(filename)
+ path = f if f.is_absolute() else Path(records_base) / srv_subdir / housing / filename
+ df = load_file(path)
+ if df is None:
+ results["errors"].append(filename)
+ continue
+
+ if verbose:
+ print(f" processing {path.name} ({len(df)} rows)")
+
+ try:
+ scalars = compute_scalars(df, flow_to_m3s, rho_cp)
+ insert_scalars(con, exp_id, scalars)
+
+ site_rows = compute_site_bin_stats(df, bins, site_channels)
+ insert_site_bin_stats(con, exp_id, site_rows)
+
+ for _, part in parts.iterrows():
+ part_rows = compute_part_bin_stats(
+ df, bins, part["part_name"], int(part["coil_index"])
+ )
+ insert_part_bin_stats(con, exp_id, part_rows)
+
+ mark_processed(con, exp_id, df, bins)
+ results["new"] += 1
+
+ except Exception as exc:
+ results["errors"].append((filename, str(exc)))
+ if verbose:
+ print(f" [ERROR] {path.name}: {exc}")
+
+ con.close()
+
+ if verbose:
+ print(
+ f"\nDone — {results['new']} processed, "
+ f"{results['skipped']} skipped, "
+ f"{len(results['errors'])} errors"
+ )
+ return results
+
+
+# ---------------------------------------------------------------------------
+# CLI
+# ---------------------------------------------------------------------------
+
+
+def _parse_bins(s: str) -> list[tuple[float, float]]:
+ bins = []
+ for pair in s.split(","):
+ lo, hi = pair.strip().split(":")
+ bins.append((float(lo), float(hi)))
+ return bins
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(
+ description="Ingest experiment statistics into DuckDB.",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=__doc__,
+ )
+ parser.add_argument("--db", default=DEFAULT_DB, help="DuckDB file path")
+ parser.add_argument("--site", required=True, help="Site name (FK)")
+ parser.add_argument(
+ "--records-base",
+ default=DEFAULT_RECORDS_BASE,
+ dest="records_base",
+ help=f"Root directory for record files (default: {DEFAULT_RECORDS_BASE})",
+ )
+ parser.add_argument(
+ "--srv-subdir",
+ default=DEFAULT_SRV_SUBDIR,
+ dest="srv_subdir",
+ help=f"Subdirectory under records-base for pupitre TXT files (default: {DEFAULT_SRV_SUBDIR})",
+ )
+ parser.add_argument(
+ "--bins",
+ default=None,
+ help="Field bins as 'low1:high1,low2:high2,...' (default: built-in 10-bin set)",
+ )
+ parser.add_argument(
+ "--channels",
+ default=",".join(SITE_CHANNELS),
+ help="Comma-separated site-level channels",
+ )
+ parser.add_argument(
+ "--flow-to-m3s",
+ type=float,
+ default=FLOW_TO_M3S,
+ help="Unit conversion: debitbrut → m³/s (default 1/3600 for m³/h input)",
+ )
+ parser.add_argument(
+ "--reprocess", action="store_true", help="Re-compute already-processed files"
+ )
+ parser.add_argument("--quiet", action="store_true", help="Suppress per-file output")
+ args = parser.parse_args()
+
+ bins = _parse_bins(args.bins) if args.bins else DEFAULT_BINS
+ channels = [c.strip() for c in args.channels.split(",") if c.strip()]
+
+ ingest_site(
+ site_name=args.site,
+ db_path=args.db,
+ records_base=args.records_base,
+ srv_subdir=args.srv_subdir,
+ bins=bins,
+ site_channels=channels,
+ flow_to_m3s=args.flow_to_m3s,
+ reprocess=args.reprocess,
+ verbose=not args.quiet,
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/to_duckdb/compute_hoop_stats.py b/to_duckdb/compute_hoop_stats.py
new file mode 100644
index 0000000..d67570a
--- /dev/null
+++ b/to_duckdb/compute_hoop_stats.py
@@ -0,0 +1,620 @@
+"""
+compute_hoop_stats.py
+=====================
+Compute per-part hoop-stress statistics for every experiment at a site and
+persist the results in DuckDB.
+
+For each experiment file not yet processed this module:
+ 1. Calls validate_fast_from_pupitre() to get the full hoop-stress time series
+ (columns H1_fast, B1_fast, Supra1_fast, … depending on magnet_type).
+ 2. Saves the time series to a Parquet file with per-column and table-level
+ PyArrow metadata (t0 timestamp, site name, unit/symbol per column, part map).
+ 3. Computes per-part stress-bin distributions → hoop_stress_bin_stats
+ 4. Computes per-part rainflow fatigue cycle counts → hoop_stress_fatigue
+ 5. Marks the experiment as processed in hoop_stress_processed (idempotent).
+
+Bin format
+----------
+Bins are specified as a comma-separated list of edge values in MPa:
+
+ --bins 0,100,200,300,400,500,600
+
+N edges define N-1 consecutive bins. The legacy pair format
+"l1:h1,l2:h2,..." is still accepted for backward compatibility.
+
+Default bins span 0–600 MPa in 100 MPa steps (6 bins).
+
+Usage
+-----
+ # via magnetdb.py (recommended):
+ python magnetdb.py hoop-stress compute --site M9_M19061901 --db magnetdb.duckdb
+
+ # standalone:
+ python compute_hoop_stats.py --site M9_M19061901 --db magnetdb.duckdb
+"""
+
+import argparse
+import json
+import re
+import sys
+import tempfile
+from pathlib import Path
+
+import duckdb
+import pandas as pd
+import pyarrow as pa
+import pyarrow.parquet as pq
+
+sys.path.insert(0, str(Path(__file__).parent))
+from config import DEFAULT_DB
+from populate import _SRV_SUBDIR as _DEFAULT_SRV_SUBDIR
+from schema import ensure_schema
+
+# ---------------------------------------------------------------------------
+# Defaults
+# ---------------------------------------------------------------------------
+
+DEFAULT_SRV_SUBDIR = _DEFAULT_SRV_SUBDIR
+DEFAULT_MAGNET_TYPE = "all"
+
+DEFAULT_BIN_EDGES: list[float] = [0.0, 100.0, 200.0, 300.0, 400.0, 500.0, 600.0]
+DEFAULT_STRESS_BINS: list[tuple[float, float]] = [
+ (DEFAULT_BIN_EDGES[i], DEFAULT_BIN_EDGES[i + 1])
+ for i in range(len(DEFAULT_BIN_EDGES) - 1)
+]
+
+_HOOP_COL_RE = re.compile(r"^(H|B|Supra)\d+_fast$")
+
+# ---------------------------------------------------------------------------
+# Bin helpers
+# ---------------------------------------------------------------------------
+
+
+def bins_to_key(bins: list[tuple[float, float]]) -> str:
+ """Return the canonical edges string used as the DB key, e.g. '0.0,100.0,200.0,...'."""
+ edges = [bins[0][0]] + [hi for _, hi in bins]
+ return ",".join(str(e) for e in edges)
+
+
+def _parse_bins(s: str) -> list[tuple[float, float]]:
+ """Parse bin specification into a list of (lo, hi) pairs.
+
+ Accepts two formats:
+ edges: '0,100,200,300' → [(0,100),(100,200),(200,300)]
+ pairs: '0:100,100:200,200:300' → same (legacy, still accepted)
+ """
+ if ":" in s:
+ bins = []
+ for pair in s.split(","):
+ lo, hi = pair.strip().split(":")
+ bins.append((float(lo), float(hi)))
+ return bins
+ edges = [float(x.strip()) for x in s.split(",")]
+ if len(edges) < 2:
+ raise ValueError(f"--bins needs at least 2 edge values, got: {s!r}")
+ return [(edges[i], edges[i + 1]) for i in range(len(edges) - 1)]
+
+
+# ---------------------------------------------------------------------------
+# Part-column mapping
+# ---------------------------------------------------------------------------
+
+
+def build_part_column_map(site_name: str, db_path: str) -> dict[str, str]:
+ """Return {column_name: part_name} for all coil parts at a site.
+
+ Column names follow the same convention as validate_fast_from_pupitre():
+ - helices → H1_fast, H2_fast, … (parts ordered by rank within insert magnets)
+ - bitters → B1_fast, B2_fast, … (parts ordered by rank within bitter magnets)
+ - supras → Supra1_fast, … (parts ordered by rank within supra magnets)
+
+ Magnets are ordered by commissioned_at DESC (same as load_site_config_from_duckdb).
+ Within each magnet, parts are ordered by rank.
+ """
+ con = duckdb.connect(db_path, read_only=True)
+
+ rows = con.execute("""
+ SELECT m.name AS magnet_name, m.type AS magnet_type,
+ p.name AS part_name, p.type AS part_type, mp.rank
+ FROM site_magnets sm
+ JOIN magnets m ON m.name = sm.magnet_name
+ JOIN magnet_parts mp ON mp.magnet_name = m.name
+ JOIN parts p ON p.name = mp.part_name
+ WHERE sm.site_name = ?
+ ORDER BY sm.commissioned_at DESC NULLS LAST, mp.rank
+ """, [site_name]).fetchall()
+ con.close()
+
+ h_idx = b_idx = s_idx = 1
+ mapping: dict[str, str] = {}
+ for _magnet, magnet_type, part_name, part_type, _rank in rows:
+ mt = (magnet_type or "").lower()
+ pt = (part_type or "").lower()
+ if mt in ("insert",) and pt in ("helix",):
+ mapping[f"H{h_idx}_fast"] = part_name
+ h_idx += 1
+ elif mt in ("bitters",) and pt in ("bitter",):
+ mapping[f"B{b_idx}_fast"] = part_name
+ b_idx += 1
+ elif mt in ("supras",) and pt in ("supra",):
+ mapping[f"Supra{s_idx}_fast"] = part_name
+ s_idx += 1
+
+ return mapping
+
+
+# ---------------------------------------------------------------------------
+# Parquet I/O
+# ---------------------------------------------------------------------------
+
+
+def _column_meta(col: str) -> dict[bytes, bytes]:
+ """Return PyArrow field-level metadata for a hoop-stress column."""
+ m = re.match(r"^(H|B|Supra)(\d+)_fast$", col)
+ if not m:
+ return {}
+ prefix, idx = m.group(1), m.group(2)
+ symbol = {"H": "σ_H", "B": "σ_B", "Supra": "σ_S"}[prefix]
+ return {b"unit": b"MPa", b"symbol": f"{symbol}{idx}".encode()}
+
+
+def save_hoop_parquet(
+ df: pd.DataFrame,
+ path: Path,
+ *,
+ site_name: str,
+ housing: str,
+ t0: str,
+ experiment_file: str,
+ part_map: dict[str, str],
+) -> Path:
+ """Write *df* to a Parquet file with rich PyArrow metadata.
+
+ Table-level metadata: site_name, housing, t0 (ISO timestamp string),
+ experiment_file, part_map (JSON).
+ Field-level metadata: unit and symbol for each *_fast column.
+ """
+ table = pa.Table.from_pandas(df, preserve_index=False)
+
+ # Per-field metadata
+ new_fields = []
+ for field in table.schema:
+ extra = _column_meta(field.name)
+ if extra:
+ new_fields.append(field.with_metadata(extra))
+ else:
+ new_fields.append(field)
+
+ # Table-level metadata
+ table_meta = {
+ b"site_name": site_name.encode(),
+ b"housing": (housing or "").encode(),
+ b"t0": (t0 or "").encode(),
+ b"experiment_file": experiment_file.encode(),
+ b"part_map": json.dumps(part_map).encode(),
+ }
+ new_schema = pa.schema(new_fields, metadata=table_meta)
+ table = table.cast(new_schema)
+
+ path = Path(path)
+ path.parent.mkdir(parents=True, exist_ok=True)
+ pq.write_table(table, path, compression="snappy")
+ return path
+
+
+# ---------------------------------------------------------------------------
+# Bin statistics (same additive pattern as compute_op_stats)
+# ---------------------------------------------------------------------------
+
+
+def _bin_series(
+ sigma: pd.Series,
+ dt: pd.Series,
+ bins: list[tuple[float, float]],
+) -> list[dict]:
+ """Return rows for hoop_stress_bin_stats for one part column."""
+ rows = []
+ sigma = sigma.astype(float)
+ dt = dt.astype(float)
+ for low, high in bins:
+ mask = (sigma >= low) & (sigma < high)
+ sub_s = sigma[mask]
+ sub_dt = dt[mask]
+ if sub_s.empty:
+ continue
+ rows.append({
+ "stress_bin_low": low,
+ "stress_bin_high": high,
+ "n_samples": len(sub_s),
+ "sum_dt": float(sub_dt.sum()),
+ "sum_x_dt": float((sub_s * sub_dt).sum()),
+ "sum_x2_dt": float((sub_s**2 * sub_dt).sum()),
+ "min_x": float(sub_s.min()),
+ "max_x": float(sub_s.max()),
+ })
+ return rows
+
+
+# ---------------------------------------------------------------------------
+# Rainflow fatigue
+# ---------------------------------------------------------------------------
+
+
+def _rainflow_stats(sigma: pd.Series) -> dict[str, float]:
+ """Return {n_cycles, sum_range3} from a rainflow count of *sigma*."""
+ try:
+ import rainflow
+ except ImportError:
+ return {"n_cycles": 0.0, "sum_range3": 0.0}
+
+ cycles = rainflow.count_cycles(sigma.to_numpy().astype(float))
+ n_cycles = 0.0
+ sum_range3 = 0.0
+ for rng, _mean, count, *_ in cycles:
+ n_cycles += count
+ sum_range3 += count * float(rng) ** 3
+ return {"n_cycles": n_cycles, "sum_range3": sum_range3}
+
+
+# ---------------------------------------------------------------------------
+# DuckDB helpers
+# ---------------------------------------------------------------------------
+
+
+def _get_experiments(con, site_name: str) -> pd.DataFrame:
+ return con.execute(
+ "SELECT id, name, file FROM experiments "
+ "WHERE site_name = ? AND file IS NOT NULL ORDER BY id",
+ [site_name],
+ ).df()
+
+
+def _check_processed(
+ con, exp_id: int, bin_key: str
+) -> tuple[bool, set[str]]:
+ """Check whether this (experiment, bin_key) pair has already been processed.
+
+ Returns (already_done, other_keys) where:
+ already_done – True if this exact bin_key is recorded for exp_id
+ other_keys – set of different bin keys already stored for exp_id
+ """
+ rows = con.execute(
+ "SELECT bin_config FROM hoop_stress_processed WHERE experiment_id = ?", [exp_id]
+ ).fetchall()
+ stored = {r[0] for r in rows}
+ return bin_key in stored, stored - {bin_key}
+
+
+def _mark_processed(
+ con, exp_id: int, magnet_type: str, bin_key: str, parquet_path: str | None
+) -> None:
+ con.execute(
+ """
+ INSERT OR REPLACE INTO hoop_stress_processed
+ (experiment_id, bin_config, magnet_type, parquet_path)
+ VALUES (?, ?, ?, ?)
+ """,
+ [exp_id, bin_key, magnet_type, parquet_path],
+ )
+
+
+def _insert_bin_stats(con, exp_id: int, part_name: str, rows: list[dict]) -> None:
+ for r in rows:
+ con.execute(
+ """
+ INSERT OR REPLACE INTO hoop_stress_bin_stats
+ (experiment_id, part_name, stress_bin_low, stress_bin_high,
+ n_samples, sum_dt, sum_x_dt, sum_x2_dt, min_x, max_x)
+ VALUES (?,?,?,?,?,?,?,?,?,?)
+ """,
+ [exp_id, part_name,
+ r["stress_bin_low"], r["stress_bin_high"],
+ r["n_samples"], r["sum_dt"], r["sum_x_dt"],
+ r["sum_x2_dt"], r["min_x"], r["max_x"]],
+ )
+
+
+def _insert_fatigue(con, exp_id: int, part_name: str, stats: dict) -> None:
+ con.execute(
+ """
+ INSERT OR REPLACE INTO hoop_stress_fatigue
+ (experiment_id, part_name, n_cycles, sum_range3)
+ VALUES (?, ?, ?, ?)
+ """,
+ [exp_id, part_name, stats["n_cycles"], stats["sum_range3"]],
+ )
+
+
+# ---------------------------------------------------------------------------
+# dt helper (same logic as compute_op_stats._compute_dt)
+# ---------------------------------------------------------------------------
+
+
+def _compute_dt(df: pd.DataFrame) -> pd.Series:
+ if "t" in df.columns:
+ return df["t"].diff().fillna(0.0).clip(lower=0.0)
+ return pd.Series(1.0, index=df.index)
+
+
+# ---------------------------------------------------------------------------
+# Main pipeline
+# ---------------------------------------------------------------------------
+
+
+def compute_hoop_stress_history(
+ site_name: str,
+ db_path: str,
+ *,
+ magnet_type: str = DEFAULT_MAGNET_TYPE,
+ bins: list[tuple[float, float]] = DEFAULT_STRESS_BINS,
+ parquet_dir: str | None = None,
+ geometries_dir: str | None = None,
+ reprocess: bool = False,
+ dry_run: bool = False,
+ use_mrun: bool = False,
+ pupitre_datadir: str = "",
+ verbose: bool = True,
+) -> dict:
+ """Process all experiment files for *site_name* and persist hoop-stress stats.
+
+ Parameters
+ ----------
+ site_name : site FK (must exist in the sites table)
+ db_path : path to the DuckDB file
+ magnet_type : "H", "B", "S", or "all"
+ bins : list of (low, high) stress bins in MPa
+ parquet_dir : directory for Parquet output files (default: /hoop_parquet)
+ geometries_dir : override for geometry YAML directory
+ reprocess : if True, overwrite already-processed files
+ dry_run : discover files but do not write to DB or disk
+ use_mrun : pass to validate_fast_from_pupitre
+ pupitre_datadir: root for pupitre files
+ verbose : print progress lines
+ """
+ from stress_map import (
+ load_site_config_from_duckdb,
+ load_magnettools,
+ prepare_geometry_directory,
+ validate_fast_from_pupitre,
+ )
+ try:
+ from python_magnetrun.utils.timestamps import parse_filename_timestamp
+ except ImportError:
+ parse_filename_timestamp = None
+
+ db_path = str(db_path)
+ con = duckdb.connect(db_path)
+ ensure_schema(con)
+
+ experiments = _get_experiments(con, site_name)
+ if experiments.empty:
+ if verbose:
+ print(f"[INFO] No experiments found for site '{site_name}'.")
+ con.close()
+ return {"new": 0, "skipped": 0, "errors": []}
+
+ # ── Load site config and magnettools (shared across all experiments) ──────
+ try:
+ housing, magnet_configs = load_site_config_from_duckdb(site_name, db_path)
+ except ValueError as exc:
+ print(f"[ERROR] Cannot load site config for '{site_name}': {exc}")
+ con.close()
+ return {"new": 0, "skipped": 0, "errors": [str(exc)]}
+
+ part_map = build_part_column_map(site_name, db_path)
+
+ # Parquet output directory
+ pq_dir = Path(parquet_dir) if parquet_dir else Path(db_path).parent / "hoop_parquet"
+ if not dry_run:
+ pq_dir.mkdir(parents=True, exist_ok=True)
+
+ results: dict = {"new": 0, "skipped": 0, "errors": []}
+
+ with tempfile.TemporaryDirectory() as tmpdir:
+ tmpdir_path = Path(tmpdir)
+
+ # Build the geometry directory once per site
+ for magnet_name, config, geometry_data in magnet_configs:
+ try:
+ prepare_geometry_directory(
+ magnet_name, config, tmpdir_path,
+ geometry_data=geometry_data,
+ geometries_dir=geometries_dir,
+ )
+ except Exception as exc:
+ if verbose:
+ print(f" [WARN] geometry prep for '{magnet_name}': {exc}")
+
+ # Load magnettools objects (Tubes, Helices, BMagnets, UMagnets, …)
+ try:
+ combined_config = magnet_configs[0][1] if len(magnet_configs) == 1 else _merge_configs(magnet_configs)
+ data = load_magnettools(combined_config, tmpdir_path)
+ except Exception as exc:
+ print(f"[ERROR] Cannot load magnettools for '{site_name}': {exc}")
+ con.close()
+ return {"new": 0, "skipped": 0, "errors": [str(exc)]}
+
+ for _, exp_row in experiments.iterrows():
+ exp_id = int(exp_row["id"])
+ exp_name = str(exp_row["name"])
+ _f = Path(str(exp_row["file"]))
+ if not _f.is_absolute() and pupitre_datadir:
+ exp_file = str(Path(pupitre_datadir) / housing / _f.name)
+ else:
+ exp_file = str(_f)
+
+ bin_key = bins_to_key(bins)
+ already_done, other_keys = _check_processed(con, exp_id, bin_key)
+ if other_keys:
+ print(
+ f" [WARN] [{exp_id}] {exp_name}: previously processed with "
+ f"different bin(s): {sorted(other_keys)}. "
+ f"Use --reprocess to overwrite."
+ )
+ if already_done and not reprocess:
+ results["skipped"] += 1
+ continue
+
+ if verbose:
+ print(f" processing [{exp_id}] {exp_name}")
+
+ if dry_run:
+ results["new"] += 1
+ continue
+
+ try:
+ df = validate_fast_from_pupitre(
+ data, exp_file, housing,
+ magnet_type=magnet_type,
+ use_mrun=use_mrun,
+ site=site_name,
+ )
+ except Exception as exc:
+ if verbose:
+ print(f" [ERROR] {exp_name}: {exc}")
+ results["errors"].append((exp_name, str(exc)))
+ continue
+
+ # Hoop stress columns present in this DataFrame
+ hoop_cols = [c for c in df.columns if _HOOP_COL_RE.match(c)]
+ if not hoop_cols:
+ if verbose:
+ print(f" [SKIP] {exp_name}: no hoop-stress columns in output")
+ results["errors"].append((exp_name, "no hoop columns"))
+ continue
+
+ dt = _compute_dt(df)
+
+ # t0 timestamp from filename
+ t0_str = ""
+ if parse_filename_timestamp is not None:
+ try:
+ t0_dt = parse_filename_timestamp(Path(exp_file).name)
+ if t0_dt is not None:
+ t0_str = t0_dt.isoformat()
+ except Exception:
+ pass
+
+ # Save Parquet
+ pq_path = pq_dir / f"{exp_name}.parquet"
+ try:
+ save_hoop_parquet(
+ df, pq_path,
+ site_name=site_name,
+ housing=housing,
+ t0=t0_str,
+ experiment_file=exp_file,
+ part_map={k: v for k, v in part_map.items() if k in hoop_cols},
+ )
+ except Exception as exc:
+ if verbose:
+ print(f" [WARN] Parquet write failed for {exp_name}: {exc}")
+ pq_path = None
+
+ # Bin stats + rainflow per part
+ for col in hoop_cols:
+ part_name = part_map.get(col, col)
+ sigma = df[col]
+
+ bin_rows = _bin_series(sigma, dt, bins)
+ _insert_bin_stats(con, exp_id, part_name, bin_rows)
+
+ fatigue = _rainflow_stats(sigma)
+ _insert_fatigue(con, exp_id, part_name, fatigue)
+
+ _mark_processed(
+ con, exp_id, magnet_type, bin_key,
+ str(pq_path) if pq_path else None,
+ )
+ results["new"] += 1
+
+ con.close()
+
+ if verbose:
+ print(
+ f"\nDone — {results['new']} processed, "
+ f"{results['skipped']} skipped, "
+ f"{len(results['errors'])} errors"
+ )
+ return results
+
+
+def _merge_configs(magnet_configs: list) -> dict:
+ """Merge multiple magnet configs into one combined dict for load_magnettools."""
+ combined: dict = {}
+ for _name, config, _geo in magnet_configs:
+ for key, val in config.items():
+ if isinstance(val, list) and key in combined:
+ combined[key] = combined[key] + val
+ else:
+ combined[key] = val
+ return combined
+
+
+# ---------------------------------------------------------------------------
+# CLI (standalone entry point)
+# ---------------------------------------------------------------------------
+
+
+def _parse_args(argv=None) -> argparse.Namespace:
+ parser = argparse.ArgumentParser(
+ description="Compute per-part hoop-stress statistics and persist to DuckDB.",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=__doc__,
+ )
+ parser.add_argument("--db", default=DEFAULT_DB,
+ help=f"DuckDB file (default: {DEFAULT_DB})")
+ parser.add_argument("--site", required=True,
+ help="Site name (FK in sites table)")
+ parser.add_argument("--magnet-type", default=DEFAULT_MAGNET_TYPE,
+ choices=["H", "B", "S", "all"],
+ dest="magnet_type",
+ help="Coil type(s) to compute (default: all)")
+ parser.add_argument("--bins", default=None,
+ help="Bin edges in MPa as a comma-separated list, e.g. "
+ f"'0,100,200,300,400,500,600' (default: {','.join(str(int(e)) for e in DEFAULT_BIN_EDGES)}). "
+ "Legacy pair format 'l1:h1,l2:h2,...' is also accepted.")
+ parser.add_argument("--parquet-dir", default=None, dest="parquet_dir",
+ help="Output directory for Parquet files (default: /hoop_parquet)")
+ parser.add_argument("--geometries", default=None,
+ help="Override geometry YAML directory")
+ parser.add_argument("--reprocess", action="store_true",
+ help="Re-compute already-processed experiments")
+ parser.add_argument("--dry-run", action="store_true", dest="dry_run",
+ help="Discover files but do not write to DB or disk")
+ parser.add_argument("--use-mrun", action="store_true", dest="use_mrun",
+ help="Load files via python_magnetrun.MagnetRun.load_mrun()")
+ parser.add_argument("--records-base", default="", dest="records_base",
+ help="Root of the records tree (parent of --srv-subdir)")
+ parser.add_argument("--srv-subdir", default=DEFAULT_SRV_SUBDIR, dest="srv_subdir",
+ help=f"Subdirectory of records-base for pupitre TXT files "
+ f"(default: {DEFAULT_SRV_SUBDIR})")
+ parser.add_argument("--quiet", action="store_true",
+ help="Suppress per-file output")
+ return parser.parse_args(argv)
+
+
+def main(argv=None) -> None:
+ args = _parse_args(argv)
+ bins = _parse_bins(args.bins) if args.bins else DEFAULT_STRESS_BINS
+ pupitre_datadir = (
+ str(Path(args.records_base) / args.srv_subdir) if args.records_base else ""
+ )
+
+ compute_hoop_stress_history(
+ site_name=args.site,
+ db_path=args.db,
+ magnet_type=args.magnet_type,
+ bins=bins,
+ parquet_dir=args.parquet_dir,
+ geometries_dir=args.geometries,
+ reprocess=args.reprocess,
+ dry_run=args.dry_run,
+ use_mrun=args.use_mrun,
+ pupitre_datadir=pupitre_datadir,
+ verbose=not args.quiet,
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/to_duckdb/compute_op_stats.py b/to_duckdb/compute_op_stats.py
new file mode 100644
index 0000000..38418ff
--- /dev/null
+++ b/to_duckdb/compute_op_stats.py
@@ -0,0 +1,568 @@
+"""
+compute_op_stats.py
+===================
+Ingest per-file operational statistics into DuckDB.
+
+For each operationaldata file not yet processed this script:
+ 1. Loads the record file (via python_magnetrun or pandas fallback).
+ 2. Computes per-run scalar stats → op_run_scalars
+ 'energy_j' = sum(Ptot * dt)
+ 'heat_extracted_j' = sum((tsb - teb) * Q_m3s * rho_cp * dt)
+ 'duration_s' = sum(dt)
+ 'duration_field_on_s' = sum(dt) where Field > field_threshold
+ 3. Computes site-level field-bin stats → op_site_bin_stats
+ channels: Pmagnet, Ptot, tsb, teb, debitbrut (configurable)
+ 4. Computes per-part field-bin stats → op_part_bin_stats
+ channels: Icoil, Ucoil, hoop_stress_proxy (= I^2)
+ only rows where |Icoil| > current_threshold are counted
+ 5. Marks the file as processed in op_stats_processed (idempotent).
+
+Usage
+-----
+ python compute_op_stats.py --db magnetdb.duckdb --records-base ../data/M9 \\
+ --site M9_M19061901
+ python compute_op_stats.py --db magnetdb.duckdb --records-base ../data/M9 \\
+ --site M9_M19061901 --type pupitre --reprocess
+
+Physical constants
+------------------
+ debitbrut is assumed to be in m³/h.
+ Override with --flow-to-m3s if your data uses different units.
+ Water: rho = 1000 kg/m³, cp = 4186 J/(kg·K) → rho_cp = 4 186 000 J/(m³·K)
+"""
+
+import argparse
+import json
+import sys
+from pathlib import Path
+
+import duckdb
+import numpy as np
+import pandas as pd
+
+sys.path.insert(0, str(Path(__file__).parent))
+from config import DEFAULT_DB
+from schema import ensure_schema
+
+# ---------------------------------------------------------------------------
+# Defaults
+# ---------------------------------------------------------------------------
+
+DEFAULT_RECORDS_BASE = "records"
+
+FIELD_COL = "Field"
+FIELD_THRESHOLD = 0.1 # T — minimum field to count as "field on"
+CURRENT_THRESHOLD = 0.1 # A — minimum |Icoil| to count as "coil on"
+FLOW_TO_M3S = 1.0 / 3600.0 # m³/h → m³/s
+RHO_CP = 1_000.0 * 4_186.0 # J / (m³·K) water
+
+DEFAULT_BINS: list[tuple[float, float]] = [
+ (0.0, 0.1),
+ (0.1, 5.0),
+ (5.0, 10.0),
+ (10.0, 15.0),
+ (15.0, 20.0),
+ (20.0, 25.0),
+ (25.0, 30.0),
+ (30.0, 35.0),
+ (35.0, 40.0),
+ (40.0, 45.0),
+]
+
+SITE_CHANNELS = ["Pmagnet", "Ptot", "tsb", "teb", "debitbrut"]
+
+# ---------------------------------------------------------------------------
+# File loading
+# ---------------------------------------------------------------------------
+
+
+def _compute_dt(df: pd.DataFrame) -> pd.Series:
+ """Return a dt Series (seconds) using Date+Time columns or a 't' column."""
+ if "Date" in df.columns and "Time" in df.columns:
+ try:
+ ts = pd.to_datetime(
+ df["Date"].astype(str) + " " + df["Time"].astype(str),
+ format="%Y.%m.%d %H:%M:%S",
+ )
+ dt = ts.diff().dt.total_seconds().fillna(0.0)
+ dt = dt.clip(lower=0.0)
+ return dt
+ except Exception:
+ pass
+ if "t" in df.columns:
+ dt = df["t"].diff().fillna(0.0).clip(lower=0.0)
+ return dt
+ # fallback: constant interval from median of non-zero gaps
+ if "t" in df.columns:
+ median_dt = df["t"].diff().dropna()
+ median_dt = median_dt[median_dt > 0].median()
+ return pd.Series(
+ float(median_dt) if pd.notna(median_dt) else 1.0, index=df.index
+ )
+ return pd.Series(1.0, index=df.index)
+
+
+def load_file(path: Path) -> pd.DataFrame | None:
+ """Load a record file into a DataFrame with a 'dt' column added.
+
+ Tries python_magnetrun.magnetdata.load_magnetdata first; falls back to
+ pd.read_csv for plain TSV files.
+ """
+ if not path.exists():
+ print(f" [SKIP] not found: {path.name}")
+ return None
+ try:
+ from python_magnetrun.magnetdata import load_magnetdata
+
+ md = load_magnetdata(str(path))
+ df = md.Data.copy()
+ except Exception:
+ try:
+ df = pd.read_csv(path, sep="\t", low_memory=False)
+ except Exception as exc:
+ print(f" [ERROR] cannot read {path.name}: {exc}")
+ return None
+
+ if FIELD_COL not in df.columns:
+ print(f" [SKIP] no '{FIELD_COL}' column in {path.name}")
+ return None
+
+ df["dt"] = _compute_dt(df)
+ return df
+
+
+# ---------------------------------------------------------------------------
+# Database helpers
+# ---------------------------------------------------------------------------
+
+
+def get_operationaldata(con, site_name: str, od_type: str | None) -> pd.DataFrame:
+ """Return operationaldata rows for a site, optionally filtered by type."""
+ q = "SELECT id, name, file FROM operationaldata WHERE site_name = ?"
+ params = [site_name]
+ if od_type:
+ q += " AND type = ?"
+ params.append(od_type)
+ q += " ORDER BY name"
+ return con.execute(q, params).df()
+
+
+def get_site_parts(con, site_name: str) -> pd.DataFrame:
+ """Return parts with their coil_index for all magnets at a site."""
+ return con.execute(
+ """
+ SELECT p.name AS part_name, mp.coil_index, mp.magnet_name
+ FROM site_magnets sm
+ JOIN magnet_parts mp ON mp.magnet_name = sm.magnet_name
+ JOIN parts p ON p.name = mp.part_name
+ WHERE sm.site_name = ?
+ AND mp.coil_index IS NOT NULL
+ ORDER BY mp.coil_index
+ """,
+ [site_name],
+ ).df()
+
+
+def is_processed(con, od_id: int) -> bool:
+ return (
+ con.execute(
+ "SELECT 1 FROM op_stats_processed WHERE operationaldata_id = ?", [od_id]
+ ).fetchone()
+ is not None
+ )
+
+
+def mark_processed(con, od_id: int, df: pd.DataFrame, bins: list[tuple]) -> None:
+ dt_median = float(df["dt"][df["dt"] > 0].median()) if (df["dt"] > 0).any() else 0.0
+ con.execute(
+ """
+ INSERT OR REPLACE INTO op_stats_processed
+ (operationaldata_id, n_rows, dt_median, bin_config)
+ VALUES (?, ?, ?, ?)
+ """,
+ [od_id, len(df), dt_median, json.dumps(bins)],
+ )
+
+
+# ---------------------------------------------------------------------------
+# Stat computation
+# ---------------------------------------------------------------------------
+
+
+def _assign_bins(field: pd.Series, bins: list[tuple]) -> pd.Series:
+ """Return the bin_low for each row, or NaN if outside every bin."""
+ out = pd.Series(np.nan, index=field.index)
+ for low, high in bins:
+ mask = (field >= low) & (field < high)
+ out[mask] = low
+ return out
+
+
+def _bin_agg(x: pd.Series, dt: pd.Series) -> dict:
+ """Aggregate one channel over the rows already filtered to a single bin."""
+ x = x.astype(float)
+ dt = dt.astype(float)
+ return {
+ "n_samples": len(x),
+ "sum_dt": float(dt.sum()),
+ "sum_x_dt": float((x * dt).sum()),
+ "sum_x2_dt": float((x**2 * dt).sum()),
+ "min_x": float(x.min()),
+ "max_x": float(x.max()),
+ }
+
+
+# ── Scalars ─────────────────────────────────────────────────────────────────
+
+
+def compute_scalars(
+ df: pd.DataFrame,
+ flow_to_m3s: float = FLOW_TO_M3S,
+ rho_cp: float = RHO_CP,
+) -> dict[str, float]:
+ """Return per-run scalar statistics."""
+ dt = df["dt"].astype(float)
+ scalars: dict[str, float] = {}
+
+ scalars["duration_s"] = float(dt.sum())
+
+ field_on = df[FIELD_COL].astype(float) > FIELD_THRESHOLD
+ scalars["duration_field_on_s"] = float(dt[field_on].sum())
+
+ if "Ptot" in df.columns:
+ ptot = df["Ptot"].astype(float)
+ scalars["energy_j"] = float((ptot * dt).sum())
+
+ if all(c in df.columns for c in ("tsb", "teb", "debitbrut")):
+ delta_t = df["tsb"].astype(float) - df["teb"].astype(float)
+ flow_m3s = df["debitbrut"].astype(float) * flow_to_m3s
+ heat_w = delta_t * flow_m3s * rho_cp
+ scalars["heat_extracted_j"] = float((heat_w * dt).sum())
+
+ return scalars
+
+
+def insert_scalars(con, od_id: int, scalars: dict[str, float]) -> None:
+ for channel, value in scalars.items():
+ con.execute(
+ "INSERT OR REPLACE INTO op_run_scalars VALUES (?, ?, ?)",
+ [od_id, channel, value],
+ )
+
+
+# ── Site-level bin stats ─────────────────────────────────────────────────────
+
+
+def compute_site_bin_stats(
+ df: pd.DataFrame,
+ bins: list[tuple],
+ channels: list[str],
+) -> list[dict]:
+ """Return rows for op_site_bin_stats (missing channels are silently skipped)."""
+ field = df[FIELD_COL].astype(float)
+ bin_low = _assign_bins(field, bins)
+ rows = []
+ for low, high in bins:
+ mask = bin_low == low
+ sub = df[mask]
+ if sub.empty:
+ continue
+ for ch in channels:
+ if ch not in sub.columns:
+ continue
+ agg = _bin_agg(sub[ch], sub["dt"])
+ rows.append(
+ {"field_bin_low": low, "field_bin_high": high, "channel": ch, **agg}
+ )
+ return rows
+
+
+def insert_site_bin_stats(con, od_id: int, rows: list[dict]) -> None:
+ for r in rows:
+ con.execute(
+ """
+ INSERT OR REPLACE INTO op_site_bin_stats
+ (operationaldata_id, field_bin_low, field_bin_high, channel,
+ n_samples, sum_dt, sum_x_dt, sum_x2_dt, min_x, max_x)
+ VALUES (?,?,?,?,?,?,?,?,?,?)
+ """,
+ [
+ od_id,
+ r["field_bin_low"],
+ r["field_bin_high"],
+ r["channel"],
+ r["n_samples"],
+ r["sum_dt"],
+ r["sum_x_dt"],
+ r["sum_x2_dt"],
+ r["min_x"],
+ r["max_x"],
+ ],
+ )
+
+
+# ── Per-part bin stats ────────────────────────────────────────────────────────
+
+
+def compute_part_bin_stats(
+ df: pd.DataFrame,
+ bins: list[tuple],
+ part_name: str,
+ coil_index: int,
+) -> list[dict]:
+ """Return rows for op_part_bin_stats for one part/coil.
+
+ Channels computed:
+ Icoil — coil current
+ Ucoil — coil voltage
+ hoop_stress_proxy — I^2, proportional to hoop stress (sigma_theta ∝ I^2)
+
+ Only rows where |Icoil| > CURRENT_THRESHOLD are included so that idle
+ periods (field off, I ≈ 0) do not dilute the distributions.
+ """
+ i_col = f"Icoil{coil_index}"
+ u_col = f"Ucoil{coil_index}"
+ if i_col not in df.columns:
+ return []
+
+ field = df[FIELD_COL].astype(float)
+ icoil = df[i_col].astype(float)
+ active = icoil.abs() > CURRENT_THRESHOLD
+ bin_low = _assign_bins(field, bins)
+
+ rows = []
+ for low, high in bins:
+ mask = (bin_low == low) & active
+ sub = df[mask]
+ if sub.empty:
+ continue
+
+ i_sub = sub[i_col].astype(float)
+ dt_sub = sub["dt"]
+
+ # Icoil
+ rows.append(
+ {
+ "part_name": part_name,
+ "field_bin_low": low,
+ "field_bin_high": high,
+ "channel": "Icoil",
+ **_bin_agg(i_sub, dt_sub),
+ }
+ )
+
+ # Ucoil
+ if u_col in sub.columns:
+ rows.append(
+ {
+ "part_name": part_name,
+ "field_bin_low": low,
+ "field_bin_high": high,
+ "channel": "Ucoil",
+ **_bin_agg(sub[u_col].astype(float), dt_sub),
+ }
+ )
+
+ # Hoop stress proxy (I^2)
+ rows.append(
+ {
+ "part_name": part_name,
+ "field_bin_low": low,
+ "field_bin_high": high,
+ "channel": "hoop_stress_proxy",
+ **_bin_agg(i_sub**2, dt_sub),
+ }
+ )
+
+ return rows
+
+
+def insert_part_bin_stats(con, od_id: int, rows: list[dict]) -> None:
+ for r in rows:
+ con.execute(
+ """
+ INSERT OR REPLACE INTO op_part_bin_stats
+ (operationaldata_id, part_name, field_bin_low, field_bin_high, channel,
+ n_samples, sum_dt, sum_x_dt, sum_x2_dt, min_x, max_x)
+ VALUES (?,?,?,?,?,?,?,?,?,?,?)
+ """,
+ [
+ od_id,
+ r["part_name"],
+ r["field_bin_low"],
+ r["field_bin_high"],
+ r["channel"],
+ r["n_samples"],
+ r["sum_dt"],
+ r["sum_x_dt"],
+ r["sum_x2_dt"],
+ r["min_x"],
+ r["max_x"],
+ ],
+ )
+
+
+# ---------------------------------------------------------------------------
+# Top-level ingestion
+# ---------------------------------------------------------------------------
+
+
+def ingest_site(
+ site_name: str,
+ db_path: str,
+ records_dir: str,
+ od_type: str | None = None,
+ bins: list[tuple] = DEFAULT_BINS,
+ site_channels: list[str] = SITE_CHANNELS,
+ flow_to_m3s: float = FLOW_TO_M3S,
+ rho_cp: float = RHO_CP,
+ reprocess: bool = False,
+ verbose: bool = True,
+) -> dict:
+ """Process all operationaldata files for *site_name* and persist stats.
+
+ Parameters
+ ----------
+ site_name: site FK (must exist in the sites table)
+ db_path: path to the DuckDB file
+ records_dir: directory containing the raw record files
+ od_type: filter operationaldata by type (e.g. 'pupitre'), or None for all
+ bins: list of (low, high) field bins in Tesla
+ site_channels: columns to track in op_site_bin_stats
+ flow_to_m3s: unit conversion for debitbrut → m³/s (default: 1/3600 for m³/h)
+ rho_cp: water rho*cp in J/(m³·K) (default: 4 186 000)
+ reprocess: if True, overwrite already-processed files
+ verbose: print progress lines
+ """
+ con = duckdb.connect(db_path)
+ ensure_schema(con)
+
+ od_df = get_operationaldata(con, site_name, od_type)
+ parts = get_site_parts(con, site_name)
+ records_path = Path(records_dir)
+
+ results = {"new": 0, "skipped": 0, "errors": []}
+
+ for _, row in od_df.iterrows():
+ od_id = int(row["id"])
+ filename = row["file"]
+
+ if not reprocess and is_processed(con, od_id):
+ results["skipped"] += 1
+ continue
+
+ path = records_path / filename
+ df = load_file(path)
+ if df is None:
+ results["errors"].append(filename)
+ continue
+
+ if verbose:
+ print(f" processing {filename} ({len(df)} rows)")
+
+ try:
+ # 1. Scalar stats
+ scalars = compute_scalars(df, flow_to_m3s, rho_cp)
+ insert_scalars(con, od_id, scalars)
+
+ # 2. Site-level bin stats
+ site_rows = compute_site_bin_stats(df, bins, site_channels)
+ insert_site_bin_stats(con, od_id, site_rows)
+
+ # 3. Per-part bin stats
+ for _, part in parts.iterrows():
+ part_rows = compute_part_bin_stats(
+ df, bins, part["part_name"], int(part["coil_index"])
+ )
+ insert_part_bin_stats(con, od_id, part_rows)
+
+ mark_processed(con, od_id, df, bins)
+ results["new"] += 1
+
+ except Exception as exc:
+ results["errors"].append((filename, str(exc)))
+ if verbose:
+ print(f" [ERROR] {filename}: {exc}")
+
+ con.close()
+
+ if verbose:
+ print(
+ f"\nDone — {results['new']} processed, "
+ f"{results['skipped']} skipped, "
+ f"{len(results['errors'])} errors"
+ )
+ return results
+
+
+# ---------------------------------------------------------------------------
+# CLI
+# ---------------------------------------------------------------------------
+
+
+def _parse_bins(s: str) -> list[tuple[float, float]]:
+ """Parse '0:0.1,0.1:5,5:10' into [(0.0, 0.1), (0.1, 5.0), (5.0, 10.0)]."""
+ bins = []
+ for pair in s.split(","):
+ lo, hi = pair.strip().split(":")
+ bins.append((float(lo), float(hi)))
+ return bins
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(
+ description="Ingest operational statistics into DuckDB.",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=__doc__,
+ )
+ parser.add_argument("--db", default=DEFAULT_DB, help="DuckDB file path")
+ parser.add_argument(
+ "--records-base",
+ default=DEFAULT_RECORDS_BASE,
+ dest="records_base",
+ help="Directory of record files",
+ )
+ parser.add_argument("--site", required=True, help="Site name (FK)")
+ parser.add_argument(
+ "--type", default=None, help="Filter operationaldata by type, e.g. 'pupitre'"
+ )
+ parser.add_argument(
+ "--bins",
+ default=None,
+ help="Field bins as 'low1:high1,low2:high2,...' (default: built-in 7-bin set)",
+ )
+ parser.add_argument(
+ "--channels",
+ default=",".join(SITE_CHANNELS),
+ help="Comma-separated site-level channels (default: Pmagnet,Ptot,tsb,teb,debitbrut)",
+ )
+ parser.add_argument(
+ "--flow-to-m3s",
+ type=float,
+ default=FLOW_TO_M3S,
+ help="Unit conversion: debitbrut → m³/s (default 1/3600 for m³/h input)",
+ )
+ parser.add_argument(
+ "--reprocess", action="store_true", help="Re-compute already-processed files"
+ )
+ parser.add_argument("--quiet", action="store_true", help="Suppress per-file output")
+ args = parser.parse_args()
+
+ bins = _parse_bins(args.bins) if args.bins else DEFAULT_BINS
+ channels = [c.strip() for c in args.channels.split(",") if c.strip()]
+
+ ingest_site(
+ site_name=args.site,
+ db_path=args.db,
+ records_dir=args.records_base,
+ od_type=args.type,
+ bins=bins,
+ site_channels=channels,
+ flow_to_m3s=args.flow_to_m3s,
+ reprocess=args.reprocess,
+ verbose=not args.quiet,
+ )
+
+
+if __name__ == "__main__":
+ main()
diff --git a/to_duckdb/config.py b/to_duckdb/config.py
new file mode 100644
index 0000000..94a5263
--- /dev/null
+++ b/to_duckdb/config.py
@@ -0,0 +1,9 @@
+"""
+Shared configuration for the to_duckdb CLI tools.
+
+Only genuinely cross-cutting values live here. Domain-specific constants
+(bin edges, physical thresholds, channel lists, filesystem layout) stay in
+the module that owns them.
+"""
+
+DEFAULT_DB = "magnetdb.duckdb"
diff --git a/to_duckdb/conftest.py b/to_duckdb/conftest.py
new file mode 100644
index 0000000..3c105ad
--- /dev/null
+++ b/to_duckdb/conftest.py
@@ -0,0 +1,6 @@
+"""Ensure the to_duckdb directory is on sys.path so schema/crud can be imported."""
+
+import sys
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).parent))
diff --git a/to_duckdb/crud.py b/to_duckdb/crud.py
new file mode 100644
index 0000000..2b9684d
--- /dev/null
+++ b/to_duckdb/crud.py
@@ -0,0 +1,1713 @@
+"""
+crud.py
+=======
+CRUD helpers for the student magnetdb DuckDB.
+
+All functions accept an open ``duckdb.DuckDBPyConnection``.
+Callers are responsible for opening, committing, and closing the connection
+and for calling ``schema.ensure_schema(con)`` before the first write.
+
+Public API
+----------
+exists(con, table, name)
+load_geometry_json(path)
+infer_magnet_type(parts)
+
+insert_material(con, mat, verbose)
+view_materials(con)
+view_material(con, name)
+delete_material(con, name)
+insert_part(con, part, verbose)
+insert_magnet(con, data, magnet_type, verbose)
+insert_magnet_parts(con, magnet_name, parts, verbose)
+insert_magnet_part_row(con, magnet_name, part_name, rank, coil_index)
+check_geometry_data(con, name)
+print_geometry_check(results)
+
+parse_timestamp(value)
+insert_site(con, data, verbose, create_housing)
+insert_housing_config_from_magnetrun(con, housing_name, verbose)
+insert_site_magnets(con, site_name, magnet_entries, verbose)
+insert_experiments(con, site_name, records, verbose)
+
+update_site_magnet(con, site_name, magnet_name, **kwargs)
+
+insert_overview_record(con, record, site_name, verbose)
+upsert_overview_record(con, record, site_name, verbose)
+insert_overview_record_from_dict(con, data, site_name, verbose, upsert)
+attach_site_to_overview_record(con, filename, site_name, verbose)
+"""
+
+import json
+import re
+from pathlib import Path
+from typing import Any
+
+from schema import COIL_TYPES
+
+# ---------------------------------------------------------------------------
+# Housing config derivation constants
+# ---------------------------------------------------------------------------
+
+_COIL_TO_SUFFIX: dict[str, str] = {"Insert": "H", "Bitter": "B"}
+_SUFFIX_TO_COIL: dict[str, str] = {v: k for k, v in _COIL_TO_SUFFIX.items()}
+_H_UCOILS: list[str] = [f"Ucoil{i}" for i in range(1, 15)]
+_B_UCOILS: list[str] = ["Ucoil15", "Ucoil16"]
+
+_PIGBROTHER_FORMULA_MAP: dict[str, dict] = {
+ "Courants_Alimentations/Référence_GR1": {
+ "formula": "Courants_Alimentations/Référence_GR1 = Référence_A1 + Référence_A2",
+ "symbol": "I_ref_GR1",
+ "unit": "ampere",
+ "label": "GR1 Reference Current",
+ "description": "Group 1 reference current sum from power supply outputs",
+ },
+ "Courants_Alimentations/Référence_GR2": {
+ "formula": "Courants_Alimentations/Référence_GR2 = Référence_A3 + Référence_A4",
+ "symbol": "I_ref_GR2",
+ "unit": "ampere",
+ "label": "GR2 Reference Current",
+ "description": "Group 2 reference current sum from power supply outputs",
+ },
+}
+
+# ---------------------------------------------------------------------------
+# JSON loading
+# ---------------------------------------------------------------------------
+
+_TRAILING_COMMA_RE = re.compile(r",\s*([}\]])")
+
+
+def load_json(path) -> dict:
+ """Read a JSON file, stripping trailing commas before parsing.
+
+ Many hand-edited or tool-generated JSON files contain trailing commas
+ (e.g. ``{"a": 1,}``), which the standard ``json`` module rejects.
+ This function removes them so such files load cleanly.
+ """
+ text = Path(path).read_text()
+ text = _TRAILING_COMMA_RE.sub(r"\1", text)
+ return json.loads(text)
+
+
+# ---------------------------------------------------------------------------
+# Generic helpers
+# ---------------------------------------------------------------------------
+
+
+def exists(con, table: str, name: str) -> bool:
+ return con.execute(f"SELECT 1 FROM {table} WHERE name = ?", [name]).fetchone() is not None
+
+
+def load_geometry_json(geometry_path) -> str | None:
+ """Serialise a geometry YAML via python_magnetgeo; returns None on failure.
+
+ Resolves the path to absolute and chdir to its parent before loading so
+ that relative paths embedded in the YAML (e.g. sub-component files) are
+ resolved correctly.
+ """
+ if not geometry_path:
+ return None
+ path = Path(geometry_path).resolve()
+ if not path.exists():
+ return None
+ try:
+ import os
+ import yaml as _yaml
+ from python_magnetgeo.deserialize import serialize_instance
+ orig_dir = os.getcwd()
+ try:
+ os.chdir(path.parent)
+ with open(path.name) as f:
+ obj = _yaml.load(f, Loader=_yaml.FullLoader)
+ finally:
+ os.chdir(orig_dir)
+ return json.dumps(obj, default=serialize_instance)
+ except Exception as exc:
+ print(f" [WARN] Could not serialize geometry '{geometry_path}': {exc}")
+ return None
+
+
+def infer_magnet_type(parts: list[dict]) -> str:
+ """Infer magnet assembly type from the types of its constituent parts."""
+ coil_types = {p.get("type") for p in parts if p.get("type") in COIL_TYPES}
+ if coil_types == {"helix"}:
+ return "insert"
+ if coil_types == {"bitter"}:
+ return "bitters"
+ if len(coil_types) > 1:
+ return "hybrid"
+ return "unknown"
+
+
+# ---------------------------------------------------------------------------
+# Material
+# ---------------------------------------------------------------------------
+
+
+def insert_material(con, mat: dict, verbose: bool = True) -> None:
+ """Insert a material row; skip silently if it already exists."""
+ name = mat["name"]
+ if exists(con, "materials", name):
+ if verbose:
+ print(f" ~ material {name} (already exists, skipped)")
+ return
+ con.execute(
+ "INSERT INTO materials VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)",
+ [
+ name,
+ mat.get("description") or None,
+ mat.get("nuance") or None,
+ mat.get("t_ref"),
+ mat.get("volumic_mass"),
+ mat.get("specific_heat"),
+ mat.get("alpha"),
+ mat.get("electrical_conductivity"),
+ mat.get("thermal_conductivity"),
+ mat.get("magnet_permeability"),
+ mat.get("young"),
+ mat.get("poisson"),
+ mat.get("expansion_coefficient"),
+ mat.get("rpe"),
+ ],
+ )
+ if verbose:
+ print(f" + material {name} [{mat.get('nuance', '?')}]")
+
+
+def view_materials(con, nuance_filter: str | None = None) -> None:
+ conditions, params = [], []
+ if nuance_filter:
+ conditions.append("nuance = ?")
+ params.append(nuance_filter)
+ where = f"WHERE {' AND '.join(conditions)}" if conditions else ""
+ rows = con.execute(
+ f"SELECT name, nuance, t_ref FROM materials {where} ORDER BY name", params
+ ).fetchall()
+ if not rows:
+ qualifier = f" with nuance '{nuance_filter}'" if nuance_filter else ""
+ print(f"No materials{qualifier} in database.")
+ return
+ print(f"{'Name':<30} {'Nuance':<15} t_ref")
+ print("-" * 55)
+ for name, nuance, t_ref in rows:
+ print(f"{name:<30} {nuance or '?':<15} {t_ref or ''}")
+
+
+def view_material(con, name: str) -> None:
+ row = con.execute(
+ "SELECT name, description, nuance, t_ref, volumic_mass, specific_heat, alpha, "
+ "electrical_conductivity, thermal_conductivity, magnet_permeability, "
+ "young, poisson, expansion_coefficient, rpe "
+ "FROM materials WHERE name = ?",
+ [name],
+ ).fetchone()
+ if not row:
+ print(f"Material '{name}' not found.")
+ return
+ labels = [
+ "description", "nuance", "t_ref", "volumic_mass", "specific_heat", "alpha",
+ "electrical_conductivity", "thermal_conductivity", "magnet_permeability",
+ "young", "poisson", "expansion_coefficient", "rpe",
+ ]
+ print(f"Material: {row[0]}")
+ for label, value in zip(labels, row[1:]):
+ if value is not None and value != "":
+ print(f" {label:<26}: {value}")
+
+
+def delete_material(con, name: str) -> None:
+ if not exists(con, "materials", name):
+ print(f"Material '{name}' not found.")
+ return
+ ref = con.execute(
+ "SELECT name FROM parts WHERE material_name = ? LIMIT 1", [name]
+ ).fetchone()
+ if ref:
+ print(f"Error: material '{name}' is referenced by part '{ref[0]}'. Remove the part first.")
+ return
+ con.execute("DELETE FROM materials WHERE name = ?", [name])
+ print(f"Deleted material '{name}'.")
+
+
+# ---------------------------------------------------------------------------
+# Part
+# ---------------------------------------------------------------------------
+
+
+def insert_part(con, part: dict, verbose: bool = True) -> None:
+ """Insert a part row; skip silently if it already exists.
+
+ ``part`` may carry ``material_name`` (seeds format) or a nested
+ ``material.name`` dict (JSON-export format).
+ """
+ name = part["name"]
+ if exists(con, "parts", name):
+ if verbose:
+ print(f" ~ part {name} (already exists, skipped)")
+ return
+ material_name = part.get("material_name") or (part.get("material") or {}).get("name")
+ geometry_data = part.get("geometry_data") or load_geometry_json(part.get("geometry") or part.get("geometry_config"))
+ con.execute(
+ """
+ INSERT INTO parts
+ (name, type, status, material_name, geometry, geometry_data, cad, design_office_reference)
+ VALUES (?,?,?,?,?,?,?,?)
+ """,
+ [
+ name,
+ part.get("type"),
+ part.get("status"),
+ material_name,
+ part.get("geometry") or None,
+ geometry_data,
+ part.get("cad") or None,
+ part.get("design_office_reference") or None,
+ ],
+ )
+ if verbose:
+ print(f" + part {name} [{part.get('type', '?')}]")
+
+
+# ---------------------------------------------------------------------------
+# Magnet
+# ---------------------------------------------------------------------------
+
+
+def insert_magnet(con, data: dict, magnet_type: str, verbose: bool = True) -> None:
+ """Insert a magnet row; skip silently if it already exists."""
+ name = data["name"]
+ if exists(con, "magnets", name):
+ if verbose:
+ print(f" ~ magnet {name} (already exists, skipped)")
+ return
+ geometry_data = data.get("geometry_data") or load_geometry_json(data.get("geometry") or data.get("geometry_config"))
+ con.execute(
+ """
+ INSERT INTO magnets
+ (name, type, status, geometry, geometry_data, design_office_reference)
+ VALUES (?,?,?,?,?,?)
+ """,
+ [
+ name,
+ magnet_type,
+ data.get("status"),
+ data.get("geometry") or None,
+ geometry_data,
+ data.get("design_office_reference") or None,
+ ],
+ )
+ if verbose:
+ print(f" + magnet {name} [{magnet_type}] {data.get('status', '')}")
+
+
+def insert_magnet_parts(con, magnet_name: str, parts: list[dict], verbose: bool = True) -> None:
+ """Link parts to a magnet, computing coil_index for helix/bitter parts.
+
+ ``parts`` must be a list of part dicts, each with at least ``name`` and
+ ``type`` keys (i.e. the raw parts list from the magnet JSON export).
+ """
+ coil_counter = 0
+ inserted = 0
+ skipped = 0
+ for rank, part in enumerate(parts):
+ part_name = part["name"]
+ part_type = part.get("type", "")
+
+ coil_index = None
+ if part_type in COIL_TYPES:
+ coil_counter += 1
+ coil_index = coil_counter
+
+ if con.execute(
+ "SELECT 1 FROM magnet_parts WHERE magnet_name = ? AND part_name = ?",
+ [magnet_name, part_name],
+ ).fetchone():
+ skipped += 1
+ continue
+
+ con.execute(
+ "INSERT INTO magnet_parts VALUES (?,?,?,?)",
+ [magnet_name, part_name, rank, coil_index],
+ )
+ inserted += 1
+
+ if verbose:
+ print(
+ f" + magnet_parts {inserted} inserted, {skipped} already present"
+ f" ({coil_counter} coil channel(s))"
+ )
+
+
+def insert_magnet_part_row(
+ con, magnet_name: str, part_name: str, rank: int, coil_index: int | None
+) -> None:
+ """Insert a single pre-computed magnet_parts row (used by seeds_to_duckdb)."""
+ if con.execute(
+ "SELECT 1 FROM magnet_parts WHERE magnet_name = ? AND part_name = ?",
+ [magnet_name, part_name],
+ ).fetchone():
+ return
+ con.execute(
+ "INSERT INTO magnet_parts VALUES (?,?,?,?)",
+ [magnet_name, part_name, rank, coil_index],
+ )
+
+
+# ---------------------------------------------------------------------------
+# Site
+# ---------------------------------------------------------------------------
+
+
+def parse_timestamp(value) -> str | None:
+ if not value or str(value).lower() in ("none", "null", ""):
+ return None
+ return str(value)
+
+
+def insert_site(
+ con, data: dict, verbose: bool = True, create_housing: bool = True
+) -> None:
+ """Insert a site row; skip silently if it already exists.
+
+ The ``housing`` field in *data* is treated as a ``housing_config.name``
+ foreign key.
+
+ Parameters
+ ----------
+ con:
+ Open DuckDB connection.
+ data:
+ Site dict with at least a ``name`` key. ``housing`` must match a
+ ``housing_config.name`` value.
+ verbose:
+ Print status lines.
+ create_housing:
+ When ``True`` (default) and the housing config is not yet in the DB,
+ auto-create it from the ``python_magnetrun`` bundled JSON files. Set
+ to ``False`` to raise :exc:`ValueError` instead when the config is
+ missing.
+ """
+ name = data["name"]
+ if exists(con, "sites", name):
+ if verbose:
+ print(f" ~ site {name} (already exists, skipped)")
+ return
+
+ housing = data.get("housing") or None
+ if housing is not None:
+ if con.execute(
+ "SELECT 1 FROM housing_config WHERE name = ?", [housing]
+ ).fetchone() is None:
+ if create_housing:
+ insert_housing_config_from_magnetrun(con, housing, verbose=verbose)
+ else:
+ raise ValueError(
+ f"Housing config '{housing}' not found in housing_config table. "
+ "Call insert_housing_config() first, or pass create_housing=True."
+ )
+
+ con.execute(
+ "INSERT INTO sites VALUES (?,?,?,?,?,?)",
+ [
+ name,
+ data.get("description") or None,
+ data.get("status", "in_study"),
+ housing,
+ parse_timestamp(data.get("commissioned_at")),
+ parse_timestamp(data.get("decommissioned_at")),
+ ],
+ )
+ if verbose:
+ print(f" + site {name} [{housing or '?'}] {data.get('status', '')}")
+
+
+def _magnet_entry_name(entry) -> str:
+ return entry if isinstance(entry, str) else entry["name"]
+
+
+def insert_site_magnets(
+ con, site_name: str, magnet_entries: list, verbose: bool = True
+) -> None:
+ """Link magnets to a site.
+
+ Each entry in *magnet_entries* is either a plain magnet name string or a
+ dict with optional positional/temporal fields (z_offset, r_offset,
+ parallax, commissioned_at, decommissioned_at, metadata).
+ """
+ for entry in magnet_entries:
+ magnet_name = _magnet_entry_name(entry)
+ extra = entry if isinstance(entry, dict) else {}
+
+ if con.execute(
+ "SELECT 1 FROM site_magnets WHERE site_name = ? AND magnet_name = ?",
+ [site_name, magnet_name],
+ ).fetchone():
+ if verbose:
+ print(f" ~ magnet {magnet_name} (already linked, skipped)")
+ continue
+
+ con.execute(
+ """
+ INSERT INTO site_magnets
+ (site_name, magnet_name, z_offset, r_offset, parallax,
+ commissioned_at, decommissioned_at, metadata)
+ VALUES (?,?,?,?,?,?,?,?)
+ """,
+ [
+ site_name,
+ magnet_name,
+ extra.get("z_offset", 0.0),
+ extra.get("r_offset", 0.0),
+ extra.get("parallax", 0.0),
+ parse_timestamp(extra.get("commissioned_at")),
+ parse_timestamp(extra.get("decommissioned_at")),
+ json.dumps(extra.get("metadata", {})),
+ ],
+ )
+ if verbose:
+ row = con.execute("SELECT type FROM magnets WHERE name = ?", [magnet_name]).fetchone()
+ print(f" + magnet {magnet_name} ({row[0] if row else '?'})")
+
+
+def insert_experiments(
+ con, site_name: str, records: list[dict], verbose: bool = True
+) -> None:
+ """Insert experiment/record rows for a site; skip duplicates by file name."""
+ row = con.execute("SELECT COALESCE(MAX(id), 0) FROM experiments").fetchone()
+ next_id = (row[0] or 0) + 1
+ inserted = 0
+ skipped = 0
+
+ for i, rec in enumerate(records):
+ file_name = rec.get("file") or rec.get("name") or rec.get("record_file")
+ if con.execute(
+ "SELECT 1 FROM experiments WHERE site_name = ? AND file = ?",
+ [site_name, file_name],
+ ).fetchone():
+ skipped += 1
+ continue
+
+ con.execute(
+ "INSERT INTO experiments VALUES (?,?,?,?,?,'pending')",
+ [
+ next_id + i,
+ rec.get("name") or file_name,
+ rec.get("description") or None,
+ file_name,
+ site_name,
+ ],
+ )
+ inserted += 1
+
+ if verbose:
+ print(f" + records {inserted} inserted, {skipped} already present")
+
+
+# ---------------------------------------------------------------------------
+# Update helpers
+# ---------------------------------------------------------------------------
+
+_FLOAT_FIELDS = frozenset({"z_offset", "r_offset", "parallax"})
+_TIMESTAMP_FIELDS = frozenset({"commissioned_at", "decommissioned_at"})
+_JSON_FIELDS = frozenset({"metadata"})
+_SITE_MAGNET_FIELDS = _FLOAT_FIELDS | _TIMESTAMP_FIELDS | _JSON_FIELDS
+
+
+# ---------------------------------------------------------------------------
+# Geometry-data check helpers
+# ---------------------------------------------------------------------------
+
+
+def check_geometry_data(con, name: str | None = None) -> list[dict]:
+ """Return one status dict per magnet (and its parts) describing geometry_data coverage.
+
+ Each dict has the keys:
+
+ ``magnet``
+ Magnet name.
+ ``magnet_has_geometry``
+ True when ``magnets.geometry_data IS NOT NULL``.
+ ``parts``
+ List of ``{"name": str, "type": str, "has_geometry": bool}`` for every
+ linked part, ordered by rank.
+ ``parts_ok``
+ Number of parts with ``geometry_data IS NOT NULL``.
+ ``parts_total``
+ Total number of linked parts.
+
+ Parameters
+ ----------
+ con : open DuckDB connection
+ name : restrict to one magnet; ``None`` checks all magnets
+ """
+ if name:
+ magnet_rows = con.execute(
+ "SELECT name, geometry_data IS NOT NULL FROM magnets WHERE name = ?",
+ [name],
+ ).fetchall()
+ else:
+ magnet_rows = con.execute(
+ "SELECT name, geometry_data IS NOT NULL FROM magnets ORDER BY name"
+ ).fetchall()
+
+ results = []
+ for magnet_name, magnet_has_geo in magnet_rows:
+ part_rows = con.execute(
+ """
+ SELECT p.name, p.type, p.geometry_data IS NOT NULL
+ FROM magnet_parts mp
+ JOIN parts p ON p.name = mp.part_name
+ WHERE mp.magnet_name = ?
+ ORDER BY mp.rank
+ """,
+ [magnet_name],
+ ).fetchall()
+ parts = [{"name": pn, "type": pt, "has_geometry": bool(hg)} for pn, pt, hg in part_rows]
+ results.append({
+ "magnet": magnet_name,
+ "magnet_has_geometry": bool(magnet_has_geo),
+ "parts": parts,
+ "parts_ok": sum(1 for p in parts if p["has_geometry"]),
+ "parts_total": len(parts),
+ })
+ return results
+
+
+def print_geometry_check(results: list[dict]) -> None:
+ """Print a human-readable geometry_data coverage report."""
+ if not results:
+ print("No magnets found.")
+ return
+
+ for r in results:
+ magnet_ok = "✓" if r["magnet_has_geometry"] else "✗"
+ parts_ok = r["parts_ok"]
+ parts_tot = r["parts_total"]
+ status = "OK" if r["magnet_has_geometry"] and parts_ok == parts_tot else "INCOMPLETE"
+ print(f"[{status}] {r['magnet']} assembly={magnet_ok} parts={parts_ok}/{parts_tot}")
+ for p in r["parts"]:
+ mark = "✓" if p["has_geometry"] else "✗"
+ print(f" {mark} {p['name']} ({p['type']})")
+
+
+# ---------------------------------------------------------------------------
+# View helpers
+# ---------------------------------------------------------------------------
+
+
+def view_magnets(
+ con,
+ type_filter: str | None = None,
+ status_filter: str | None = None,
+) -> None:
+ conditions, params = [], []
+ if type_filter:
+ conditions.append("type = ?")
+ params.append(type_filter)
+ if status_filter:
+ conditions.append("status = ?")
+ params.append(status_filter)
+ where = f"WHERE {' AND '.join(conditions)}" if conditions else ""
+ rows = con.execute(
+ f"SELECT name, type, status FROM magnets {where} ORDER BY name", params
+ ).fetchall()
+ if not rows:
+ parts = []
+ if type_filter:
+ parts.append(f"type '{type_filter}'")
+ if status_filter:
+ parts.append(f"status '{status_filter}'")
+ qualifier = " matching " + ", ".join(parts) if parts else ""
+ print(f"No magnets{qualifier} in database.")
+ return
+ print(f"{'Name':<30} {'Type':<10} Status")
+ print("-" * 55)
+ for name, type_, status in rows:
+ print(f"{name:<30} {type_ or '?':<10} {status or ''}")
+
+
+def view_magnet(con, name: str) -> None:
+ row = con.execute(
+ "SELECT name, type, status, design_office_reference FROM magnets WHERE name = ?",
+ [name],
+ ).fetchone()
+ if not row:
+ print(f"Magnet '{name}' not found.")
+ return
+ print(f"Magnet : {row[0]}")
+ print(f" type : {row[1] or '?'}")
+ print(f" status: {row[2] or ''}")
+ print(f" ref : {row[3] or ''}")
+ parts = con.execute(
+ "SELECT p.name, p.type, mp.rank, mp.coil_index "
+ "FROM magnet_parts mp JOIN parts p ON mp.part_name = p.name "
+ "WHERE mp.magnet_name = ? ORDER BY mp.rank",
+ [name],
+ ).fetchall()
+ if parts:
+ print(f" parts ({len(parts)}):")
+ for pname, ptype, rank, coil_index in parts:
+ ci = f" coil#{coil_index}" if coil_index else ""
+ print(f" [{rank}] {pname} ({ptype or '?'}){ci}")
+
+
+def view_sites(
+ con,
+ housing_filter: str | None = None,
+ status_filter: str | None = None,
+) -> None:
+ conditions, params = [], []
+ if housing_filter:
+ conditions.append("housing = ?")
+ params.append(housing_filter)
+ if status_filter:
+ conditions.append("status = ?")
+ params.append(status_filter)
+ where = f"WHERE {' AND '.join(conditions)}" if conditions else ""
+ rows = con.execute(
+ f"SELECT name, housing, status FROM sites {where} ORDER BY name", params
+ ).fetchall()
+ if not rows:
+ parts = []
+ if housing_filter:
+ parts.append(f"housing '{housing_filter}'")
+ if status_filter:
+ parts.append(f"status '{status_filter}'")
+ qualifier = " matching " + ", ".join(parts) if parts else ""
+ print(f"No sites{qualifier} in database.")
+ return
+ print(f"{'Name':<40} {'Housing':<15} Status")
+ print("-" * 65)
+ for name, housing, status in rows:
+ print(f"{name:<40} {housing or '?':<15} {status or ''}")
+
+
+def view_site(con, name: str) -> None:
+ row = con.execute(
+ "SELECT name, housing, status, commissioned_at, decommissioned_at "
+ "FROM sites WHERE name = ?",
+ [name],
+ ).fetchone()
+ if not row:
+ print(f"Site '{name}' not found.")
+ return
+ print(f"Site : {row[0]}")
+ print(f" housing : {row[1] or '?'}")
+ print(f" status : {row[2] or ''}")
+ print(f" commissioned_at : {row[3] or ''}")
+ print(f" decommissioned_at: {row[4] or ''}")
+ magnets = con.execute(
+ "SELECT magnet_name, z_offset, r_offset "
+ "FROM site_magnets WHERE site_name = ? ORDER BY magnet_name",
+ [name],
+ ).fetchall()
+ if magnets:
+ print(f" magnets ({len(magnets)}):")
+ for mname, z, r in magnets:
+ print(f" {mname} (z={z}, r={r})")
+ count = con.execute(
+ "SELECT COUNT(*) FROM experiments WHERE site_name = ?", [name]
+ ).fetchone()[0]
+ print(f" experiments: {count}")
+
+
+# ---------------------------------------------------------------------------
+# View helpers — housing_config, experiments, operationaldata, overview_records
+# ---------------------------------------------------------------------------
+
+
+def view_housing_configs(con) -> None:
+ rows = con.execute(
+ "SELECT name, formats FROM housing_config ORDER BY name"
+ ).fetchall()
+ if not rows:
+ print("No housing configs in database.")
+ return
+ print(f"{'Name':<12} Formats")
+ print("-" * 50)
+ for name, formats in rows:
+ fmts = ", ".join(formats) if formats else "—"
+ print(f"{name:<12} {fmts}")
+
+
+def view_housing_config(con, name: str) -> None:
+ row = con.execute(
+ "SELECT name, coil_assignment, formats, extra_config "
+ "FROM housing_config WHERE name = ?",
+ [name],
+ ).fetchone()
+ if not row:
+ print(f"Housing config '{name}' not found.")
+ return
+ print(f"Housing: {row[0]}")
+ print(f" formats : {', '.join(row[2]) if row[2] else '—'}")
+ assignment = row[1] or {}
+ if assignment:
+ print(" coil_assignment:")
+ for coil, gr in assignment.items():
+ print(f" {coil} → {gr}")
+ extra = row[3]
+ if extra:
+ if isinstance(extra, str):
+ extra = json.loads(extra)
+ if isinstance(extra, dict):
+ for k, v in extra.items():
+ print(f" {k}: {v}")
+
+
+# SQL fragments for timestamp extraction from file paths (experiments / operationaldata
+# have no timestamp column; the timestamp is encoded in the filename).
+# Used only when --from / --to filtering is requested.
+#
+# _EXP_FILE_TS : pupitre TXT pattern "YYYY.MM.DD - HH:MM:SS.txt"
+# _OD_FILE_TS : COALESCE of pupitre + TDMS Overview/Archive (%y%m%d) +
+# TDMS Spike/Default (%y%m%d)
+#
+# NOTE: these strings reference the table aliases used in their respective queries
+# ("e.file" and "od.file"). They must NOT be used in f-string templates directly;
+# instead assign to a local variable first so that the regex quantifiers {N} are
+# treated as ordinary characters and not as f-string placeholders.
+_EXP_FILE_TS = (
+ "TRY_STRPTIME("
+ "regexp_extract(e.file, '(\\d{4}\\.\\d{2}\\.\\d{2} - \\d{2}:\\d{2}:\\d{2})', 1),"
+ " '%Y.%m.%d - %H:%M:%S')"
+)
+
+_OD_FILE_TS = (
+ "COALESCE("
+ "TRY_STRPTIME(regexp_extract(od.file,"
+ " '(\\d{4}\\.\\d{2}\\.\\d{2} - \\d{2}:\\d{2}:\\d{2})', 1), '%Y.%m.%d - %H:%M:%S'),"
+ " TRY_STRPTIME(regexp_extract(od.file,"
+ " '([0-9]{6}-[0-9]{4})\\.tdms$', 1), '%y%m%d-%H%M'),"
+ " TRY_STRPTIME(regexp_extract(od.file,"
+ " '(?:Spikes|Default)_([0-9]{6}-[0-9]{6})', 1), '%y%m%d-%H%M%S')"
+ ")"
+)
+
+
+def view_experiments(
+ con,
+ site_name: str | None = None,
+ magnet_name: str | None = None,
+ part_name: str | None = None,
+ from_ts: str | None = None,
+ to_ts: str | None = None,
+) -> None:
+ joins, conditions, params = [], [], []
+
+ if site_name:
+ conditions.append("e.site_name = ?")
+ params.append(site_name)
+ if magnet_name or part_name:
+ joins.append("JOIN site_magnets sm ON sm.site_name = e.site_name")
+ if magnet_name:
+ conditions.append("sm.magnet_name = ?")
+ params.append(magnet_name)
+ if part_name:
+ joins.append("JOIN magnet_parts mp ON mp.magnet_name = sm.magnet_name")
+ conditions.append("mp.part_name = ?")
+ params.append(part_name)
+
+ join_sql = " ".join(joins)
+ where = f"WHERE {' AND '.join(conditions)}" if conditions else ""
+ distinct = "DISTINCT " if (magnet_name or part_name) else ""
+
+ if from_ts or to_ts:
+ ts_expr = _EXP_FILE_TS
+ ts_conds, ts_params = [], list(params)
+ if from_ts:
+ ts_conds.append("file_ts >= CAST(? AS TIMESTAMP)")
+ ts_params.append(from_ts)
+ if to_ts:
+ ts_conds.append("file_ts <= CAST(? AS TIMESTAMP)")
+ ts_params.append(to_ts)
+ ts_where = "WHERE " + " AND ".join(ts_conds)
+ rows = con.execute(
+ f"SELECT id, name, file, site_name, status FROM ("
+ f"SELECT {distinct}e.id, e.name, e.file, e.site_name, e.status,"
+ f" {ts_expr} AS file_ts"
+ f" FROM experiments e {join_sql} {where}"
+ f") t {ts_where} ORDER BY site_name, id",
+ ts_params,
+ ).fetchall()
+ else:
+ rows = con.execute(
+ f"SELECT {distinct}e.id, e.name, e.file, e.site_name, e.status "
+ f"FROM experiments e {join_sql} {where} ORDER BY e.site_name, e.id",
+ params,
+ ).fetchall()
+
+ labels = []
+ if site_name:
+ labels.append(f"site={site_name}")
+ if magnet_name:
+ labels.append(f"magnet={magnet_name}")
+ if part_name:
+ labels.append(f"part={part_name}")
+ if from_ts:
+ labels.append(f"from={from_ts}")
+ if to_ts:
+ labels.append(f"to={to_ts}")
+ qualifier = " " + " ".join(labels) if labels else ""
+
+ if not rows:
+ print(f"No experiments{qualifier.replace(' ', ' for ', 1).replace(' ', ', ')}.")
+ return
+
+ print(f"experiments{qualifier} ({len(rows)} row(s))\n")
+ col_s = max((len(r[3] or "") for r in rows), default=20)
+ col_f = min(max((len(r[2] or "") for r in rows), default=40), 60)
+ print(f"{'ID':<6} {'Site':<{col_s}} {'File':<{col_f}} Status")
+ print("-" * (col_s + col_f + 14))
+ for id_, name, file_, site_, status in rows:
+ print(f"{id_:<6} {(site_ or ''):<{col_s}} {(file_ or '')[:col_f]:<{col_f}} {status or ''}")
+
+
+def view_operationaldata(
+ con,
+ site_name: str | None = None,
+ type_filter: str | None = None,
+ magnet_name: str | None = None,
+ part_name: str | None = None,
+ from_ts: str | None = None,
+ to_ts: str | None = None,
+) -> None:
+ joins, conditions, params = [], [], []
+
+ if site_name:
+ conditions.append("od.site_name = ?")
+ params.append(site_name)
+ if type_filter:
+ conditions.append("od.type = ?")
+ params.append(type_filter)
+ if magnet_name or part_name:
+ joins.append("JOIN site_magnets sm ON sm.site_name = od.site_name")
+ if magnet_name:
+ conditions.append("sm.magnet_name = ?")
+ params.append(magnet_name)
+ if part_name:
+ joins.append("JOIN magnet_parts mp ON mp.magnet_name = sm.magnet_name")
+ conditions.append("mp.part_name = ?")
+ params.append(part_name)
+
+ join_sql = " ".join(joins)
+ where = f"WHERE {' AND '.join(conditions)}" if conditions else ""
+ distinct = "DISTINCT " if (magnet_name or part_name) else ""
+
+ if from_ts or to_ts:
+ ts_expr = _OD_FILE_TS
+ ts_conds, ts_params = [], list(params)
+ if from_ts:
+ ts_conds.append("file_ts >= CAST(? AS TIMESTAMP)")
+ ts_params.append(from_ts)
+ if to_ts:
+ ts_conds.append("file_ts <= CAST(? AS TIMESTAMP)")
+ ts_params.append(to_ts)
+ ts_where = "WHERE " + " AND ".join(ts_conds)
+ rows = con.execute(
+ f"SELECT id, name, file, type, site_name, status FROM ("
+ f"SELECT {distinct}od.id, od.name, od.file, od.type, od.site_name, od.status,"
+ f" {ts_expr} AS file_ts"
+ f" FROM operationaldata od {join_sql} {where}"
+ f") t {ts_where} ORDER BY site_name, type, id",
+ ts_params,
+ ).fetchall()
+ else:
+ rows = con.execute(
+ f"SELECT {distinct}od.id, od.name, od.file, od.type, od.site_name, od.status "
+ f"FROM operationaldata od {join_sql} {where} ORDER BY od.site_name, od.type, od.id",
+ params,
+ ).fetchall()
+
+ labels = []
+ if site_name:
+ labels.append(f"site={site_name}")
+ if type_filter:
+ labels.append(f"type={type_filter}")
+ if magnet_name:
+ labels.append(f"magnet={magnet_name}")
+ if part_name:
+ labels.append(f"part={part_name}")
+ if from_ts:
+ labels.append(f"from={from_ts}")
+ if to_ts:
+ labels.append(f"to={to_ts}")
+ qualifier = " " + " ".join(labels) if labels else ""
+
+ if not rows:
+ print(f"No operationaldata{qualifier.replace(' ', ' for ', 1).replace(' ', ', ')}.")
+ return
+
+ print(f"operationaldata{qualifier} ({len(rows)} row(s))\n")
+ col_s = max((len(r[4] or "") for r in rows), default=20)
+ col_t = max((len(r[3] or "") for r in rows), default=10)
+ col_f = min(max((len(r[2] or "") for r in rows), default=40), 60)
+ print(f"{'ID':<6} {'Site':<{col_s}} {'Type':<{col_t}} {'File':<{col_f}} Status")
+ print("-" * (col_s + col_t + col_f + 16))
+ for id_, name, file_, type_, site_, status in rows:
+ print(f"{id_:<6} {(site_ or ''):<{col_s}} {(type_ or ''):<{col_t}} {(file_ or '')[:col_f]:<{col_f}} {status or ''}")
+
+
+def _duration_str(seconds: float | None) -> str:
+ if seconds is None:
+ return "?"
+ m, s = divmod(int(seconds), 60)
+ h, m = divmod(m, 60)
+ return f"{h:02d}:{m:02d}:{s:02d}" if h else f"{m:02d}:{s:02d}"
+
+
+def view_overview_records(
+ con,
+ site_name: str | None = None,
+ show_signatures: bool = False,
+ magnet_name: str | None = None,
+ part_name: str | None = None,
+ from_ts: str | None = None,
+ to_ts: str | None = None,
+) -> None:
+ joins, conditions, params = [], [], []
+
+ if site_name:
+ conditions.append("ovr.site_name = ?")
+ params.append(site_name)
+ if magnet_name or part_name:
+ joins.append("JOIN site_magnets sm ON sm.site_name = ovr.site_name")
+ if magnet_name:
+ conditions.append("sm.magnet_name = ?")
+ params.append(magnet_name)
+ if part_name:
+ joins.append("JOIN magnet_parts mp ON mp.magnet_name = sm.magnet_name")
+ conditions.append("mp.part_name = ?")
+ params.append(part_name)
+ if from_ts:
+ conditions.append("ovr.t0 >= CAST(? AS TIMESTAMP)")
+ params.append(from_ts)
+ if to_ts:
+ conditions.append("ovr.t0 <= CAST(? AS TIMESTAMP)")
+ params.append(to_ts)
+
+ join_sql = " ".join(joins)
+ where = f"WHERE {' AND '.join(conditions)}" if conditions else ""
+ distinct = "DISTINCT " if (magnet_name or part_name) else ""
+
+ rows = con.execute(
+ f"SELECT {distinct}ovr.filename, ovr.housing, ovr.mode, ovr.t0, ovr.duration, ovr.teb, ovr.bp, "
+ f"len(ovr.sources_overview) + len(ovr.sources_archive) + len(ovr.sources_pupitre) "
+ f"+ len(ovr.sources_default) + len(ovr.sources_trigger) + len(ovr.sources_spike) "
+ f"+ len(ovr.sources_hybrid_kHz) + len(ovr.sources_hybrid_rms) + len(ovr.sources_hybrid_trigger) "
+ f" AS n_sources, "
+ f"ovr.signatures, ovr.sync_info "
+ f"FROM overview_records ovr {join_sql} {where} ORDER BY ovr.t0 NULLS LAST, ovr.filename",
+ params,
+ ).fetchall()
+
+ labels = []
+ if site_name:
+ labels.append(f"site={site_name}")
+ if magnet_name:
+ labels.append(f"magnet={magnet_name}")
+ if part_name:
+ labels.append(f"part={part_name}")
+ if from_ts:
+ labels.append(f"from={from_ts}")
+ if to_ts:
+ labels.append(f"to={to_ts}")
+ qualifier = " " + " ".join(labels) if labels else ""
+
+ if not rows:
+ print(f"No overview_records{qualifier.replace(' ', ' for ', 1).replace(' ', ', ')}.")
+ return
+
+ print(f"overview_records{qualifier} ({len(rows)} row(s))\n")
+
+ col_f = max((len(r[0]) for r in rows), default=20)
+ col_m = max((len(r[2] or "") for r in rows), default=4)
+ print(
+ f"{'Filename':<{col_f}} {'t0':<19} {'Duration':<8} {'Mode':<{col_m}} teb bp n_src"
+ )
+ print("-" * (col_f + col_m + 65))
+
+ for filename, housing, mode, t0, duration, teb, bp, n_src, sigs, sync in rows:
+ t0_str = str(t0)[:19] if t0 else "—"
+ dur_str = _duration_str(duration)
+ print(
+ f"{filename:<{col_f}} {t0_str:<19} {dur_str:<8} {(mode or ''):<{col_m}}"
+ f" {teb or 0:5.1f} {bp or 0:5.1f} {n_src or 0}"
+ )
+
+ if show_signatures and sigs:
+ if isinstance(sigs, str):
+ sigs = json.loads(sigs)
+ if isinstance(sigs, dict):
+ for key, vals in sigs.items():
+ mn = vals.get("min", float("nan"))
+ mx = vals.get("max", float("nan"))
+ avg = vals.get("mean", float("nan"))
+ print(f" {key}: min={mn:.2f} max={mx:.2f} mean={avg:.2f}")
+ if sync:
+ if isinstance(sync, str):
+ sync = json.loads(sync)
+ ts = sync.get("timeshift_seconds") if isinstance(sync, dict) else None
+ if ts is not None:
+ print(f" sync timeshift: {ts:.3f} s")
+
+
+# ---------------------------------------------------------------------------
+# Delete helpers
+# ---------------------------------------------------------------------------
+
+
+def list_objects(con) -> dict[str, list[str]]:
+ """Return a dict mapping each entity type to its sorted list of names."""
+ return {
+ "materials": [r[0] for r in con.execute("SELECT name FROM materials ORDER BY name").fetchall()],
+ "magnets": [r[0] for r in con.execute("SELECT name FROM magnets ORDER BY name").fetchall()],
+ "sites": [r[0] for r in con.execute("SELECT name FROM sites ORDER BY name").fetchall()],
+ "housings": [r[0] for r in con.execute("SELECT name FROM housing_config ORDER BY name").fetchall()],
+ }
+
+
+def delete_magnet(con, name: str) -> None:
+ if not exists(con, "magnets", name):
+ print(f"Magnet '{name}' not found.")
+ return
+ con.execute("DELETE FROM magnet_parts WHERE magnet_name = ?", [name])
+ con.execute("DELETE FROM magnets WHERE name = ?", [name])
+ print(f"Deleted magnet '{name}' and its part links.")
+
+
+def delete_site(con, name: str) -> None:
+ if not exists(con, "sites", name):
+ print(f"Site '{name}' not found.")
+ return
+ con.execute("DELETE FROM experiments WHERE site_name = ?", [name])
+ con.execute("DELETE FROM site_magnets WHERE site_name = ?", [name])
+ con.execute("DELETE FROM sites WHERE name = ?", [name])
+ print(f"Deleted site '{name}', its magnet links, and its experiments.")
+
+
+# ---------------------------------------------------------------------------
+# Update helpers
+# ---------------------------------------------------------------------------
+
+
+# ---------------------------------------------------------------------------
+# Housing config
+# ---------------------------------------------------------------------------
+
+
+def _derive_housing_config_dict(
+ name: str,
+ coil_assignment: dict[str, str],
+ formats: list[str],
+ extra_config: dict | None,
+) -> dict[str, Any]:
+ """Derive a full housing-config dict from a ``coil_assignment`` mapping.
+
+ Parameters
+ ----------
+ name:
+ Housing identifier, e.g. ``"M9"``.
+ coil_assignment:
+ ``{"Insert": "GR1", "Bitter": "GR2"}`` or vice-versa.
+ formats:
+ List of supported format names (``"pupitre"``, ``"pigbrother"``, …).
+ extra_config:
+ Optional dict of extra/override fields stored verbatim (hybrid fields
+ for M8: ``reference_gr{1,2}_hybrid``, ``hybrid_formula_map``, …).
+
+ Returns
+ -------
+ dict
+ Ready to serialise as ``-housing-config.json``.
+ """
+ gr_to_coil = {gr: coil for coil, gr in coil_assignment.items()}
+ gr1_coil = gr_to_coil["GR1"]
+ gr2_coil = gr_to_coil["GR2"]
+ s1 = _COIL_TO_SUFFIX[gr1_coil]
+ s2 = _COIL_TO_SUFFIX[gr2_coil]
+
+ gr1_ucoils = _H_UCOILS if gr1_coil == "Insert" else _B_UCOILS
+ gr2_ucoils = _H_UCOILS if gr2_coil == "Insert" else _B_UCOILS
+
+ label1 = "Upper Coil Current" if s1 == "H" else "Lower Coil Current"
+ label2 = "Upper Coil Current" if s2 == "H" else "Lower Coil Current"
+ desc1 = f"{'Upper' if s1 == 'H' else 'Lower'} coil current sum from DCCT sensors"
+ desc2 = f"{'Upper' if s2 == 'H' else 'Lower'} coil current sum from DCCT sensors"
+
+ pupitre_formula_map = {
+ f"I{s1}": {
+ "formula": f"I{s1} = Idcct1 + Idcct2",
+ "symbol": f"I_{s1}",
+ "unit": "ampere",
+ "label": label1,
+ "description": desc1,
+ },
+ f"I{s2}": {
+ "formula": f"I{s2} = Idcct3 + Idcct4",
+ "symbol": f"I_{s2}",
+ "unit": "ampere",
+ "label": label2,
+ "description": desc2,
+ },
+ }
+
+ cfg: dict[str, Any] = {
+ "name": name,
+ "formats": formats,
+ "reference_gr1_current": f"I{s1}",
+ "reference_gr2_current": f"I{s2}",
+ "reference_gr1_flow": f"Flow{s1}",
+ "reference_gr2_flow": f"Flow{s2}",
+ "reference_gr1_rpm": f"Rpm{s1}",
+ "reference_gr2_rpm": f"Rpm{s2}",
+ "reference_gr1_pin": f"HP{s1}",
+ "reference_gr2_pin": f"HP{s2}",
+ "voltage_channels_gr1": gr1_ucoils,
+ "voltage_channels_gr2": gr2_ucoils,
+ "reference_gr1_voltage": f"U{s1}",
+ "reference_gr2_voltage": f"U{s2}",
+ "pupitre_formula_map": pupitre_formula_map,
+ "pigbrother_formula_map": (
+ _PIGBROTHER_FORMULA_MAP if "pigbrother" in formats else {}
+ ),
+ "hybrid_formula_map": {},
+ "hybrid_voltage_mask_map": {},
+ }
+
+ if extra_config:
+ cfg.update(extra_config)
+
+ return cfg
+
+
+def _housing_config_data_from_magnetrun(housing_name: str) -> dict:
+ """Load and convert a bundled python_magnetrun housing config to DB insert format.
+
+ Uses ``python_magnetrun.housing_config.get_bundled_housing_config_path`` to
+ locate the JSON file for *housing_name* (e.g. ``"M8"``, ``"M9"``, ``"M10"``),
+ then derives the compact ``coil_assignment`` from the ``reference_gr1_current``
+ field (suffix ``"H"`` → Insert, ``"B"`` → Bitter).
+
+ Raises
+ ------
+ ImportError
+ If ``python_magnetrun`` is not installed.
+ ValueError
+ If no bundled JSON exists for *housing_name* or the suffix cannot be
+ mapped to a coil type.
+ """
+ try:
+ from python_magnetrun.housing_config import get_bundled_housing_config_path
+ except ImportError as exc:
+ raise ImportError(
+ "python_magnetrun is not installed — cannot auto-create housing config."
+ ) from exc
+
+ json_path = get_bundled_housing_config_path(housing_name)
+ if not json_path.exists():
+ raise ValueError(
+ f"No bundled housing config for '{housing_name}' in python_magnetrun. "
+ f"Expected: {json_path}"
+ )
+
+ raw = json.loads(json_path.read_text(encoding="utf-8"))
+
+ gr1_current = raw.get("reference_gr1_current", "")
+ suffix = gr1_current[-1] if gr1_current else ""
+ gr1_coil = _SUFFIX_TO_COIL.get(suffix)
+ if gr1_coil is None:
+ raise ValueError(
+ f"Cannot infer coil_assignment for '{housing_name}': "
+ f"reference_gr1_current={gr1_current!r} has unknown suffix {suffix!r}. "
+ f"Expected one of {list(_SUFFIX_TO_COIL)}"
+ )
+ gr2_coil = "Bitter" if gr1_coil == "Insert" else "Insert"
+
+ extra: dict = {}
+ for key in (
+ "reference_gr1_hybrid",
+ "reference_gr2_hybrid",
+ "hybrid_formula_map",
+ "hybrid_voltage_mask_map",
+ ):
+ val = raw.get(key)
+ if val:
+ extra[key] = val
+
+ return {
+ "name": housing_name,
+ "coil_assignment": {gr1_coil: "GR1", gr2_coil: "GR2"},
+ "formats": list(raw.get("formats", [])),
+ "extra_config": extra or None,
+ }
+
+
+def insert_housing_config_from_magnetrun(
+ con, housing_name: str, verbose: bool = True
+) -> None:
+ """Insert a housing_config row loaded from the python_magnetrun bundled JSON.
+
+ This is the preferred way to populate M8, M9, and M10 configs: the JSON
+ files inside the ``python_magnetrun`` package are the authoritative source.
+ The function is idempotent — it skips silently if the row already exists.
+
+ Parameters
+ ----------
+ con:
+ Open DuckDB connection.
+ housing_name:
+ Housing identifier matching a bundled JSON, e.g. ``"M9"``.
+ verbose:
+ Print a status line when inserting.
+
+ Raises
+ ------
+ ImportError
+ If ``python_magnetrun`` is not installed.
+ ValueError
+ If no bundled JSON is found for *housing_name*.
+ """
+ if exists(con, "housing_config", housing_name):
+ if verbose:
+ print(f" ~ housing_config {housing_name} (already exists, skipped)")
+ return
+ data = _housing_config_data_from_magnetrun(housing_name)
+ insert_housing_config(con, data, verbose=verbose)
+
+
+def insert_housing_config(con, data: dict, verbose: bool = True) -> None:
+ """Insert or replace a housing_config row.
+
+ Parameters
+ ----------
+ data:
+ Dict with keys:
+
+ - ``name`` (str) — housing identifier, e.g. ``"M9"``
+ - ``coil_assignment`` (dict) — ``{"Insert": "GR1", "Bitter": "GR2"}``
+ - ``formats`` (list[str]) — e.g. ``["pupitre", "pigbrother"]``
+ - ``extra_config`` (dict | None) — optional hybrid/override fields
+ """
+ name = data["name"]
+ con.execute(
+ """
+ INSERT OR REPLACE INTO housing_config
+ (name, coil_assignment, formats, extra_config)
+ VALUES (?, ?, ?, ?)
+ """,
+ [
+ name,
+ data["coil_assignment"],
+ data["formats"],
+ json.dumps(data["extra_config"]) if data.get("extra_config") else None,
+ ],
+ )
+ if verbose:
+ print(f" + housing_config {name} {data['coil_assignment']}")
+
+
+def export_housing_config_json(
+ con, name: str, output_dir: str | Path = "."
+) -> Path:
+ """Write ``/-housing-config.json`` from the DB row.
+
+ Returns the path of the written file.
+ Raises ``ValueError`` if no row for *name* exists in the table.
+ """
+ row = con.execute(
+ "SELECT coil_assignment, formats, extra_config FROM housing_config WHERE name = ?",
+ [name],
+ ).fetchone()
+ if row is None:
+ raise ValueError(f"No housing_config row found for {name!r}")
+
+ coil_assignment, formats, extra_config_raw = row
+ extra_config = json.loads(extra_config_raw) if extra_config_raw else None
+
+ cfg_dict = _derive_housing_config_dict(
+ name, dict(coil_assignment), list(formats), extra_config
+ )
+
+ dest = Path(output_dir) / f"{name}-housing-config.json"
+ with open(dest, "w") as fh:
+ json.dump(cfg_dict, fh, indent=2, ensure_ascii=False)
+ fh.write("\n")
+ print(f" Wrote {dest}")
+ return dest
+
+
+# ---------------------------------------------------------------------------
+# Overview record
+# ---------------------------------------------------------------------------
+
+
+def _fileset_lists(sources) -> dict[str, list[str]]:
+ """Extract FileSet field lists, returning empty lists for None sources."""
+ if sources is None:
+ empty: list[str] = []
+ return {k: empty for k in (
+ "overview", "archive", "pupitre", "default", "trigger", "spike",
+ "hybrid_kHz", "hybrid_rms", "hybrid_trigger", "hybrid_vprocess",
+ "pigbrother_runlog", "pupitre_runlog",
+ )}
+ return {
+ "overview": list(getattr(sources, "overview", []) or []),
+ "archive": list(getattr(sources, "archive", []) or []),
+ "pupitre": list(getattr(sources, "pupitre", []) or []),
+ "default": list(getattr(sources, "default", []) or []),
+ "trigger": list(getattr(sources, "trigger", []) or []),
+ "spike": list(getattr(sources, "spike", []) or []),
+ "hybrid_kHz": list(getattr(sources, "hybrid_kHz", []) or []),
+ "hybrid_rms": list(getattr(sources, "hybrid_rms", []) or []),
+ "hybrid_trigger": list(getattr(sources, "hybrid_trigger", []) or []),
+ "hybrid_vprocess": list(getattr(sources, "hybrid_vprocess", []) or []),
+ "pigbrother_runlog": list(getattr(sources, "pigbrother_runlog", []) or []),
+ "pupitre_runlog": list(getattr(sources, "pupitre_runlog", []) or []),
+ }
+
+
+def insert_overview_record(
+ con, record, site_name: str | None = None, verbose: bool = True
+) -> None:
+ """Insert an OverviewRecord row; skip silently if filename already exists.
+
+ Parameters
+ ----------
+ con:
+ Open DuckDB connection.
+ record:
+ An ``OverviewRecord`` dataclass instance (``data`` attribute is ignored).
+ site_name:
+ Site name FK (references ``sites.name``). Pass ``None`` to leave unset.
+ verbose:
+ Print a status line when inserting.
+ """
+ filename = record.filename
+ if con.execute(
+ "SELECT 1 FROM overview_records WHERE filename = ?", [filename]
+ ).fetchone():
+ if verbose:
+ print(f" ~ overview_record {filename} (already exists, skipped)")
+ return
+
+ src = _fileset_lists(record.sources)
+ t0 = str(record.t0) if record.t0 is not None else None
+
+ con.execute(
+ """
+ INSERT INTO overview_records (
+ filename, site_name, housing, mode, t0, duration, teb, bp,
+ sources_overview, sources_archive, sources_pupitre,
+ sources_default, sources_trigger, sources_spike,
+ sources_hybrid_kHz, sources_hybrid_rms, sources_hybrid_trigger,
+ sources_hybrid_vprocess, sources_pigbrother_runlog, sources_pupitre_runlog,
+ signatures, sync_info, flow_params, metrics, debitbrut
+ ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
+ """,
+ [
+ filename,
+ site_name,
+ record.housing,
+ record.mode or None,
+ t0,
+ float(record.duration),
+ float(record.teb),
+ float(record.BP),
+ src["overview"],
+ src["archive"],
+ src["pupitre"],
+ src["default"],
+ src["trigger"],
+ src["spike"],
+ src["hybrid_kHz"],
+ src["hybrid_rms"],
+ src["hybrid_trigger"],
+ src["hybrid_vprocess"],
+ src["pigbrother_runlog"],
+ src["pupitre_runlog"],
+ json.dumps(record.signatures),
+ json.dumps(record.sync_info),
+ json.dumps(record.flow_params),
+ json.dumps(record.metrics),
+ json.dumps(record.debitbrut),
+ ],
+ )
+ if verbose:
+ print(f" + overview_record {filename} [{record.housing}] duration={record.duration:.1f}s")
+
+
+def upsert_overview_record(
+ con, record, site_name: str | None = None, verbose: bool = True
+) -> None:
+ """Insert or replace an OverviewRecord row (idempotent re-processing).
+
+ Parameters
+ ----------
+ con:
+ Open DuckDB connection.
+ record:
+ An ``OverviewRecord`` dataclass instance (``data`` attribute is ignored).
+ site_name:
+ Site name FK (references ``sites.name``). Pass ``None`` to leave unset.
+ verbose:
+ Print a status line when upserting.
+ """
+ src = _fileset_lists(record.sources)
+ t0 = str(record.t0) if record.t0 is not None else None
+
+ con.execute(
+ """
+ INSERT OR REPLACE INTO overview_records (
+ filename, site_name, housing, mode, t0, duration, teb, bp,
+ sources_overview, sources_archive, sources_pupitre,
+ sources_default, sources_trigger, sources_spike,
+ sources_hybrid_kHz, sources_hybrid_rms, sources_hybrid_trigger,
+ sources_hybrid_vprocess, sources_pigbrother_runlog, sources_pupitre_runlog,
+ signatures, sync_info, flow_params, metrics, debitbrut
+ ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
+ """,
+ [
+ record.filename,
+ site_name,
+ record.housing,
+ record.mode or None,
+ t0,
+ float(record.duration),
+ float(record.teb),
+ float(record.BP),
+ src["overview"],
+ src["archive"],
+ src["pupitre"],
+ src["default"],
+ src["trigger"],
+ src["spike"],
+ src["hybrid_kHz"],
+ src["hybrid_rms"],
+ src["hybrid_trigger"],
+ src["hybrid_vprocess"],
+ src["pigbrother_runlog"],
+ src["pupitre_runlog"],
+ json.dumps(record.signatures),
+ json.dumps(record.sync_info),
+ json.dumps(record.flow_params),
+ json.dumps(record.metrics),
+ json.dumps(record.debitbrut),
+ ],
+ )
+ if verbose:
+ print(f" ~ overview_record {record.filename} [{record.housing}] (upserted)")
+
+
+def insert_overview_record_from_dict(
+ con, data: dict, site_name: str | None = None, verbose: bool = True, upsert: bool = False
+) -> None:
+ """Insert (or upsert) an overview_record row from a plain dict.
+
+ Accepts the dict format produced by ``find_site_overview_records --json``,
+ the pandas-records JSON written by ``magnetrun analysis/cli.py``, or any
+ dict whose keys match the ``overview_records`` table columns.
+
+ Source lists may be given as Python ``list[str]`` **or** as a
+ comma-separated string (as written by ``cli.py``). Both the canonical
+ ``sources_`` column names and the short ```` aliases used by
+ ``cli.py`` are accepted (e.g. ``sources_overview`` or ``overview``).
+
+ Parameters
+ ----------
+ con:
+ Open DuckDB connection.
+ data:
+ Dict representing one overview record. ``filename`` is required.
+ site_name:
+ Site name FK. If *data* already contains ``site_name`` that value
+ is used; this argument takes precedence when not ``None``.
+ verbose:
+ Print a status line.
+ upsert:
+ If ``True`` use ``INSERT OR REPLACE``; otherwise skip duplicates.
+ """
+ filename = data.get("filename")
+ if not filename:
+ raise ValueError("Record dict is missing required key 'filename'")
+
+ def _to_list(v) -> list[str]:
+ if v is None:
+ return []
+ if isinstance(v, list):
+ return [str(x) for x in v if x]
+ return [x.strip() for x in str(v).split(",") if x.strip()]
+
+ _source_keys = [
+ "overview", "archive", "pupitre", "default", "trigger", "spike",
+ "hybrid_kHz", "hybrid_rms", "hybrid_trigger", "hybrid_vprocess",
+ "pigbrother_runlog", "pupitre_runlog",
+ ]
+
+ def _get_sources(key: str) -> list[str]:
+ return _to_list(data.get(f"sources_{key}", data.get(key)))
+
+ def _json_field(key: str) -> str:
+ v = data.get(key, {})
+ if isinstance(v, (dict, list)):
+ return json.dumps(v)
+ return v if isinstance(v, str) else "{}"
+
+ t0_raw = data.get("t0")
+ t0 = str(t0_raw) if t0_raw is not None else None
+
+ effective_site = site_name if site_name is not None else data.get("site_name")
+ bp = float(data.get("bp", data.get("BP", 0.0)) or 0.0)
+
+ row = [
+ filename,
+ effective_site,
+ data.get("housing") or None,
+ data.get("mode") or None,
+ t0,
+ float(data.get("duration") or 0.0),
+ float(data.get("teb") or 0.0),
+ bp,
+ _get_sources("overview"),
+ _get_sources("archive"),
+ _get_sources("pupitre"),
+ _get_sources("default"),
+ _get_sources("trigger"),
+ _get_sources("spike"),
+ _get_sources("hybrid_kHz"),
+ _get_sources("hybrid_rms"),
+ _get_sources("hybrid_trigger"),
+ _get_sources("hybrid_vprocess"),
+ _get_sources("pigbrother_runlog"),
+ _get_sources("pupitre_runlog"),
+ _json_field("signatures"),
+ _json_field("sync_info"),
+ _json_field("flow_params"),
+ _json_field("metrics"),
+ _json_field("debitbrut"),
+ ]
+
+ if upsert:
+ con.execute(
+ """
+ INSERT OR REPLACE INTO overview_records (
+ filename, site_name, housing, mode, t0, duration, teb, bp,
+ sources_overview, sources_archive, sources_pupitre,
+ sources_default, sources_trigger, sources_spike,
+ sources_hybrid_kHz, sources_hybrid_rms, sources_hybrid_trigger,
+ sources_hybrid_vprocess, sources_pigbrother_runlog, sources_pupitre_runlog,
+ signatures, sync_info, flow_params, metrics, debitbrut
+ ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
+ """,
+ row,
+ )
+ if verbose:
+ housing = data.get("housing", "?")
+ print(f" ~ overview_record {filename} [{housing}] (upserted)")
+ else:
+ if con.execute(
+ "SELECT 1 FROM overview_records WHERE filename = ?", [filename]
+ ).fetchone():
+ if verbose:
+ print(f" ~ overview_record {filename} (already exists, skipped)")
+ return
+ con.execute(
+ """
+ INSERT INTO overview_records (
+ filename, site_name, housing, mode, t0, duration, teb, bp,
+ sources_overview, sources_archive, sources_pupitre,
+ sources_default, sources_trigger, sources_spike,
+ sources_hybrid_kHz, sources_hybrid_rms, sources_hybrid_trigger,
+ sources_hybrid_vprocess, sources_pigbrother_runlog, sources_pupitre_runlog,
+ signatures, sync_info, flow_params, metrics, debitbrut
+ ) VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?,?)
+ """,
+ row,
+ )
+ if verbose:
+ housing = data.get("housing", "?")
+ dur = float(data.get("duration") or 0.0)
+ print(f" + overview_record {filename} [{housing}] duration={dur:.1f}s")
+
+
+def attach_site_to_overview_record(
+ con, filename: str, site_name: str, verbose: bool = True
+) -> None:
+ """Set or overwrite site_name and housing on an existing overview_record row.
+
+ The housing value is taken from sites.housing for the given site_name.
+
+ Parameters
+ ----------
+ con:
+ Open DuckDB connection.
+ filename:
+ Primary key of the overview_records row (basename without extension).
+ site_name:
+ Site name to attach (must exist in the sites table).
+ verbose:
+ Print a status line on success.
+
+ Raises
+ ------
+ ValueError
+ If *filename* is not found in overview_records, or *site_name* is not
+ found in sites.
+ """
+ if con.execute(
+ "SELECT 1 FROM overview_records WHERE filename = ?", [filename]
+ ).fetchone() is None:
+ raise ValueError(f"No overview_record found for filename '{filename}'")
+
+ row = con.execute(
+ "SELECT housing FROM sites WHERE name = ?", [site_name]
+ ).fetchone()
+ if row is None:
+ raise ValueError(f"No site found for site_name '{site_name}'")
+ housing = row[0]
+
+ con.execute(
+ "UPDATE overview_records SET site_name = ?, housing = ? WHERE filename = ?",
+ [site_name, housing, filename],
+ )
+ if verbose:
+ print(f" ~ overview_record {filename} site_name → {site_name} housing → {housing}")
+
+
+def update_site_magnet(con, site_name: str, magnet_name: str, **kwargs) -> None:
+ """Update positional/temporal fields on an existing site_magnets row.
+
+ Accepted kwargs: z_offset, r_offset, parallax, commissioned_at,
+ decommissioned_at, metadata. Only non-None values are updated.
+ Raises ValueError if the (site_name, magnet_name) row does not exist.
+ """
+ updates = {k: v for k, v in kwargs.items() if k in _SITE_MAGNET_FIELDS and v is not None}
+ if not updates:
+ print("Nothing to update.")
+ return
+
+ if not con.execute(
+ "SELECT 1 FROM site_magnets WHERE site_name = ? AND magnet_name = ?",
+ [site_name, magnet_name],
+ ).fetchone():
+ raise ValueError(f"No link between site '{site_name}' and magnet '{magnet_name}'.")
+
+ set_clauses = []
+ values = []
+ for field, value in updates.items():
+ set_clauses.append(f"{field} = ?")
+ if field in _TIMESTAMP_FIELDS:
+ values.append(parse_timestamp(value))
+ elif field in _JSON_FIELDS:
+ values.append(json.dumps(value) if not isinstance(value, str) else value)
+ else:
+ values.append(float(value))
+
+ values.extend([site_name, magnet_name])
+ con.execute(
+ f"UPDATE site_magnets SET {', '.join(set_clauses)} "
+ "WHERE site_name = ? AND magnet_name = ?",
+ values,
+ )
+ print(f"Updated site_magnets ({site_name}, {magnet_name}): {sorted(updates)}")
diff --git a/to_duckdb/docs/hoop-stress.md b/to_duckdb/docs/hoop-stress.md
new file mode 100644
index 0000000..60f8a6d
--- /dev/null
+++ b/to_duckdb/docs/hoop-stress.md
@@ -0,0 +1,164 @@
+# Hoop-stress analysis — `magnetdb.py hoop-stress`
+
+Per-part hoop-stress statistics are computed from pupitre time-series files and stored in three `hoop_stress_*` tables. The `hoop-stress` group of subcommands covers both the computation pipeline and the visualisation tools.
+
+---
+
+## Stress bins
+
+Bins are specified as **edge values in MPa** — a comma-separated list of N values defining N-1 consecutive intervals:
+
+```
+--bins 0,100,200,300,400,500,600 → [(0,100), (100,200), ..., (500,600)]
+```
+
+The default is `0,100,200,300,400,500,600` (6 bins spanning 0–600 MPa in 100 MPa steps).
+
+The legacy pair format `0:100,100:200,...` is still accepted for backward compatibility.
+
+### Bin config tracking
+
+The bin configuration is stored in `hoop_stress_processed` as a canonical edges string (e.g. `"0.0,100.0,200.0,300.0,400.0,500.0,600.0"`). The primary key is `(experiment_id, bin_config)`, so re-running with different bins coexists safely with existing results — no data loss occurs. A warning is printed when an experiment has already been processed with a different bin configuration:
+
+```
+[WARN] [42] M10_261105-1530: previously processed with different bin(s):
+ {'0.0,100.0,200.0,300.0,400.0,500.0,600.0'}. Use --reprocess to overwrite.
+```
+
+---
+
+## `hoop-stress compute`
+
+Processes all experiment files for one or more sites and persists results in `hoop_stress_bin_stats` and `hoop_stress_fatigue`.
+
+```bash
+# One site (default bins)
+python magnetdb.py hoop-stress compute M10_M19071101_13 --db student.duckdb
+
+# All sites
+python magnetdb.py hoop-stress compute --all --db student.duckdb
+
+# Custom bin edges
+python magnetdb.py hoop-stress compute M10_M19071101_13 \
+ --bins 0,150,300,450,600 --db student.duckdb
+
+# Re-process already-computed experiments
+python magnetdb.py hoop-stress compute M10_M19071101_13 --reprocess
+
+# Dry run — discover files without writing
+python magnetdb.py hoop-stress compute M10_M19071101_13 --dry-run
+```
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `--bins` | `0,100,200,300,400,500,600` | Bin edges in MPa |
+| `--magnet-type` | `all` | Restrict to `H` (helix), `B` (bitter), `S` (supra), or `all` |
+| `--parquet-dir` | `/hoop_parquet` | Directory for Parquet output files |
+| `--geometries` | — | Override geometry YAML directory |
+| `--reprocess` | — | Overwrite already-processed experiments |
+| `--dry-run` | — | Discover files without writing |
+| `--use-mrun` | — | Load files via `python_magnetrun.MagnetRun.load_mrun()` |
+| `--quiet` | — | Suppress per-file output |
+
+---
+
+## `hoop-stress barchart`
+
+Bar chart of per-part hoop stress at specific nominal currents, compared against the material Rpe limit.
+
+```bash
+python magnetdb.py hoop-stress barchart M10_M19071101_13 --db student.duckdb
+
+# Specify operating currents
+python magnetdb.py hoop-stress barchart M10_M19071101_13 --i-h 26000 --i-b 0
+```
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `--i-h` | `20000` | Helix current [A] |
+| `--i-b` | `0` | Bitter current [A] |
+| `--i-s` | `0` | Supra current [A] |
+
+---
+
+## `hoop-stress history`
+
+Normalised hoop-stress vs time plot from a pupitre measurement file.
+
+```bash
+python magnetdb.py hoop-stress history M10_M19071101_13 --db student.duckdb
+
+# Explicit pupitre file
+python magnetdb.py hoop-stress history M10_M19071101_13 \
+ --pupitre /path/to/file.txt
+
+# Use python_magnetrun loader (supports .tdms and path auto-resolution)
+python magnetdb.py hoop-stress history M10_M19071101_13 --use-mrun
+```
+
+---
+
+## `hoop-stress stats`
+
+Descriptive statistics (mean, std, peak) of the hoop-stress time series.
+
+```bash
+python magnetdb.py hoop-stress stats M10_M19071101_13 --db student.duckdb
+
+# Save to CSV
+python magnetdb.py hoop-stress stats M10_M19071101_13 --output stats.csv
+```
+
+---
+
+## `hoop-stress fatigue`
+
+Rainflow cycle counting on the hoop-stress time series (fatigue assessment).
+
+```bash
+python magnetdb.py hoop-stress fatigue M10_M19071101_13 --db student.duckdb
+
+# Change number of histogram bins
+python magnetdb.py hoop-stress fatigue M10_M19071101_13 --bins 20
+```
+
+---
+
+## Shared options (history / stats / fatigue)
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `--db` | `student_magnetdb.duckdb` | DuckDB file |
+| `--geometries` | `geometries/` | Directory of YAML geometry files |
+| `--debug` | — | Enable debug output from `magnet_setup()` |
+| `--pupitre FILE ...` | — | Explicit pupitre file(s); omit to use all experiments for the site |
+| `--pupitre-datadir DIR` | from `python_magnetrun` | Root directory for pupitre TXT resolution |
+| `--use-mrun` | — | Load via `python_magnetrun.MagnetRun.load_mrun()` |
+| `--check` | — | Validate fast results row by row against `bmap.getHoop` |
+| `--magnet-type` | `all` | Coil type(s): `H`, `B`, `S`, or `all` |
+
+---
+
+## Standalone pipeline (`compute_hoop_stats.py`)
+
+The `hoop-stress compute` subcommand delegates to `compute_hoop_stats.py`, which can also be run directly:
+
+```bash
+python compute_hoop_stats.py --site M9_M19061901 --db student.duckdb
+python compute_hoop_stats.py --site M9_M19061901 --bins 0,150,300,450,600 \
+ --db student.duckdb --reprocess
+```
+
+---
+
+## `hoop_stress_processed` — idempotency table
+
+| Column | Type | Description |
+|--------|------|-------------|
+| `experiment_id` | INTEGER | FK → experiments(id) |
+| `bin_config` | VARCHAR | Canonical edges string, e.g. `"0.0,100.0,..."` — part of composite PK |
+| `processed_at` | TIMESTAMP | When this row was written |
+| `magnet_type` | VARCHAR | `H`, `B`, `S`, or `all` |
+| `parquet_path` | VARCHAR | Path to the Parquet time-series file (if saved) |
+
+Primary key: `(experiment_id, bin_config)`.
diff --git a/to_duckdb/docs/loading.md b/to_duckdb/docs/loading.md
new file mode 100644
index 0000000..37019f8
--- /dev/null
+++ b/to_duckdb/docs/loading.md
@@ -0,0 +1,220 @@
+# Loading data — magnets, sites, materials
+
+This page covers the complete workflow for building a student DuckDB from the JSON exports in `../../hifimagnet-projects/magnetdb.json/`.
+
+---
+
+## JSON file naming conventions
+
+```
+magnetdb.json/
+├── .json magnet assembly e.g. M19061901.json, M10Bitters.json
+├── .json helix part e.g. H17030101.json
+├── .json ring/lead part e.g. R20061901.json
+└── __.json site config e.g. M9_M19061901_0.json
+```
+
+The suffix `_N` in site files is a **version counter**: each time the magnet configuration at a housing changes (magnet swap, recommissioning), a new file `_N+1` is created. Each file is an independent site entry with its own commissioning dates and list of pupitre records.
+
+Available housings: **M7**, **M8**, **M9**, **M10**.
+
+---
+
+## Loading order
+
+Dependencies flow upward — always load in this order:
+
+```
+db create → material JSONs (MA*) → part JSONs (H*, R*) → magnet JSONs → site JSONs
+```
+
+`magnetdb.py site add` handles the last three automatically: it resolves magnet JSONs from the same directory (or `--magnet-dir`) and the magnet JSONs embed part definitions. A single `site add` call is usually sufficient.
+
+---
+
+## Step 0 — Create the database
+
+```bash
+cd to_duckdb/
+python magnetdb.py db create --db student.duckdb
+```
+
+Creates the file and initialises all tables in one step. Fails if the file already exists, preventing accidental overwrites.
+
+```bash
+# Delete an existing database (with confirmation prompt)
+python magnetdb.py db delete --db student.duckdb
+
+# Delete without prompt (useful in scripts)
+python magnetdb.py db delete --db student.duckdb --yes
+```
+
+---
+
+## Step 1 — Add materials (optional)
+
+Materials can be imported independently of magnets, which is useful when you want to inspect or correct physical properties without re-importing a full magnet hierarchy.
+
+```bash
+JSON=../../hifimagnet-projects/magnetdb.json
+
+python magnetdb.py material add $JSON/MA20072304.json --dry-run
+python magnetdb.py material add $JSON/MA20072304.json --db student.duckdb
+
+python magnetdb.py material view --db student.duckdb
+python magnetdb.py material view MA20072304 --db student.duckdb
+python magnetdb.py material delete MA20072304 --db student.duckdb
+```
+
+The operation is **idempotent**: adding the same material twice is safe.
+
+See [schema.md — Material JSON format](schema.md#material-json-format) for the expected JSON structure.
+
+---
+
+## Step 2 — Add magnets
+
+Load a magnet from a MagnetDB JSON export. The JSON embeds all part and material definitions.
+
+```bash
+JSON=../../hifimagnet-projects/magnetdb.json
+
+# Preview without writing
+python magnetdb.py magnet add $JSON/M25032101.json --dry-run
+
+# Write to DB (creates DB file if it does not exist)
+python magnetdb.py magnet add $JSON/M25032101.json --db student.duckdb
+
+# If part JSONs live elsewhere
+python magnetdb.py magnet add M25032101.json --input-dir $JSON \
+ --part-dir /path/to/parts --db student.duckdb
+```
+
+The magnet type (`insert`, `bitters`, `hybrid`) is inferred automatically from the part types. The operation is **idempotent**.
+
+### Inspect and manage magnets
+
+```bash
+python magnetdb.py magnet view --db student.duckdb
+python magnetdb.py magnet view M25032101 --db student.duckdb
+python magnetdb.py magnet delete M25032101 --db student.duckdb
+```
+
+---
+
+## Step 3 — Add sites
+
+Sites reference magnets by name. `site add` auto-resolves missing magnets from JSON files in the same directory (or `--magnet-dir`), inserts magnet links, and inserts the `records` list into the `experiments` table.
+
+```bash
+JSON=../../hifimagnet-projects/magnetdb.json
+
+python magnetdb.py site add $JSON/M10_M19071101_13.json --dry-run
+python magnetdb.py site add $JSON/M10_M19071101_13.json --db student.duckdb
+
+# Using --input-dir
+python magnetdb.py site add M10_M19071101_13.json \
+ --input-dir $JSON --db student.duckdb
+```
+
+The operation is **idempotent**: running it twice with the same JSON is safe.
+
+### Loading multiple site versions
+
+Each `__.json` file is an independent operational campaign. Load each version you want:
+
+```bash
+# All campaigns for M9 housing with M19061901 insert
+for f in $JSON/M9_M19061901_*.json; do
+ python magnetdb.py site add "$f" --db student.duckdb
+done
+
+# All known sites across all housings
+for f in $JSON/M{7,8,9,10}_*_*.json; do
+ python magnetdb.py site add "$f" --db student.duckdb
+done
+```
+
+### Inspect and manage sites
+
+```bash
+python magnetdb.py site view --db student.duckdb
+python magnetdb.py site view M10_M19071101_13 --db student.duckdb
+python magnetdb.py site delete M10_M19071101_13 --db student.duckdb
+```
+
+### Update SiteMagnet fields
+
+Patch positional or temporal fields on a specific magnet within a site without re-importing the full JSON:
+
+```bash
+python magnetdb.py site update-magnet M10_M19071101_13 M19071101 \
+ --z-offset 12.5 --r-offset 0.0 --parallax 0.0
+
+python magnetdb.py site update-magnet M10_M19071101_13 M19071101 \
+ --commissioned-at "2025-11-12 00:00:00"
+
+python magnetdb.py site update-magnet M10_M19071101_13 M19071101 \
+ --metadata '{"current_max_A": 26000}'
+```
+
+Only the fields explicitly passed are updated; all others are left unchanged.
+
+---
+
+## Housing configs
+
+Housing configs describe the physical magnet housing at each experimental station (M7, M8, M9, M10). They map coil-type names (`Insert`, `Bitter`) to current-group labels (`GR1`, `GR2`) and record the set of file formats available for each housing.
+
+Housing configs are **created automatically** when you call `site add` — the config for the housing named in the site JSON is loaded from the `python_magnetrun` package if it is not already present in the DB. You do not need to pre-load them manually.
+
+### Inspect housing configs
+
+```bash
+# List all housings in the DB
+python magnetdb.py housing view --db student.duckdb
+
+# Show full detail for one housing
+python magnetdb.py housing view M9 --db student.duckdb
+```
+
+**Example output — list all:**
+
+```
+Name Formats
+--------------------------------------------------
+M9 pupitre, tdms
+M10 pupitre, tdms
+```
+
+**Example output — single housing:**
+
+```
+Housing: M9
+ formats : pupitre, tdms
+ coil_assignment:
+ Insert → GR1
+ Bitter → GR2
+```
+
+### Filter sites by housing
+
+`site view` accepts `--housing` to show only sites in a given housing:
+
+```bash
+python magnetdb.py site view --housing M9 --db student.duckdb
+```
+
+---
+
+## Viewing all objects at once
+
+```bash
+python magnetdb.py list --db student.duckdb
+```
+
+Lists all materials, magnets, sites, and housings in one call.
+
+---
+
+See [schema.md](schema.md) for the Site JSON format and full schema reference.
diff --git a/to_duckdb/docs/mysql_connect.md b/to_duckdb/docs/mysql_connect.md
new file mode 100644
index 0000000..e016a90
--- /dev/null
+++ b/to_duckdb/docs/mysql_connect.md
@@ -0,0 +1,829 @@
+# `mysql_connect.py` — MySQL ↔ DuckDB bridge
+
+`mysql_connect.py` attaches a remote MySQL database to an in-memory DuckDB
+session via the `mysql_scanner` extension. Four independent modes are
+available: **live** (schema inspection), **export** (snapshot to file),
+**view** (tabular table display), and **poll** (live chart from repeated queries).
+
+---
+
+## Requirements
+
+```bash
+pip install duckdb matplotlib plotly textual dash rich
+```
+
+| Mode / Backend | Extra package | Notes |
+|----------------|---------------|-------|
+| `view` | `rich` | terminal table |
+| `--plot matplotlib` (default) | `matplotlib` | native window |
+| `--plot plotly` | `plotly` | auto-refreshing HTML file |
+| `--plot textual` | `textual` | full-screen TUI in terminal |
+| `--plot dash` | `dash` + `plotly` | interactive web app in browser |
+
+`matplotlib` is only required for `--plot matplotlib` (default).
+`plotly` is only required for `--plot plotly`.
+
+---
+
+## Connection parameters
+
+All connection flags can be supplied via environment variables (e.g. with
+[direnv](https://direnv.net/)). CLI flags always take precedence.
+
+| CLI flag | Environment variable | Default |
+|----------|----------------------|---------|
+| `--host` | `MYSQL_HOST` | `localhost` |
+| `--port` | `MYSQL_PORT` | `3306` |
+| `--user` | `MYSQL_USER` | *(required)* |
+| `--password` | `MYSQL_PASSWORD` | *(required)* |
+| `--database` | `MYSQL_DB` | *(required)* |
+
+Example `.envrc` for direnv:
+
+```bash
+export MYSQL_HOST=db.example.com
+export MYSQL_USER=admin
+export MYSQL_PASSWORD=secret
+export MYSQL_DB=magnetdb
+```
+
+From here on the connection flags are omitted from examples for brevity.
+Add `--host … --user … --password … --database …` (or source the `.envrc`)
+to every command below.
+
+---
+
+## Mode: `live` — inspect the schema
+
+Attaches MySQL and prints every table with its columns, types, and role markers.
+No data is copied locally.
+
+```bash
+python mysql_connect.py --mode live
+```
+
+Sample output:
+
+```
+Connected to magnetdb@db.example.com:3306
+3 table(s) found:
+
+ measurements
+ timestamp TIMESTAMP @
+ Icoil FLOAT *
+ Ucoil FLOAT *
+ tsb FLOAT *
+ teb FLOAT *
+ label VARCHAR
+
+ sensors
+ id INTEGER *
+ measurement_id INTEGER *
+ temp FLOAT *
+ flow FLOAT *
+
+ sites
+ name VARCHAR
+ description VARCHAR
+
+(* = numeric / y-axis @ = timestamp / x-axis)
+```
+
+---
+
+## Mode: `export` — snapshot tables to a local file
+
+### Export all tables to CSV
+
+```bash
+python mysql_connect.py --mode export --format csv --output-dir ./out
+```
+
+One `.csv` file is created per table under `./out/`.
+
+### Export selected tables to Parquet
+
+```bash
+python mysql_connect.py --mode export --format parquet \
+ --output-dir ./out \
+ --tables measurements sensors
+```
+
+### Export to a DuckDB file
+
+```bash
+python mysql_connect.py --mode export --format duckdb \
+ --output magnetdb_mysql.duckdb \
+ --tables measurements sensors sites
+```
+
+The DuckDB file is created if it does not exist; existing tables are replaced
+(`CREATE OR REPLACE`).
+
+### Export a subset of columns from one table
+
+`--export-fields` restricts which columns are written. It requires exactly one
+table to be named via `--tables`.
+
+```bash
+python mysql_connect.py --mode export --format csv --output-dir ./out \
+ --tables measurements \
+ --export-fields timestamp Icoil Ucoil tsb teb
+```
+
+### Export a time range
+
+Use `--start` and/or `--end` with an ISO 8601 datetime string. The
+`--time-field` option names the TIMESTAMP column to filter on; if omitted the
+first TIMESTAMP column found in the schema is used automatically.
+
+```bash
+# Auto-detect the timestamp column
+python mysql_connect.py --mode export --format csv --output-dir ./out \
+ --tables measurements \
+ --start "2024-01-15 08:00:00" \
+ --end "2024-01-15 20:00:00"
+
+# Explicit time field
+python mysql_connect.py --mode export --format parquet --output-dir ./out \
+ --tables measurements \
+ --time-field "Timestamp Field" \
+ --start "2024-01-15 08:00:00" \
+ --end "2024-01-15 20:00:00"
+```
+
+### Combine column selection and time range
+
+```bash
+python mysql_connect.py --mode export --format parquet --output-dir ./out \
+ --tables measurements \
+ --export-fields timestamp Icoil Ucoil tsb teb \
+ --start "2024-01-15 08:00:00" \
+ --end "2024-01-15 20:00:00"
+```
+
+When `--export-fields` is used together with `--start`/`--end`, the time field
+is automatically prepended to the column list if it is not already present, so
+the exported file always contains the timestamp column.
+
+```bash
+# Export to DuckDB with field selection and time range
+python mysql_connect.py --mode export --format duckdb \
+ --output run42.duckdb \
+ --tables measurements \
+ --export-fields Icoil Ucoil tsb teb \
+ --time-field timestamp \
+ --start "2024-03-10 06:00:00" \
+ --end "2024-03-10 18:00:00" \
+ --verbose
+```
+
+Add `-v` / `--verbose` to print the generated SQL and row count before writing.
+
+---
+
+## Mode: `view` — tabular table display
+
+Display rows from a MySQL table (or any custom SQL query) as a styled table
+in the terminal. Requires [`rich`](https://rich.readthedocs.io/):
+`pip install rich`.
+
+### Quick view of the most recent rows
+
+```bash
+python mysql_connect.py --mode view --table measurements --limit 50
+```
+
+Sample output (columns auto-sized to terminal width):
+
+```
+ timestamp Icoil Ucoil tsb teb label
+ ──────────────────── ──────── ──────── ────── ────── ───────
+ 2024-01-15 10:00:00 1200.5 4.21 12.3 11.8 run42
+ 2024-01-15 10:00:05 1201.0 4.22 12.4 11.9 run42
+ ...
+50 row(s)
+```
+
+### Select specific columns
+
+```bash
+python mysql_connect.py --mode view --table measurements \
+ --fields timestamp Icoil Ucoil \
+ --limit 100
+```
+
+### Apply a WHERE filter
+
+```bash
+python mysql_connect.py --mode view --table measurements \
+ --where "label = 'run42'" \
+ --limit 200
+```
+
+### Remove the row cap (show all matching rows)
+
+```bash
+python mysql_connect.py --mode view --table measurements \
+ --where "label = 'run42'" \
+ --limit 0
+```
+
+`--limit 0` disables the row cap entirely. Default is `200`.
+
+### View results of a JOIN query
+
+```bash
+python mysql_connect.py --mode view \
+ --query "SELECT m.timestamp, m.Icoil, m.Ucoil, s.temp
+ FROM mysqldb.measurements m
+ JOIN mysqldb.sensors s ON m.id = s.measurement_id
+ ORDER BY m.timestamp DESC
+ LIMIT 100"
+```
+
+### JOIN query with a time range
+
+Time filtering is expressed directly in the SQL `WHERE` clause:
+
+```bash
+python mysql_connect.py --mode view \
+ --query "SELECT m.timestamp, m.Icoil, m.Ucoil, s.temp
+ FROM mysqldb.measurements m
+ JOIN mysqldb.sensors s ON m.id = s.measurement_id
+ WHERE m.timestamp >= '2024-01-15 08:00:00'
+ AND m.timestamp <= '2024-01-15 20:00:00'
+ ORDER BY m.timestamp
+ LIMIT 500"
+```
+
+The same pattern applies to single-table queries:
+
+```bash
+python mysql_connect.py --mode view \
+ --query "SELECT timestamp, Icoil, Ucoil
+ FROM mysqldb.measurements
+ WHERE timestamp >= '2024-01-15 08:00:00'
+ AND timestamp <= '2024-01-15 20:00:00'
+ ORDER BY timestamp"
+```
+
+> **Tip:** Use `--verbose` to print the generated SQL before execution.
+
+---
+
+## Mode: `poll` — live chart from repeated queries
+
+Connects to MySQL, runs a query every `--interval` seconds, and displays the
+result as a live chart. Press **Ctrl+C** to stop.
+
+### Discovery helpers
+
+Always start by listing what is available:
+
+```bash
+# List all tables in the database
+python mysql_connect.py --mode poll --list-tables
+
+# List plottable columns of a table (* = y-axis, @ = x-axis)
+python mysql_connect.py --mode poll --table measurements --list-fields
+```
+
+Sample `--list-fields` output:
+
+```
+Columns in 'measurements':
+ timestamp TIMESTAMP @
+ Timestamp Field TIMESTAMP @
+ Icoil FLOAT *
+ Ucoil FLOAT *
+ tsb FLOAT *
+ teb FLOAT *
+(* = numeric / y-axis @ = timestamp / x-axis)
+```
+
+### Single-table polling
+
+#### Minimal — auto-detect everything
+
+When `--fields` and `--x-field` are both omitted, the tool selects all
+numeric columns as y-fields and the first `TIMESTAMP` column as the x-axis
+automatically:
+
+```bash
+python mysql_connect.py --mode poll --table measurements --interval 5
+```
+
+#### Explicit fields, matplotlib (default backend)
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil tsb teb \
+ --x-field timestamp \
+ --interval 10 \
+ --limit 300
+```
+
+#### With a WHERE filter
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil \
+ --x-field timestamp \
+ --where "label = 'run42'" \
+ --interval 5
+```
+
+#### All fields on one shared graph (`overlay`)
+
+Use `"layout":"overlay"` to draw every y-field on a single axes instead of
+one subplot per field. This is the quickest way to compare signals whose
+values are on similar scales.
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil Iref \
+ --x-field timestamp \
+ --interval 10 \
+ --plot-options '{"layout":"overlay"}'
+```
+
+With explicit colours (one per y-field, in the same order as `--fields`):
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil Iref \
+ --x-field timestamp \
+ --interval 10 \
+ --plot-options '{"layout":"overlay","colors":["steelblue","tomato","seagreen"]}'
+```
+
+#### Mixed layout — some fields overlaid, others on separate subplots (`groups`)
+
+Use `"layout":"groups"` with a `"groups"` list when you want certain fields
+to share a subplot while others get their own. Each inner list is one subplot;
+all subplots share the same x-axis.
+
+```bash
+# Icoil and Iref overlaid on subplot 1; Ucoil alone on subplot 2
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil Iref \
+ --x-field timestamp \
+ --interval 10 \
+ --plot-options '{"layout":"groups","groups":[["Icoil","Iref"],["Ucoil"]]}'
+```
+
+With colours (one entry per y-field in the order they appear across all groups):
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil Iref \
+ --x-field timestamp \
+ --interval 10 \
+ --plot-options '{
+ "layout": "groups",
+ "groups": [["Icoil", "Iref"], ["Ucoil"]],
+ "colors": ["steelblue", "seagreen", "tomato"]
+ }'
+```
+
+#### Plotly backend (auto-opens browser, writes HTML)
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil tsb teb \
+ --x-field timestamp \
+ --interval 10 \
+ --plot plotly \
+ --output-html live_magnets.html
+```
+
+The HTML file contains a `` tag so the browser
+reloads automatically on each poll.
+
+#### Run a fixed number of polls, then exit
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil \
+ --x-field timestamp \
+ --interval 5 \
+ --count 20
+```
+
+### Multi-table polling with `--query`
+
+Use `--query` with an explicit SQL `SELECT` when you need a `JOIN`.
+Tables must be prefixed with `mysqldb.` (the alias used by `mysql_scanner`).
+`--limit` and `--where` are ignored in query mode — put them in the SQL.
+
+#### Discover columns returned by a JOIN query
+
+```bash
+python mysql_connect.py --mode poll --list-fields \
+ --query "SELECT m.timestamp, m.Icoil, m.Ucoil, s.temp, s.flow
+ FROM mysqldb.measurements m
+ JOIN mysqldb.sensors s ON m.id = s.measurement_id
+ ORDER BY m.timestamp DESC LIMIT 300"
+```
+
+Sample output:
+
+```
+Columns returned by query:
+ timestamp TIMESTAMP @
+ Icoil FLOAT *
+ Ucoil FLOAT *
+ temp FLOAT *
+ flow FLOAT *
+(* = numeric / y-axis @ = timestamp / x-axis)
+```
+
+#### Poll a JOIN query — matplotlib
+
+```bash
+python mysql_connect.py --mode poll \
+ --query "SELECT m.timestamp, m.Icoil, m.Ucoil, s.temp, s.flow
+ FROM mysqldb.measurements m
+ JOIN mysqldb.sensors s ON m.id = s.measurement_id
+ ORDER BY m.timestamp DESC LIMIT 300" \
+ --x-field timestamp \
+ --fields Icoil Ucoil temp flow \
+ --interval 10
+```
+
+#### Poll a JOIN query — plotly
+
+```bash
+python mysql_connect.py --mode poll \
+ --query "SELECT m.timestamp, m.Icoil, m.Ucoil, s.temp, s.flow
+ FROM mysqldb.measurements m
+ JOIN mysqldb.sensors s ON m.id = s.measurement_id
+ ORDER BY m.timestamp DESC LIMIT 300" \
+ --x-field timestamp \
+ --fields Icoil Ucoil temp flow \
+ --interval 10 \
+ --plot plotly \
+ --output-html live_join.html
+```
+
+### Two-source polling (`--table2` / `--query2`)
+
+When you need to poll **two tables simultaneously** and display their fields in
+**separate subplots that share a common x-axis**, use `--table2` (or `--query2`
+for raw SQL). Zooming or panning in one subplot automatically mirrors the other.
+
+Supported backends: `matplotlib`, `plotly`, `dash`.
+
+#### Two tables by name — matplotlib
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements --fields timestamp Icoil Ucoil --x-field timestamp \
+ --table2 temperatures --fields2 tsb teb \
+ --interval 10 \
+ --plot matplotlib
+```
+
+#### Two tables by name — Dash (linked zoom/pan, pause button)
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements --fields timestamp Icoil Ucoil --x-field timestamp \
+ --table2 temperatures --fields2 tsb teb \
+ --interval 10 \
+ --plot dash
+```
+
+#### Two independent SQL queries (tables not directly joinable)
+
+Use `--query` for the first source and `--query2` for the second when the
+tables cannot be joined (different row counts, different time grids, etc.):
+
+```bash
+python mysql_connect.py --mode poll \
+ --query "SELECT t, Icoil, Ucoil FROM mysqldb.measurements ORDER BY t LIMIT 500" \
+ --fields Icoil Ucoil --x-field t \
+ --query2 "SELECT t, tsb, teb FROM mysqldb.temperatures ORDER BY t LIMIT 500" \
+ --fields2 tsb teb \
+ --interval 10 \
+ --plot dash
+```
+
+#### With a WHERE filter on the second table
+
+`--where2` applies an SQL filter to `--table2` (has no effect when `--query2`
+is used — put the filter directly in the SQL instead).
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements --fields timestamp Icoil Ucoil --x-field timestamp \
+ --table2 temperatures --fields2 tsb teb --where2 "sensor_id = 3" \
+ --interval 10 \
+ --plot dash
+```
+
+---
+
+## `--plot-options` reference
+
+Pass a JSON object to control chart style. All keys are optional.
+
+| Key | Values | Default | Note |
+|-----|--------|---------|------|
+| `type` | `line` \| `scatter` \| `bar` | `line` | chart geometry |
+| `layout` | `subplots` \| `overlay` \| `groups` | `subplots` | subplot arrangement |
+| `groups` | list of field-name lists | `[]` | required when `layout=groups` |
+| `figsize` | `[width, height]` | `[12, 6]` | inches, matplotlib only |
+| `colors` | list of color strings | library defaults | one per y-field; applied to sparkline colour in textual |
+| `font` | font family string | library default | e.g. `"Arial"`, `"monospace"`; matplotlib and plotly only |
+| `fontsize` | number (points) | library default | base font size; matplotlib and plotly only |
+
+### Layout examples
+
+#### `overlay` — all fields on one shared axes
+
+```bash
+--plot-options '{"layout":"overlay","colors":["steelblue","tomato","seagreen","orange"]}'
+```
+
+#### `subplots` — one subplot per field (default)
+
+```bash
+--plot-options '{"layout":"subplots","figsize":[12,8]}'
+```
+
+#### `groups` — user-defined field groups, each on its own subplot
+
+```bash
+--plot-options '{
+ "layout": "groups",
+ "groups": [["Icoil", "Ucoil"], ["temp", "flow"]],
+ "colors": ["steelblue", "tomato", "seagreen", "orange"],
+ "font": "Arial",
+ "fontsize": 11
+}'
+```
+
+Fields within a group share one subplot and are distinguished by color and
+legend. Groups share the same x-axis.
+
+### Full styled example
+
+```bash
+python mysql_connect.py --mode poll \
+ --query "SELECT m.timestamp, m.Icoil, m.Ucoil, s.temp, s.flow
+ FROM mysqldb.measurements m
+ JOIN mysqldb.sensors s ON m.id = s.measurement_id
+ ORDER BY m.timestamp DESC LIMIT 500" \
+ --x-field timestamp \
+ --fields Icoil Ucoil temp flow \
+ --interval 10 \
+ --plot matplotlib \
+ --plot-options '{
+ "layout": "groups",
+ "groups": [["Icoil", "Ucoil"], ["temp", "flow"]],
+ "type": "line",
+ "figsize": [14, 7],
+ "colors": ["steelblue", "tomato", "seagreen", "darkorange"],
+ "font": "DejaVu Sans",
+ "fontsize": 11
+ }'
+```
+
+---
+
+## Mode: `poll` — TUI backend (`--plot textual`)
+
+The textual backend runs entirely in the terminal — no window manager needed.
+Each y-field gets a live **Sparkline** widget that scrolls with each new poll.
+
+```bash
+pip install textual
+
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --interval 5 \
+ --plot textual
+```
+
+### Key bindings
+
+| Key | Action |
+|-----|--------|
+| `q` | Quit |
+| `p` | Pause / Resume polling |
+
+### Layout in TUI mode
+
+`layout` from `--plot-options` controls visual grouping:
+
+- **`subplots`** (default) — one sparkline row per field.
+- **`overlay`** — all fields in a single group (one section, multiple sparklines stacked).
+- **`groups`** — named sections with a header label per group, each containing its fields.
+
+`colors` applies a custom colour to each sparkline. `font` and `fontsize`
+have no effect in textual mode.
+
+```bash
+# Grouped layout with custom colours
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil tsb teb \
+ --interval 5 \
+ --plot textual \
+ --plot-options '{
+ "layout": "groups",
+ "groups": [["Icoil", "Ucoil"], ["tsb", "teb"]],
+ "colors": ["steelblue", "tomato", "seagreen", "orange"]
+ }'
+```
+
+### Multi-table TUI poll
+
+```bash
+python mysql_connect.py --mode poll \
+ --query "SELECT m.timestamp, m.Icoil, m.Ucoil, s.temp, s.flow
+ FROM mysqldb.measurements m
+ JOIN mysqldb.sensors s ON m.id = s.measurement_id
+ ORDER BY m.timestamp DESC LIMIT 300" \
+ --fields Icoil Ucoil temp flow \
+ --interval 10 \
+ --plot textual \
+ --plot-options '{"layout":"groups","groups":[["Icoil","Ucoil"],["temp","flow"]]}'
+```
+
+---
+
+## Mode: `poll` — Dash backend (`--plot dash`)
+
+The Dash backend starts a local Flask/Dash web server and opens the app in
+the default browser. Unlike the plotly backend (which writes a static HTML
+file that reloads the page), Dash updates only the chart data via WebSocket /
+XHR — **no full page reload**, so zoom/pan state is preserved between polls.
+
+```bash
+pip install dash
+
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --interval 5 \
+ --plot dash
+```
+
+The server listens on `127.0.0.1:8050` by default. Use `--dash-host` and
+`--dash-port` to change it (e.g. to expose it on a LAN):
+
+```bash
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --interval 5 \
+ --plot dash \
+ --dash-host 0.0.0.0 \
+ --dash-port 8080
+```
+
+### Pause / Resume
+
+A **⏸ Pause / Resume** button in the app header disables the `dcc.Interval`
+component, stopping queries to MySQL without closing the server.
+
+### Layout and styling
+
+All `--plot-options` keys (`type`, `layout`, `groups`, `colors`, `font`,
+`fontsize`) work the same as for the plotly backend. Each group gets its own
+`dcc.Graph` panel.
+
+```bash
+# Two groups, line chart, custom colours
+python mysql_connect.py --mode poll \
+ --table measurements \
+ --fields Icoil Ucoil tsb teb \
+ --x-field timestamp \
+ --interval 10 \
+ --plot dash \
+ --plot-options '{
+ "layout": "groups",
+ "groups": [["Icoil", "Ucoil"], ["tsb", "teb"]],
+ "type": "line",
+ "colors": ["steelblue", "tomato", "seagreen", "orange"],
+ "font": "Arial",
+ "fontsize": 12
+ }'
+```
+
+### Multi-table Dash poll
+
+```bash
+python mysql_connect.py --mode poll \
+ --query "SELECT m.timestamp, m.Icoil, m.Ucoil, s.temp, s.flow
+ FROM mysqldb.measurements m
+ JOIN mysqldb.sensors s ON m.id = s.measurement_id
+ ORDER BY m.timestamp DESC LIMIT 300" \
+ --fields Icoil Ucoil temp flow \
+ --interval 10 \
+ --plot dash \
+ --plot-options '{"layout":"groups","groups":[["Icoil","Ucoil"],["temp","flow"]]}'
+```
+
+---
+
+## Complete CLI reference
+
+```
+usage: mysql_connect.py [--mode {live,export,view,poll,plot}]
+ [--host HOST] [--port PORT]
+ [--user USER] [--password PASSWORD] [--database DATABASE]
+ [--format {csv,parquet,duckdb}]
+ [--output FILE] [--output-dir DIR] [--tables TABLE ...]
+ [--export-fields COL ...] [--time-field COL]
+ [--start DATETIME] [--end DATETIME]
+ [--table TABLE] [--query SQL]
+ [--list-tables] [--list-fields]
+ [--fields COL ...] [--x-field COL]
+ [--where EXPR] [--limit N]
+ [--table2 TABLE] [--query2 SQL]
+ [--fields2 COL ...] [--where2 EXPR]
+ [--interval SECONDS] [--count N]
+ [--plot {table,matplotlib,plotly,textual,dash}]
+ [--plot-options JSON] [--output-html FILE]
+ [--dash-host HOST] [--dash-port PORT]
+ [-v]
+```
+
+| Flag | Mode | Description |
+|------|------|-------------|
+| `--mode` | all | `live` (default), `export`, `view`, `poll`, `plot` |
+| `--host/port/user/password/database` | all | MySQL connection (or env vars) |
+| `--format` | export | `csv`, `parquet`, `duckdb` |
+| `--output` | export | DuckDB output file (format duckdb) |
+| `--output-dir` | export | directory for CSV / Parquet files |
+| `--tables` | export | subset of tables to export (default: all) |
+| `--export-fields` | export | columns to include; requires exactly one table in `--tables` |
+| `--time-field` | export | TIMESTAMP column for `--start`/`--end` filtering (auto-detected) |
+| `--start` | export | start of time range, ISO 8601, e.g. `'2024-01-15 08:00:00'` |
+| `--end` | export | end of time range, ISO 8601, e.g. `'2024-01-15 20:00:00'` |
+| `--table` | view, poll | table to query (mutually exclusive with `--query`) |
+| `--query` | view, poll | raw SELECT query; reference tables as `mysqldb.` |
+| `--list-tables` | poll | print tables and exit |
+| `--list-fields` | poll | print plottable columns and exit |
+| `--fields` | poll | y-axis columns (default: all numeric columns) |
+| `--x-field` | poll | x-axis column (default: first TIMESTAMP column) |
+| `--where` | poll | SQL WHERE clause (single-table path only) |
+| `--limit` | poll | max rows per poll, default 200 (single-table path only) |
+| `--table2` | poll | second table for two-source mode (mutually exclusive with `--query2`) |
+| `--query2` | poll | raw SELECT for the second subplot (mutually exclusive with `--table2`) |
+| `--fields2` | poll | y-axis columns from the second source (default: all numeric) |
+| `--where2` | poll | SQL WHERE clause for `--table2` only |
+| `--interval` | poll | seconds between polls, default 5 |
+| `--count` | poll | number of polls; 0 = run until Ctrl+C (default) |
+| `--plot` | poll | `matplotlib` (default), `table`, `plotly`, `textual`, `dash` |
+| `--plot-options` | poll | JSON style object (see table above) |
+| `--output-html` | poll | HTML path for plotly backend (default: `poll_output.html`) |
+| `--dash-host` | poll | Dash server host (default: `127.0.0.1`) |
+| `--dash-port` | poll | Dash server port (default: `8050`) |
+| `-v / --verbose` | all | print SQL, auto-selected fields, row counts |
+
+---
+
+## Running the tests
+
+Tests live in `tests/test_mysql_connect.py` and are split into three categories.
+
+### Unit and smoke tests (no MySQL required)
+
+```bash
+cd to_duckdb/
+venv-systempackages/bin/python -m pytest tests/test_mysql_connect.py -v -m "not integration"
+```
+
+These tests cover all pure-logic helpers (`_is_numeric_type`, `_build_dsn`,
+`_resolve_groups`, `_safe_widget_id`, …) and CLI argument parsing via in-memory
+DuckDB — no network connection needed.
+
+### Integration tests (live MySQL server required)
+
+Set environment variables pointing to a test MySQL database, then run:
+
+```bash
+export MYSQL_TEST_HOST=db.example.com
+export MYSQL_TEST_USER=admin
+export MYSQL_TEST_PASSWORD=secret
+export MYSQL_TEST_DB=magnetdb
+# optional: export MYSQL_TEST_PORT=3306
+
+venv-systempackages/bin/python -m pytest tests/test_mysql_connect.py -v -m integration
+```
+
+Integration tests verify `list_mysql_tables`, `describe_table`,
+`list_numeric_columns`, and `_fetch_poll` against a real MySQL server.
+They are automatically skipped when the env vars are absent.
diff --git a/to_duckdb/docs/populate.md b/to_duckdb/docs/populate.md
new file mode 100644
index 0000000..793f47f
--- /dev/null
+++ b/to_duckdb/docs/populate.md
@@ -0,0 +1,333 @@
+# Populating data tables — `magnetdb.py populate`
+
+`magnetdb.py populate` fills the file-level tables from the filesystem or from pre-computed JSON summaries. Each subcommand accepts one or more site names **or** `--all` to process every site in the DB.
+
+---
+
+## `populate operationaldata`
+
+Scans the storage server for TDMS and pupitre TXT files within each site's operational window and registers them in the `operationaldata` table. File IDs are assigned automatically via a database sequence.
+
+```bash
+# Dry run — preview file counts without writing
+python magnetdb.py populate operationaldata M10_M19071101_13 --dry-run
+
+# Scan all types for one site
+python magnetdb.py populate operationaldata M10_M19071101_13 --db student.duckdb
+
+# Restrict to specific types
+python magnetdb.py populate operationaldata M10_M19071101_13 --type Archive Overview
+
+# Process all sites in the DB
+python magnetdb.py populate operationaldata --all --db student.duckdb
+
+# DB timestamps stored as French local time instead of UTC
+python magnetdb.py populate operationaldata --all --db-tz Europe/Paris
+```
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `--type` | all | Restrict to one or more of `Overview Archive Spike Default Pupitre` |
+| `--records-base` | `/mnt/LNCMIG-Data/records` | Root of the records tree |
+| `--srv-subdir` | `srv-data-install` | Subdirectory of `records-base` for pupitre TXT files |
+| `--pbsurv` | `pbsurv` | Subdirectory of `records-base` for TDMS files |
+| `--db-tz` | `UTC` | Timezone of `commissioned_at` / `decommissioned_at` in the DB |
+| `--dry-run` | — | Match files without writing to the DB |
+
+---
+
+## `populate experiments`
+
+Scans the pupitre TXT directory and registers matching files in the `experiments` table. The operation is idempotent — rows already present are skipped.
+
+> **Note:** `site add` already inserts the `records` field from the site JSON into `experiments`. Use `populate experiments` to discover additional pupitre files that were not listed in the original JSON export.
+
+```bash
+python magnetdb.py populate experiments M10_M19071101_13 --dry-run
+python magnetdb.py populate experiments M10_M19071101_13 --db student.duckdb
+python magnetdb.py populate experiments --all --db student.duckdb
+python magnetdb.py populate experiments --all --db-tz Europe/Paris
+```
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `--records-base` | `/mnt/LNCMIG-Data/records` | Root of the records tree |
+| `--srv-subdir` | `srv-data-install` | Subdirectory of `records-base` for pupitre TXT files |
+| `--db-tz` | `UTC` | Timezone of `commissioned_at` / `decommissioned_at` in the DB |
+| `--dry-run` | — | Match files without writing to the DB |
+
+---
+
+## `populate overview-records`
+
+Processes Overview TDMS files registered in `operationaldata` (type = `Overview`) using the `python_magnetrun` analysis pipeline and inserts the results into `overview_records`. Requires `python_magnetrun` to be installed.
+
+Run `populate operationaldata --type Overview` first if `operationaldata` is empty.
+
+```bash
+python magnetdb.py populate overview-records M10_M19071101_13 --db student.duckdb
+python magnetdb.py populate overview-records --all --db student.duckdb
+python magnetdb.py populate overview-records --all --reprocess
+python magnetdb.py populate overview-records M10_M19071101_13 --dry-run
+```
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `--reprocess` | — | Overwrite existing `overview_records` rows (upsert instead of skip) |
+| `--dry-run` | — | List files without processing or writing to the DB |
+
+Data directories used by `python_magnetrun` are resolved from environment variables:
+
+```bash
+export MAGNETRUN_PUPITRE_DATA_DIR=/data/records/srv-data-install
+python magnetdb.py populate overview-records --all --db student.duckdb
+```
+
+---
+
+## `populate overview-records-from-json`
+
+Loads `overview_records` from a pre-computed summary JSON file, without requiring `python_magnetrun` or the raw TDMS files. Use this when a summary has already been produced (e.g. by `python -m python_magnetrun.analysis.cli`) or when TDMS files are not locally accessible.
+
+```bash
+python magnetdb.py populate overview-records-from-json summary-2026.json \
+ --site M10_M19071101_13 --db student.duckdb
+
+python magnetdb.py populate overview-records-from-json summary-2026.json \
+ --site M10_M19071101_13 --dry-run
+
+python magnetdb.py populate overview-records-from-json summary-2026.json \
+ --site M10_M19071101_13 --reprocess --db student.duckdb
+
+# Records already carry site_name — no --site needed
+python magnetdb.py populate overview-records-from-json summary-2026.json \
+ --db student.duckdb
+```
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `--site SITE` | — | Site name to assign to all loaded records; overrides any `site_name` in the JSON |
+| `--reprocess` | — | Overwrite existing rows (upsert instead of skip) |
+| `--dry-run` | — | Preview records without writing to the DB |
+| `--db` | `student_magnetdb.duckdb` | Target DuckDB file |
+
+### Accepted JSON format
+
+The file must contain a top-level JSON array. Each element is a dict with the following fields (all optional except `filename`):
+
+| Field | Type | Description |
+|-------|------|-------------|
+| `filename` | string | **Required.** Base filename without extension (primary key) |
+| `housing` | string | Housing identifier (`M8`, `M9`, `M10`, …) |
+| `mode` | string | Measurement mode |
+| `t0` | string \| null | Start timestamp (`"YYYY-MM-DD HH:MM:SS"` or ISO 8601) |
+| `duration` | float | Run duration in seconds |
+| `teb` | float | Pupitre inlet water temperature (°C) |
+| `bp` | float | Pupitre pressure (bar) |
+| `sources_overview` | list\[str\] \| csv | Overview TDMS file path(s) |
+| `sources_archive` | list\[str\] \| csv | Archive TDMS file path(s) |
+| `sources_pupitre` | list\[str\] \| csv | Pupitre TXT file path(s) |
+| `sources_default` | list\[str\] \| csv | Default incident file path(s) |
+| `sources_trigger` | list\[str\] \| csv | Trigger incident file path(s) |
+| `sources_spike` | list\[str\] \| csv | Spike incident file path(s) |
+| `sources_hybrid_kHz` | list\[str\] \| csv | Hybrid kHz file path(s) |
+| `sources_hybrid_rms` | list\[str\] \| csv | Hybrid RMS file path(s) |
+| `sources_hybrid_trigger` | list\[str\] \| csv | Hybrid trigger file path(s) |
+| `sources_hybrid_vprocess` | list\[str\] \| csv | Hybrid vprocess file path(s) |
+| `sources_pigbrother_runlog` | list\[str\] \| csv | Pigbrother run-log file path(s) |
+| `sources_pupitre_runlog` | list\[str\] \| csv | Pupitre Cirrus run-log file path(s) |
+| `signatures` | dict | Per-channel signature statistics |
+| `sync_info` | dict | Synchronisation metadata |
+| `flow_params` | dict | Computed flow parameters |
+| `metrics` | dict | Distance / correlation metrics |
+| `debitbrut` | dict | Raw flow-rate data |
+| `site_name` | string | Site FK (overridden by `--site` when supplied) |
+
+Each `sources_*` field accepts either a Python list of paths or a comma-separated string. The short alias without the `sources_` prefix (e.g. `overview` instead of `sources_overview`) is also accepted.
+
+**Minimal example:**
+
+```json
+[
+ {
+ "filename": "M10_261105-1530",
+ "housing": "M10",
+ "t0": "2026-11-05 15:30:00",
+ "duration": 182.4,
+ "teb": 14.2,
+ "bp": 9.8,
+ "sources_overview": ["/data/records/pbsurv/M10/Overview/M10_261105-1530.tdms"],
+ "signatures": {"Courant_GR1": {"min": 0.0, "max": 26100.0, "mean": 25980.3}}
+ }
+]
+```
+
+---
+
+## Inspecting the data tables
+
+### `experiments view`
+
+Lists rows in the `experiments` table — pupitre files (and any other records) associated with each site. The table is populated by `site add` (from the `records` field of the site JSON) and by `populate experiments`.
+
+```bash
+# List all experiments across all sites
+python magnetdb.py experiments view --db student.duckdb
+
+# Filter by site
+python magnetdb.py experiments view --site M10_M19071101_13 --db student.duckdb
+
+# Filter by magnet (all sites/campaigns where that magnet was installed)
+python magnetdb.py experiments view --magnet M19071101 --db student.duckdb
+
+# Filter by part (all sites/campaigns where that part was installed)
+python magnetdb.py experiments view --part H17030101 --db student.duckdb
+
+# Filter by time range (timestamp extracted from pupitre filename)
+python magnetdb.py experiments view --from 2026-03-01 --to 2026-03-31 --db student.duckdb
+python magnetdb.py experiments view --from "2026-03-01 08:00:00" --db student.duckdb
+
+# Combine filters freely
+python magnetdb.py experiments view \
+ --magnet M19071101 --from 2026-01-01 --to 2026-12-31 --db student.duckdb
+```
+
+| Option | Description |
+|--------|-------------|
+| `--site SITE` | Filter by site name |
+| `--magnet MAGNET` | Filter by magnet name (joins via `site_magnets`) |
+| `--part PART` | Filter by part name (joins via `site_magnets → magnet_parts`) |
+| `--from DATETIME` | Include records at or after this date/time (`YYYY-MM-DD` or `YYYY-MM-DD HH:MM:SS`) |
+| `--to DATETIME` | Include records at or before this date/time (inclusive) |
+
+> **Note:** For `experiments`, the timestamp is extracted from the pupitre filename (`YYYY.MM.DD - HH:MM:SS.txt`). Records with non-matching filenames are excluded when `--from` or `--to` is used.
+
+**Example output:**
+
+```
+experiments site=M10_M19071101_13 (3 row(s))
+
+ID Site File Status
+-----------------------------------------------------------------------------------------------
+1 M10_M19071101_13 /data/records/srv-data-install/...
+2 M10_M19071101_13 /data/records/srv-data-install/...
+3 M10_M19071101_13 /data/records/srv-data-install/...
+```
+
+---
+
+### `operationaldata view`
+
+Lists rows in the `operationaldata` table — every TDMS and pupitre file registered for a site, with its type and status. Populated by `populate operationaldata`.
+
+```bash
+# List all records
+python magnetdb.py operationaldata view --db student.duckdb
+
+# Filter by site
+python magnetdb.py operationaldata view --site M10_M19071101_13 --db student.duckdb
+
+# Filter by file type (Overview, Archive, Spike, Default, Pupitre)
+python magnetdb.py operationaldata view --type Pupitre --db student.duckdb
+
+# Filter by magnet or part
+python magnetdb.py operationaldata view --magnet M19071101 --db student.duckdb
+python magnetdb.py operationaldata view --part H17030101 --db student.duckdb
+
+# Filter by time range
+python magnetdb.py operationaldata view --from 2026-03-01 --to 2026-03-31 --db student.duckdb
+
+# Combine filters
+python magnetdb.py operationaldata view \
+ --site M10_M19071101_13 --type Overview --from 2026-01-01 --db student.duckdb
+```
+
+| Option | Description |
+|--------|-------------|
+| `--site SITE` | Filter by site name |
+| `--type TYPE` | Filter by file type: `Overview`, `Archive`, `Spike`, `Default`, `Pupitre` |
+| `--magnet MAGNET` | Filter by magnet name (joins via `site_magnets`) |
+| `--part PART` | Filter by part name (joins via `site_magnets → magnet_parts`) |
+| `--from DATETIME` | Include records at or after this date/time |
+| `--to DATETIME` | Include records at or before this date/time (inclusive) |
+
+> **Note:** For `operationaldata`, the timestamp is extracted from the filename. Pupitre TXT files use `YYYY.MM.DD - HH:MM:SS`; TDMS Overview/Archive files use `YYMMDD-HHMM`; TDMS Spike/Default files use `YYMMDD-HHMMSS`. Records whose filenames don't match any known pattern are excluded when `--from`/`--to` is used.
+
+**Example output (site + type filter):**
+
+```
+operationaldata site=M10_M19071101_13 type=Overview (2 row(s))
+
+ID Site Type File Status
+---------------------------------------------------------------------------------------------------------
+42 M10_M19071101_13 Overview /data/records/pbsurv/M10/Overview/...
+43 M10_M19071101_13 Overview /data/records/pbsurv/M10/Overview/...
+```
+
+---
+
+### `overview-records view`
+
+Lists rows in the `overview_records` table — processed summaries derived from Overview TDMS files. Populated by `populate overview-records` or `populate overview-records-from-json`.
+
+```bash
+# List all overview records
+python magnetdb.py overview-records view --db student.duckdb
+
+# Filter by site, magnet, or part
+python magnetdb.py overview-records view --site M10_M19071101_13 --db student.duckdb
+python magnetdb.py overview-records view --magnet M19071101 --db student.duckdb
+python magnetdb.py overview-records view --part H17030101 --db student.duckdb
+
+# Filter by time range (uses the t0 column directly)
+python magnetdb.py overview-records view --from 2026-03-01 --to 2026-03-31 --db student.duckdb
+python magnetdb.py overview-records view --from "2026-03-01 08:00:00" --db student.duckdb
+
+# Combine filters
+python magnetdb.py overview-records view \
+ --magnet M19071101 --from 2026-01-01 --to 2026-12-31 --db student.duckdb
+
+# Include per-record channel signatures and sync details
+python magnetdb.py overview-records view \
+ --site M10_M19071101_13 --signatures --db student.duckdb
+```
+
+| Option | Description |
+|--------|-------------|
+| `--site SITE` | Filter by site name |
+| `--magnet MAGNET` | Filter by magnet name (joins via `site_magnets`) |
+| `--part PART` | Filter by part name (joins via `site_magnets → magnet_parts`) |
+| `--from DATETIME` | Include records where `t0 >=` this date/time (`YYYY-MM-DD` or `YYYY-MM-DD HH:MM:SS`) |
+| `--to DATETIME` | Include records where `t0 <=` this date/time (inclusive) |
+| `--signatures` | Include per-channel min/max/mean and sync timeshift for each record |
+
+**Example output:**
+
+```
+overview_records site=M10_M19071101_13 (2 row(s))
+
+Filename t0 Duration Mode teb bp n_src
+----------------------------------------------------------------------------------------------
+M10_261105-1530 2026-11-05 15:30:00 03:02 HP 14.2 9.8 3
+M10_261106-0910 2026-11-06 09:10:00 01:24 HP 13.8 9.6 3
+```
+
+With `--signatures`, each row is followed by per-channel min/max/mean statistics and sync timeshift (if available):
+
+```
+M10_261105-1530 2026-11-05 15:30:00 03:02 HP 14.2 9.8 3
+ Courant_GR1: min=0.00 max=26100.00 mean=25980.30
+ sync timeshift: 0.012 s
+```
+
+**Columns:**
+
+| Column | Description |
+|--------|-------------|
+| `Filename` | Base filename without extension (primary key) |
+| `t0` | Run start timestamp |
+| `Duration` | Run duration `HH:MM` or `MM:SS` |
+| `Mode` | Measurement mode (e.g. `HP`, `HP+Bitter`) |
+| `teb` | Inlet water temperature (°C) |
+| `bp` | Water pressure (bar) |
+| `n_src` | Total number of source files across all `sources_*` columns |
diff --git a/to_duckdb/docs/query_cumstats.md b/to_duckdb/docs/query_cumstats.md
new file mode 100644
index 0000000..3e93d90
--- /dev/null
+++ b/to_duckdb/docs/query_cumstats.md
@@ -0,0 +1,212 @@
+# Cumulative statistics queries — `query_cumstats.py`
+
+`query_cumstats.py` is a **read-only** tool that aggregates pre-computed statistics stored in the `op_*` and `exp_*` tables. No raw record files are ever re-read.
+
+Two parallel families of subcommands are provided:
+
+| Family | Source tables | Description |
+|--------|--------------|-------------|
+| `scalars`, `site-bins`, `magnet-bins`, `part-bins` | `op_run_scalars`, `op_site_bin_stats`, `op_part_bin_stats` | Cumulative stats from operational data files |
+| `exp-scalars`, `exp-site-bins`, `exp-magnet-bins`, `exp-part-bins` | `exp_run_scalars`, `exp_site_bin_stats`, `exp_part_bin_stats` | Cumulative stats from experiment records |
+
+Both families share identical aggregation logic, CLI flags, and output helpers.
+
+---
+
+## Prerequisites
+
+The relevant compute step must have been run before querying:
+
+- **Operational data** — `compute_op_stats.py` (see [statistics.md](statistics.md))
+- **Experiment data** — `compute_exp_stats.py` (same approach, `exp_*` tables)
+- **Hoop stress** — `magnetdb.py hoop-stress compute` (see [hoop-stress.md](hoop-stress.md))
+
+---
+
+## CLI reference
+
+```
+python query_cumstats.py [options]
+```
+
+### Global options
+
+| Flag | Default | Description |
+|------|---------|-------------|
+| `--db` | `student.duckdb` | Path to DuckDB file |
+| `--site` | — | Site name (FK into `sites`) |
+| `--magnet` | — | Magnet name |
+| `--part` | — | Part name |
+| `--channels` | all | Comma-separated channel filter, e.g. `Ptot,tsb` |
+| `--experiment` | all | Filter `exp-*` commands to a single experiment by name |
+| `--plot` | off | Save PNG bar charts alongside tabular output |
+
+### Subcommands — operational data
+
+| Subcommand | Required flag | Source table | Description |
+|------------|--------------|-------------|-------------|
+| `scalars` | `--site` or `--magnet` | `op_run_scalars` | Total scalar quantities (energy, heat, duration) |
+| `site-bins` | `--site` | `op_site_bin_stats` | Field-bin distributions at site level |
+| `magnet-bins` | `--magnet` | `op_part_bin_stats` | Per-part field-bin distributions for a magnet |
+| `part-bins` | `--part` | `op_part_bin_stats` | Field-bin distributions for a single part |
+
+### Subcommands — experiment data
+
+| Subcommand | Required flag | Source table | Description |
+|------------|--------------|-------------|-------------|
+| `exp-scalars` | `--site` or `--magnet` | `exp_run_scalars` | Total scalar quantities across experiments |
+| `exp-site-bins` | `--site` | `exp_site_bin_stats` | Field-bin distributions at site level |
+| `exp-magnet-bins` | `--magnet` | `exp_part_bin_stats` | Per-part field-bin distributions for a magnet |
+| `exp-part-bins` | `--part` | `exp_part_bin_stats` | Field-bin distributions for a single part |
+
+---
+
+## Examples
+
+### Operational data
+
+```bash
+DB=magnetdb.duckdb
+
+# Scalar totals for a site (energy, heat, duration)
+python query_cumstats.py --db $DB --site M9_M19061901 scalars
+
+# Scalar totals aggregated over all runs of a magnet
+python query_cumstats.py --db $DB --magnet M9Bitters scalars
+
+# Field-bin distribution at site level — all channels, tabular
+python query_cumstats.py --db $DB --site M9_M19061901 site-bins
+
+# Selected channels with bar-chart PNG
+python query_cumstats.py --db $DB --site M9_M19061901 site-bins \
+ --channels Ptot,tsb --plot
+
+# Per-part stats for all parts of a magnet
+python query_cumstats.py --db $DB --magnet M9Bitters magnet-bins --plot
+
+# Stats for a single part across all runs and sites
+python query_cumstats.py --db $DB --part M9Bi part-bins \
+ --channels Icoil,hoop_stress_proxy --plot
+```
+
+### Experiment data
+
+```bash
+# Scalar totals for a site from experiment records
+python query_cumstats.py --db $DB --site M9_M19061901 exp-scalars
+
+# Field-bin distribution at site level
+python query_cumstats.py --db $DB --site M9_M19061901 exp-site-bins
+
+# Restrict to a single named experiment
+python query_cumstats.py --db $DB --site M9_M19061901 \
+ --experiment myrun_2024 exp-site-bins
+
+# Per-part field-bin stats for a magnet (with plot)
+python query_cumstats.py --db $DB --magnet M9Bitters exp-magnet-bins --plot
+
+# Stats for a single part across all experiments
+python query_cumstats.py --db $DB --part M9Bi exp-part-bins \
+ --channels Icoil,hoop_stress_proxy --plot
+
+# Same part, restricted to one experiment
+python query_cumstats.py --db $DB --part M9Bi \
+ --experiment myrun_2024 exp-part-bins
+```
+
+---
+
+## Output formats
+
+### Scalar output (`scalars` / `exp-scalars`)
+
+```
+───────────────────────────────────────────────────────
+ Scalar statistics — M9_M19061901
+───────────────────────────────────────────────────────
+ Total duration 1234.567 h (42 files)
+ Field-on duration 987.123 h (42 files)
+ Electrical energy 12.345 MWh (42 files)
+ Heat extracted 9.876 MWh (42 files)
+```
+
+### Bin output (`site-bins`, `magnet-bins`, `part-bins` and `exp-*` variants)
+
+```
+──────────────────────────────────────────────────────────────────────────
+ Ptot — site M9_M19061901
+ Bin (T) Hours Mean Std Min Max
+──────────────────────────────────────────────────────────────────────────
+ 0.0–5.0 12.340 123.456 10.234 98.000 145.000
+ 5.0–10.0 234.560 456.789 23.456 300.000 600.000
+ ...
+```
+
+### Plot output (`--plot`)
+
+A `cumstats__.png` file is written in the current directory for each channel. Site-level commands produce one figure per channel; part/magnet commands produce one figure per channel with one bar group per part.
+
+---
+
+## Python API
+
+The query functions can be imported and called directly:
+
+```python
+import duckdb
+from query_cumstats import (
+ # Operational
+ query_scalars,
+ query_site_bins,
+ query_magnet_bins,
+ query_part_bins,
+ # Experiment
+ query_exp_scalars,
+ query_exp_site_bins,
+ query_exp_magnet_bins,
+ query_exp_part_bins,
+)
+
+con = duckdb.connect("magnetdb.duckdb", read_only=True)
+
+# All functions return a pandas DataFrame.
+df_scalars = query_scalars(con, site_name="M9_M19061901")
+df_site = query_site_bins(con, "M9_M19061901", channels=["Ptot", "tsb"])
+df_magnet = query_magnet_bins(con, "M9Bitters")
+df_part = query_part_bins(con, "M9Bi", channels=["Icoil"])
+
+# Experiment variants — identical signatures, extra experiment_name kwarg
+df_exp_site = query_exp_site_bins(con, "M9_M19061901", channels=["Ptot"])
+df_exp_part = query_exp_part_bins(con, "M9Bi", experiment_name="myrun_2024")
+
+con.close()
+```
+
+All functions accept `channels: list[str] | None` to restrict output. The `exp_*` variants additionally accept `experiment_name: str | None`.
+
+---
+
+## Aggregation reference
+
+These expressions are applied in every bin query:
+
+| Derived quantity | SQL expression |
+|-----------------|----------------|
+| Operating time (h) | `SUM(sum_dt) / 3600` |
+| Time-weighted mean | `SUM(sum_x_dt) / SUM(sum_dt)` |
+| Time-weighted std | `sqrt(SUM(sum_x2_dt)/SUM(sum_dt) − mean²)` |
+| Cumulative integral | `SUM(sum_x_dt)` (energy, heat, …) |
+| Peak value | `MAX(max_x)` |
+
+The five primitive columns (`sum_dt`, `sum_x_dt`, `sum_x2_dt`, `min_x`, `max_x`) are **additive**: summing over any subset of files or experiments produces a valid cumulative result without re-reading raw data.
+
+---
+
+## Related documentation
+
+| Topic | File |
+|-------|------|
+| Ingesting operational statistics | [statistics.md](statistics.md) |
+| Hoop-stress compute and visualisation | [hoop-stress.md](hoop-stress.md) |
+| Database schema reference | [schema.md](schema.md) |
+| Populating TDMS / pupitre tables | [populate.md](populate.md) |
diff --git a/to_duckdb/docs/schema.md b/to_duckdb/docs/schema.md
new file mode 100644
index 0000000..4282696
--- /dev/null
+++ b/to_duckdb/docs/schema.md
@@ -0,0 +1,156 @@
+# Database schema reference
+
+## Table overview
+
+```
+materials physical properties of conductor alloys (rpe in Pa)
+parts individual physical components (helix, ring, bitter, lead)
+magnets magnet assemblies (insert, bitters, hybrid, …)
+magnet_parts ordered parts within a magnet, with coil_index
+housing_config wiring layout for a magnet housing (GR1/GR2 coil assignment)
+sites operational configurations (housing, commissioning dates)
+site_magnets magnets active in a site — positional & temporal metadata
+experiments operational records (TSV files) attached to a site
+operationaldata discovered archive files (TDMS/TXT) linked to a site, with type tag
+ (IDs auto-assigned via sequence operationaldata_id_seq)
+overview_records processed overview file metadata (OverviewRecord, no raw data)
+
+── Operational statistics ───────────────────────────────────────────────────
+op_stats_processed idempotency guard — which files have been ingested and with which bins
+op_run_scalars per-run scalar totals: energy (billing), heat extracted, duration
+op_site_bin_stats site-level field-bin distributions: Pmagnet, Ptot, tsb, teb, debitbrut
+op_part_bin_stats per-part field-bin distributions: Icoil, Ucoil, hoop_stress_proxy
+
+── Hoop-stress statistics ───────────────────────────────────────────────────
+hoop_stress_processed idempotency guard — PK (experiment_id, bin_config); one row per
+ processed (experiment, bin edge set); warns if bin config changes
+hoop_stress_bin_stats per-part stress-bin distributions: n_samples, sum_dt, sum_x_dt,
+ sum_x2_dt, min_x, max_x — PK (experiment_id, part_name, stress_bin_low)
+hoop_stress_fatigue per-part rainflow cycle counts: n_cycles, sum_range3 (Miner proxy)
+ PK (experiment_id, part_name)
+```
+
+The authoritative DDL is in [`schema.py`](../schema.py).
+
+---
+
+## site_magnets columns
+
+| Column | Type | Default | Description |
+|--------|------|---------|-------------|
+| `site_name` | VARCHAR | — | FK → sites |
+| `magnet_name` | VARCHAR | — | FK → magnets |
+| `z_offset` | DOUBLE | 0.0 | Axial offset of the magnet in the site (m) |
+| `r_offset` | DOUBLE | 0.0 | Radial offset of the magnet in the site (m) |
+| `parallax` | DOUBLE | 0.0 | Parallax angle |
+| `commissioned_at` | TIMESTAMP | NULL | When this magnet was commissioned in this site |
+| `decommissioned_at` | TIMESTAMP | NULL | When removed (NULL = still active) |
+| `metadata` | JSON | `{}` | Free-form key/value store |
+
+---
+
+## coil_index
+
+The `magnet_parts.coil_index` column maps each helix or bitter part to its `Icoil_N` column in the operational TSV records:
+
+- Assigned 1-based, in the order parts appear in the magnet definition
+- Only `helix` and `bitter` parts receive a coil_index
+- `ring` and `lead` parts get `NULL`
+
+Example query to retrieve the mapping:
+
+```python
+import duckdb
+con = duckdb.connect("student_magnetdb.duckdb", read_only=True)
+
+con.execute("""
+ SELECT 'Icoil' || mp.coil_index AS column,
+ p.name AS part,
+ p.type,
+ mat.nuance,
+ mat.rpe / 1e6 AS rpe_MPa
+ FROM magnet_parts mp
+ JOIN parts p ON p.name = mp.part_name
+ JOIN magnets m ON m.name = mp.magnet_name
+ LEFT JOIN materials mat ON mat.name = p.material_name
+ WHERE m.name = 'M19061901'
+ AND mp.coil_index IS NOT NULL
+ ORDER BY mp.coil_index
+""").df()
+```
+
+---
+
+## Site JSON format
+
+The JSON expected by `magnetdb.py site add` matches the format produced by `python_magnetapi`. The minimal required fields are:
+
+```json
+{
+ "name": "M10_M19071101_13",
+ "status": "in_operation",
+ "housing": "M10",
+ "commissioned_at": "2025-11-12 00:00:00",
+ "decommissioned_at": "None",
+ "magnets": [
+ "M19071101",
+ "M10Bitters"
+ ],
+ "records": [
+ {
+ "name": "M10_2025.11.13---09:14:21.txt",
+ "description": "",
+ "file": "M10_2025.11.13---09:14:21.txt"
+ }
+ ]
+}
+```
+
+Each entry in `magnets` is either a **plain string** (name only — positional fields default to `0.0`, metadata to `{}`) or a **dict** with the full `SiteMagnet` fields:
+
+```json
+"magnets": [
+ "M19071101",
+ {
+ "name": "M10Bitters",
+ "z_offset": 0.0,
+ "r_offset": 0.0,
+ "parallax": 0.0,
+ "commissioned_at": "2025-11-12 00:00:00",
+ "decommissioned_at": null,
+ "metadata": {"current_max_A": 26000}
+ }
+]
+```
+
+Notes:
+- `magnets` contains magnet **names** — magnets must already be in the DB (or resolvable from a JSON file in the same directory).
+- `decommissioned_at` can be `"None"` or omitted for active sites.
+- `records` is inserted into the `experiments` table automatically; it can be an empty list `[]`.
+
+---
+
+## Material JSON format
+
+The JSON produced by `python_magnetapi` for a material record:
+
+```json
+{
+ "name": "MA20072304",
+ "description": "",
+ "nuance": "CuCrZr",
+ "t_ref": 293,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385,
+ "alpha": 0.0036,
+ "electrical_conductivity": 47200000.0,
+ "thermal_conductivity": 380,
+ "magnet_permeability": 1,
+ "young": 117000000000.0,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-05,
+ "rpe": 324000000.0
+}
+```
+
+All fields except `name` are optional. `rpe` is stored in Pa.
diff --git a/to_duckdb/docs/statistics.md b/to_duckdb/docs/statistics.md
new file mode 100644
index 0000000..1399506
--- /dev/null
+++ b/to_duckdb/docs/statistics.md
@@ -0,0 +1,188 @@
+# Statistics pipeline
+
+Rather than loading all raw record files on every analysis, statistics are computed once per file and stored in pre-aggregated tables. Cumulative results for any scope (site, magnet, part, date range) are then obtained by pure SQL aggregation — no raw files are re-read.
+
+Two parallel pipelines exist:
+
+| Pipeline | Source table | Stats tables | Script |
+|----------|-------------|--------------|--------|
+| Operational | `operationaldata` | `op_run_scalars`, `op_site_bin_stats`, `op_part_bin_stats`, `op_stats_processed` | `compute_op_stats.py` |
+| Experiment | `experiments` | `exp_run_scalars`, `exp_site_bin_stats`, `exp_part_bin_stats`, `exp_stats_processed` | `compute_exp_stats.py` |
+
+Both pipelines produce identical column structures and the same aggregation primitives.
+
+---
+
+## Design
+
+Each `op_site_bin_stats` / `op_part_bin_stats` row stores five aggregation primitives per *(file, field bin, channel)*:
+
+| Column | Use |
+|--------|-----|
+| `n_samples` | row count |
+| `sum_dt` | total time in bin (s) — directly gives operating hours |
+| `sum_x_dt` | `Σ(X·dt)` — divide by `sum_dt` for time-weighted mean |
+| `sum_x2_dt` | `Σ(X²·dt)` — combined with above gives time-weighted std; also fatigue input (e.g. `Σ(I²·dt)`) |
+| `min_x` / `max_x` | extremes — take `MIN`/`MAX` across files |
+
+These are **additive**: summing over any subset of files gives the cumulative result without re-reading raw data.
+
+---
+
+## Ingesting statistics — `compute_op_stats.py`
+
+Run after the `operationaldata` table has been populated (see [populate.md](populate.md)).
+
+```bash
+# Process all operationaldata files for a site
+python compute_op_stats.py --db magnetdb.duckdb --records-base /path/to/records \
+ --site M9_M19061901
+
+# Pupitre TXT files only
+python compute_op_stats.py --db magnetdb.duckdb --records-base /path/to/records \
+ --site M9_M19061901 --type Pupitre
+
+# Custom field bins as low:high pairs, comma-separated
+python compute_op_stats.py --db magnetdb.duckdb --records-base /path/to/records \
+ --site M9_M19061901 --bins "0:0.1,0.1:5,5:10,10:15,15:20,25:30,30:35,35:40,40:45"
+
+# Re-compute already-processed files (e.g. after changing bins)
+python compute_op_stats.py --db magnetdb.duckdb --records-base /path/to/records \
+ --site M9_M19061901 --reprocess
+```
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `--db` | `magnetdb.duckdb` | DuckDB file |
+| `--records-base` | `records/` | Directory containing the raw record files |
+| `--site` | — | Site name (FK into `sites`) |
+| `--type` | all | Filter `operationaldata` by type (`Pupitre`, `Archive`, …) |
+| `--bins` | 10-bin set (0–45 T) | Field bins as `lo:hi,lo:hi,...` pairs in Tesla |
+| `--channels` | `Pmagnet,Ptot,tsb,teb,debitbrut` | Site-level channels for `op_site_bin_stats` |
+| `--flow-to-m3s` | `1/3600` | Unit conversion for `debitbrut` → m³/s (default assumes m³/h) |
+| `--reprocess` | off | Overwrite already-processed files |
+| `--quiet` | off | Suppress per-file progress output |
+
+---
+
+## Ingesting experiment statistics — `compute_exp_stats.py`
+
+Run after the `experiments` table has been populated (`magnetdb.py populate experiments`, see [populate.md](populate.md)).
+
+`experiments.file` stores only the filename (e.g. `2025.04.30 - 13:06:03.txt`). The full path is reconstructed as `records-base / srv-subdir / housing / filename`, where `housing` is read from `sites.housing` for the experiment's site.
+
+```bash
+# Process all experiment files for a site (defaults match the standard filesystem layout)
+python compute_exp_stats.py --db magnetdb.duckdb --site M10_A250429_00
+
+# Override the root if your records are elsewhere
+python compute_exp_stats.py --db magnetdb.duckdb --site M10_A250429_00 \
+ --records-base /mnt/LNCMIG-Data/records --srv-subdir srv-data-install
+
+# Custom field bins
+python compute_exp_stats.py --db magnetdb.duckdb --site M10_A250429_00 \
+ --bins "0:0.1,0.1:5,5:10,10:15,15:20,20:25,25:30,30:35,35:40,40:45"
+
+# Re-compute already-processed experiments
+python compute_exp_stats.py --db magnetdb.duckdb --site M10_A250429_00 --reprocess
+```
+
+| Option | Default | Description |
+|--------|---------|-------------|
+| `--db` | `magnetdb.duckdb` | DuckDB file |
+| `--site` | — | Site name (FK into `sites`) |
+| `--records-base` | `/mnt/LNCMIG-Data/records` | Root directory for record files |
+| `--srv-subdir` | `srv-data-install` | Subdirectory under `records-base` containing pupitre TXT files |
+| `--bins` | 10-bin set (0–45 T) | Field bins as `lo:hi,lo:hi,...` pairs in Tesla |
+| `--channels` | `Pmagnet,Ptot,tsb,teb,debitbrut` | Site-level channels for `exp_site_bin_stats` |
+| `--flow-to-m3s` | `1/3600` | Unit conversion for `debitbrut` → m³/s (default assumes m³/h) |
+| `--reprocess` | off | Overwrite already-processed experiments |
+| `--quiet` | off | Suppress per-file progress output |
+
+### Computed quantities (both pipelines)
+
+*Scalars (`op_run_scalars` / `exp_run_scalars`)* — one value per run, no field binning:
+
+| Channel | Formula | Use |
+|---------|---------|-----|
+| `energy_j` | `Σ(Ptot · dt)` | Electricity billing |
+| `heat_extracted_j` | `Σ((tsb−teb) · Q_m³s · ρ·cₚ · dt)` | Heat estimate |
+| `duration_s` | `Σ(dt)` | Total run duration |
+| `duration_field_on_s` | `Σ(dt)` where `Field > 0.1 T` | Magnet-on time |
+
+*Site-level bins (`op_site_bin_stats` / `exp_site_bin_stats`)* — one row per (file, bin, channel):
+`Pmagnet`, `Ptot`, `tsb`, `teb`, `debitbrut` (configurable via `--channels`).
+
+*Per-part bins (`op_part_bin_stats` / `exp_part_bin_stats`)* — one row per (file, part, bin, channel):
+`Icoil`, `Ucoil`, `hoop_stress_proxy` (= I², proportional to σ_θ).
+Only rows where `|Icoil| > 0.1 A` are included so idle periods do not dilute the distributions.
+
+---
+
+## Querying cumulative statistics — `query_cumstats.py`
+
+All queries are read-only. Operational and experiment subcommands follow the same pattern.
+
+```bash
+# ── Operational data ─────────────────────────────────────────────────────────
+
+# Scalar totals for a site (energy, heat, duration)
+python query_cumstats.py --db magnetdb.duckdb --site M9_A19061901_00 scalars
+
+# Field-bin distributions at site level (all channels)
+python query_cumstats.py --db magnetdb.duckdb --site M9_A19061901_00 site-bins
+
+# Selected channels with bar-chart plots
+python query_cumstats.py --db magnetdb.duckdb --site M9_A19061901_00 site-bins \
+ --channels Ptot,tsb --plot
+
+# Per-part stats for all parts of a magnet
+python query_cumstats.py --db magnetdb.duckdb --magnet M9Bitters magnet-bins --plot
+
+# Stats for a single part across all runs and sites
+python query_cumstats.py --db magnetdb.duckdb --part M9Bi part-bins \
+ --channels Icoil,hoop_stress_proxy --plot
+
+# ── Experiment data ───────────────────────────────────────────────────────────
+
+# Scalar totals across all experiments for a site
+python query_cumstats.py --db magnetdb.duckdb --site M10_A250429_00 exp-scalars
+
+# Site-level field-bin distributions from experiment data
+python query_cumstats.py --db magnetdb.duckdb --site M10_A250429_00 exp-site-bins
+
+# Filter to a single experiment by name
+python query_cumstats.py --db magnetdb.duckdb --site M10_A250429_00 \
+ --experiment "2025.04.30 - 13:06:03" exp-site-bins
+
+# Per-part field-bin distributions for a specific part
+python query_cumstats.py --db magnetdb.duckdb --part M10Bi exp-part-bins \
+ --channels Icoil,hoop_stress_proxy --plot
+```
+
+| Subcommand | Required flag | Source table |
+|------------|--------------|--------------|
+| `scalars` | `--site` or `--magnet` | `op_run_scalars` |
+| `site-bins` | `--site` | `op_site_bin_stats` |
+| `magnet-bins` | `--magnet` | `op_part_bin_stats` |
+| `part-bins` | `--part` | `op_part_bin_stats` |
+| `exp-scalars` | `--site` or `--magnet` | `exp_run_scalars` |
+| `exp-site-bins` | `--site` | `exp_site_bin_stats` |
+| `exp-part-bins` | `--part` | `exp_part_bin_stats` |
+
+Add `--channels ch1,ch2` to restrict the channel output.
+Add `--plot` to save PNG bar charts alongside the tabular output.
+Add `--experiment ` (exp-* subcommands only) to filter to a single experiment.
+
+---
+
+## Aggregation reference
+
+| Derived quantity | SQL expression |
+|-----------------|----------------|
+| Operating time (h) | `SUM(sum_dt) / 3600` |
+| Time-weighted mean | `SUM(sum_x_dt) / SUM(sum_dt)` |
+| Time-weighted std | `sqrt(SUM(sum_x2_dt)/SUM(sum_dt) − mean²)` |
+| Cumulative integral | `SUM(sum_x_dt)` (energy, heat, …) |
+| Peak value ever | `MAX(max_x)` |
+| Fatigue proxy | `SUM(sum_x2_dt)` where channel = `hoop_stress_proxy` gives `Σ(I²·dt)` |
diff --git a/to_duckdb/magnetdb.py b/to_duckdb/magnetdb.py
new file mode 100644
index 0000000..6de90e8
--- /dev/null
+++ b/to_duckdb/magnetdb.py
@@ -0,0 +1,1424 @@
+"""
+magnetdb.py
+===========
+Unified CLI entry point for the student MagnetDB DuckDB.
+
+ python magnetdb.py list [--db ...]
+
+ python magnetdb.py db create [--db ...]
+ python magnetdb.py db delete [--db ...] [--yes]
+
+ python magnetdb.py material add [--db ...] [--input-dir ...] [--dry-run]
+ python magnetdb.py material view [] [--db ...] [--nuance NUANCE]
+ python magnetdb.py material delete [--db ...]
+
+ python magnetdb.py magnet add [--db ...] [--input-dir ...] [--part-dir ...] [--geometry ...] [--dry-run]
+ python magnetdb.py magnet view [] [--db ...] [--type insert|bitters|hybrid] [--status STATUS]
+ python magnetdb.py magnet check-geometry [] [--db ...]
+ python magnetdb.py magnet delete [--db ...]
+
+ python magnetdb.py site add [--db ...] [--input-dir ...] [--magnet-dir ...] [--dry-run]
+ python magnetdb.py site view [] [--db ...] [--housing HOUSING] [--status STATUS]
+ python magnetdb.py site delete [--db ...]
+ python magnetdb.py site update-magnet [--db ...] [--z-offset ...]
+
+ python magnetdb.py housing view [] [--db ...]
+ python magnetdb.py experiments view [--site ] [--magnet ] [--part ]
+ [--from DATETIME] [--to DATETIME] [--db ...]
+ python magnetdb.py operationaldata view [--site ] [--type TYPE]
+ [--magnet ] [--part ]
+ [--from DATETIME] [--to DATETIME] [--db ...]
+ python magnetdb.py overview-records view [--site ] [--magnet ] [--part ]
+ [--from DATETIME] [--to DATETIME] [--signatures] [--db ...]
+
+ python magnetdb.py populate operationaldata [SITE ...] [--all] [--type ...] [--records-base ...] [--dry-run]
+ python magnetdb.py populate experiments [SITE ...] [--all] [--dry-run]
+ python magnetdb.py populate overview-records [SITE ...] [--all] [--reprocess] [--dry-run]
+ python magnetdb.py populate overview-records-from-json [--site SITE] [--reprocess] [--dry-run] [--db ...]
+
+ python magnetdb.py hoop-stress compute [SITE ...] [--all] [--db ...] [--magnet-type H|B|S|all]
+ [--bins 0,100,200,...] [--parquet-dir ...] [--geometries ...]
+ [--reprocess] [--dry-run] [--use-mrun]
+ [--records-base ...] [--srv-subdir ...]
+
+ python magnetdb.py hoop-stress barchart [--db ...] [--geometries ...] [--debug]
+ [--i-h A] [--i-b A] [--i-s A]
+ python magnetdb.py hoop-stress history [--db ...] [--geometries ...] [--debug]
+ [--pupitre FILE ...] [--records-base DIR] [--srv-subdir DIR]
+ [--use-mrun] [--check] [--magnet-type H|B|S|all]
+ python magnetdb.py hoop-stress stats [--db ...] [--geometries ...] [--debug]
+ [--pupitre FILE ...] [--records-base DIR] [--srv-subdir DIR]
+ [--use-mrun] [--check] [--magnet-type H|B|S|all]
+ [--output CSV]
+ python magnetdb.py hoop-stress fatigue [--db ...] [--geometries ...] [--debug]
+ [--pupitre FILE ...] [--records-base DIR] [--srv-subdir DIR]
+ [--use-mrun] [--check] [--magnet-type H|B|S|all]
+ [--bins N]
+"""
+
+import argparse
+import json
+import sys
+from pathlib import Path
+
+try:
+ from zoneinfo import ZoneInfo
+except ImportError:
+ from backports.zoneinfo import ZoneInfo # type: ignore[no-redef]
+
+import duckdb
+
+from crud import (
+ check_geometry_data,
+ delete_magnet,
+ delete_material,
+ delete_site,
+ infer_magnet_type,
+ insert_experiments,
+ insert_magnet,
+ insert_magnet_parts,
+ insert_material,
+ insert_overview_record,
+ insert_overview_record_from_dict,
+ insert_part,
+ insert_site,
+ insert_site_magnets,
+ list_objects,
+ load_json,
+ print_geometry_check,
+ update_site_magnet,
+ upsert_overview_record,
+ view_experiments,
+ view_housing_config,
+ view_housing_configs,
+ view_magnet,
+ view_magnets,
+ view_material,
+ view_materials,
+ view_operationaldata,
+ view_overview_records,
+ view_site,
+ view_sites,
+)
+from populate import (
+ ALL_POPULATE_TYPES,
+ _PBSURV as _DEFAULT_PBSURV,
+ _RECORDS_BASE as _DEFAULT_RECORDS_BASE,
+ _SRV_SUBDIR as _DEFAULT_SRV_SUBDIR,
+ find_and_register_pupitre as _pupitre_find_and_register,
+ find_and_register_tdms as _tdms_find_and_register,
+ load_site as _load_site,
+)
+from config import DEFAULT_DB
+from schema import COIL_TYPES, ensure_schema
+
+
+# ---------------------------------------------------------------------------
+# list handler
+# ---------------------------------------------------------------------------
+
+
+def cmd_list(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ objects = list_objects(con)
+ for entity, names in objects.items():
+ print(f"{entity} ({len(names)}):")
+ if names:
+ for name in names:
+ print(f" {name}")
+ else:
+ print(" (none)")
+
+
+# ---------------------------------------------------------------------------
+# db handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_db_create(args) -> None:
+ db_path = Path(args.db)
+ if db_path.exists():
+ print(f"Database '{db_path}' already exists.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path)) as con:
+ ensure_schema(con)
+ print(f"Created database '{db_path}'.")
+
+
+def cmd_db_delete(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ if not args.yes:
+ answer = input(f"Delete '{db_path}'? [y/N] ").strip().lower()
+ if answer not in ("y", "yes"):
+ print("Aborted.")
+ return
+ db_path.unlink()
+ wal = db_path.with_suffix(".duckdb.wal")
+ if wal.exists():
+ wal.unlink()
+ print(f"Deleted '{db_path}'.")
+
+
+# ---------------------------------------------------------------------------
+# material handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_material_add(args) -> None:
+ json_path = Path(args.json_file)
+ if args.input_dir:
+ json_path = Path(args.input_dir) / json_path
+ if not json_path.exists():
+ print(f"Error: '{json_path}' not found.")
+ sys.exit(1)
+ data = load_json(json_path)
+ if args.dry_run:
+ print(f"[DRY RUN] would insert material '{data.get('name', '?')}' nuance={data.get('nuance', '?')}")
+ return
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path)) as con:
+ ensure_schema(con)
+ insert_material(con, data)
+
+
+def cmd_material_view(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ if args.name:
+ view_material(con, args.name)
+ else:
+ view_materials(con, nuance_filter=args.nuance)
+
+
+def cmd_material_delete(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path)) as con:
+ delete_material(con, args.name)
+
+
+# ---------------------------------------------------------------------------
+# add_magnet / add_site (migrated from deprecated/add_magnet.py and add_site.py)
+# ---------------------------------------------------------------------------
+
+
+def _resolve_parts(parts: list, part_dir: Path) -> list[dict]:
+ """Return fully-resolved part dicts; string entries are loaded from /.json."""
+ resolved = []
+ for entry in parts:
+ if isinstance(entry, dict):
+ resolved.append(entry)
+ continue
+ name = entry
+ json_path = part_dir / f"{name}.json"
+ if not json_path.exists():
+ print(
+ f"Error: part '{name}' is a name reference but '{json_path}' not found.\n"
+ f"Place the part definition there or use --part-dir."
+ )
+ sys.exit(1)
+ print(f" ~ part '{name}' not inline — loading from {json_path.name} …")
+ resolved.append(load_json(json_path))
+ return resolved
+
+
+def _validate_magnet(data: dict) -> list[str]:
+ errors = []
+ if not data.get("name"):
+ errors.append("Missing top-level 'name'")
+ if not data.get("parts"):
+ errors.append("'parts' list is empty or missing")
+ for i, part in enumerate(data.get("parts", [])):
+ if isinstance(part, str):
+ errors.append(f"Part[{i}] '{part}' is an unresolved name reference")
+ continue
+ if not part.get("name"):
+ errors.append(f"Part[{i}] is missing 'name'")
+ if not part.get("type"):
+ errors.append(f"Part '{part.get('name', i)}' is missing 'type'")
+ if not part.get("material") or not part["material"].get("name"):
+ errors.append(f"Part '{part.get('name', i)}' is missing 'material.name'")
+ return errors
+
+
+def _add_magnet(
+ data: dict,
+ db_path,
+ dry_run: bool = False,
+ part_dir=None,
+ geometry_path=None,
+) -> None:
+ # db_path is created by DuckDB if absent — intentional: `magnet add` bootstraps the DB.
+ # `_add_site` requires the file to exist because a site depends on prior magnet records.
+ db_path = Path(db_path)
+ part_dir = Path(part_dir) if part_dir else Path(".")
+
+ if geometry_path:
+ data = {**data, "geometry": str(geometry_path)}
+
+ if data.get("name", "").endswith(".json"):
+ data = {**data, "name": data["name"][:-5]}
+
+ raw_parts = data.get("parts") or []
+ if any(isinstance(p, str) for p in raw_parts):
+ data = {**data, "parts": _resolve_parts(raw_parts, part_dir)}
+
+ errors = _validate_magnet(data)
+ if errors:
+ print("Validation errors:")
+ for e in errors:
+ print(f" • {e}")
+ sys.exit(1)
+
+ parts = data["parts"]
+ magnet_type = infer_magnet_type(parts)
+
+ if dry_run:
+ coil_parts = [p for p in parts if p.get("type") in COIL_TYPES]
+ mats = {p["material"]["name"] for p in parts if p.get("material")}
+ print("[dry-run] Validation passed. Would insert:")
+ print(f" magnet : {data['name']} [{magnet_type}] {data.get('status', '')}")
+ print(f" parts : {len(parts)} ({len(coil_parts)} coil channel(s))")
+ print(f" materials: {len(mats)}")
+ return
+
+ with duckdb.connect(str(db_path)) as con:
+ ensure_schema(con)
+ print(f"\nAdding magnet '{data['name']}' to {db_path.name} …\n")
+
+ seen_materials: set[str] = set()
+ for part in parts:
+ mat = part.get("material", {})
+ mat_name = mat.get("name")
+ if mat_name and mat_name not in seen_materials:
+ insert_material(con, mat)
+ seen_materials.add(mat_name)
+
+ print()
+ for part in parts:
+ insert_part(con, part)
+
+ print()
+ insert_magnet(con, data, magnet_type)
+
+ print()
+ insert_magnet_parts(con, data["name"], parts)
+
+ print("\nDone.")
+
+
+def _magnet_name(entry) -> str:
+ return entry if isinstance(entry, str) else entry["name"]
+
+
+def _validate_site(data: dict) -> list[str]:
+ errors = []
+ if not data.get("name"):
+ errors.append("Missing 'name'")
+ if not data.get("magnets"):
+ errors.append("'magnets' list is empty or missing")
+ return errors
+
+
+def _ensure_magnets(
+ magnet_entries: list, db_path: Path, magnet_dir: Path, dry_run: bool = False
+) -> list[str]:
+ """Auto-load magnets absent from the DB; returns a list of error strings."""
+ names = [_magnet_name(e) for e in magnet_entries]
+ if not names:
+ return []
+
+ placeholders = ", ".join("?" * len(names))
+ with duckdb.connect(str(db_path)) as chk:
+ rows = chk.execute(
+ f"SELECT name FROM magnets WHERE name IN ({placeholders})", names
+ ).fetchall()
+ present = {r[0] for r in rows}
+
+ errors = []
+ for name in names:
+ if name in present:
+ continue
+ json_path = magnet_dir / f"{name}.json"
+ if not json_path.exists():
+ errors.append(
+ f"Magnet '{name}' not in DB and '{json_path}' not found. "
+ f"Load it manually with: python magnetdb.py magnet add {name}.json"
+ )
+ continue
+ print(f" ~ magnet '{name}' not in DB — loading from {json_path.name} …")
+ _add_magnet(load_json(json_path), db_path, dry_run=dry_run,
+ part_dir=json_path.parent)
+ return errors
+
+
+def _add_site(data: dict, db_path, dry_run: bool = False, magnet_dir=None) -> None:
+ db_path = Path(db_path)
+ magnet_dir = Path(magnet_dir) if magnet_dir else Path(".")
+
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ print("Create it first with: python magnetdb.py db create")
+ print("Then add magnets with: python magnetdb.py magnet add ")
+ sys.exit(1)
+
+ if data.get("name", "").endswith(".json"):
+ data["name"] = data["name"][:-5]
+
+ errors = _validate_site(data)
+ if errors:
+ print("Validation errors:")
+ for e in errors:
+ print(f" • {e}")
+ sys.exit(1)
+
+ missing_errors = _ensure_magnets(
+ data.get("magnets", []), db_path, magnet_dir, dry_run=dry_run
+ )
+ if missing_errors:
+ print("Errors resolving magnets:")
+ for e in missing_errors:
+ print(f" • {e}")
+ sys.exit(1)
+
+ if dry_run:
+ magnet_names = [_magnet_name(e) for e in data.get("magnets", [])]
+ print("[dry-run] Validation passed. Would insert:")
+ print(f" site : {data['name']} [{data.get('housing', '?')}]")
+ print(f" magnets : {magnet_names}")
+ return
+
+ with duckdb.connect(str(db_path)) as con:
+ ensure_schema(con)
+ site_name = data["name"]
+ print(f"\nAdding site '{site_name}' to {db_path.name} …\n")
+
+ insert_site(con, data)
+ insert_site_magnets(con, site_name, data.get("magnets", []))
+
+ records = data.get("records") or []
+ if records:
+ insert_experiments(con, site_name, records)
+
+ print("\nDone.")
+
+
+# ---------------------------------------------------------------------------
+# magnet handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_magnet_add(args) -> None:
+ json_path = Path(args.json_file)
+ if args.input_dir:
+ json_path = Path(args.input_dir) / json_path
+ if not json_path.exists():
+ print(f"Error: '{json_path}' not found.")
+ sys.exit(1)
+ part_dir = Path(args.part_dir) if args.part_dir else json_path.parent
+ geometry_path = Path(args.geometry) if args.geometry else None
+ if geometry_path and not geometry_path.exists():
+ print(f"Error: geometry file '{geometry_path}' not found.")
+ sys.exit(1)
+ _add_magnet(load_json(json_path), args.db, dry_run=args.dry_run,
+ part_dir=part_dir, geometry_path=geometry_path)
+
+
+def cmd_magnet_view(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path)) as con:
+ if args.name:
+ view_magnet(con, args.name)
+ else:
+ view_magnets(con, type_filter=args.type, status_filter=args.status)
+
+
+def cmd_magnet_check_geometry(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ results = check_geometry_data(con, args.name or None)
+ print_geometry_check(results)
+
+
+def cmd_magnet_delete(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path)) as con:
+ delete_magnet(con, args.name)
+
+
+# ---------------------------------------------------------------------------
+# site handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_site_add(args) -> None:
+ json_path = Path(args.json_file)
+ if args.input_dir:
+ json_path = Path(args.input_dir) / json_path
+ if not json_path.exists():
+ print(f"Error: '{json_path}' not found.")
+ sys.exit(1)
+ magnet_dir = Path(args.magnet_dir) if args.magnet_dir else json_path.parent
+ _add_site(load_json(json_path), args.db, dry_run=args.dry_run, magnet_dir=magnet_dir)
+
+
+def cmd_site_view(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path)) as con:
+ if args.name:
+ view_site(con, args.name)
+ else:
+ view_sites(con, housing_filter=args.housing, status_filter=args.status)
+
+
+def cmd_site_delete(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path)) as con:
+ delete_site(con, args.name)
+
+
+def cmd_site_update_magnet(args) -> None:
+ metadata = None
+ if args.metadata:
+ try:
+ metadata = json.loads(args.metadata)
+ except json.JSONDecodeError as exc:
+ print(f"Error: --metadata is not valid JSON: {exc}")
+ sys.exit(1)
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path)) as con:
+ ensure_schema(con)
+ try:
+ update_site_magnet(
+ con,
+ args.site_name,
+ args.magnet_name,
+ z_offset=args.z_offset,
+ r_offset=args.r_offset,
+ parallax=args.parallax,
+ commissioned_at=args.commissioned_at,
+ decommissioned_at=args.decommissioned_at,
+ metadata=metadata,
+ )
+ except ValueError as exc:
+ print(f"Error: {exc}")
+ sys.exit(1)
+
+
+# ---------------------------------------------------------------------------
+# housing handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_housing_view(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ if args.name:
+ view_housing_config(con, args.name)
+ else:
+ view_housing_configs(con)
+
+
+# ---------------------------------------------------------------------------
+# experiments handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_experiments_view(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ view_experiments(
+ con,
+ site_name=args.site,
+ magnet_name=args.magnet,
+ part_name=args.part,
+ from_ts=args.date_from,
+ to_ts=args.date_to,
+ )
+
+
+# ---------------------------------------------------------------------------
+# operationaldata handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_operationaldata_view(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ view_operationaldata(
+ con,
+ site_name=args.site,
+ type_filter=args.type,
+ magnet_name=args.magnet,
+ part_name=args.part,
+ from_ts=args.date_from,
+ to_ts=args.date_to,
+ )
+
+
+# ---------------------------------------------------------------------------
+# overview-records handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_overview_records_view(args) -> None:
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ view_overview_records(
+ con,
+ site_name=args.site,
+ show_signatures=args.signatures,
+ magnet_name=args.magnet,
+ part_name=args.part,
+ from_ts=args.date_from,
+ to_ts=args.date_to,
+ )
+
+
+def _resolve_site_names(args, db_path: str) -> list[str]:
+ if getattr(args, "all", False):
+ with duckdb.connect(db_path, read_only=True) as con:
+ return [r[0] for r in con.execute("SELECT name FROM sites ORDER BY name").fetchall()]
+ return list(args.site_names)
+
+
+# ---------------------------------------------------------------------------
+# populate handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_populate_operationaldata(args) -> None:
+ db_path = args.db
+ if not Path(db_path).exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ try:
+ db_tz = ZoneInfo(args.db_tz)
+ except Exception:
+ print(f"Error: Unknown timezone '{args.db_tz}'")
+ sys.exit(1)
+
+ site_names = _resolve_site_names(args, db_path)
+ if not site_names:
+ print("No sites specified. Pass site name(s) or --all.")
+ sys.exit(1)
+
+ records_base = Path(args.records_base)
+ active_types = args.types if args.types else ALL_POPULATE_TYPES
+ tdms_types = [t for t in active_types if t != "Pupitre"]
+ do_pupitre = "Pupitre" in active_types
+
+ for site_name in site_names:
+ site = _load_site(site_name, db_path)
+ if site is None:
+ print(f"[SKIP] '{site_name}' not found in DB.")
+ continue
+ print(f"\nSite: {site_name} housing={site['housing']}")
+ if do_pupitre:
+ _pupitre_find_and_register(
+ site, db_path, db_tz, dry_run=args.dry_run,
+ records_base=records_base, srv_subdir=args.srv_subdir,
+ )
+ if tdms_types:
+ _tdms_find_and_register(
+ site, db_path, db_tz, dry_run=args.dry_run,
+ type_filter=tdms_types, records_base=records_base, pbsurv=args.pbsurv,
+ )
+
+
+def cmd_populate_experiments(args) -> None:
+ db_path = args.db
+ if not Path(db_path).exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+ try:
+ db_tz = ZoneInfo(args.db_tz)
+ except Exception:
+ print(f"Error: Unknown timezone '{args.db_tz}'")
+ sys.exit(1)
+
+ site_names = _resolve_site_names(args, db_path)
+ if not site_names:
+ print("No sites specified. Pass site name(s) or --all.")
+ sys.exit(1)
+
+ records_base = Path(args.records_base)
+
+ for site_name in site_names:
+ site = _load_site(site_name, db_path)
+ if site is None:
+ print(f"[SKIP] '{site_name}' not found in DB.")
+ continue
+ print(f"\nSite: {site_name} housing={site['housing']}")
+
+ # Scan filesystem for matching pupitre TXT files (dry_run=True so
+ # find_and_register returns matches without writing to operationaldata).
+ matches = _pupitre_find_and_register(
+ site, db_path, db_tz, dry_run=True,
+ records_base=records_base, srv_subdir=args.srv_subdir,
+ )
+
+ if not matches:
+ continue
+
+ records = [
+ {"name": fpath.stem, "description": "", "file": fpath.name}
+ for fpath, _ in matches
+ ]
+
+ if args.dry_run:
+ print(f" [DRY RUN] {len(records)} pupitre file(s) would be added to experiments")
+ continue
+
+ with duckdb.connect(db_path) as con:
+ ensure_schema(con)
+ insert_experiments(con, site_name, records, verbose=True)
+
+
+def cmd_populate_overview_records_from_json(args) -> None:
+ json_path = Path(args.json_file)
+ if not json_path.exists():
+ print(f"Error: '{json_path}' not found.")
+ sys.exit(1)
+
+ try:
+ with open(json_path, encoding="utf-8") as fh:
+ records = json.load(fh)
+ except json.JSONDecodeError as exc:
+ print(f"Error: '{json_path}' is not valid JSON: {exc}")
+ sys.exit(1)
+
+ if not isinstance(records, list):
+ print("Error: JSON file must contain a top-level array of records.")
+ sys.exit(1)
+
+ db_path = Path(args.db)
+ if not db_path.exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+
+ site_name = args.site or None
+
+ print(f"\nLoading {len(records)} overview record(s) from {json_path.name} …\n")
+
+ if args.dry_run:
+ for rec in records:
+ fname = rec.get("filename", "")
+ housing = rec.get("housing", "?")
+ dur = rec.get("duration", 0.0)
+ print(f" [dry-run] would insert: {fname} [{housing}] duration={float(dur or 0):.1f}s")
+ return
+
+ with duckdb.connect(str(db_path)) as con:
+ ensure_schema(con)
+ for rec in records:
+ try:
+ insert_overview_record_from_dict(
+ con, rec, site_name=site_name, verbose=True, upsert=args.reprocess
+ )
+ except (ValueError, KeyError) as exc:
+ fname = rec.get("filename", "")
+ print(f" [ERROR] {fname}: {exc}")
+
+ print("\nDone.")
+
+
+def cmd_populate_overview_records(args) -> None:
+ try:
+ from python_magnetrun.analysis.processing import (
+ ProcessingConfig,
+ process_overview_file,
+ )
+ except ImportError:
+ print("Error: python_magnetrun is not installed.")
+ print("Install it with: pip install python_magnetrun")
+ sys.exit(1)
+
+ db_path = args.db
+ if not Path(db_path).exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+
+ site_names = _resolve_site_names(args, db_path)
+ if not site_names:
+ print("No sites specified. Pass site name(s) or --all.")
+ sys.exit(1)
+
+ insert_fn = upsert_overview_record if args.reprocess else insert_overview_record
+ config = ProcessingConfig(dry_run=args.dry_run)
+
+ for site_name in site_names:
+ with duckdb.connect(db_path, read_only=True) as con:
+ rows = con.execute(
+ "SELECT file FROM operationaldata "
+ "WHERE site_name = ? AND type = 'Overview' ORDER BY file",
+ [site_name],
+ ).fetchall()
+
+ if not rows:
+ print(f"[INFO] {site_name}: no Overview entries in operationaldata — "
+ "run 'populate operationaldata' first.")
+ continue
+
+ print(f"\nSite: {site_name} ({len(rows)} Overview file(s))")
+ for (fpath,) in rows:
+ if not Path(fpath).exists():
+ print(f" [SKIP] {Path(fpath).name} — file not found")
+ continue
+ if args.dry_run:
+ print(f" [DRY RUN] would process {Path(fpath).name}")
+ continue
+ try:
+ record = process_overview_file(fpath, config)
+ with duckdb.connect(db_path) as con:
+ ensure_schema(con)
+ insert_fn(con, record, site_name=site_name, verbose=True)
+ except Exception as exc:
+ print(f" [ERROR] {Path(fpath).name}: {exc}")
+
+
+# ---------------------------------------------------------------------------
+# hoop-stress handlers
+# ---------------------------------------------------------------------------
+
+
+def cmd_hoop_stress_compute(args) -> None:
+ from compute_hoop_stats import DEFAULT_STRESS_BINS, _parse_bins, compute_hoop_stress_history
+
+ db_path = args.db
+ if not Path(db_path).exists():
+ print(f"Error: '{db_path}' does not exist.")
+ sys.exit(1)
+
+ site_names = _resolve_site_names(args, db_path)
+ if not site_names:
+ print("No sites specified. Pass site name(s) or --all.")
+ sys.exit(1)
+
+ bins = _parse_bins(args.bins) if args.bins else DEFAULT_STRESS_BINS
+ pupitre_datadir = (
+ str(Path(args.records_base) / args.srv_subdir) if args.records_base else ""
+ )
+
+ for site_name in site_names:
+ print(f"\nSite: {site_name}")
+ compute_hoop_stress_history(
+ site_name=site_name,
+ db_path=db_path,
+ magnet_type=args.magnet_type,
+ bins=bins,
+ parquet_dir=args.parquet_dir,
+ geometries_dir=args.geometries,
+ reprocess=args.reprocess,
+ dry_run=args.dry_run,
+ use_mrun=args.use_mrun,
+ pupitre_datadir=pupitre_datadir,
+ verbose=not args.quiet,
+ )
+
+
+def cmd_hoop_stress_barchart(args) -> None:
+ from stress_map import cmd_barchart
+ cmd_barchart(args)
+
+
+def _inject_pupitre_datadir(args) -> None:
+ """Compute args.pupitre_datadir from --records-base / --srv-subdir."""
+ args.pupitre_datadir = (
+ str(Path(args.records_base) / args.srv_subdir) if args.records_base else ""
+ )
+
+
+def cmd_hoop_stress_history(args) -> None:
+ from stress_map import cmd_history
+ _inject_pupitre_datadir(args)
+ cmd_history(args)
+
+
+def cmd_hoop_stress_stats(args) -> None:
+ from stress_map import cmd_stats
+ _inject_pupitre_datadir(args)
+ cmd_stats(args)
+
+
+def cmd_hoop_stress_fatigue(args) -> None:
+ from stress_map import cmd_fatigue
+ _inject_pupitre_datadir(args)
+ cmd_fatigue(args)
+
+
+# ---------------------------------------------------------------------------
+# Parser
+# ---------------------------------------------------------------------------
+
+_DISPATCH = {
+ ("list", None): cmd_list,
+ ("db", "create"): cmd_db_create,
+ ("db", "delete"): cmd_db_delete,
+ ("material", "add"): cmd_material_add,
+ ("material", "view"): cmd_material_view,
+ ("material", "delete"): cmd_material_delete,
+ ("magnet", "add"): cmd_magnet_add,
+ ("magnet", "view"): cmd_magnet_view,
+ ("magnet", "check-geometry"): cmd_magnet_check_geometry,
+ ("magnet", "delete"): cmd_magnet_delete,
+ ("site", "add"): cmd_site_add,
+ ("site", "view"): cmd_site_view,
+ ("site", "delete"): cmd_site_delete,
+ ("site", "update-magnet"): cmd_site_update_magnet,
+ ("housing", "view"): cmd_housing_view,
+ ("experiments", "view"): cmd_experiments_view,
+ ("operationaldata", "view"): cmd_operationaldata_view,
+ ("overview-records", "view"): cmd_overview_records_view,
+ ("populate", "operationaldata"): cmd_populate_operationaldata,
+ ("populate", "experiments"): cmd_populate_experiments,
+ ("populate", "overview-records"): cmd_populate_overview_records,
+ ("populate", "overview-records-from-json"): cmd_populate_overview_records_from_json,
+ ("hoop-stress", "compute"): cmd_hoop_stress_compute,
+ ("hoop-stress", "barchart"): cmd_hoop_stress_barchart,
+ ("hoop-stress", "history"): cmd_hoop_stress_history,
+ ("hoop-stress", "stats"): cmd_hoop_stress_stats,
+ ("hoop-stress", "fatigue"): cmd_hoop_stress_fatigue,
+}
+
+
+def _db_arg(p: argparse.ArgumentParser) -> None:
+ p.add_argument("--db", default=DEFAULT_DB,
+ help=f"DuckDB file (default: {DEFAULT_DB})")
+
+
+def _input_dir_arg(p: argparse.ArgumentParser) -> None:
+ p.add_argument("--input-dir", dest="input_dir", default=None,
+ help="Directory to look up the JSON file in "
+ "(default: use the path given to json_file as-is)")
+
+
+def _sites_arg(p: argparse.ArgumentParser) -> None:
+ p.add_argument("site_names", nargs="*", metavar="SITE",
+ help="Site name(s). Use --all to process every site in the DB.")
+ p.add_argument("--all", action="store_true",
+ help="Process all sites in the database.")
+
+
+def _time_range_args(p: argparse.ArgumentParser) -> None:
+ p.add_argument(
+ "--from", dest="date_from", default=None, metavar="DATETIME",
+ help="Include only records at or after this date/time "
+ "(YYYY-MM-DD or YYYY-MM-DD HH:MM:SS)",
+ )
+ p.add_argument(
+ "--to", dest="date_to", default=None, metavar="DATETIME",
+ help="Include only records at or before this date/time "
+ "(YYYY-MM-DD or YYYY-MM-DD HH:MM:SS)",
+ )
+
+
+def _hs_shared_args(p: argparse.ArgumentParser) -> None:
+ """Arguments shared by all hoop-stress visualisation subcommands."""
+ p.add_argument("site_name", help="Site name as registered in DuckDB (e.g. M9)")
+ _db_arg(p)
+ p.add_argument(
+ "--geometries", default="geometries",
+ help="Directory of YAML geometry files (default: geometries/)",
+ )
+ p.add_argument("--debug", action="store_true",
+ help="Enable debug output from magnet_setup()")
+
+
+def _hs_pupitre_args(p: argparse.ArgumentParser) -> None:
+ """Arguments for subcommands that read a pupitre time-series file."""
+ p.add_argument(
+ "--pupitre", nargs="*", default=None, metavar="FILE",
+ help="Pupitre file(s) (.txt, .tdms, .csv). "
+ "Omit to use all experiment files registered for the site.",
+ )
+ p.add_argument(
+ "--records-base", default=str(_DEFAULT_RECORDS_BASE), dest="records_base",
+ metavar="DIR",
+ help=f"Root of the records tree (default: {_DEFAULT_RECORDS_BASE})",
+ )
+ p.add_argument(
+ "--srv-subdir", default=_DEFAULT_SRV_SUBDIR, dest="srv_subdir",
+ help=f"Subdirectory of records-base for pupitre TXT files "
+ f"(default: {_DEFAULT_SRV_SUBDIR})",
+ )
+ p.add_argument(
+ "--use-mrun", action="store_true", dest="use_mrun",
+ help="Load via python_magnetrun.MagnetRun.load_mrun() "
+ "(supports .tdms and path auto-resolution)",
+ )
+ p.add_argument(
+ "--check", action="store_true",
+ help="Validate fast results against bmap.getHoop row by row",
+ )
+ p.add_argument(
+ "--magnet-type", default="all", dest="magnet_type",
+ choices=["H", "B", "S", "all"],
+ help="Coil type(s) to compute hoop stress for (default: all)",
+ )
+
+
+def build_parser() -> argparse.ArgumentParser:
+ parser = argparse.ArgumentParser(
+ prog="magnetdb",
+ description="Manage a student MagnetDB DuckDB.",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=__doc__,
+ )
+ entity = parser.add_subparsers(
+ dest="entity", required=True,
+ metavar="{list,db,material,magnet,site,housing,experiments,operationaldata,overview-records,populate,hoop-stress}",
+ )
+
+ # ── list ─────────────────────────────────────────────────────────────────
+ list_p = entity.add_parser("list", help="List all objects (materials, magnets, sites, housings).")
+ _db_arg(list_p)
+
+ # ── db ───────────────────────────────────────────────────────────────────
+ db_p = entity.add_parser("db", help="Manage the DuckDB database file.")
+ db_sub = db_p.add_subparsers(dest="action", required=True,
+ metavar="{create,delete}")
+
+ db_create = db_sub.add_parser("create", help="Create a new database and initialise the schema.")
+ _db_arg(db_create)
+
+ db_del = db_sub.add_parser("delete", help="Delete the database file.")
+ _db_arg(db_del)
+ db_del.add_argument("--yes", "-y", action="store_true",
+ help="Skip confirmation prompt")
+
+ # ── material ─────────────────────────────────────────────────────────────
+ mat_p = entity.add_parser("material", help="Manage materials.")
+ mat_sub = mat_p.add_subparsers(dest="action", required=True,
+ metavar="{add,view,delete}")
+
+ ma_add = mat_sub.add_parser("add", help="Add a material from a JSON file.")
+ ma_add.add_argument("json_file", help="Path to the material JSON file (or bare name with --input-dir)")
+ _db_arg(ma_add)
+ _input_dir_arg(ma_add)
+ ma_add.add_argument("--dry-run", action="store_true",
+ help="Validate and preview without writing")
+
+ ma_view = mat_sub.add_parser("view", help="List all materials or show one.")
+ ma_view.add_argument("name", nargs="?", default=None,
+ help="Material name (omit to list all)")
+ ma_view.add_argument("--nuance", default=None,
+ help="Filter list by nuance (ignored when is given)")
+ _db_arg(ma_view)
+
+ ma_del = mat_sub.add_parser("delete", help="Delete a material (fails if referenced by a part).")
+ ma_del.add_argument("name", help="Material name")
+ _db_arg(ma_del)
+
+ # ── magnet ──────────────────────────────────────────────────────────────
+ magnet_p = entity.add_parser("magnet", help="Manage magnets.")
+ magnet_sub = magnet_p.add_subparsers(dest="action", required=True,
+ metavar="{add,view,check-geometry,delete}")
+
+ m_add = magnet_sub.add_parser("add", help="Add a magnet from a JSON export.")
+ m_add.add_argument("json_file", help="Path to the magnet JSON file (or bare name with --input-dir)")
+ _db_arg(m_add)
+ _input_dir_arg(m_add)
+ m_add.add_argument("--part-dir", dest="part_dir",
+ help="Directory for .json files "
+ "(default: same dir as the JSON file)")
+ m_add.add_argument("--geometry",
+ help="Path to the assembly-level YAML geometry file "
+ "(Insert, Bitters, …) to store in magnets.geometry_data. "
+ "Required for geometry_config_to_yaml / the 'geometry' "
+ "subcommand of stress_map.py / magnetdb.py hoop-stress.")
+ m_add.add_argument("--dry-run", action="store_true",
+ help="Validate and preview without writing")
+
+ m_view = magnet_sub.add_parser("view", help="List all magnets or show one.")
+ m_view.add_argument("name", nargs="?", default=None,
+ help="Magnet name (omit to list all)")
+ m_view.add_argument("--type", default=None,
+ choices=["insert", "bitters", "hybrid", "unknown"],
+ help="Filter list by magnet type (ignored when is given)")
+ m_view.add_argument("--status", default=None,
+ help="Filter list by status (ignored when is given)")
+ _db_arg(m_view)
+
+ m_chk = magnet_sub.add_parser(
+ "check-geometry",
+ help="Report geometry_data coverage for magnet assembly and parts.",
+ )
+ m_chk.add_argument("name", nargs="?", default=None,
+ help="Magnet name (omit to check all magnets)")
+ _db_arg(m_chk)
+
+ m_del = magnet_sub.add_parser("delete", help="Delete a magnet and its part links.")
+ m_del.add_argument("name", help="Magnet name")
+ _db_arg(m_del)
+
+ # ── site ─────────────────────────────────────────────────────────────────
+ site_p = entity.add_parser("site", help="Manage sites.")
+ site_sub = site_p.add_subparsers(dest="action", required=True,
+ metavar="{add,view,delete,update-magnet}")
+
+ s_add = site_sub.add_parser("add", help="Add a site from a JSON export.")
+ s_add.add_argument("json_file", help="Path to the site JSON file (or bare name with --input-dir)")
+ _db_arg(s_add)
+ _input_dir_arg(s_add)
+ s_add.add_argument("--magnet-dir",
+ help="Directory for .json files "
+ "(default: same dir as the JSON file)")
+ s_add.add_argument("--dry-run", action="store_true",
+ help="Validate and preview without writing")
+
+ s_view = site_sub.add_parser("view", help="List all sites or show one.")
+ s_view.add_argument("name", nargs="?", default=None,
+ help="Site name (omit to list all)")
+ s_view.add_argument("--housing", default=None,
+ help="Filter list by housing name (ignored when is given)")
+ s_view.add_argument("--status", default=None,
+ help="Filter list by status (ignored when is given)")
+ _db_arg(s_view)
+
+ s_del = site_sub.add_parser("delete",
+ help="Delete a site, its magnet links, and experiments.")
+ s_del.add_argument("name", help="Site name")
+ _db_arg(s_del)
+
+ s_upd = site_sub.add_parser("update-magnet",
+ help="Update SiteMagnet fields for a site/magnet pair.")
+ s_upd.add_argument("site_name", help="Site name")
+ s_upd.add_argument("magnet_name", help="Magnet name")
+ _db_arg(s_upd)
+ s_upd.add_argument("--z-offset", type=float, dest="z_offset", help="z offset (m)")
+ s_upd.add_argument("--r-offset", type=float, dest="r_offset", help="r offset (m)")
+ s_upd.add_argument("--parallax", type=float, help="Parallax angle")
+ s_upd.add_argument("--commissioned-at", dest="commissioned_at",
+ help="Commissioning timestamp (YYYY-MM-DD or datetime)")
+ s_upd.add_argument("--decommissioned-at", dest="decommissioned_at",
+ help="Decommissioning timestamp (YYYY-MM-DD or datetime)")
+ s_upd.add_argument("--metadata", help="JSON string for metadata field")
+
+ # ── housing ──────────────────────────────────────────────────────────────
+ housing_p = entity.add_parser("housing", help="View housing configurations.")
+ housing_sub = housing_p.add_subparsers(dest="action", required=True,
+ metavar="{view}")
+
+ h_view = housing_sub.add_parser("view", help="List all housings or show one.")
+ h_view.add_argument("name", nargs="?", default=None,
+ help="Housing name (omit to list all)")
+ _db_arg(h_view)
+
+ # ── experiments ───────────────────────────────────────────────────────────
+ exp_p = entity.add_parser("experiments", help="View experiment records.")
+ exp_sub = exp_p.add_subparsers(dest="action", required=True,
+ metavar="{view}")
+
+ e_view = exp_sub.add_parser("view", help="List experiments, optionally filtered.")
+ e_view.add_argument("--site", default=None, metavar="SITE",
+ help="Filter by site name")
+ e_view.add_argument("--magnet", default=None, metavar="MAGNET",
+ help="Filter by magnet name (shows all sites that used this magnet)")
+ e_view.add_argument("--part", default=None, metavar="PART",
+ help="Filter by part name (shows all sites that used this part)")
+ _time_range_args(e_view)
+ _db_arg(e_view)
+
+ # ── operationaldata ───────────────────────────────────────────────────────
+ opdata_p = entity.add_parser("operationaldata", help="View operationaldata records.")
+ opdata_sub = opdata_p.add_subparsers(dest="action", required=True,
+ metavar="{view}")
+
+ o_view = opdata_sub.add_parser(
+ "view", help="List operationaldata records, optionally filtered."
+ )
+ o_view.add_argument("--site", default=None, metavar="SITE",
+ help="Filter by site name")
+ o_view.add_argument(
+ "--type", default=None, choices=ALL_POPULATE_TYPES, metavar="TYPE",
+ help=f"Filter by file type ({', '.join(ALL_POPULATE_TYPES)})",
+ )
+ o_view.add_argument("--magnet", default=None, metavar="MAGNET",
+ help="Filter by magnet name (shows all sites that used this magnet)")
+ o_view.add_argument("--part", default=None, metavar="PART",
+ help="Filter by part name (shows all sites that used this part)")
+ _time_range_args(o_view)
+ _db_arg(o_view)
+
+ # ── overview-records ──────────────────────────────────────────────────────
+ ovr_p = entity.add_parser("overview-records", help="View overview_records.")
+ ovr_sub = ovr_p.add_subparsers(dest="action", required=True,
+ metavar="{view}")
+
+ ov_view = ovr_sub.add_parser(
+ "view", help="List overview_records, optionally filtered."
+ )
+ ov_view.add_argument("--site", default=None, metavar="SITE",
+ help="Filter by site name")
+ ov_view.add_argument("--magnet", default=None, metavar="MAGNET",
+ help="Filter by magnet name (shows all sites that used this magnet)")
+ ov_view.add_argument("--part", default=None, metavar="PART",
+ help="Filter by part name (shows all sites that used this part)")
+ _time_range_args(ov_view)
+ ov_view.add_argument("--signatures", action="store_true",
+ help="Include per-record signature and sync details")
+ _db_arg(ov_view)
+
+ # ── populate ─────────────────────────────────────────────────────────────
+ pop_p = entity.add_parser("populate", help="Populate data tables from files.")
+ pop_sub = pop_p.add_subparsers(dest="action", required=True,
+ metavar="{operationaldata,experiments,overview-records,overview-records-from-json}")
+
+ # populate operationaldata
+ p_opdata = pop_sub.add_parser(
+ "operationaldata",
+ help="Scan filesystem and register TDMS/pupitre files in operationaldata.",
+ )
+ _db_arg(p_opdata)
+ _sites_arg(p_opdata)
+ p_opdata.add_argument(
+ "--type", nargs="+", choices=ALL_POPULATE_TYPES, dest="types", metavar="TYPE",
+ help=f"File type(s) to scan ({', '.join(ALL_POPULATE_TYPES)}). Default: all.",
+ )
+ p_opdata.add_argument(
+ "--records-base", default=str(_DEFAULT_RECORDS_BASE), dest="records_base",
+ help=f"Root of the records tree (default: {_DEFAULT_RECORDS_BASE})",
+ )
+ p_opdata.add_argument(
+ "--srv-subdir", default=_DEFAULT_SRV_SUBDIR, dest="srv_subdir",
+ help=f"Subdirectory of records-base for pupitre TXT files (default: {_DEFAULT_SRV_SUBDIR})",
+ )
+ p_opdata.add_argument(
+ "--pbsurv", default=_DEFAULT_PBSURV,
+ help=f"Subdirectory of records-base for TDMS files (default: {_DEFAULT_PBSURV})",
+ )
+ p_opdata.add_argument(
+ "--db-tz", default="UTC", dest="db_tz",
+ help="Timezone of commissioned_at / decommissioned_at in the DB (default: UTC)",
+ )
+ p_opdata.add_argument("--dry-run", action="store_true",
+ help="Match files but do not write to the DB.")
+
+ # populate experiments
+ p_exp = pop_sub.add_parser(
+ "experiments",
+ help="Scan filesystem for pupitre TXT files and register them in experiments.",
+ )
+ _db_arg(p_exp)
+ _sites_arg(p_exp)
+ p_exp.add_argument(
+ "--records-base", default=str(_DEFAULT_RECORDS_BASE), dest="records_base",
+ help=f"Root of the records tree (default: {_DEFAULT_RECORDS_BASE})",
+ )
+ p_exp.add_argument(
+ "--srv-subdir", default=_DEFAULT_SRV_SUBDIR, dest="srv_subdir",
+ help=f"Subdirectory of records-base for pupitre TXT files (default: {_DEFAULT_SRV_SUBDIR})",
+ )
+ p_exp.add_argument(
+ "--db-tz", default="UTC", dest="db_tz",
+ help="Timezone of commissioned_at / decommissioned_at in the DB (default: UTC)",
+ )
+ p_exp.add_argument("--dry-run", action="store_true",
+ help="Match files but do not write to the DB.")
+
+ # populate overview-records
+ p_ov = pop_sub.add_parser(
+ "overview-records",
+ help="Process Overview TDMS files (from operationaldata) via python_magnetrun.",
+ )
+ _db_arg(p_ov)
+ _sites_arg(p_ov)
+ p_ov.add_argument(
+ "--reprocess", action="store_true",
+ help="Overwrite existing overview_records rows (upsert instead of skip).",
+ )
+ p_ov.add_argument("--dry-run", action="store_true",
+ help="Discover files but do not write to the DB.")
+
+ # populate overview-records-from-json
+ p_ov_json = pop_sub.add_parser(
+ "overview-records-from-json",
+ help="Load overview_records directly from a pre-computed summary JSON file.",
+ )
+ _db_arg(p_ov_json)
+ p_ov_json.add_argument(
+ "json_file",
+ help=(
+ "Path to a JSON file containing an array of overview record dicts "
+ "(e.g. summary-2026.json produced by python_magnetrun analysis/cli.py). "
+ "Source lists may be plain Python lists or comma-separated strings. "
+ "Both 'sources_' and '' column-name aliases are accepted."
+ ),
+ )
+ p_ov_json.add_argument(
+ "--site", default=None, metavar="SITE",
+ help="Site name to assign to all loaded records (overrides any site_name in the JSON).",
+ )
+ p_ov_json.add_argument(
+ "--reprocess", action="store_true",
+ help="Overwrite existing overview_records rows (upsert instead of skip).",
+ )
+ p_ov_json.add_argument("--dry-run", action="store_true",
+ help="Preview records without writing to the DB.")
+
+ # ── hoop-stress ───────────────────────────────────────────────────────────
+ hs_p = entity.add_parser("hoop-stress",
+ help="Compute and visualise per-part hoop-stress statistics.")
+ hs_sub = hs_p.add_subparsers(dest="action", required=True,
+ metavar="{compute,barchart,history,stats,fatigue}")
+
+ hs_compute = hs_sub.add_parser(
+ "compute",
+ help="Compute hoop-stress time series, bin stats, and fatigue for experiments.",
+ )
+ _db_arg(hs_compute)
+ _sites_arg(hs_compute)
+ hs_compute.add_argument(
+ "--magnet-type", default="all", choices=["H", "B", "S", "all"],
+ dest="magnet_type",
+ help="Coil type(s) to compute (default: all)",
+ )
+ hs_compute.add_argument(
+ "--bins", default=None,
+ help="Bin edges in MPa as a comma-separated list, e.g. '0,100,200,300,400,500,600' "
+ "(default: 0–600 MPa in 100 MPa steps). "
+ "Legacy pair format 'l1:h1,l2:h2,...' also accepted.",
+ )
+ hs_compute.add_argument(
+ "--parquet-dir", default=None, dest="parquet_dir",
+ help="Output directory for Parquet files (default: /hoop_parquet)",
+ )
+ hs_compute.add_argument(
+ "--geometries", default=None,
+ help="Override geometry YAML directory",
+ )
+ hs_compute.add_argument(
+ "--reprocess", action="store_true",
+ help="Re-compute already-processed experiments",
+ )
+ hs_compute.add_argument(
+ "--dry-run", action="store_true", dest="dry_run",
+ help="Discover files but do not write to DB or disk",
+ )
+ hs_compute.add_argument(
+ "--use-mrun", action="store_true", dest="use_mrun",
+ help="Load files via python_magnetrun.MagnetRun.load_mrun()",
+ )
+ hs_compute.add_argument(
+ "--records-base", default="", dest="records_base",
+ help="Root of the records tree (parent of --srv-subdir)",
+ )
+ hs_compute.add_argument(
+ "--srv-subdir", default=_DEFAULT_SRV_SUBDIR, dest="srv_subdir",
+ help=f"Subdirectory of records-base for pupitre TXT files "
+ f"(default: {_DEFAULT_SRV_SUBDIR})",
+ )
+ hs_compute.add_argument(
+ "--quiet", action="store_true",
+ help="Suppress per-file output",
+ )
+
+ hs_bar = hs_sub.add_parser(
+ "barchart",
+ help="Bar chart of hoop stress at given currents vs Rpe.",
+ )
+ _hs_shared_args(hs_bar)
+ hs_bar.add_argument(
+ "--i-h", type=float, default=20000.0, dest="i_h",
+ help="Helix current [A] (default: 20000)",
+ )
+ hs_bar.add_argument(
+ "--i-b", type=float, default=0.0, dest="i_b",
+ help="Bitter current [A] (default: 0)",
+ )
+ hs_bar.add_argument(
+ "--i-s", type=float, default=0.0, dest="i_s",
+ help="Supra current [A] (default: 0)",
+ )
+
+ hs_hist = hs_sub.add_parser(
+ "history",
+ help="Hoop stress vs time from a pupitre file (normalised plot).",
+ )
+ _hs_shared_args(hs_hist)
+ _hs_pupitre_args(hs_hist)
+
+ hs_stats = hs_sub.add_parser(
+ "stats",
+ help="Descriptive statistics of hoop stress time series.",
+ )
+ _hs_shared_args(hs_stats)
+ _hs_pupitre_args(hs_stats)
+ hs_stats.add_argument(
+ "--output", default=None,
+ help="Save stats table to CSV (default: print only)",
+ )
+
+ hs_fat = hs_sub.add_parser(
+ "fatigue",
+ help="Rainflow cycle counting on hoop stress time series.",
+ )
+ _hs_shared_args(hs_fat)
+ _hs_pupitre_args(hs_fat)
+ hs_fat.add_argument(
+ "--bins", type=int, default=15,
+ help="Number of histogram bins (default: 15)",
+ )
+
+ return parser
+
+
+def main() -> None:
+ parser = build_parser()
+ args = parser.parse_args()
+ action = getattr(args, "action", None)
+ handler = _DISPATCH.get((args.entity, action))
+ if handler is None:
+ parser.print_help()
+ sys.exit(1)
+ handler(args)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/to_duckdb/marimo/select_site.py b/to_duckdb/marimo/select_site.py
new file mode 100644
index 0000000..bb6b53b
--- /dev/null
+++ b/to_duckdb/marimo/select_site.py
@@ -0,0 +1,197 @@
+import marimo
+
+__generated_with = "0.23.6"
+app = marimo.App(width="medium", app_title="MagnetDB Site Explorer")
+
+
+@app.cell
+def _():
+ import marimo as mo
+ import duckdb
+ import pandas as pd
+ from pathlib import Path
+
+ return Path, duckdb, mo, pd
+
+
+@app.cell
+def _(Path, mo):
+ db_input = mo.ui.text(
+ value=str(Path(__file__).parent / ".." / "magnetdb.duckdb"),
+ label="DuckDB file",
+ full_width=True,
+ )
+ mo.md(f"## Database\n{db_input}")
+ return (db_input,)
+
+
+@app.cell
+def _(db_input, duckdb, mo):
+ db_path = db_input.value.strip()
+ try:
+ _con = duckdb.connect(db_path, read_only=True)
+ _sites = _con.execute(
+ "SELECT name, housing, status, commissioned_at, decommissioned_at "
+ "FROM sites ORDER BY name"
+ ).fetchall()
+ _con.close()
+ db_error = None
+ site_rows = _sites
+ except Exception as _e:
+ db_error = str(_e)
+ site_rows = []
+
+ if db_error:
+ mo.stop(
+ True,
+ mo.callout(mo.md(f"**Cannot open database:** {db_error}"), kind="danger"),
+ )
+ return db_error, db_path, site_rows
+
+
+@app.cell
+def _(mo, site_rows):
+ site_names = [r[0] for r in site_rows]
+ site_selector = mo.ui.dropdown(
+ options=site_names,
+ value=site_names[0] if site_names else None,
+ label="Select site",
+ )
+ mo.md(f"## Site selection\n{site_selector}")
+ return site_names, site_selector
+
+
+@app.cell
+def _(db_path, duckdb, mo, pd, site_selector):
+ selected = site_selector.value
+ mo.stop(selected is None, mo.callout(mo.md("No site selected."), kind="warn"))
+
+ con = duckdb.connect(db_path, read_only=True)
+
+ # --- Site metadata ---
+ site_row = con.execute(
+ "SELECT name, housing, status, commissioned_at, decommissioned_at "
+ "FROM sites WHERE name = ?",
+ [selected],
+ ).fetchone()
+
+ # --- Magnets in this site ---
+ magnets_df = con.execute(
+ """
+ SELECT
+ sm.magnet_name AS magnet,
+ m.type AS type,
+ m.status AS status,
+ sm.z_offset,
+ sm.r_offset,
+ sm.commissioned_at AS commissioned,
+ sm.decommissioned_at AS decommissioned
+ FROM site_magnets sm
+ JOIN magnets m ON m.name = sm.magnet_name
+ WHERE sm.site_name = ?
+ ORDER BY sm.magnet_name
+ """,
+ [selected],
+ ).df()
+
+ # --- Parts hierarchy ---
+ hierarchy_df = con.execute(
+ """
+ SELECT
+ m.name AS magnet,
+ m.type AS magnet_type,
+ mp.coil_index,
+ mp.rank,
+ p.name AS part,
+ p.type AS part_type,
+ mat.nuance,
+ ROUND(mat.rpe / 1e6, 1) AS rpe_MPa
+ FROM site_magnets sm
+ JOIN magnets m ON m.name = sm.magnet_name
+ JOIN magnet_parts mp ON mp.magnet_name = m.name
+ JOIN parts p ON p.name = mp.part_name
+ LEFT JOIN materials mat ON mat.name = p.material_name
+ WHERE sm.site_name = ?
+ ORDER BY m.name, mp.rank
+ """,
+ [selected],
+ ).df()
+
+ # --- Experiments with duration ---
+ exp_df = con.execute(
+ """
+ SELECT
+ e.id,
+ e.name,
+ e.file,
+ e.status,
+ ers.value AS duration_s
+ FROM experiments e
+ LEFT JOIN exp_run_scalars ers
+ ON ers.experiment_id = e.id AND ers.channel = 'duration_s'
+ WHERE e.site_name = ?
+ ORDER BY e.file
+ """,
+ [selected],
+ ).df()
+
+ con.close()
+
+ def _fmt_duration(seconds):
+ if seconds is None or (hasattr(seconds, '__class__') and seconds != seconds):
+ return "—"
+ s = int(seconds)
+ h, rem = divmod(s, 3600)
+ m, sec = divmod(rem, 60)
+ if h:
+ return f"{h}h {m:02d}m {sec:02d}s"
+ return f"{m}m {sec:02d}s"
+
+ exp_df["duration"] = exp_df["duration_s"].apply(_fmt_duration)
+ exp_df = exp_df.drop(columns=["duration_s"])
+
+ # ── Display ──────────────────────────────────────────────────────────────
+ name, housing, status, comm_at, decomm_at = site_row
+ decomm_str = str(decomm_at) if decomm_at else "—"
+
+ summary = mo.md(f"""
+## Site: `{name}`
+
+| Field | Value |
+|-------|-------|
+| Housing | **{housing or '—'}** |
+| Status | **{status or '—'}** |
+| Commissioned | {comm_at} |
+| Decommissioned | {decomm_str} |
+| Magnets | {len(magnets_df)} |
+| Experiments | {len(exp_df)} |
+""")
+
+ magnets_section = mo.vstack(
+ [
+ mo.md("### Magnets"),
+ mo.ui.table(magnets_df, selection=None),
+ ]
+ )
+
+ hierarchy_section = mo.vstack(
+ [
+ mo.md("### Parts hierarchy"),
+ mo.ui.table(hierarchy_df, selection=None),
+ ]
+ )
+
+ exp_section = mo.vstack(
+ [
+ mo.md(f"### Experiments ({len(exp_df)})"),
+ (
+ mo.ui.table(exp_df, selection=None)
+ if not exp_df.empty
+ else mo.callout(
+ mo.md("No experiments registered for this site."), kind="info"
+ )
+ ),
+ ]
+ )
+
+ mo.vstack([summary, magnets_section, hierarchy_section, exp_section])
diff --git a/to_duckdb/marimo/select_site_note.md b/to_duckdb/marimo/select_site_note.md
new file mode 100644
index 0000000..1d9ccfe
--- /dev/null
+++ b/to_duckdb/marimo/select_site_note.md
@@ -0,0 +1,137 @@
+# Student Note — Interactive Site Browser with Marimo
+
+> `select_site.py` is a [Marimo](https://marimo.io) reactive notebook that lets you
+> browse any site stored in the student DuckDB without writing SQL.
+> Every widget is live-reactive: changing the DB path or the site dropdown
+> immediately re-runs all downstream cells.
+
+---
+
+## Requirements
+
+`marimo` must be installed in the virtualenv alongside `duckdb` and `pandas`:
+
+```bash
+cd to_duckdb/
+source venv/bin/activate
+pip install marimo # if not already present
+pip install duckdb pandas # already in requirements.txt
+```
+
+---
+
+## Running the notebook
+
+### Read-only presentation mode
+
+Launches the app in a browser tab; no code is visible to the student.
+
+```bash
+cd to_duckdb/
+source venv/bin/activate
+marimo run select_site.py
+```
+
+### Edit / development mode
+
+Shows the source cells alongside the output; useful for extending the notebook.
+
+```bash
+marimo edit select_site.py
+```
+
+By default Marimo opens `http://localhost:2718` (or the next free port).
+
+---
+
+## What each section shows
+
+| Section | Contents |
+|---------|----------|
+| **Database** | Text field — enter the path to any `.duckdb` file; defaults to `magnetdb.duckdb` next to the notebook |
+| **Site selection** | Dropdown — lists every site found in `sites`; pick one to load its data |
+| **Summary card** | Housing, status, commissioning / decommissioning dates, counts of magnets and experiments |
+| **Magnets** | One row per magnet in `site_magnets`: type, status, axial/radial offsets, commissioning window |
+| **Parts hierarchy** | Full join `site_magnets → magnets → magnet_parts → parts → materials`: coil index, part type, nuance, rpe (MPa) |
+| **Experiments** | All rows from `experiments` for the selected site (filename, status); info callout if none are registered |
+
+---
+
+## Changing the database file
+
+The text field at the top accepts any absolute or relative path.
+If the file cannot be opened (wrong path, locked by another process, missing tables),
+a red error callout is shown and the rest of the notebook is stopped cleanly.
+
+Common paths used in this project:
+
+| File | Contents |
+|------|----------|
+| `magnetdb.duckdb` | Full teacher database (may be locked if the CLI is running) |
+| `student_magnetdb-2604.duckdb` | Student snapshot distributed with the 2026-04 data package |
+| `student.duckdb` | Any database you created with `magnetdb.py db create` |
+
+---
+
+## Extending the notebook
+
+Open the notebook in edit mode (`marimo edit select_site.py`) and add new cells
+after the last one. Each cell is a plain Python function; any variable it returns
+becomes available to later cells.
+
+### Example — plot experiment count per year
+
+```python
+@app.cell
+def _(con, selected, pd, mo):
+ import matplotlib.pyplot as plt
+
+ df = con.execute("""
+ SELECT
+ YEAR(CAST(REGEXP_EXTRACT(file, r'(\d{4})', 1) AS DATE)) AS year,
+ COUNT(*) AS n
+ FROM experiments
+ WHERE site_name = ?
+ GROUP BY 1 ORDER BY 1
+ """, [selected]).df()
+
+ fig, ax = plt.subplots()
+ ax.bar(df["year"].astype(str), df["n"])
+ ax.set_xlabel("Year")
+ ax.set_ylabel("Experiments")
+ ax.set_title(f"Experiments per year — {selected}")
+ return mo.as_html(fig)
+```
+
+### Example — show the coil-to-channel mapping
+
+```python
+@app.cell
+def _(con, selected, mo):
+ df = con.execute("""
+ SELECT 'Icoil' || mp.coil_index AS channel,
+ p.name AS part, p.type,
+ mat.nuance,
+ ROUND(mat.rpe / 1e6, 1) AS rpe_MPa
+ FROM site_magnets sm
+ JOIN magnets m ON m.name = sm.magnet_name
+ JOIN magnet_parts mp ON mp.magnet_name = m.name
+ JOIN parts p ON p.name = mp.part_name
+ LEFT JOIN materials mat ON mat.name = p.material_name
+ WHERE sm.site_name = ?
+ AND mp.coil_index IS NOT NULL
+ ORDER BY mp.coil_index
+ """, [selected]).df()
+ return mo.vstack([mo.md("### Coil → channel mapping"), mo.ui.table(df, selection=None)])
+```
+
+---
+
+## Relationship to other student scripts
+
+| Script | When to use |
+|--------|-------------|
+| `select_site.py` | Interactive exploration — browse structure, no coding required |
+| `tutorials/queries.py` | Static script — copy cells into Jupyter, adapt for analysis |
+| `tutorials/statheures_demo.py` | Field-time histogram — loads TSV files, no interactive UI |
+| `tutorials/query_cumstats.py` | Query pre-computed `op_*` statistics — requires `compute_op_stats.py` to have run first |
diff --git a/to_duckdb/migrate_experiments_file_relpath.py b/to_duckdb/migrate_experiments_file_relpath.py
new file mode 100644
index 0000000..ecc985f
--- /dev/null
+++ b/to_duckdb/migrate_experiments_file_relpath.py
@@ -0,0 +1,75 @@
+"""
+Migrate experiments.file from absolute paths to bare filenames.
+
+Before: /mnt/LNCMIG-Data/records/srv-data-install/M10/2025.04.30 - 13:06:03.txt
+After: 2025.04.30 - 13:06:03.txt
+
+Safe to run multiple times — rows that already contain only a filename are
+not touched by the WHERE clause.
+"""
+
+import argparse
+import sys
+from pathlib import Path
+
+import duckdb
+
+sys.path.insert(0, str(Path(__file__).parent))
+from config import DEFAULT_DB
+
+
+def migrate(db_path: str, dry_run: bool = False) -> None:
+ con = duckdb.connect(db_path)
+
+ count = con.execute(
+ "SELECT COUNT(*) FROM experiments WHERE file LIKE '/%'"
+ ).fetchone()[0]
+
+ if count == 0:
+ print("Nothing to migrate — no absolute paths found.")
+ con.close()
+ return
+
+ print(f"Found {count} row(s) with absolute paths.")
+
+ if dry_run:
+ rows = con.execute(
+ "SELECT id, site_name, file FROM experiments WHERE file LIKE '/%' LIMIT 5"
+ ).fetchall()
+ print("Sample rows (dry run, no changes written):")
+ for row in rows:
+ print(f" id={row[0]} site={row[1]} {row[2]!r} → {Path(row[2]).name!r}")
+ con.close()
+ return
+
+ con.execute(
+ "UPDATE experiments "
+ "SET file = regexp_extract(file, '[^/]+$', 0) "
+ "WHERE file LIKE '/%'"
+ )
+ print(f"Migrated {count} row(s).")
+
+ remaining = con.execute(
+ "SELECT COUNT(*) FROM experiments WHERE file LIKE '/%'"
+ ).fetchone()[0]
+ if remaining:
+ print(f"[WARN] {remaining} row(s) still have absolute paths — check manually.")
+ else:
+ print("Verification passed: no absolute paths remain.")
+
+ con.close()
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(description=__doc__)
+ parser.add_argument("--db", default=DEFAULT_DB, help="DuckDB file path")
+ parser.add_argument(
+ "--dry-run", action="store_true",
+ help="Show what would be changed without writing anything",
+ )
+ args = parser.parse_args()
+ migrate(args.db, dry_run=args.dry_run)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/to_duckdb/mysql_connect.py b/to_duckdb/mysql_connect.py
new file mode 100644
index 0000000..c1ece8d
--- /dev/null
+++ b/to_duckdb/mysql_connect.py
@@ -0,0 +1,2701 @@
+"""
+mysql_connect.py
+================
+Connect DuckDB to a remote MySQL server.
+
+Four modes are available:
+
+live
+ Attach the MySQL database via the ``mysql_scanner`` extension and print the
+ full schema (tables + column names/types). No local copy is made. Use
+ this mode first to inspect an unknown MySQL database before deciding on an
+ export or poll strategy.
+
+export
+ Copy tables from MySQL into a local file. Three output formats are
+ supported (``--format``):
+
+ csv One CSV file per table in ``--output-dir``.
+ parquet One Parquet file per table in ``--output-dir``.
+ duckdb All tables in a single DuckDB file (``--output``).
+ The file is created if it does not exist.
+ Existing tables are replaced (``CREATE OR REPLACE``).
+
+view
+ Query a MySQL table (or custom SQL) once and render the result as a
+ styled table in the terminal using ``rich``. Use ``--table`` or
+ ``--query``, optionally filtered with ``--where``. ``--limit`` caps
+ the number of rows returned (default: 200; use ``--limit 0`` for all rows).
+
+plot
+ Query a MySQL table (or custom SQL) once and display all selected data as
+ a static chart. Supports the same ``--plot``, ``--fields``, ``--x-field``,
+ ``--where``, ``--query``, and ``--plot-options`` flags as ``poll``.
+ ``--limit`` defaults to 0 (all rows). ``--plot textual`` is not supported.
+
+ matplotlib Static chart in a native window (blocks until closed).
+ plotly Writes a static HTML file and opens it in the browser.
+ dash Interactive web app served at http://127.0.0.1:8050; data
+ loaded once on page open with full zoom/pan support.
+
+poll
+ Repeatedly query a single MySQL table at a fixed interval and display
+ selected columns as a live plot. Backend is selected via ``--plot``:
+
+ table Rich terminal table updated in-place every interval seconds.
+ All queried columns are shown; Ctrl-C to stop.
+ matplotlib Live-updating chart in a native window (default).
+ plotly Writes an auto-refreshing HTML file (default: poll_output.html)
+ and opens it in the default browser on the first poll.
+ textual Full-screen TUI in the terminal. One scatter plot per group,
+ rendered via plotext (pip install plotext).
+ Updated every interval seconds. Press q to quit, p to pause.
+ dash Interactive web app served at http://127.0.0.1:8050.
+ Uses dcc.Interval for live updates — no page refresh.
+ Pause button, zoom/pan, and hover tooltips included.
+ Host and port are set via --dash-host / --dash-port.
+
+ Two-source mode: add ``--table2`` (or ``--query2``) with optional
+ ``--fields2`` and ``--where2`` to poll a second table simultaneously.
+ Fields from each table are displayed in separate subplots that share the
+ same x-axis, so zooming or panning in one subplot mirrors the other.
+ Supported backends: matplotlib, plotly, dash.
+
+ --plot-options accepts a JSON object with any of:
+ type "line" | "scatter" | "bar" (default "line")
+ layout "subplots" | "overlay" | "groups" (default "subplots")
+ subplots one subplot per field
+ overlay all fields on a single shared axes
+ groups user-defined groups; also set "groups" key
+ groups list of field-name lists, e.g. [["Icoil","Ucoil"],["tsb","teb"]]
+ required when layout="groups"
+ figsize [width, height] in inches (default [12, 6], matplotlib only)
+ colors list of color strings, one per y-field
+ font font family name, e.g. "DejaVu Sans" / "Arial" / "monospace"
+ fontsize base font size in points, e.g. 12
+
+Usage
+-----
+ # Inspect schema
+ python mysql_connect.py --mode live \\
+ --host myhost --user myuser --password mypw --database mydb
+
+ # Export to CSV
+ python mysql_connect.py --mode export --format csv --output-dir ./out \\
+ --host myhost --user myuser --password mypw --database mydb
+
+ # Export selected tables to DuckDB
+ python mysql_connect.py --mode export --format duckdb \\
+ --output magnetdb_mysql.duckdb --tables sites magnets \\
+ --host myhost --user myuser --password mypw --database mydb
+
+ # Poll every 10 s, matplotlib line plot
+ python mysql_connect.py --mode poll --table measurements \\
+ --fields timestamp Icoil Ucoil --x-field timestamp \\
+ --interval 10 --limit 200 --plot matplotlib \\
+ --plot-options '{"type":"line","figsize":[14,6],"colors":["steelblue","tomato"]}' \\
+ --host myhost --user myuser --password mypw --database mydb
+
+ # Same with plotly (opens browser, writes poll_output.html)
+ python mysql_connect.py --mode poll --table measurements \\
+ --fields timestamp Icoil Ucoil --x-field timestamp \\
+ --interval 10 --limit 200 --plot plotly \\
+ --plot-options '{"type":"scatter","colors":["navy","crimson"]}' \\
+ --host myhost --user myuser --password mypw --database mydb
+
+ # Two tables, shared x-axis — graph 1: Icoil/Ucoil, graph 2: tsb/teb (matplotlib)
+ python mysql_connect.py --mode poll \\
+ --table measurements --fields timestamp Icoil Ucoil --x-field timestamp \\
+ --table2 temperatures --fields2 tsb teb \\
+ --interval 10 --plot matplotlib \\
+ --host myhost --user myuser --password mypw --database mydb
+
+ # Same with Dash (interactive; zoom/pan is linked between the two graphs)
+ python mysql_connect.py --mode poll \\
+ --table measurements --fields timestamp Icoil Ucoil --x-field timestamp \\
+ --table2 temperatures --fields2 tsb teb \\
+ --interval 10 --plot dash \\
+ --host myhost --user myuser --password mypw --database mydb
+
+ # Two tables via raw SQL (tables not directly joinable)
+ python mysql_connect.py --mode poll \\
+ --query "SELECT t, Icoil, Ucoil FROM mysqldb.measurements ORDER BY t LIMIT 500" \\
+ --fields Icoil Ucoil --x-field t \\
+ --query2 "SELECT t, tsb, teb FROM mysqldb.temperatures ORDER BY t LIMIT 500" \\
+ --fields2 tsb teb \\
+ --interval 10 --plot dash \\
+ --host myhost --user myuser --password mypw --database mydb
+
+ # View most recent 50 rows of measurements as a table
+ python mysql_connect.py --mode view --table measurements --limit 50 \\
+ --host myhost --user myuser --password mypw --database mydb
+
+ # View all rows matching a filter, no row cap
+ python mysql_connect.py --mode view --table measurements \\
+ --where "label='run42'" --limit 0 \\
+ --host myhost --user myuser --password mypw --database mydb
+
+Connection parameters may also be supplied via environment variables
+(MYSQL_HOST, MYSQL_PORT, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB).
+CLI flags take precedence over env vars; env vars take precedence over
+built-in defaults.
+"""
+
+import argparse
+import collections
+import json
+import os
+import sys
+import time
+import webbrowser
+from pathlib import Path
+from typing import Any, Optional
+
+import duckdb
+
+
+# ---------------------------------------------------------------------------
+# Defaults
+# ---------------------------------------------------------------------------
+
+_DEFAULT_HOST = "localhost"
+_DEFAULT_PORT = 3306
+_DEFAULT_OUTPUT = "magnetdb_mysql.duckdb"
+_DEFAULT_OUTPUT_DIR = "."
+
+
+# ---------------------------------------------------------------------------
+# Helpers
+# ---------------------------------------------------------------------------
+
+
+def _env(key: str, default: Optional[str] = None) -> Optional[str]:
+ return os.environ.get(key, default)
+
+
+def _build_dsn(
+ host: str, port: int, user: str, password: str, database: str
+) -> str:
+ """Build a mysql_scanner DSN string."""
+ return (
+ f"host={host} port={port} user={user} "
+ f"password={password} database={database}"
+ )
+
+
+def _load_mysql_extension(
+ con: duckdb.DuckDBPyConnection, verbose: bool = False
+) -> None:
+ """Install and load the mysql_scanner DuckDB extension."""
+ if verbose:
+ print("Loading mysql_scanner extension...")
+ con.execute("INSTALL mysql; LOAD mysql;")
+
+
+def _attach_mysql(
+ con: duckdb.DuckDBPyConnection, dsn: str, verbose: bool = False
+) -> None:
+ """Attach a MySQL database as the alias 'mysqldb'."""
+ if verbose:
+ print("Attaching MySQL database...")
+ con.execute(f"ATTACH '{dsn}' AS mysqldb (TYPE mysql_scanner)")
+
+
+def list_mysql_tables(con: duckdb.DuckDBPyConnection, database: str) -> list[str]:
+ """Return sorted list of table names in the attached MySQL database.
+
+ Parameters
+ ----------
+ con : duckdb.DuckDBPyConnection
+ Open connection with mysqldb already attached.
+ database : str
+ The MySQL database (schema) name to list tables from.
+
+ Returns
+ -------
+ list[str]
+ Table names, sorted alphabetically.
+ """
+ rows = con.execute(
+ "SELECT table_name FROM information_schema.tables "
+ "WHERE table_catalog = 'mysqldb' AND table_schema = ? ORDER BY table_name",
+ [database],
+ ).fetchall()
+ return [r[0] for r in rows]
+
+
+def describe_table(
+ con: duckdb.DuckDBPyConnection, table: str
+) -> list[tuple]:
+ """Return column descriptors for a single table.
+
+ Parameters
+ ----------
+ con : duckdb.DuckDBPyConnection
+ Open connection with mysqldb already attached.
+ table : str
+ Table name (unqualified).
+
+ Returns
+ -------
+ list[tuple]
+ Each tuple: (column_name, column_type, ...) as returned by DESCRIBE.
+ """
+ return con.execute(f"DESCRIBE mysqldb.{table}").fetchall()
+
+
+# DuckDB type-name prefixes that are safe to plot as numeric y-values.
+# MySQL types are translated by mysql_scanner: FLOAT→FLOAT, DOUBLE→DOUBLE,
+# INT/BIGINT/…→INTEGER/BIGINT/…, DECIMAL→DECIMAL, etc.
+_NUMERIC_PREFIXES = (
+ "FLOAT", "DOUBLE", "DECIMAL", "NUMERIC", "REAL",
+ "INTEGER", "INT", "BIGINT", "SMALLINT", "TINYINT",
+ "HUGEINT", "UBIGINT", "UINTEGER", "USMALLINT", "UTINYINT",
+)
+
+# DuckDB type-name prefixes that are suitable as an x-axis (time axis).
+# MySQL TIMESTAMP / DATETIME → DuckDB TIMESTAMP; MySQL DATE → DuckDB DATE.
+_TIMESTAMP_PREFIXES = ("TIMESTAMP", "TIMESTAMPTZ", "DATE", "DATETIME")
+
+
+def _is_numeric_type(col_type: str) -> bool:
+ """Return True if the DuckDB column type is numeric / plottable as y."""
+ upper = col_type.upper().strip()
+ return upper.startswith(_NUMERIC_PREFIXES)
+
+
+def _is_timestamp_type(col_type: str) -> bool:
+ """Return True if the DuckDB column type is temporal (suitable as x-axis)."""
+ upper = col_type.upper().strip()
+ return upper.startswith(_TIMESTAMP_PREFIXES)
+
+
+def _is_id_field(name: str) -> bool:
+ """Return True for columns that are ID keys and should not be plotted."""
+ lower = name.lower()
+ return lower == "id" or lower.endswith("_id")
+
+
+def _safe_widget_id(name: str) -> str:
+ """Return a CSS-safe identifier by replacing non-alphanumeric chars with '_'."""
+ import re
+ return re.sub(r"[^A-Za-z0-9_]", "_", name)
+
+
+def _auto_x_field(cols: list[tuple[str, str]]) -> Optional[str]:
+ """Return the name of the first TIMESTAMP column in *cols*, or None."""
+ for name, col_type in cols:
+ if _is_timestamp_type(col_type):
+ return name
+ return None
+
+
+def list_numeric_columns(
+ con: duckdb.DuckDBPyConnection, table: str
+) -> list[tuple[str, str]]:
+ """Return (name, type) pairs for numeric columns in *table*.
+
+ Parameters
+ ----------
+ con : duckdb.DuckDBPyConnection
+ Open connection with mysqldb already attached.
+ table : str
+ Table name (unqualified).
+
+ Returns
+ -------
+ list[tuple[str, str]]
+ ``[(column_name, column_type), ...]`` for all numeric columns,
+ in schema order.
+ """
+ return [
+ (c[0], c[1])
+ for c in describe_table(con, table)
+ if _is_numeric_type(c[1])
+ ]
+
+
+# ---------------------------------------------------------------------------
+# Mode: live
+# ---------------------------------------------------------------------------
+
+
+def mode_live(args: argparse.Namespace) -> None:
+ """Attach MySQL and print the full schema summary.
+
+ Parameters
+ ----------
+ args : argparse.Namespace
+ Parsed CLI arguments.
+ """
+ dsn = _build_dsn(args.host, args.port, args.user, args.password, args.database)
+ con = duckdb.connect()
+ _load_mysql_extension(con, args.verbose)
+ _attach_mysql(con, dsn, args.verbose)
+
+ tables = list_mysql_tables(con, args.database)
+ print(f"Connected to {args.database}@{args.host}:{args.port}")
+ print(f"{len(tables)} table(s) found:\n")
+
+ for table in tables:
+ cols = describe_table(con, table)
+ print(f" {table}")
+ for col in cols:
+ col_name, col_type = col[0], col[1]
+ if _is_numeric_type(col_type):
+ marker = " *"
+ elif _is_timestamp_type(col_type):
+ marker = " @"
+ else:
+ marker = ""
+ print(f" {col_name:<30} {col_type}{marker}")
+ print()
+ print("(* = numeric / y-axis @ = timestamp / x-axis)")
+
+
+# ---------------------------------------------------------------------------
+# Mode: export
+# ---------------------------------------------------------------------------
+
+
+def _build_export_select(
+ table: str,
+ fields: list[str],
+ time_field: Optional[str],
+ start: Optional[str],
+ end: Optional[str],
+) -> str:
+ """Build a SELECT for exporting *table* with optional column and time filtering."""
+ field_list = ", ".join(fields) if fields else "*"
+ sql = f"SELECT {field_list} FROM mysqldb.{table}"
+ conditions: list[str] = []
+ if time_field and start:
+ conditions.append(f"{time_field} >= CAST('{start}' AS TIMESTAMP)")
+ if time_field and end:
+ conditions.append(f"{time_field} <= CAST('{end}' AS TIMESTAMP)")
+ if conditions:
+ sql += " WHERE " + " AND ".join(conditions)
+ return sql
+
+
+def mode_export(args: argparse.Namespace) -> None:
+ """Export MySQL tables to a local file (CSV, Parquet, or DuckDB).
+
+ Parameters
+ ----------
+ args : argparse.Namespace
+ Parsed CLI arguments.
+ """
+ dsn = _build_dsn(args.host, args.port, args.user, args.password, args.database)
+
+ if args.fmt == "duckdb":
+ con = duckdb.connect(args.output)
+ if args.verbose:
+ print(f"Output database: {args.output}")
+ else:
+ con = duckdb.connect()
+ out_dir = Path(args.output_dir)
+ out_dir.mkdir(parents=True, exist_ok=True)
+
+ _load_mysql_extension(con, args.verbose)
+ _attach_mysql(con, dsn, args.verbose)
+
+ all_tables = list_mysql_tables(con, args.database)
+ tables = args.tables if args.tables else all_tables
+
+ unknown = set(tables) - set(all_tables)
+ if unknown:
+ print(
+ f"Error: unknown table(s): {', '.join(sorted(unknown))}",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ # ── field / time-range filtering (requires a single table) ──────────────
+ filtered = bool(args.export_fields or args.time_field or args.start or args.end)
+
+ if filtered and len(tables) != 1:
+ print(
+ "Error: --export-fields / --time-field / --start / --end require "
+ "exactly one table (use --tables TABLE).",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ time_field = args.time_field
+ export_fields: list[str] = args.export_fields or []
+
+ if filtered:
+ table_name = tables[0]
+ all_cols_raw = describe_table(con, table_name)
+ all_col_names = [c[0] for c in all_cols_raw]
+
+ # validate requested columns
+ if export_fields:
+ unknown_cols = set(export_fields) - set(all_col_names)
+ if unknown_cols:
+ print(
+ f"Error: unknown column(s) in '{table_name}': "
+ f"{', '.join(sorted(unknown_cols))}",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ # auto-detect time field if not given
+ if not time_field and (args.start or args.end):
+ all_cols_typed = [(c[0], c[1]) for c in all_cols_raw]
+ time_field = _auto_x_field(all_cols_typed)
+ if time_field:
+ if args.verbose:
+ print(f"Auto-selected time field: {time_field}")
+ else:
+ print(
+ f"Error: no TIMESTAMP column found in '{table_name}'. "
+ "Use --time-field to specify one.",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ # ensure time_field is included in the SELECT when fields are restricted
+ if export_fields and time_field and time_field not in export_fields:
+ export_fields = [time_field] + export_fields
+
+ if args.verbose:
+ print(f"Exporting {len(tables)} table(s): {', '.join(tables)}")
+
+ for table in tables:
+ if filtered:
+ select_sql = _build_export_select(
+ table, export_fields, time_field, args.start, args.end
+ )
+ else:
+ select_sql = f"SELECT * FROM mysqldb.{table}"
+
+ if args.verbose:
+ print(f" SQL: {select_sql}")
+
+ if args.fmt == "duckdb":
+ con.execute(f"CREATE OR REPLACE TABLE {table} AS {select_sql}")
+ if args.verbose:
+ n = con.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0]
+ print(f" {table}: {n} row(s)")
+
+ elif args.fmt == "csv":
+ dest = Path(args.output_dir) / f"{table}.csv"
+ con.execute(f"COPY ({select_sql}) TO '{dest}' (HEADER, DELIMITER ',')")
+ if args.verbose:
+ print(f" {table} → {dest}")
+
+ elif args.fmt == "parquet":
+ dest = Path(args.output_dir) / f"{table}.parquet"
+ con.execute(f"COPY ({select_sql}) TO '{dest}' (FORMAT PARQUET)")
+ if args.verbose:
+ print(f" {table} → {dest}")
+
+ print(f"Export complete: {len(tables)} table(s).")
+
+
+# ---------------------------------------------------------------------------
+# Mode: view
+# ---------------------------------------------------------------------------
+
+
+def mode_view(args: argparse.Namespace) -> None:
+ """Display query results as a rich table in the terminal.
+
+ Uses ``--table`` / ``--query``, ``--fields``, ``--where``, and ``--limit``
+ from the CLI. ``--limit 0`` means no row cap (show everything).
+ """
+ try:
+ from rich.console import Console
+ from rich.table import Table as RichTable
+ except ImportError:
+ print(
+ "Error: rich is required for --mode view. pip install rich",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ dsn = _build_dsn(args.host, args.port, args.user, args.password, args.database)
+ con = duckdb.connect()
+ _load_mysql_extension(con, args.verbose)
+ _attach_mysql(con, dsn, args.verbose)
+
+ if args.query:
+ sql = args.query
+ else:
+ field_list = ", ".join(args.fields) if args.fields else "*"
+ sql = f"SELECT {field_list} FROM mysqldb.{args.table}"
+ if args.where:
+ sql += f" WHERE {args.where}"
+ view_limit = args.limit if args.limit is not None else 200
+ if view_limit > 0:
+ sql += f" LIMIT {view_limit}"
+
+ if args.verbose:
+ print(f"SQL: {sql}")
+
+ cols, rows = _fetch_poll(con, sql)
+ con.close()
+
+ console = Console()
+ rich_table = RichTable(show_header=True, header_style="bold cyan", show_lines=False)
+ for col in cols:
+ rich_table.add_column(col, overflow="fold")
+ for row in rows:
+ rich_table.add_row(*["" if v is None else str(v) for v in row])
+
+ console.print(rich_table)
+ console.print(f"[dim]{len(rows)} row(s)[/dim]")
+
+
+# ---------------------------------------------------------------------------
+# Mode: poll
+# ---------------------------------------------------------------------------
+
+_POLL_DEFAULTS: dict[str, Any] = {
+ "type": "line",
+ "figsize": [12, 6],
+ "colors": [],
+ # layout: "subplots" (one axes per field), "overlay" (all on one axes),
+ # "groups" (user-defined groups; set "groups": [[f1,f2],[f3]] too)
+ "layout": "subplots",
+ "groups": [],
+ "font": None, # font family string, e.g. "DejaVu Sans" / "Arial"
+ "fontsize": None, # base font size in points, e.g. 12
+}
+
+
+def _resolve_groups(y_fields: list[str], opts: dict[str, Any]) -> list[list[str]]:
+ """Return a list of field groups based on opts['layout'] / opts['groups'].
+
+ overlay → [[field1, field2, ...]] (one group = all fields)
+ subplots → [[field1], [field2], ...] (one group per field)
+ groups → opts['groups'] if provided, else falls back to subplots
+ """
+ layout = opts.get("layout", "subplots")
+ if layout == "overlay":
+ return [list(y_fields)]
+ if layout == "groups":
+ user_groups = opts.get("groups", [])
+ if user_groups:
+ # Validate: every named field must be in y_fields
+ flat = [f for g in user_groups for f in g]
+ unknown = set(flat) - set(y_fields)
+ if unknown:
+ print(
+ f"Error: --plot-options groups reference unknown field(s): "
+ f"{', '.join(sorted(unknown))}",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+ return [list(g) for g in user_groups]
+ # default: subplots
+ return [[f] for f in y_fields]
+
+
+def _parse_plot_options(raw: Optional[str]) -> dict[str, Any]:
+ """Merge user-supplied JSON plot options with defaults."""
+ opts = dict(_POLL_DEFAULTS)
+ if raw:
+ try:
+ user = json.loads(raw)
+ except json.JSONDecodeError as exc:
+ print(f"Error: --plot-options is not valid JSON: {exc}", file=sys.stderr)
+ sys.exit(1)
+ if not isinstance(user, dict):
+ print("Error: --plot-options must be a JSON object.", file=sys.stderr)
+ sys.exit(1)
+ opts.update(user)
+ return opts
+
+
+def _build_poll_query(
+ table: str,
+ fields: list[str],
+ where: Optional[str],
+ limit: int,
+ order_by: Optional[str],
+ start_time: Optional[str] = None,
+) -> str:
+ field_list = ", ".join(fields) if fields else "*"
+ sql = f"SELECT {field_list} FROM mysqldb.{table}"
+ conditions: list[str] = []
+ if where:
+ conditions.append(f"({where})")
+ if start_time is not None and order_by:
+ conditions.append(f"{order_by} >= CAST('{start_time}' AS TIMESTAMP)")
+ if conditions:
+ sql += " WHERE " + " AND ".join(conditions)
+ if order_by:
+ sql += f" ORDER BY {order_by}"
+ if limit > 0:
+ sql += f" LIMIT {limit}"
+ return sql
+
+
+def _fetch_poll(con: duckdb.DuckDBPyConnection, sql: str) -> tuple[list[str], list[tuple]]:
+ rel = con.execute(sql)
+ cols = [desc[0] for desc in rel.description]
+ return cols, rel.fetchall()
+
+
+def _fmt_x_latest(val: Any) -> str:
+ """Format the last x-axis value for display in a chart title."""
+ if hasattr(val, "strftime"):
+ return val.strftime("%Y-%m-%d %H:%M:%S")
+ return str(val)
+
+
+# ── matplotlib backend ──────────────────────────────────────────────────────
+
+def _poll_matplotlib(
+ con: duckdb.DuckDBPyConnection,
+ sql: str,
+ x_field: Optional[str],
+ y_fields: list[str],
+ opts: dict[str, Any],
+ interval: float,
+ count: Optional[int],
+ verbose: bool,
+) -> None:
+ try:
+ import matplotlib.pyplot as plt
+ except ImportError:
+ print("Error: matplotlib is required for --plot matplotlib. pip install matplotlib", file=sys.stderr)
+ sys.exit(1)
+
+ figsize = tuple(opts["figsize"])
+ colors = opts["colors"] or [None] * len(y_fields)
+ plot_type = opts["type"]
+ groups = _resolve_groups(y_fields, opts)
+ field_color = {f: i for i, f in enumerate(y_fields)}
+
+ if opts["font"]:
+ plt.rcParams["font.family"] = opts["font"]
+ if opts["fontsize"]:
+ plt.rcParams["font.size"] = opts["fontsize"]
+
+ plt.ion()
+ fig, axes = plt.subplots(len(groups), 1, figsize=figsize, sharex=True, squeeze=False)
+
+ buffers: dict[str, collections.deque] = {
+ f: collections.deque()
+ for f in (y_fields + ([x_field] if x_field else []))
+ }
+
+ fields_label = ", ".join(y_fields)
+ suptitle_obj = fig.suptitle(fields_label)
+ poll_n = 0
+ try:
+ while count is None or poll_n < count:
+ cols, rows = _fetch_poll(con, sql)
+ if verbose:
+ print(f"[poll {poll_n + 1}] {len(rows)} row(s) fetched")
+
+ for f in buffers:
+ buffers[f].clear()
+ for row in rows:
+ row_dict = dict(zip(cols, row))
+ for f in buffers:
+ if f in row_dict:
+ buffers[f].append(row_dict[f])
+
+ x_data = (
+ list(buffers[x_field])
+ if x_field and x_field in buffers
+ else list(range(len(rows)))
+ )
+
+ if x_data:
+ suptitle_obj.set_text(f"{fields_label} ({_fmt_x_latest(x_data[-1])})")
+
+ for ax, group in zip(axes[:, 0], groups):
+ ax.cla()
+ for y_field in group:
+ y_data = list(buffers[y_field])
+ cidx = field_color[y_field]
+ color = colors[cidx] if cidx < len(colors) else None
+ kw = {"color": color, "label": y_field} if color else {"label": y_field}
+ if plot_type == "scatter":
+ ax.scatter(x_data, y_data, s=10, **kw)
+ elif plot_type == "bar":
+ ax.bar(x_data, y_data, **kw)
+ else:
+ ax.plot(x_data, y_data, **kw)
+ # show y-label: single field name, or legend for multiple
+ if len(group) == 1:
+ ax.set_ylabel(group[0])
+ else:
+ ax.legend(loc="upper left", fontsize="small")
+ ax.grid(True, linestyle="--", alpha=0.5)
+
+ if x_field:
+ axes[-1, 0].set_xlabel(x_field)
+
+ plt.tight_layout()
+ plt.draw()
+ plt.pause(interval)
+ poll_n += 1
+
+ except KeyboardInterrupt:
+ pass
+ finally:
+ plt.ioff()
+ plt.show()
+
+
+# ── static backends (plot mode) ────────────────────────────────────────────
+
+
+def _plot_static_matplotlib(
+ con: duckdb.DuckDBPyConnection,
+ sql: str,
+ x_field: Optional[str],
+ y_fields: list[str],
+ opts: dict[str, Any],
+ verbose: bool,
+) -> None:
+ try:
+ import matplotlib.pyplot as plt
+ except ImportError:
+ print("Error: matplotlib is required for --plot matplotlib. pip install matplotlib", file=sys.stderr)
+ sys.exit(1)
+
+ figsize = tuple(opts["figsize"])
+ colors = opts["colors"] or [None] * len(y_fields)
+ plot_type = opts["type"]
+ groups = _resolve_groups(y_fields, opts)
+ field_color = {f: i for i, f in enumerate(y_fields)}
+
+ if opts["font"]:
+ plt.rcParams["font.family"] = opts["font"]
+ if opts["fontsize"]:
+ plt.rcParams["font.size"] = opts["fontsize"]
+
+ cols, rows = _fetch_poll(con, sql)
+ if verbose:
+ print(f"{len(rows)} row(s) fetched")
+
+ row_dicts = [dict(zip(cols, r)) for r in rows]
+ x_data = (
+ [r[x_field] for r in row_dicts]
+ if x_field and row_dicts and x_field in row_dicts[0]
+ else list(range(len(rows)))
+ )
+
+ fig, axes = plt.subplots(len(groups), 1, figsize=figsize, sharex=True, squeeze=False)
+
+ for ax, group in zip(axes[:, 0], groups):
+ for y_field in group:
+ y_data = [r.get(y_field) for r in row_dicts]
+ cidx = field_color[y_field]
+ color = colors[cidx] if cidx < len(colors) else None
+ kw = {"color": color, "label": y_field} if color else {"label": y_field}
+ if plot_type == "scatter":
+ ax.scatter(x_data, y_data, s=10, **kw)
+ elif plot_type == "bar":
+ ax.bar(x_data, y_data, **kw)
+ else:
+ ax.plot(x_data, y_data, **kw)
+ if len(group) == 1:
+ ax.set_ylabel(group[0])
+ else:
+ ax.legend(loc="upper left", fontsize="small")
+ ax.grid(True, linestyle="--", alpha=0.5)
+
+ if x_field:
+ axes[-1, 0].set_xlabel(x_field)
+
+ fig.suptitle(f"MySQL — {sql[:60]}…" if len(sql) > 60 else f"MySQL — {sql}")
+ plt.tight_layout()
+ plt.show()
+
+
+def _plot_static_plotly(
+ con: duckdb.DuckDBPyConnection,
+ sql: str,
+ x_field: Optional[str],
+ y_fields: list[str],
+ opts: dict[str, Any],
+ output_html: str,
+ verbose: bool,
+) -> None:
+ try:
+ import plotly.graph_objects as go
+ from plotly.subplots import make_subplots
+ except ImportError:
+ print("Error: plotly is required for --plot plotly. pip install plotly", file=sys.stderr)
+ sys.exit(1)
+
+ colors = opts["colors"] or [None] * len(y_fields)
+ plot_type = opts["type"]
+ groups = _resolve_groups(y_fields, opts)
+ field_color = {f: i for i, f in enumerate(y_fields)}
+
+ cols, rows = _fetch_poll(con, sql)
+ if verbose:
+ print(f"{len(rows)} row(s) fetched")
+
+ row_dicts = [dict(zip(cols, r)) for r in rows]
+ x_data = (
+ [r[x_field] for r in row_dicts]
+ if x_field and row_dicts and x_field in row_dicts[0]
+ else list(range(len(rows)))
+ )
+
+ subplot_titles = [", ".join(g) for g in groups]
+ fig = make_subplots(
+ rows=len(groups), cols=1, shared_xaxes=True,
+ vertical_spacing=0.04, subplot_titles=subplot_titles,
+ )
+
+ for row_idx, group in enumerate(groups, start=1):
+ for y_field in group:
+ y_data = [r.get(y_field) for r in row_dicts]
+ cidx = field_color[y_field]
+ color = colors[cidx] if cidx < len(colors) else None
+ marker = {"color": color} if color else {}
+
+ if plot_type == "scatter":
+ trace = go.Scatter(x=x_data, y=y_data, mode="markers", name=y_field, marker=marker)
+ elif plot_type == "bar":
+ trace = go.Bar(x=x_data, y=y_data, name=y_field, marker=marker)
+ else:
+ trace = go.Scatter(x=x_data, y=y_data, mode="lines", name=y_field, line=marker)
+ fig.add_trace(trace, row=row_idx, col=1)
+
+ y_title = group[0] if len(group) == 1 else ""
+ fig.update_yaxes(title_text=y_title, row=row_idx, col=1)
+
+ if x_field:
+ fig.update_xaxes(title_text=x_field, row=len(groups), col=1)
+
+ font_dict: dict[str, Any] = {}
+ if opts["font"]:
+ font_dict["family"] = opts["font"]
+ if opts["fontsize"]:
+ font_dict["size"] = opts["fontsize"]
+
+ fig.update_layout(
+ title=f"MySQL — {sql[:80]}…" if len(sql) > 80 else f"MySQL — {sql}",
+ height=max(300, 280 * len(groups)),
+ **({"font": font_dict} if font_dict else {}),
+ )
+
+ html_path = Path(output_html).resolve()
+ html_path.write_text(fig.to_html(full_html=True, include_plotlyjs="cdn"), encoding="utf-8")
+ webbrowser.open(html_path.as_uri())
+ print(f"Plotly output written to {html_path}")
+
+
+def _plot_static_dash(
+ con: duckdb.DuckDBPyConnection,
+ sql: str,
+ x_field: Optional[str],
+ y_fields: list[str],
+ opts: dict[str, Any],
+ host: str,
+ port: int,
+ verbose: bool,
+) -> None:
+ try:
+ from dash import Dash, dcc, html
+ import plotly.graph_objects as go
+ except ImportError:
+ print("Error: dash is required for --plot dash. pip install dash", file=sys.stderr)
+ sys.exit(1)
+
+ import logging
+ logging.getLogger("werkzeug").setLevel(logging.ERROR)
+
+ colors = opts["colors"] or [None] * len(y_fields)
+ plot_type = opts["type"]
+ groups = _resolve_groups(y_fields, opts)
+ field_color = {f: i for i, f in enumerate(y_fields)}
+
+ font_dict: dict[str, Any] = {}
+ if opts["font"]:
+ font_dict["family"] = opts["font"]
+ if opts["fontsize"]:
+ font_dict["size"] = opts["fontsize"]
+
+ cols, rows = _fetch_poll(con, sql)
+ if verbose:
+ print(f"{len(rows)} row(s) fetched")
+
+ row_dicts = [dict(zip(cols, r)) for r in rows]
+ x_data = (
+ [r[x_field] for r in row_dicts]
+ if x_field and row_dicts and x_field in row_dicts[0]
+ else list(range(len(rows)))
+ )
+
+ figs = []
+ for group in groups:
+ fig = go.Figure()
+ for y_field in group:
+ y_data = [r.get(y_field) for r in row_dicts]
+ cidx = field_color[y_field]
+ color = colors[cidx] if cidx < len(colors) else None
+ marker = {"color": color} if color else {}
+
+ if plot_type == "scatter":
+ trace = go.Scatter(x=x_data, y=y_data, mode="markers", name=y_field, marker=marker)
+ elif plot_type == "bar":
+ trace = go.Bar(x=x_data, y=y_data, name=y_field, marker=marker)
+ else:
+ trace = go.Scatter(x=x_data, y=y_data, mode="lines", name=y_field, line=marker)
+ fig.add_trace(trace)
+
+ fig.update_layout(
+ title=", ".join(group) if len(groups) > 1 else "",
+ height=280,
+ xaxis_title=x_field or "",
+ yaxis_title=group[0] if len(group) == 1 else "",
+ margin={"t": 40, "b": 40, "l": 60, "r": 20},
+ **({"font": font_dict} if font_dict else {}),
+ )
+ figs.append(fig)
+
+ heading = f"MySQL — {sql[:80]}…" if len(sql) > 80 else f"MySQL — {sql}"
+ app = Dash(__name__, title="MySQL Plot")
+ app.layout = html.Div(
+ style={"fontFamily": opts["font"] or "sans-serif", "padding": "16px"},
+ children=[
+ html.H4(heading, style={"marginBottom": "8px"}),
+ html.P(
+ f"{len(rows)} row(s)",
+ style={"color": "gray", "fontSize": "0.85em", "marginBottom": "12px"},
+ ),
+ html.Div([
+ dcc.Graph(figure=fig, config={"displayModeBar": True})
+ for fig in figs
+ ]),
+ ],
+ )
+
+ url = f"http://{host}:{port}"
+ print(f"Dash server at {url} (Ctrl+C to stop)")
+ webbrowser.open(url)
+ app.run(host=host, port=port, debug=False, use_reloader=False)
+
+
+# ── plotly backend ──────────────────────────────────────────────────────────
+
+def _poll_plotly(
+ con: duckdb.DuckDBPyConnection,
+ sql: str,
+ x_field: Optional[str],
+ y_fields: list[str],
+ opts: dict[str, Any],
+ interval: float,
+ count: Optional[int],
+ output_html: str,
+ verbose: bool,
+) -> None:
+ try:
+ import plotly.graph_objects as go
+ from plotly.subplots import make_subplots
+ except ImportError:
+ print("Error: plotly is required for --plot plotly. pip install plotly", file=sys.stderr)
+ sys.exit(1)
+
+ colors = opts["colors"] or [None] * len(y_fields)
+ plot_type = opts["type"]
+ groups = _resolve_groups(y_fields, opts)
+ field_color = {f: i for i, f in enumerate(y_fields)}
+
+ html_path = Path(output_html).resolve()
+ browser_opened = False
+ fields_label = ", ".join(y_fields)
+ title = fields_label
+ poll_n = 0
+
+ try:
+ while count is None or poll_n < count:
+ cols, rows = _fetch_poll(con, sql)
+ if verbose:
+ print(f"[poll {poll_n + 1}] {len(rows)} row(s) fetched")
+
+ row_dicts = [dict(zip(cols, r)) for r in rows]
+ x_data = (
+ [r[x_field] for r in row_dicts]
+ if x_field and row_dicts and x_field in row_dicts[0]
+ else list(range(len(rows)))
+ )
+
+ if x_data:
+ title = f"{fields_label} ({_fmt_x_latest(x_data[-1])})"
+
+ subplot_titles = [", ".join(g) for g in groups]
+ fig = make_subplots(
+ rows=len(groups),
+ cols=1,
+ shared_xaxes=True,
+ vertical_spacing=0.04,
+ subplot_titles=subplot_titles,
+ )
+
+ for row_idx, group in enumerate(groups, start=1):
+ for y_field in group:
+ y_data = [r.get(y_field) for r in row_dicts]
+ cidx = field_color[y_field]
+ color = colors[cidx] if cidx < len(colors) else None
+ marker = {"color": color} if color else {}
+
+ if plot_type == "scatter":
+ trace = go.Scatter(x=x_data, y=y_data, mode="markers", name=y_field, marker=marker)
+ elif plot_type == "bar":
+ trace = go.Bar(x=x_data, y=y_data, name=y_field, marker=marker)
+ else:
+ trace = go.Scatter(x=x_data, y=y_data, mode="lines", name=y_field, line=marker)
+
+ fig.add_trace(trace, row=row_idx, col=1)
+
+ # y-axis label: single field or blank (legend handles multi-field groups)
+ y_title = group[0] if len(group) == 1 else ""
+ fig.update_yaxes(title_text=y_title, row=row_idx, col=1)
+
+ if x_field:
+ fig.update_xaxes(title_text=x_field, row=len(groups), col=1)
+
+ font_dict: dict[str, Any] = {}
+ if opts["font"]:
+ font_dict["family"] = opts["font"]
+ if opts["fontsize"]:
+ font_dict["size"] = opts["fontsize"]
+
+ fig.update_layout(
+ title=title,
+ height=max(300, 280 * len(groups)),
+ **({"font": font_dict} if font_dict else {}),
+ )
+
+ # Inject meta-refresh so the browser reloads automatically
+ html_body = fig.to_html(full_html=True, include_plotlyjs="cdn")
+ refresh_tag = f''
+ html_body = html_body.replace("", f"\n {refresh_tag}", 1)
+ html_path.write_text(html_body, encoding="utf-8")
+
+ if not browser_opened:
+ webbrowser.open(html_path.as_uri())
+ browser_opened = True
+
+ poll_n += 1
+ if count is None or poll_n < count:
+ time.sleep(interval)
+
+ except KeyboardInterrupt:
+ pass
+
+ print(f"Plotly output written to {html_path}")
+
+
+# ── textual backend ────────────────────────────────────────────────────────
+
+
+def _poll_textual(
+ con: duckdb.DuckDBPyConnection,
+ sql: str,
+ x_field: Optional[str],
+ y_fields: list[str],
+ opts: dict[str, Any],
+ interval: float,
+ count: Optional[int],
+ verbose: bool,
+) -> None:
+ try:
+ from textual.app import App, ComposeResult
+ from textual.containers import ScrollableContainer
+ from textual.widgets import Footer, Header, Static
+ except ImportError:
+ print(
+ "Error: textual is required for --plot textual. pip install textual",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ try:
+ import plotext as _plt
+ except ImportError:
+ print(
+ "Error: plotext is required for --plot textual. pip install plotext",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ import datetime as _dt
+
+ colors = opts["colors"] or []
+ groups = _resolve_groups(y_fields, opts)
+
+ def _to_plotext_x(vals: list) -> tuple[list, list, list]:
+ """Convert x-values for plotext.
+
+ Returns (x_values, xtick_positions, xtick_labels).
+ Datetimes become float Unix timestamps so plotext never sees date
+ strings and date_form() is never needed (it resets unpredictably
+ across clf/subplot calls).
+ """
+ if not vals:
+ return [], [], []
+ clean = [v for v in vals if v is not None and hasattr(v, "timestamp")]
+ if clean:
+ x_num = [
+ v.timestamp() if (v is not None and hasattr(v, "timestamp"))
+ else float("nan")
+ for v in vals
+ ]
+ pairs = [(xn, v) for xn, v in zip(x_num, vals) if xn == xn] # skip NaN
+ if pairs:
+ step = max(1, len(pairs) // 6)
+ ticks = pairs[::step][:6]
+ tick_pos = [p[0] for p in ticks]
+ tick_lbl = [p[1].strftime("%H:%M:%S") for p in ticks]
+ else:
+ tick_pos, tick_lbl = [], []
+ return x_num, tick_pos, tick_lbl
+ return list(vals), [], []
+
+ # plotext uses a module-level singleton figure. Using one widget that owns
+ # the entire render pass avoids concurrent clf()/scatter()/build() calls
+ # from multiple widgets corrupting each other's output.
+ class PollWidget(Static): # type: ignore[type-arg]
+ DEFAULT_CSS = """
+ PollWidget {
+ height: 1fr;
+ padding: 0;
+ }
+ """
+
+ def __init__(self, **kwargs: Any) -> None:
+ super().__init__("Connecting…", **kwargs)
+ self._x: list = []
+ self._ys: dict[str, list[float]] = {f: [] for f in y_fields}
+
+ def refresh_data(self, x: list, ys: dict[str, list[float]]) -> None:
+ self._x = x
+ self._ys = ys
+ self._redraw()
+
+ def on_resize(self, _event: object) -> None:
+ self._redraw()
+
+ def _redraw(self) -> None:
+ w = self.size.width
+ h = self.size.height
+ if w < 10 or h < 4:
+ return
+
+ n = len(groups)
+ x_vals, tick_pos, tick_lbl = _to_plotext_x(self._x)
+ any_plotted = False
+
+ try:
+ _plt.clf()
+ if n > 1:
+ _plt.subplots(n, 1)
+ _plt.plotsize(w, h)
+ _plt.theme("dark")
+
+ for gi, group in enumerate(groups):
+ if n > 1:
+ _plt.subplot(gi + 1, 1)
+ _plt.title(", ".join(group))
+ if x_field:
+ _plt.xlabel(x_field)
+ if tick_pos:
+ _plt.xticks(tick_pos, tick_lbl)
+
+ for field in group:
+ y = self._ys.get(field, [])
+ if x_vals and y and len(x_vals) == len(y):
+ fi = y_fields.index(field)
+ kw: dict[str, Any] = {"label": field}
+ c = colors[fi] if fi < len(colors) else None
+ if c:
+ kw["color"] = c
+ _plt.scatter(x_vals, y, **kw)
+ any_plotted = True
+
+ if any_plotted:
+ self.update(_plt.build())
+ else:
+ self.update("Waiting for data…")
+ except Exception as exc:
+ self.update(f"Plot error: {exc}")
+
+ class PollApp(App): # type: ignore[type-arg]
+ THEME = "textual-dark"
+ CSS = """
+ Screen { background: $surface; }
+ #plot { height: 1fr; }
+ #status {
+ height: 1;
+ background: $primary-darken-3;
+ color: $text-muted;
+ padding: 0 1;
+ }
+ """
+
+ BINDINGS = [
+ ("q", "quit", "Quit"),
+ ("p", "toggle_pause", "Pause / Resume"),
+ ]
+
+ def __init__(self) -> None:
+ super().__init__()
+ self._fields_label = ", ".join(y_fields)
+ self.title = self._fields_label
+ self._poll_n = 0
+ self._paused = False
+
+ def compose(self) -> ComposeResult:
+ yield Header(show_clock=True)
+ yield PollWidget(id="plot")
+ yield Static("Connecting…", id="status")
+ yield Footer()
+
+ def on_mount(self) -> None:
+ self.set_interval(interval, self._do_poll)
+
+ async def _do_poll(self) -> None:
+ if self._paused:
+ return
+ if count is not None and self._poll_n >= count:
+ self.exit()
+ return
+
+ try:
+ cols, rows = _fetch_poll(con, sql)
+ except Exception as exc:
+ self.query_one("#status", Static).update(f"Error: {exc}")
+ return
+
+ if x_field and rows:
+ x_latest = dict(zip(cols, rows[-1])).get(x_field)
+ if x_latest is not None:
+ self.title = f"{self._fields_label} ({_fmt_x_latest(x_latest)})"
+
+ x_data: list = []
+ ys: dict[str, list[float]] = {f: [] for f in y_fields}
+ for row in rows:
+ rd = dict(zip(cols, row))
+ if x_field:
+ x_data.append(rd.get(x_field))
+ for f in y_fields:
+ val = rd.get(f)
+ try:
+ ys[f].append(float(val) if val is not None else float("nan"))
+ except (TypeError, ValueError):
+ ys[f].append(float("nan"))
+
+ if not x_field:
+ x_data = list(range(len(rows)))
+
+ try:
+ self.query_one("#plot", PollWidget).refresh_data(x_data, ys)
+ except Exception:
+ pass
+
+ self._poll_n += 1
+ now = _dt.datetime.now().strftime("%H:%M:%S")
+ paused_tag = " [PAUSED]" if self._paused else ""
+ self.query_one("#status", Static).update(
+ f"Poll #{self._poll_n} rows={len(rows)}"
+ f" interval={interval}s updated={now}{paused_tag}"
+ )
+
+ def action_toggle_pause(self) -> None:
+ self._paused = not self._paused
+
+ PollApp().run()
+
+
+# ── terminal table backend ─────────────────────────────────────────────────
+
+
+def _poll_table(
+ con: duckdb.DuckDBPyConnection,
+ sql: str,
+ x_field: Optional[str],
+ y_fields: list[str],
+ opts: dict[str, Any],
+ interval: float,
+ count: Optional[int],
+ verbose: bool,
+) -> None:
+ try:
+ from rich.console import Console, Group
+ from rich.live import Live
+ from rich.table import Table as RichTable
+ from rich.text import Text
+ except ImportError:
+ print(
+ "Error: rich is required for --plot table. pip install rich",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ import datetime as _dt
+
+ fields_label = ", ".join(y_fields)
+ poll_n = 0
+ console = Console()
+
+ def _build_rich_table(cols: list[str], rows: list[tuple]) -> RichTable:
+ t = RichTable(
+ show_header=True, header_style="bold cyan",
+ show_lines=False, expand=False,
+ )
+ for col in cols:
+ t.add_column(col, overflow="fold", no_wrap=(col == x_field))
+ for row in rows:
+ t.add_row(*["—" if v is None else str(v) for v in row])
+ return t
+
+ try:
+ with Live(console=console, refresh_per_second=4, screen=False) as live:
+ while count is None or poll_n < count:
+ try:
+ cols, rows = _fetch_poll(con, sql)
+ except Exception as exc:
+ live.update(Text(f"Poll error: {exc}", style="red"))
+ time.sleep(interval)
+ continue
+
+ now = _dt.datetime.now().strftime("%H:%M:%S")
+ x_info = ""
+ if x_field and rows:
+ last_val = dict(zip(cols, rows[-1])).get(x_field)
+ if last_val is not None:
+ x_info = f" · {x_field}: {_fmt_x_latest(last_val)}"
+
+ status = Text(
+ f"[Poll #{poll_n + 1}] {len(rows)} row(s)"
+ f" · updated {now}{x_info}"
+ f" · interval {interval}s · Ctrl-C to stop",
+ style="dim",
+ )
+ live.update(Group(status, _build_rich_table(cols, rows)))
+
+ if verbose:
+ print(f"[poll {poll_n + 1}] {len(rows)} row(s)")
+
+ poll_n += 1
+ if count is None or poll_n < count:
+ time.sleep(interval)
+
+ except KeyboardInterrupt:
+ pass
+
+
+# ── dash backend ───────────────────────────────────────────────────────────
+
+
+def _poll_dash(
+ con: duckdb.DuckDBPyConnection,
+ sql: str,
+ x_field: Optional[str],
+ y_fields: list[str],
+ opts: dict[str, Any],
+ interval: float,
+ count: Optional[int],
+ host: str,
+ port: int,
+ verbose: bool,
+) -> None:
+ try:
+ from dash import Dash, Input, Output, State, dcc, html, no_update
+ from dash.exceptions import PreventUpdate
+ import plotly.graph_objects as go
+ except ImportError:
+ print(
+ "Error: dash is required for --plot dash. pip install dash",
+ file=sys.stderr,
+ )
+ sys.exit(1)
+
+ import datetime as _dt
+ import logging
+
+ logging.getLogger("werkzeug").setLevel(logging.ERROR)
+
+ colors = opts["colors"] or [None] * len(y_fields)
+ plot_type = opts["type"]
+ groups = _resolve_groups(y_fields, opts)
+ field_color = {f: i for i, f in enumerate(y_fields)}
+
+ font_dict: dict[str, Any] = {}
+ if opts["font"]:
+ font_dict["family"] = opts["font"]
+ if opts["fontsize"]:
+ font_dict["size"] = opts["fontsize"]
+
+ app = Dash(__name__, title="MySQL Poll", suppress_callback_exceptions=True)
+ graph_ids = [f"graph-{i}" for i in range(len(groups))]
+ interval_ms = int(interval * 1000)
+ fields_label = ", ".join(y_fields)
+
+ app.layout = html.Div(
+ style={"fontFamily": opts["font"] or "sans-serif", "padding": "16px"},
+ children=[
+ html.H4(id="heading", children=fields_label, style={"marginBottom": "8px"}),
+ html.Div(
+ style={"display": "flex", "alignItems": "center",
+ "gap": "16px", "marginBottom": "12px"},
+ children=[
+ html.Button("⏸ Pause / Resume", id="pause-btn", n_clicks=0),
+ html.Span(id="status-text",
+ style={"color": "gray", "fontSize": "0.85em"}),
+ ],
+ ),
+ dcc.Interval(id="interval", interval=interval_ms,
+ n_intervals=0, disabled=False),
+ dcc.Store(id="paused", data=False),
+ dcc.Store(id="poll-n", data=0),
+ html.Div([
+ dcc.Graph(id=gid, config={"displayModeBar": True})
+ for gid in graph_ids
+ ]),
+ ],
+ )
+
+ @app.callback(
+ Output("paused", "data"),
+ Output("interval", "disabled"),
+ Input("pause-btn", "n_clicks"),
+ State("paused", "data"),
+ prevent_initial_call=True,
+ )
+ def toggle_pause(n_clicks, paused):
+ new_state = not paused
+ return new_state, new_state
+
+ @app.callback(
+ [Output(gid, "figure") for gid in graph_ids]
+ + [Output("status-text", "children"), Output("heading", "children"),
+ Output("poll-n", "data")],
+ Input("interval", "n_intervals"),
+ State("poll-n", "data"),
+ )
+ def refresh(n_intervals, poll_n):
+ if count is not None and poll_n >= count:
+ raise PreventUpdate
+
+ try:
+ cols, rows = _fetch_poll(con, sql)
+ except Exception as exc:
+ if verbose:
+ print(f"Poll error: {exc}", file=sys.stderr)
+ raise PreventUpdate
+
+ row_dicts = [dict(zip(cols, r)) for r in rows]
+ x_data = (
+ [r[x_field] for r in row_dicts]
+ if x_field and row_dicts and x_field in row_dicts[0]
+ else list(range(len(rows)))
+ )
+
+ if x_data:
+ new_heading = f"{fields_label} ({_fmt_x_latest(x_data[-1])})"
+ else:
+ new_heading = no_update
+
+ figs = []
+ for group in groups:
+ fig = go.Figure()
+ for y_field in group:
+ y_data = [r.get(y_field) for r in row_dicts]
+ cidx = field_color[y_field]
+ color = colors[cidx] if cidx < len(colors) else None
+ marker = {"color": color} if color else {}
+
+ if plot_type == "scatter":
+ trace = go.Scatter(x=x_data, y=y_data, mode="markers",
+ name=y_field, marker=marker)
+ elif plot_type == "bar":
+ trace = go.Bar(x=x_data, y=y_data, name=y_field,
+ marker=marker)
+ else:
+ trace = go.Scatter(x=x_data, y=y_data, mode="lines",
+ name=y_field, line=marker)
+ fig.add_trace(trace)
+
+ fig.update_layout(
+ title=", ".join(group) if len(groups) > 1 else "",
+ height=280,
+ xaxis_title=x_field or "",
+ yaxis_title=group[0] if len(group) == 1 else "",
+ margin={"t": 40, "b": 40, "l": 60, "r": 20},
+ **({"font": font_dict} if font_dict else {}),
+ )
+ figs.append(fig)
+
+ poll_n += 1
+ now = _dt.datetime.now().strftime("%H:%M:%S")
+ status = f"Poll #{poll_n} · {len(rows)} row(s) · updated {now}"
+ if verbose:
+ print(status)
+
+ return figs + [status, new_heading, poll_n]
+
+ url = f"http://{host}:{port}"
+ print(f"Dash server at {url} (Ctrl+C to stop)")
+ webbrowser.open(url)
+ app.run(host=host, port=port, debug=False, use_reloader=False)
+
+
+# ── multi-source backends (two tables, shared x-axis) ─────────────────────
+
+
+def _poll_matplotlib_multi(
+ con: duckdb.DuckDBPyConnection,
+ sql1: str,
+ sql2: str,
+ x_field: Optional[str],
+ y_fields1: list[str],
+ y_fields2: list[str],
+ opts: dict[str, Any],
+ interval: float,
+ count: Optional[int],
+ verbose: bool,
+) -> None:
+ """Live matplotlib poll: y_fields1 in subplot 1, y_fields2 in subplot 2, shared x."""
+ try:
+ import matplotlib.pyplot as plt
+ except ImportError:
+ print("Error: matplotlib is required for --plot matplotlib. pip install matplotlib", file=sys.stderr)
+ sys.exit(1)
+
+ figsize = tuple(opts["figsize"])
+ colors = opts["colors"] or []
+ plot_type = opts["type"]
+
+ if opts["font"]:
+ plt.rcParams["font.family"] = opts["font"]
+ if opts["fontsize"]:
+ plt.rcParams["font.size"] = opts["fontsize"]
+
+ label1 = ", ".join(y_fields1)
+ label2 = ", ".join(y_fields2)
+
+ plt.ion()
+ fig, (ax1, ax2) = plt.subplots(2, 1, figsize=figsize, sharex=True)
+ suptitle_obj = fig.suptitle(f"{label1} | {label2}")
+
+ poll_n = 0
+ try:
+ while count is None or poll_n < count:
+ cols1, rows1 = _fetch_poll(con, sql1)
+ cols2, rows2 = _fetch_poll(con, sql2)
+ if verbose:
+ print(f"[poll {poll_n + 1}] src1={len(rows1)} row(s), src2={len(rows2)} row(s)")
+
+ rd1 = [dict(zip(cols1, r)) for r in rows1]
+ rd2 = [dict(zip(cols2, r)) for r in rows2]
+
+ x1 = (
+ [r[x_field] for r in rd1]
+ if x_field and rd1 and x_field in rd1[0]
+ else list(range(len(rows1)))
+ )
+ x2 = (
+ [r[x_field] for r in rd2]
+ if x_field and rd2 and x_field in rd2[0]
+ else list(range(len(rows2)))
+ )
+
+ ax1.cla()
+ ax2.cla()
+
+ for i, yf in enumerate(y_fields1):
+ y = [r.get(yf) for r in rd1]
+ color = colors[i] if i < len(colors) else None
+ kw: dict[str, Any] = {"label": yf}
+ if color:
+ kw["color"] = color
+ if plot_type == "scatter":
+ ax1.scatter(x1, y, s=10, **kw)
+ elif plot_type == "bar":
+ ax1.bar(x1, y, **kw)
+ else:
+ ax1.plot(x1, y, **kw)
+ if len(y_fields1) == 1:
+ ax1.set_ylabel(label1)
+ else:
+ ax1.legend(loc="upper left", fontsize="small")
+ ax1.grid(True, linestyle="--", alpha=0.5)
+
+ n_colors1 = len(y_fields1)
+ for j, yf in enumerate(y_fields2):
+ cidx = n_colors1 + j
+ y = [r.get(yf) for r in rd2]
+ color = colors[cidx] if cidx < len(colors) else None
+ kw = {"label": yf}
+ if color:
+ kw["color"] = color
+ if plot_type == "scatter":
+ ax2.scatter(x2, y, s=10, **kw)
+ elif plot_type == "bar":
+ ax2.bar(x2, y, **kw)
+ else:
+ ax2.plot(x2, y, **kw)
+ if len(y_fields2) == 1:
+ ax2.set_ylabel(label2)
+ else:
+ ax2.legend(loc="upper left", fontsize="small")
+ ax2.grid(True, linestyle="--", alpha=0.5)
+
+ if x_field:
+ ax2.set_xlabel(x_field)
+ if x1:
+ suptitle_obj.set_text(
+ f"{label1} | {label2} ({_fmt_x_latest(x1[-1])})"
+ )
+
+ plt.tight_layout()
+ plt.draw()
+ plt.pause(interval)
+ poll_n += 1
+
+ except KeyboardInterrupt:
+ pass
+ finally:
+ plt.ioff()
+ plt.show()
+
+
+def _poll_plotly_multi(
+ con: duckdb.DuckDBPyConnection,
+ sql1: str,
+ sql2: str,
+ x_field: Optional[str],
+ y_fields1: list[str],
+ y_fields2: list[str],
+ opts: dict[str, Any],
+ interval: float,
+ count: Optional[int],
+ output_html: str,
+ verbose: bool,
+) -> None:
+ """Two-source plotly polling with two rows sharing one x-axis."""
+ try:
+ import plotly.graph_objects as go
+ from plotly.subplots import make_subplots
+ except ImportError:
+ print("Error: plotly is required for --plot plotly. pip install plotly", file=sys.stderr)
+ sys.exit(1)
+
+ colors = opts["colors"] or []
+ plot_type = opts["type"]
+ html_path = Path(output_html).resolve()
+ browser_opened = False
+ label1 = ", ".join(y_fields1)
+ label2 = ", ".join(y_fields2)
+ title = f"{label1} | {label2}"
+ poll_n = 0
+
+ font_dict: dict[str, Any] = {}
+ if opts["font"]:
+ font_dict["family"] = opts["font"]
+ if opts["fontsize"]:
+ font_dict["size"] = opts["fontsize"]
+
+ try:
+ while count is None or poll_n < count:
+ cols1, rows1 = _fetch_poll(con, sql1)
+ cols2, rows2 = _fetch_poll(con, sql2)
+ if verbose:
+ print(f"[poll {poll_n + 1}] src1={len(rows1)} row(s), src2={len(rows2)} row(s)")
+
+ rd1 = [dict(zip(cols1, r)) for r in rows1]
+ rd2 = [dict(zip(cols2, r)) for r in rows2]
+
+ x1 = (
+ [r[x_field] for r in rd1]
+ if x_field and rd1 and x_field in rd1[0]
+ else list(range(len(rows1)))
+ )
+ x2 = (
+ [r[x_field] for r in rd2]
+ if x_field and rd2 and x_field in rd2[0]
+ else list(range(len(rows2)))
+ )
+
+ if x1:
+ title = f"{label1} | {label2} ({_fmt_x_latest(x1[-1])})"
+
+ fig = make_subplots(
+ rows=2, cols=1,
+ shared_xaxes=True,
+ vertical_spacing=0.06,
+ subplot_titles=[label1, label2],
+ )
+
+ for i, yf in enumerate(y_fields1):
+ y = [r.get(yf) for r in rd1]
+ color = colors[i] if i < len(colors) else None
+ marker = {"color": color} if color else {}
+ if plot_type == "scatter":
+ trace = go.Scatter(x=x1, y=y, mode="markers", name=yf, marker=marker)
+ elif plot_type == "bar":
+ trace = go.Bar(x=x1, y=y, name=yf, marker=marker)
+ else:
+ trace = go.Scatter(x=x1, y=y, mode="lines", name=yf, line=marker)
+ fig.add_trace(trace, row=1, col=1)
+
+ n_colors1 = len(y_fields1)
+ for j, yf in enumerate(y_fields2):
+ cidx = n_colors1 + j
+ y = [r.get(yf) for r in rd2]
+ color = colors[cidx] if cidx < len(colors) else None
+ marker = {"color": color} if color else {}
+ if plot_type == "scatter":
+ trace = go.Scatter(x=x2, y=y, mode="markers", name=yf, marker=marker)
+ elif plot_type == "bar":
+ trace = go.Bar(x=x2, y=y, name=yf, marker=marker)
+ else:
+ trace = go.Scatter(x=x2, y=y, mode="lines", name=yf, line=marker)
+ fig.add_trace(trace, row=2, col=1)
+
+ if x_field:
+ fig.update_xaxes(title_text=x_field, row=2, col=1)
+ fig.update_yaxes(title_text=label1 if len(y_fields1) == 1 else "", row=1, col=1)
+ fig.update_yaxes(title_text=label2 if len(y_fields2) == 1 else "", row=2, col=1)
+ fig.update_layout(
+ title=title,
+ height=560,
+ **({"font": font_dict} if font_dict else {}),
+ )
+
+ html_body = fig.to_html(full_html=True, include_plotlyjs="cdn")
+ refresh_tag = f''
+ html_body = html_body.replace("", f"\n {refresh_tag}", 1)
+ html_path.write_text(html_body, encoding="utf-8")
+
+ if not browser_opened:
+ webbrowser.open(html_path.as_uri())
+ browser_opened = True
+
+ poll_n += 1
+ if count is None or poll_n < count:
+ time.sleep(interval)
+
+ except KeyboardInterrupt:
+ pass
+
+ print(f"Plotly output written to {html_path}")
+
+
+def _poll_dash_multi(
+ con: duckdb.DuckDBPyConnection,
+ sql1: str,
+ sql2: str,
+ x_field: Optional[str],
+ y_fields1: list[str],
+ y_fields2: list[str],
+ opts: dict[str, Any],
+ interval: float,
+ count: Optional[int],
+ host: str,
+ port: int,
+ verbose: bool,
+) -> None:
+ """Two-source Dash polling: two rows in one make_subplots figure with shared x-axis."""
+ try:
+ from dash import Dash, Input, Output, State, dcc, html, no_update
+ from dash.exceptions import PreventUpdate
+ import plotly.graph_objects as go
+ from plotly.subplots import make_subplots
+ except ImportError:
+ print("Error: dash is required for --plot dash. pip install dash", file=sys.stderr)
+ sys.exit(1)
+
+ import datetime as _dt
+ import logging
+ logging.getLogger("werkzeug").setLevel(logging.ERROR)
+
+ colors = opts["colors"] or []
+ plot_type = opts["type"]
+ interval_ms = int(interval * 1000)
+ label1 = ", ".join(y_fields1)
+ label2 = ", ".join(y_fields2)
+ heading_base = f"{label1} | {label2}"
+
+ font_dict: dict[str, Any] = {}
+ if opts["font"]:
+ font_dict["family"] = opts["font"]
+ if opts["fontsize"]:
+ font_dict["size"] = opts["fontsize"]
+
+ app = Dash(__name__, title="MySQL Poll (dual)", suppress_callback_exceptions=True)
+
+ app.layout = html.Div(
+ style={"fontFamily": opts["font"] or "sans-serif", "padding": "16px"},
+ children=[
+ html.H4(id="heading", children=heading_base, style={"marginBottom": "8px"}),
+ html.Div(
+ style={"display": "flex", "alignItems": "center",
+ "gap": "16px", "marginBottom": "12px"},
+ children=[
+ html.Button("⏸ Pause / Resume", id="pause-btn", n_clicks=0),
+ html.Span(id="status-text",
+ style={"color": "gray", "fontSize": "0.85em"}),
+ ],
+ ),
+ dcc.Interval(id="interval", interval=interval_ms,
+ n_intervals=0, disabled=False),
+ dcc.Store(id="paused", data=False),
+ dcc.Store(id="poll-n", data=0),
+ dcc.Graph(id="dual-graph", config={"displayModeBar": True}),
+ ],
+ )
+
+ @app.callback(
+ Output("paused", "data"),
+ Output("interval", "disabled"),
+ Input("pause-btn", "n_clicks"),
+ State("paused", "data"),
+ prevent_initial_call=True,
+ )
+ def toggle_pause(n_clicks, paused):
+ new_state = not paused
+ return new_state, new_state
+
+ @app.callback(
+ Output("dual-graph", "figure"),
+ Output("status-text", "children"),
+ Output("heading", "children"),
+ Output("poll-n", "data"),
+ Input("interval", "n_intervals"),
+ State("poll-n", "data"),
+ )
+ def refresh(n_intervals, poll_n):
+ if count is not None and poll_n >= count:
+ raise PreventUpdate
+
+ try:
+ cols1, rows1 = _fetch_poll(con, sql1)
+ cols2, rows2 = _fetch_poll(con, sql2)
+ except Exception as exc:
+ if verbose:
+ print(f"Poll error: {exc}", file=sys.stderr)
+ raise PreventUpdate
+
+ rd1 = [dict(zip(cols1, r)) for r in rows1]
+ rd2 = [dict(zip(cols2, r)) for r in rows2]
+
+ x1 = (
+ [r[x_field] for r in rd1]
+ if x_field and rd1 and x_field in rd1[0]
+ else list(range(len(rows1)))
+ )
+ x2 = (
+ [r[x_field] for r in rd2]
+ if x_field and rd2 and x_field in rd2[0]
+ else list(range(len(rows2)))
+ )
+
+ new_heading = no_update
+ if x1:
+ new_heading = f"{heading_base} ({_fmt_x_latest(x1[-1])})"
+
+ fig = make_subplots(
+ rows=2, cols=1,
+ shared_xaxes=True,
+ vertical_spacing=0.08,
+ subplot_titles=[label1, label2],
+ )
+
+ for i, yf in enumerate(y_fields1):
+ y = [r.get(yf) for r in rd1]
+ color = colors[i] if i < len(colors) else None
+ marker = {"color": color} if color else {}
+ if plot_type == "scatter":
+ trace = go.Scatter(x=x1, y=y, mode="markers", name=yf, marker=marker)
+ elif plot_type == "bar":
+ trace = go.Bar(x=x1, y=y, name=yf, marker=marker)
+ else:
+ trace = go.Scatter(x=x1, y=y, mode="lines", name=yf, line=marker)
+ fig.add_trace(trace, row=1, col=1)
+
+ n_colors1 = len(y_fields1)
+ for j, yf in enumerate(y_fields2):
+ cidx = n_colors1 + j
+ y = [r.get(yf) for r in rd2]
+ color = colors[cidx] if cidx < len(colors) else None
+ marker = {"color": color} if color else {}
+ if plot_type == "scatter":
+ trace = go.Scatter(x=x2, y=y, mode="markers", name=yf, marker=marker)
+ elif plot_type == "bar":
+ trace = go.Bar(x=x2, y=y, name=yf, marker=marker)
+ else:
+ trace = go.Scatter(x=x2, y=y, mode="lines", name=yf, line=marker)
+ fig.add_trace(trace, row=2, col=1)
+
+ if x_field:
+ fig.update_xaxes(title_text=x_field, row=2, col=1)
+ fig.update_yaxes(title_text=label1 if len(y_fields1) == 1 else "", row=1, col=1)
+ fig.update_yaxes(title_text=label2 if len(y_fields2) == 1 else "", row=2, col=1)
+ fig.update_layout(
+ height=560,
+ **({"font": font_dict} if font_dict else {}),
+ )
+
+ poll_n += 1
+ now = _dt.datetime.now().strftime("%H:%M:%S")
+ status = (
+ f"Poll #{poll_n} · src1: {len(rows1)} row(s) · "
+ f"src2: {len(rows2)} row(s) · updated {now}"
+ )
+ if verbose:
+ print(status)
+
+ return fig, status, new_heading, poll_n
+
+ url = f"http://{host}:{port}"
+ print(f"Dash server at {url} (Ctrl+C to stop)")
+ webbrowser.open(url)
+ app.run(host=host, port=port, debug=False, use_reloader=False)
+
+
+# ── mode entry point ────────────────────────────────────────────────────────
+
+def mode_poll(args: argparse.Namespace) -> None:
+ """Poll a MySQL table and display selected fields as a live chart."""
+ import datetime as _dt
+
+ opts = _parse_plot_options(args.plot_options)
+ dsn = _build_dsn(args.host, args.port, args.user, args.password, args.database)
+
+ con = duckdb.connect()
+ _load_mysql_extension(con, args.verbose)
+ _attach_mysql(con, dsn, args.verbose)
+
+ if args.list_tables:
+ tables = list_mysql_tables(con, args.database)
+ print(f"Tables in '{args.database}' ({len(tables)}):")
+ for t in tables:
+ print(f" {t}")
+ return
+
+ # These are needed for second-source resolution in the table path.
+ limit: int = 0
+ start_time: Optional[str] = None
+
+ if args.query:
+ # ── raw-query path ──────────────────────────────────────────────────
+ sql = args.query
+
+ # Run the query once to discover result-column names and types.
+ rel = con.execute(sql)
+ result_cols = [(desc[0], desc[1]) for desc in rel.description]
+ result_col_names = [c[0] for c in result_cols]
+
+ if args.list_fields:
+ print("Columns returned by query:")
+ for name, col_type in result_cols:
+ if _is_numeric_type(col_type):
+ marker = " *"
+ elif _is_timestamp_type(col_type):
+ marker = " @"
+ else:
+ marker = ""
+ print(f" {name:<30} {col_type}{marker}")
+ print("(* = numeric / y-axis @ = timestamp / x-axis)")
+ return
+
+ # Resolve x-axis: explicit flag → first TIMESTAMP column → None
+ x_field = args.x_field or _auto_x_field(result_cols)
+ if x_field and x_field not in result_col_names:
+ print(f"Error: x-field '{x_field}' not in query result columns.", file=sys.stderr)
+ sys.exit(1)
+ if x_field and not args.x_field and args.verbose:
+ print(f"Auto-selected x-axis: {x_field}")
+
+ requested = args.fields or []
+ if requested:
+ unknown = set(requested) - set(result_col_names)
+ if unknown:
+ print(f"Error: unknown column(s) in query result: {', '.join(sorted(unknown))}", file=sys.stderr)
+ sys.exit(1)
+ y_fields = [f for f in requested if f != x_field]
+ else:
+ numeric_names = [c[0] for c in result_cols if _is_numeric_type(c[1]) and not _is_id_field(c[0])]
+ y_fields = [f for f in numeric_names if f != x_field]
+ if not y_fields:
+ print("Error: no numeric columns in query result. Use --fields to specify columns explicitly.", file=sys.stderr)
+ sys.exit(1)
+ if args.verbose:
+ print(f"Auto-selected y-fields: {', '.join(y_fields)}")
+
+ else:
+ # ── single-table path ───────────────────────────────────────────────
+ all_cols_raw = describe_table(con, args.table)
+ all_col_names = [c[0] for c in all_cols_raw]
+ all_cols_typed = [(c[0], c[1]) for c in all_cols_raw]
+ numeric_cols = list_numeric_columns(con, args.table)
+
+ if args.list_fields:
+ print(f"Columns in '{args.table}':")
+ for name, col_type in all_cols_typed:
+ if _is_numeric_type(col_type):
+ marker = " *"
+ elif _is_timestamp_type(col_type):
+ marker = " @"
+ else:
+ marker = ""
+ print(f" {name:<30} {col_type}{marker}")
+ print("(* = numeric / y-axis @ = timestamp / x-axis)")
+ return
+
+ # Resolve x-axis: explicit flag → first TIMESTAMP column → None
+ x_field = args.x_field or _auto_x_field(all_cols_typed)
+ if x_field and not args.x_field and args.verbose:
+ print(f"Auto-selected x-axis: {x_field}")
+
+ requested = args.fields or []
+ if requested:
+ unknown = set(requested) - set(all_col_names)
+ if unknown:
+ print(f"Error: unknown column(s) in {args.table}: {', '.join(sorted(unknown))}", file=sys.stderr)
+ sys.exit(1)
+ fields = [f for f in requested if f != x_field]
+ else:
+ fields = [name for name, _ in numeric_cols if name != x_field and not _is_id_field(name)]
+ if not fields:
+ print(f"Error: no numeric columns found in '{args.table}'. Use --fields to specify columns explicitly.", file=sys.stderr)
+ sys.exit(1)
+ if args.verbose:
+ print(f"Auto-selected y-fields: {', '.join(fields)}")
+
+ if x_field:
+ # ensure x_field is fetched even if not listed as a y-field
+ select_fields = [x_field] + fields
+ else:
+ select_fields = fields
+
+ y_fields = fields
+
+ if not y_fields:
+ print("Error: no y-fields to plot.", file=sys.stderr)
+ sys.exit(1)
+
+ # When a time axis is available: filter to data from launch time onwards so
+ # the plot starts "now" rather than at the beginning of the table.
+ # Default to no row cap in this mode so rows accumulate as they arrive.
+ if x_field and args.limit is None:
+ start_time = _dt.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
+ limit = 0
+ else:
+ start_time = None
+ limit = args.limit if args.limit is not None else 200
+ sql = _build_poll_query(args.table, select_fields, args.where, limit, x_field, start_time=start_time)
+
+ # ── resolve second source (--table2 / --query2) ─────────────────────────
+ sql2: Optional[str] = None
+ y_fields2: list[str] = []
+
+ has_table2 = bool(getattr(args, "table2", None))
+ has_query2 = bool(getattr(args, "query2", None))
+
+ if has_query2:
+ sql2 = args.query2
+ rel2 = con.execute(sql2)
+ result_cols2 = [(desc[0], desc[1]) for desc in rel2.description]
+ requested2 = getattr(args, "fields2", None) or []
+ if requested2:
+ y_fields2 = [f for f in requested2 if f != x_field]
+ else:
+ y_fields2 = [
+ c[0] for c in result_cols2
+ if _is_numeric_type(c[1]) and not _is_id_field(c[0]) and c[0] != x_field
+ ]
+ if not y_fields2:
+ print("Error: no y-fields for second source. Use --fields2.", file=sys.stderr)
+ sys.exit(1)
+ if args.verbose:
+ print(f"Second source (query): {sql2} fields: {', '.join(y_fields2)}")
+
+ elif has_table2:
+ all_cols2_raw = describe_table(con, args.table2)
+ all_cols2_typed = [(c[0], c[1]) for c in all_cols2_raw]
+ requested2 = getattr(args, "fields2", None) or []
+ if requested2:
+ f2 = [f for f in requested2 if f != x_field]
+ else:
+ f2 = [
+ name for name, t in all_cols2_typed
+ if _is_numeric_type(t) and not _is_id_field(name) and name != x_field
+ ]
+ if not f2:
+ print(f"Error: no y-fields for '{args.table2}'. Use --fields2.", file=sys.stderr)
+ sys.exit(1)
+ y_fields2 = f2
+ sel2 = ([x_field] + f2) if x_field else f2
+ where2 = getattr(args, "where2", None)
+ sql2 = _build_poll_query(args.table2, sel2, where2, limit, x_field, start_time=start_time)
+ if args.verbose:
+ print(f"Second source (table): {sql2} fields: {', '.join(y_fields2)}")
+
+ if args.verbose:
+ print(f"Query: {sql}")
+
+ count = args.count if args.count and args.count > 0 else None
+
+ if args.plot == "table":
+ if sql2:
+ print(
+ "Warning: --table2/--query2 is not supported with --plot table; "
+ "ignoring second source.",
+ file=sys.stderr,
+ )
+ _poll_table(
+ con, sql, x_field, y_fields, opts,
+ args.interval, count, args.verbose,
+ )
+ elif args.plot == "plotly":
+ if sql2:
+ _poll_plotly_multi(
+ con, sql, sql2, x_field, y_fields, y_fields2, opts,
+ args.interval, count, args.output_html, args.verbose,
+ )
+ else:
+ _poll_plotly(
+ con, sql, x_field, y_fields, opts,
+ args.interval, count, args.output_html, args.verbose,
+ )
+ elif args.plot == "textual":
+ if sql2:
+ print(
+ "Warning: --table2/--query2 is not supported with --plot textual; "
+ "ignoring second source.",
+ file=sys.stderr,
+ )
+ _poll_textual(
+ con, sql, x_field, y_fields, opts,
+ args.interval, count, args.verbose,
+ )
+ elif args.plot == "dash":
+ if sql2:
+ _poll_dash_multi(
+ con, sql, sql2, x_field, y_fields, y_fields2, opts,
+ args.interval, count, args.dash_host, args.dash_port, args.verbose,
+ )
+ else:
+ _poll_dash(
+ con, sql, x_field, y_fields, opts,
+ args.interval, count, args.dash_host, args.dash_port, args.verbose,
+ )
+ else:
+ if sql2:
+ _poll_matplotlib_multi(
+ con, sql, sql2, x_field, y_fields, y_fields2, opts,
+ args.interval, count, args.verbose,
+ )
+ else:
+ _poll_matplotlib(
+ con, sql, x_field, y_fields, opts,
+ args.interval, count, args.verbose,
+ )
+
+
+def mode_plot(args: argparse.Namespace) -> None:
+ """Fetch MySQL data once and display selected fields as a static chart."""
+ opts = _parse_plot_options(args.plot_options)
+
+ if args.plot == "textual":
+ print("Error: --plot textual is not supported in plot mode.", file=sys.stderr)
+ sys.exit(1)
+
+ dsn = _build_dsn(args.host, args.port, args.user, args.password, args.database)
+
+ con = duckdb.connect()
+ _load_mysql_extension(con, args.verbose)
+ _attach_mysql(con, dsn, args.verbose)
+
+ if args.list_tables:
+ tables = list_mysql_tables(con, args.database)
+ print(f"Tables in '{args.database}' ({len(tables)}):")
+ for t in tables:
+ print(f" {t}")
+ return
+
+ if args.query:
+ # ── raw-query path ──────────────────────────────────────────────────
+ sql = args.query
+
+ rel = con.execute(sql)
+ result_cols = [(desc[0], desc[1]) for desc in rel.description]
+ result_col_names = [c[0] for c in result_cols]
+
+ if args.list_fields:
+ print("Columns returned by query:")
+ for name, col_type in result_cols:
+ if _is_numeric_type(col_type):
+ marker = " *"
+ elif _is_timestamp_type(col_type):
+ marker = " @"
+ else:
+ marker = ""
+ print(f" {name:<30} {col_type}{marker}")
+ print("(* = numeric / y-axis @ = timestamp / x-axis)")
+ return
+
+ x_field = args.x_field or _auto_x_field(result_cols)
+ if x_field and x_field not in result_col_names:
+ print(f"Error: x-field '{x_field}' not in query result columns.", file=sys.stderr)
+ sys.exit(1)
+ if x_field and not args.x_field and args.verbose:
+ print(f"Auto-selected x-axis: {x_field}")
+
+ requested = args.fields or []
+ if requested:
+ unknown = set(requested) - set(result_col_names)
+ if unknown:
+ print(f"Error: unknown column(s) in query result: {', '.join(sorted(unknown))}", file=sys.stderr)
+ sys.exit(1)
+ y_fields = [f for f in requested if f != x_field]
+ else:
+ numeric_names = [c[0] for c in result_cols if _is_numeric_type(c[1]) and not _is_id_field(c[0])]
+ y_fields = [f for f in numeric_names if f != x_field]
+ if not y_fields:
+ print("Error: no numeric columns in query result. Use --fields to specify columns explicitly.", file=sys.stderr)
+ sys.exit(1)
+ if args.verbose:
+ print(f"Auto-selected y-fields: {', '.join(y_fields)}")
+
+ else:
+ # ── single-table path ───────────────────────────────────────────────
+ all_cols_raw = describe_table(con, args.table)
+ all_col_names = [c[0] for c in all_cols_raw]
+ all_cols_typed = [(c[0], c[1]) for c in all_cols_raw]
+ numeric_cols = list_numeric_columns(con, args.table)
+
+ if args.list_fields:
+ print(f"Columns in '{args.table}':")
+ for name, col_type in all_cols_typed:
+ if _is_numeric_type(col_type):
+ marker = " *"
+ elif _is_timestamp_type(col_type):
+ marker = " @"
+ else:
+ marker = ""
+ print(f" {name:<30} {col_type}{marker}")
+ print("(* = numeric / y-axis @ = timestamp / x-axis)")
+ return
+
+ x_field = args.x_field or _auto_x_field(all_cols_typed)
+ if x_field and not args.x_field and args.verbose:
+ print(f"Auto-selected x-axis: {x_field}")
+
+ requested = args.fields or []
+ if requested:
+ unknown = set(requested) - set(all_col_names)
+ if unknown:
+ print(f"Error: unknown column(s) in {args.table}: {', '.join(sorted(unknown))}", file=sys.stderr)
+ sys.exit(1)
+ fields = [f for f in requested if f != x_field]
+ else:
+ fields = [name for name, _ in numeric_cols if name != x_field and not _is_id_field(name)]
+ if not fields:
+ print(f"Error: no numeric columns found in '{args.table}'. Use --fields to specify columns explicitly.", file=sys.stderr)
+ sys.exit(1)
+ if args.verbose:
+ print(f"Auto-selected y-fields: {', '.join(fields)}")
+
+ if x_field:
+ select_fields = [x_field] + fields
+ else:
+ select_fields = fields
+
+ y_fields = fields
+
+ if not y_fields:
+ print("Error: no y-fields to plot.", file=sys.stderr)
+ sys.exit(1)
+
+ limit = args.limit if args.limit is not None else 0
+ sql = _build_poll_query(args.table, select_fields, args.where, limit, x_field)
+
+ if args.verbose:
+ print(f"Query: {sql}")
+
+ if args.plot == "plotly":
+ _plot_static_plotly(
+ con, sql, x_field, y_fields, opts,
+ args.output_html, args.verbose,
+ )
+ elif args.plot == "dash":
+ _plot_static_dash(
+ con, sql, x_field, y_fields, opts,
+ args.dash_host, args.dash_port, args.verbose,
+ )
+ else:
+ _plot_static_matplotlib(
+ con, sql, x_field, y_fields, opts, args.verbose,
+ )
+
+
+# ---------------------------------------------------------------------------
+# CLI
+# ---------------------------------------------------------------------------
+
+
+def parse_args() -> argparse.Namespace:
+ """Parse and validate command-line arguments.
+
+ Returns
+ -------
+ argparse.Namespace
+ Validated arguments with connection parameters resolved from
+ CLI flags → env vars → built-in defaults (highest priority first).
+ """
+ parser = argparse.ArgumentParser(
+ description="Connect DuckDB to a remote MySQL server.",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=(
+ "Parameters can also be set via environment variables (e.g. direnv):\n"
+ " MYSQL_HOST, MYSQL_PORT, MYSQL_USER, MYSQL_PASSWORD, MYSQL_DB\n"
+ " MYSQL_OUTPUT, MYSQL_OUTPUT_DIR\n\n"
+ "Examples:\n"
+ " %(prog)s --mode live --host db.example.com --user admin"
+ " --password secret --database magnetdb\n"
+ " %(prog)s --mode export --format csv --output-dir ./out"
+ " --host db.example.com --user admin --password secret"
+ " --database magnetdb\n"
+ " %(prog)s --mode poll --table measurements --fields t Icoil Ucoil"
+ " --x-field t --interval 5 --plot matplotlib"
+ " --host db.example.com --user admin --password secret"
+ " --database magnetdb\n"
+ " %(prog)s --mode view --table measurements --limit 50"
+ " --host db.example.com --user admin --password secret"
+ " --database magnetdb\n"
+ ),
+ )
+
+ parser.add_argument(
+ "--mode",
+ choices=["live", "export", "poll", "plot", "view"],
+ default="live",
+ help=(
+ "live: print schema (default); export: copy tables; "
+ "poll: live chart; plot: one-shot static chart; view: tabular table display"
+ ),
+ )
+
+ # Connection parameters
+ conn = parser.add_argument_group("MySQL connection")
+ conn.add_argument(
+ "--host",
+ default=_env("MYSQL_HOST", _DEFAULT_HOST),
+ metavar="HOST",
+ help=f"MySQL host (env: MYSQL_HOST, default: {_DEFAULT_HOST})",
+ )
+ conn.add_argument(
+ "--port",
+ type=int,
+ default=int(_env("MYSQL_PORT", str(_DEFAULT_PORT))),
+ metavar="PORT",
+ help=f"MySQL port (env: MYSQL_PORT, default: {_DEFAULT_PORT})",
+ )
+ conn.add_argument(
+ "--user",
+ default=_env("MYSQL_USER"),
+ metavar="USER",
+ help="MySQL user (env: MYSQL_USER, required)",
+ )
+ conn.add_argument(
+ "--password",
+ default=_env("MYSQL_PASSWORD"),
+ metavar="PASSWORD",
+ help="MySQL password (env: MYSQL_PASSWORD, required)",
+ )
+ conn.add_argument(
+ "--database",
+ default=_env("MYSQL_DB"),
+ metavar="DATABASE",
+ help="MySQL database name (env: MYSQL_DB, required)",
+ )
+
+ # Export options
+ exp = parser.add_argument_group("export options (--mode export only)")
+ exp.add_argument(
+ "--format",
+ choices=["csv", "parquet", "duckdb"],
+ default="csv",
+ dest="fmt",
+ metavar="{csv,parquet,duckdb}",
+ help="output format (default: csv)",
+ )
+ exp.add_argument(
+ "--output",
+ default=_env("MYSQL_OUTPUT", _DEFAULT_OUTPUT),
+ metavar="FILE",
+ help=f"DuckDB output file for --format duckdb "
+ f"(env: MYSQL_OUTPUT, default: {_DEFAULT_OUTPUT})",
+ )
+ exp.add_argument(
+ "--output-dir",
+ default=_env("MYSQL_OUTPUT_DIR", _DEFAULT_OUTPUT_DIR),
+ metavar="DIR",
+ help="output directory for CSV/Parquet files "
+ "(env: MYSQL_OUTPUT_DIR, default: current dir)",
+ )
+ exp.add_argument(
+ "--tables",
+ nargs="+",
+ metavar="TABLE",
+ help="subset of tables to export (default: all)",
+ )
+ exp.add_argument(
+ "--export-fields",
+ nargs="+",
+ metavar="COL",
+ dest="export_fields",
+ help="columns to include in the export; requires exactly one table in --tables",
+ )
+ exp.add_argument(
+ "--time-field",
+ metavar="COL",
+ dest="time_field",
+ help=(
+ "TIMESTAMP column used for --start/--end filtering "
+ "(auto-detected from schema if omitted)"
+ ),
+ )
+ exp.add_argument(
+ "--start",
+ metavar="DATETIME",
+ help="start of time range, ISO 8601, e.g. '2024-01-15 08:00:00'",
+ )
+ exp.add_argument(
+ "--end",
+ metavar="DATETIME",
+ help="end of time range, ISO 8601, e.g. '2024-01-15 20:00:00'",
+ )
+
+ # Poll / plot options
+ poll = parser.add_argument_group("poll/plot options (--mode poll or --mode plot)")
+ poll.add_argument(
+ "--table",
+ metavar="TABLE",
+ help="MySQL table to poll. Mutually exclusive with --query.",
+ )
+ poll.add_argument(
+ "--query",
+ metavar="SQL",
+ help=(
+ "Raw SELECT query to run instead of --table/--fields. "
+ "Must reference tables as mysqldb.. "
+ "Use --fields to choose which result columns to plot, "
+ "--x-field for the x-axis column. "
+ "Example: \"SELECT t, m.Icoil, s.temp "
+ "FROM mysqldb.meas m JOIN mysqldb.sensors s ON m.id=s.mid "
+ "ORDER BY t LIMIT 500\""
+ ),
+ )
+ poll.add_argument(
+ "--list-tables",
+ action="store_true",
+ dest="list_tables",
+ help="print all tables in the database and exit, no polling",
+ )
+ poll.add_argument(
+ "--list-fields",
+ action="store_true",
+ dest="list_fields",
+ help="print numeric (plottable) columns of --table and exit, no polling",
+ )
+ poll.add_argument(
+ "--fields",
+ nargs="+",
+ metavar="COL",
+ help="columns to extract and plot (default: all columns)",
+ )
+ poll.add_argument(
+ "--x-field",
+ metavar="COL",
+ help="column to use as x-axis (default: row index)",
+ )
+ poll.add_argument(
+ "--where",
+ metavar="EXPR",
+ help="SQL WHERE clause filter (e.g. \"status='active'\")",
+ )
+ poll.add_argument(
+ "--limit",
+ type=int,
+ default=None,
+ metavar="N",
+ help="max rows fetched (poll default: 200; plot default: 0 = all rows; 0 = no cap)",
+ )
+ poll.add_argument(
+ "--interval",
+ type=float,
+ default=5.0,
+ metavar="SECONDS",
+ help="seconds between polls (default: 5)",
+ )
+ poll.add_argument(
+ "--count",
+ type=int,
+ default=0,
+ metavar="N",
+ help="number of polls to run (default: 0 = run until Ctrl+C)",
+ )
+ poll.add_argument(
+ "--plot",
+ choices=["table", "matplotlib", "plotly", "textual", "dash"],
+ default="matplotlib",
+ help=(
+ "poll backend: matplotlib (default, live chart), "
+ "table (rich terminal table), plotly (auto-refresh HTML), "
+ "textual (TUI sparklines), dash (web app)"
+ ),
+ )
+ poll.add_argument(
+ "--table2",
+ metavar="TABLE",
+ dest="table2",
+ help=(
+ "Second MySQL table to poll simultaneously. "
+ "Its fields are shown in a separate subplot sharing the same x-axis. "
+ "Mutually exclusive with --query2. "
+ "Supported backends: matplotlib, plotly, dash."
+ ),
+ )
+ poll.add_argument(
+ "--query2",
+ metavar="SQL",
+ dest="query2",
+ help=(
+ "Raw SELECT query for the second subplot. "
+ "Must reference tables as mysqldb.. "
+ "Mutually exclusive with --table2."
+ ),
+ )
+ poll.add_argument(
+ "--fields2",
+ nargs="+",
+ metavar="COL",
+ dest="fields2",
+ help="Columns to plot from the second table/query (default: all numeric).",
+ )
+ poll.add_argument(
+ "--where2",
+ metavar="EXPR",
+ dest="where2",
+ help="SQL WHERE clause for the second table (--table2 only).",
+ )
+ poll.add_argument(
+ "--plot-options",
+ metavar="JSON",
+ dest="plot_options",
+ help=(
+ 'JSON object with plot style options. '
+ 'Keys: '
+ 'type (line|scatter|bar, default line); '
+ 'layout (subplots|overlay|groups, default subplots); '
+ 'groups (list of field-name lists, used when layout=groups, '
+ 'e.g. [["Icoil","Ucoil"],["tsb","teb"]]); '
+ 'figsize ([w,h] inches, matplotlib only, default [12,6]); '
+ 'colors (list of color strings, one per y-field); '
+ 'font (font family, e.g. "Arial"); '
+ 'fontsize (base font size in points, e.g. 12). '
+ 'Example: \'{"layout":"groups","groups":[["Icoil","Ucoil"],["tsb"]],'
+ '"font":"Arial","fontsize":11}\''
+ ),
+ )
+ poll.add_argument(
+ "--output-html",
+ metavar="FILE",
+ default="poll_output.html",
+ dest="output_html",
+ help="HTML output path for --plot plotly (default: poll_output.html)",
+ )
+ poll.add_argument(
+ "--dash-host",
+ metavar="HOST",
+ default="127.0.0.1",
+ dest="dash_host",
+ help="host for the Dash web server (default: 127.0.0.1)",
+ )
+ poll.add_argument(
+ "--dash-port",
+ type=int,
+ metavar="PORT",
+ default=8050,
+ dest="dash_port",
+ help="port for the Dash web server (default: 8050)",
+ )
+
+ parser.add_argument("-v", "--verbose", action="store_true", help="verbose output")
+
+ args = parser.parse_args()
+
+ missing = [
+ name
+ for name, val in [
+ ("--user / MYSQL_USER", args.user),
+ ("--password / MYSQL_PASSWORD", args.password),
+ ("--database / MYSQL_DB", args.database),
+ ]
+ if not val
+ ]
+ if missing:
+ parser.error(
+ "Missing required connection parameter(s): "
+ + ", ".join(missing)
+ )
+
+ if args.mode in ("poll", "plot", "view"):
+ if args.table and args.query:
+ parser.error("--table and --query are mutually exclusive")
+
+ if args.mode == "poll":
+ if not args.table and not args.query and not args.list_tables:
+ parser.error("--mode poll requires --table TABLE or --query SQL (or --list-tables)")
+ table2 = getattr(args, "table2", None)
+ query2 = getattr(args, "query2", None)
+ if table2 and query2:
+ parser.error("--table2 and --query2 are mutually exclusive")
+ if (table2 or query2) and not (args.table or args.query):
+ parser.error("--table2/--query2 require --table or --query for the first source")
+
+ if args.mode == "plot":
+ if not args.table and not args.query and not args.list_tables:
+ parser.error("--mode plot requires --table TABLE or --query SQL (or --list-tables)")
+
+ if args.mode == "view":
+ if not args.table and not args.query:
+ parser.error("--mode view requires --table TABLE or --query SQL")
+
+ return args
+
+
+def main() -> None:
+ args = parse_args()
+ try:
+ if args.mode == "live":
+ mode_live(args)
+ elif args.mode == "export":
+ mode_export(args)
+ elif args.mode == "view":
+ mode_view(args)
+ elif args.mode == "plot":
+ mode_plot(args)
+ else:
+ mode_poll(args)
+ except duckdb.Error as e:
+ print(f"DuckDB error: {e}", file=sys.stderr)
+ sys.exit(1)
+ except OSError as e:
+ print(f"I/O error: {e}", file=sys.stderr)
+ sys.exit(1)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/to_duckdb/populate.py b/to_duckdb/populate.py
new file mode 100644
index 0000000..a74ccd7
--- /dev/null
+++ b/to_duckdb/populate.py
@@ -0,0 +1,297 @@
+"""
+populate.py
+===========
+File-system scanning and operationaldata registration for pupitre TXT
+and TDMS archive files.
+
+Used by ``magnetdb.py populate operationaldata`` and
+``magnetdb.py populate experiments``.
+
+Public API
+----------
+ TDMS_TYPES list of known TDMS file-type names
+ ALL_POPULATE_TYPES TDMS_TYPES + ["Pupitre"]
+ _RECORDS_BASE default filesystem root for all records
+ _SRV_SUBDIR default subdirectory for pupitre TXT files
+ _PBSURV default subdirectory for TDMS files
+
+ load_site(site_name, db_path) → dict | None
+ find_and_register_pupitre(...) → list[(Path, datetime)]
+ find_and_register_tdms(...) → list[(Path, datetime, str)]
+"""
+
+import re
+from datetime import datetime
+from pathlib import Path
+
+try:
+ from zoneinfo import ZoneInfo
+except ImportError:
+ from backports.zoneinfo import ZoneInfo # type: ignore[no-redef]
+
+import duckdb
+
+from schema import ensure_schema
+
+# ---------------------------------------------------------------------------
+# Shared constants
+# ---------------------------------------------------------------------------
+
+_RECORDS_BASE = Path("/mnt/LNCMIG-Data/records")
+_SRV_SUBDIR = "srv-data-install" # pupitre TXT: records_base / srv_subdir / housing
+_PBSURV = "pbsurv" # TDMS files: records_base / pbsurv / housing / subdir
+FILE_TZ = ZoneInfo("Europe/Paris")
+
+# ---------------------------------------------------------------------------
+# TDMS type registry
+# ---------------------------------------------------------------------------
+
+# subdir name on disk per logical type
+_TDMS_SUBDIR_NAMES: dict[str, str] = {
+ "Overview": "Overview",
+ "Archive": "Fichiers_Archive",
+ "Spike": "Fichiers_Spike",
+ "Default": "Fichiers_Default",
+}
+TDMS_TYPES = list(_TDMS_SUBDIR_NAMES)
+
+# Per-type: (compiled pattern, strptime format)
+# Overview/Archive: YYDDMM-HHMM (French day-first, minute precision)
+# Spike/Default: YYMMDD-HHMMSS (ISO order, second precision)
+_TDMS_TS_PATTERNS: dict[str, tuple[re.Pattern, str]] = {
+ "Overview": (re.compile(r"(\d{6}-\d{4})\.tdms$", re.IGNORECASE), "%y%m%d-%H%M"),
+ "Archive": (re.compile(r"(\d{6}-\d{4})\.tdms$", re.IGNORECASE), "%y%m%d-%H%M"),
+ "Spike": (re.compile(r"_Spikes_(\d{6}-\d{6})", re.IGNORECASE), "%y%m%d-%H%M%S"),
+ "Default": (re.compile(r"_Default_(\d{6}-\d{6})", re.IGNORECASE), "%y%m%d-%H%M%S"),
+}
+
+# ---------------------------------------------------------------------------
+# Pupitre filename pattern "YYYY.MM.DD - HH:MM:SS.txt"
+# ---------------------------------------------------------------------------
+
+_PUPITRE_FNAME_RE = re.compile(
+ r"(\d{4}\.\d{2}\.\d{2} - \d{2}:\d{2}:\d{2})\.txt$",
+ re.IGNORECASE,
+)
+_PUPITRE_TS_FMT = "%Y.%m.%d - %H:%M:%S"
+
+# Convenience aggregate used by magnetdb.py --type filter
+ALL_POPULATE_TYPES = TDMS_TYPES + ["Pupitre"]
+
+# ---------------------------------------------------------------------------
+# Shared helpers
+# ---------------------------------------------------------------------------
+
+def as_aware(ts: datetime | None, tz: ZoneInfo) -> datetime | None:
+ """Attach *tz* to a naive datetime (e.g. returned by DuckDB), or re-express."""
+ if ts is None:
+ return None
+ return ts.replace(tzinfo=tz) if ts.tzinfo is None else ts.astimezone(tz)
+
+
+def load_site(site_name: str, db_path: str) -> dict | None:
+ """Return the site row as a dict, or None if not found."""
+ with duckdb.connect(db_path, read_only=True) as con:
+ row = con.execute(
+ "SELECT name, housing, status, commissioned_at, decommissioned_at "
+ "FROM sites WHERE name = ?",
+ [site_name],
+ ).fetchone()
+ if row is None:
+ return None
+ return {
+ "name": row[0],
+ "housing": row[1],
+ "status": row[2],
+ "commissioned_at": row[3],
+ "decommissioned_at": row[4],
+ }
+
+
+def _insert_operationaldata(con, site_name: str, fpath: Path, file_type: str) -> bool:
+ """Insert one file record. Returns True if newly inserted, False if already present."""
+ already = con.execute(
+ "SELECT COUNT(*) FROM operationaldata WHERE file = ?", [str(fpath)]
+ ).fetchone()[0]
+ if already:
+ return False
+ con.execute(
+ "INSERT INTO operationaldata (name, description, file, site_name, type, status) "
+ "VALUES (?, '', ?, ?, ?, 'pending')",
+ [fpath.stem, str(fpath), site_name, file_type],
+ )
+ return True
+
+
+def _site_window(
+ site: dict, db_tz: ZoneInfo
+) -> tuple[datetime | None, datetime | None]:
+ """Return (t_start, t_end) both expressed in FILE_TZ (Europe/Paris)."""
+ t_start = as_aware(site["commissioned_at"], db_tz)
+ t_end = as_aware(site["decommissioned_at"], db_tz)
+ if t_start is not None:
+ t_start = t_start.astimezone(FILE_TZ)
+ if t_end is not None:
+ t_end = t_end.astimezone(FILE_TZ)
+ return t_start, t_end
+
+
+# ---------------------------------------------------------------------------
+# Pupitre
+# ---------------------------------------------------------------------------
+
+def parse_pupitre_file_ts(filename: str) -> datetime | None:
+ """Return a timezone-aware datetime parsed from a pupitre filename, or None."""
+ m = _PUPITRE_FNAME_RE.search(filename)
+ if not m:
+ return None
+ try:
+ naive = datetime.strptime(m.group(1), _PUPITRE_TS_FMT)
+ return naive.replace(tzinfo=FILE_TZ)
+ except ValueError:
+ return None
+
+
+def find_and_register_pupitre(
+ site: dict,
+ db_path: str,
+ db_tz: ZoneInfo,
+ dry_run: bool,
+ records_base: Path = _RECORDS_BASE,
+ srv_subdir: str = _SRV_SUBDIR,
+) -> list[tuple[Path, datetime]]:
+ """Scan for pupitre TXT files in the site's operational window.
+
+ Returns matched (path, timestamp) pairs. Writes to operationaldata
+ unless *dry_run* is True.
+ """
+ housing = site["housing"]
+ if not housing:
+ print(f"[WARN] site '{site['name']}' has no housing value.")
+ return []
+
+ pupitre_dir = records_base / srv_subdir / housing
+ if not pupitre_dir.is_dir():
+ print(f"[WARN] pupitre directory not found: {pupitre_dir}")
+ return []
+
+ t_start, t_end = _site_window(site, db_tz)
+
+ matches: list[tuple[Path, datetime]] = []
+ for fpath in sorted(pupitre_dir.glob("*.txt")):
+ ts = parse_pupitre_file_ts(fpath.name)
+ if ts is None:
+ continue
+ if t_start is not None and ts < t_start:
+ continue
+ if t_end is not None and ts > t_end:
+ continue
+ matches.append((fpath, ts))
+
+ print(f"[OK] {pupitre_dir}/ — {len(matches)} file(s) matched")
+
+ if matches and not dry_run:
+ with duckdb.connect(db_path) as con:
+ ensure_schema(con)
+ new_count = sum(
+ _insert_operationaldata(con, site["name"], fpath, "Pupitre")
+ for fpath, _ in matches
+ )
+ skipped = len(matches) - new_count
+ print(
+ f"\noperationaldata: inserted {new_count} new row(s)"
+ + (f", {skipped} already present." if skipped else ".")
+ )
+
+ return matches
+
+
+# ---------------------------------------------------------------------------
+# TDMS
+# ---------------------------------------------------------------------------
+
+def parse_tdms_file_ts(filename: str, file_type: str) -> datetime | None:
+ """Return a timezone-aware datetime parsed from a TDMS filename, or None."""
+ pattern, fmt = _TDMS_TS_PATTERNS[file_type]
+ m = pattern.search(filename)
+ if not m:
+ return None
+ try:
+ naive = datetime.strptime(m.group(1), fmt)
+ return naive.replace(tzinfo=FILE_TZ)
+ except ValueError:
+ return None
+
+
+def scan_tdms_subdir(
+ subdir: Path,
+ file_type: str,
+ t_start: datetime | None,
+ t_end: datetime | None,
+) -> list[tuple[Path, datetime, str]]:
+ """Scan one TDMS subdirectory; return matching (path, timestamp, type) tuples."""
+ if not subdir.is_dir():
+ return []
+ matches = []
+ for fpath in sorted(subdir.glob("*.tdms")):
+ ts = parse_tdms_file_ts(fpath.name, file_type)
+ if ts is None:
+ continue
+ if t_start is not None and ts < t_start:
+ continue
+ if t_end is not None and ts > t_end:
+ continue
+ matches.append((fpath, ts, file_type))
+ return matches
+
+
+def find_and_register_tdms(
+ site: dict,
+ db_path: str,
+ db_tz: ZoneInfo,
+ dry_run: bool,
+ type_filter: list[str] | None = None,
+ records_base: Path = _RECORDS_BASE,
+ pbsurv: str = _PBSURV,
+) -> list[tuple[Path, datetime, str]]:
+ """Scan for TDMS files in the site's operational window.
+
+ Returns matched (path, timestamp, type) triples. Writes to operationaldata
+ unless *dry_run* is True.
+ """
+ housing = site["housing"]
+ if not housing:
+ print(f"[WARN] site '{site['name']}' has no housing value.")
+ return []
+
+ t_start, t_end = _site_window(site, db_tz)
+
+ active_types = type_filter if type_filter else TDMS_TYPES
+ matches: list[tuple[Path, datetime, str]] = []
+
+ pbsurv_dir = records_base / pbsurv
+ for file_type in active_types:
+ subdir = pbsurv_dir / housing / _TDMS_SUBDIR_NAMES[file_type]
+ found = scan_tdms_subdir(subdir, file_type, t_start, t_end)
+ if not subdir.is_dir():
+ print(f"[SKIP] {subdir}/ not found")
+ elif not found:
+ print(f"[INFO] {subdir}/ — no matching files")
+ else:
+ print(f"[OK] {subdir}/ — {len(found)} file(s)")
+ matches.extend(found)
+
+ if matches and not dry_run:
+ with duckdb.connect(db_path) as con:
+ ensure_schema(con)
+ new_count = sum(
+ _insert_operationaldata(con, site["name"], fpath, file_type)
+ for fpath, _, file_type in matches
+ )
+ skipped = len(matches) - new_count
+ print(
+ f"\noperationaldata: inserted {new_count} new row(s)"
+ + (f", {skipped} already present." if skipped else ".")
+ )
+
+ return matches
diff --git a/to_duckdb/pytest.ini b/to_duckdb/pytest.ini
new file mode 100644
index 0000000..50c3053
--- /dev/null
+++ b/to_duckdb/pytest.ini
@@ -0,0 +1,5 @@
+[pytest]
+testpaths = tests
+pythonpath = .
+markers =
+ integration: mark test as requiring a live MySQL server (set MYSQL_TEST_HOST/USER/PASSWORD/DB)
diff --git a/to_duckdb/requirements.txt b/to_duckdb/requirements.txt
new file mode 100644
index 0000000..a6776e6
--- /dev/null
+++ b/to_duckdb/requirements.txt
@@ -0,0 +1,55 @@
+# to_duckdb — Python dependencies
+# Install with: pip install -r requirements.txt
+#
+# ── magnettools ───────────────────────────────────────────────────────────────
+# magnettools is a pybind11 C++ extension. Two installation paths are supported:
+#
+# Option A — Debian package (no build required, recommended for most users):
+# The Debian package python3-magnettools is already installed at system level.
+# Create the venv WITH --system-site-packages so Python picks it up:
+# python3 -m venv --system-site-packages venv
+# pip install -r requirements.txt # (no magnettools entry needed here)
+#
+# Option B — Local source build from ../my-magnettools/Python:
+# Requires the C++ dev headers first (one-time, needs sudo):
+# sudo apt install libmagnettools-dev
+# Then uncomment the line below and install normally into any venv:
+# python3 -m venv venv
+# pip install -r requirements.txt
+#
+# -e ../../my-magnettools/Python
+#
+# ── duckdb CLI ────────────────────────────────────────────────────────────────
+# duckdb-cli is a standalone binary, not a pip package.
+# Install from https://duckdb.org/docs/installation or:
+# sudo apt install duckdb (if available in your distro)
+#
+# ── Local packages (editable installs from sibling directories) ───────────────
+-e ../python_magnetgeo
+-e ../python_magnetcooling
+-e ../python_magnetrun
+-e ../python_magnetsetup
+
+# Core data stack
+duckdb
+numpy
+pandas
+pyyaml
+
+# Plotting
+matplotlib
+
+# Rainflow fatigue cycle counting (tutorials/stress_map.py fatigue subcommand)
+rainflow
+
+# Parquet I/O with column-level metadata (compute_hoop_stats.py)
+pyarrow
+
+# Testing
+pytest
+
+# Notebook / interactive UI (optional)
+marimo
+
+# Interactive UI for database management (optional, but recommended for ease of use)
+duckdb-cli
\ No newline at end of file
diff --git a/to_duckdb/schema.py b/to_duckdb/schema.py
new file mode 100644
index 0000000..5595a85
--- /dev/null
+++ b/to_duckdb/schema.py
@@ -0,0 +1,335 @@
+"""
+schema.py
+=========
+Canonical DuckDB schema for the student magnetdb.
+Import ``SCHEMA_SQL`` or call ``ensure_schema(con)`` from any module that
+needs to create or migrate the database.
+"""
+
+COIL_TYPES: frozenset[str] = frozenset({"helix", "bitter"})
+
+SCHEMA_SQL = """
+CREATE TABLE IF NOT EXISTS materials (
+ name VARCHAR PRIMARY KEY,
+ description VARCHAR,
+ nuance VARCHAR,
+ t_ref DOUBLE,
+ volumic_mass DOUBLE,
+ specific_heat DOUBLE,
+ alpha DOUBLE,
+ electrical_conductivity DOUBLE,
+ thermal_conductivity DOUBLE,
+ magnet_permeability DOUBLE,
+ young DOUBLE,
+ poisson DOUBLE,
+ expansion_coefficient DOUBLE,
+ rpe DOUBLE
+);
+
+CREATE TABLE IF NOT EXISTS parts (
+ name VARCHAR PRIMARY KEY,
+ type VARCHAR,
+ status VARCHAR,
+ material_name VARCHAR REFERENCES materials(name),
+ geometry VARCHAR,
+ geometry_data JSON,
+ cad VARCHAR,
+ design_office_reference VARCHAR
+);
+
+CREATE TABLE IF NOT EXISTS magnets (
+ name VARCHAR PRIMARY KEY,
+ type VARCHAR,
+ status VARCHAR,
+ geometry VARCHAR,
+ geometry_data JSON,
+ design_office_reference VARCHAR
+);
+
+-- idempotent migrations for databases that predate geometry_data columns
+ALTER TABLE parts ADD COLUMN IF NOT EXISTS geometry_data JSON;
+ALTER TABLE magnets ADD COLUMN IF NOT EXISTS geometry_data JSON;
+
+CREATE TABLE IF NOT EXISTS magnet_parts (
+ magnet_name VARCHAR REFERENCES magnets(name),
+ part_name VARCHAR REFERENCES parts(name),
+ rank INTEGER,
+ coil_index INTEGER,
+ PRIMARY KEY (magnet_name, part_name)
+);
+
+-- Housing configuration must be created before sites so the FK reference below resolves.
+CREATE TABLE IF NOT EXISTS housing_config (
+ name VARCHAR PRIMARY KEY,
+ coil_assignment MAP(VARCHAR, VARCHAR),
+ formats VARCHAR[],
+ extra_config JSON
+);
+
+CREATE TABLE IF NOT EXISTS sites (
+ name VARCHAR PRIMARY KEY,
+ description VARCHAR,
+ status VARCHAR,
+ housing VARCHAR REFERENCES housing_config(name),
+ commissioned_at TIMESTAMP,
+ decommissioned_at TIMESTAMP
+);
+
+CREATE TABLE IF NOT EXISTS site_magnets (
+ site_name VARCHAR REFERENCES sites(name),
+ magnet_name VARCHAR REFERENCES magnets(name),
+ z_offset DOUBLE DEFAULT 0.0,
+ r_offset DOUBLE DEFAULT 0.0,
+ parallax DOUBLE DEFAULT 0.0,
+ commissioned_at TIMESTAMP,
+ decommissioned_at TIMESTAMP,
+ metadata JSON DEFAULT '{}',
+ PRIMARY KEY (site_name, magnet_name)
+);
+
+-- idempotent migrations for databases that predate SiteMagnet positional fields
+ALTER TABLE site_magnets ADD COLUMN IF NOT EXISTS z_offset DOUBLE DEFAULT 0.0;
+ALTER TABLE site_magnets ADD COLUMN IF NOT EXISTS r_offset DOUBLE DEFAULT 0.0;
+ALTER TABLE site_magnets ADD COLUMN IF NOT EXISTS parallax DOUBLE DEFAULT 0.0;
+ALTER TABLE site_magnets ADD COLUMN IF NOT EXISTS commissioned_at TIMESTAMP;
+ALTER TABLE site_magnets ADD COLUMN IF NOT EXISTS decommissioned_at TIMESTAMP;
+ALTER TABLE site_magnets ADD COLUMN IF NOT EXISTS metadata JSON DEFAULT '{}';
+
+CREATE TABLE IF NOT EXISTS experiments (
+ id INTEGER PRIMARY KEY,
+ name VARCHAR,
+ description VARCHAR,
+ file VARCHAR,
+ site_name VARCHAR REFERENCES sites(name),
+ status VARCHAR DEFAULT 'pending'
+);
+
+CREATE SEQUENCE IF NOT EXISTS operationaldata_id_seq START 1;
+
+CREATE TABLE IF NOT EXISTS operationaldata (
+ id INTEGER PRIMARY KEY DEFAULT nextval('operationaldata_id_seq'),
+ name VARCHAR,
+ description VARCHAR,
+ file VARCHAR UNIQUE,
+ site_name VARCHAR REFERENCES sites(name),
+ type VARCHAR DEFAULT 'Archive',
+ status VARCHAR DEFAULT 'pending'
+);
+
+-- idempotent migration for databases that predate the type column
+ALTER TABLE operationaldata ADD COLUMN IF NOT EXISTS type VARCHAR DEFAULT 'Archive';
+-- idempotent migration: ensure id has the sequence default (fixes DBs created before the DEFAULT was added)
+ALTER TABLE operationaldata ALTER COLUMN id SET DEFAULT nextval('operationaldata_id_seq');
+
+-- One row per processed overview file (OverviewRecord, data attribute excluded).
+-- sources_* columns hold the file-path lists from FileSet.
+-- signatures / sync_info / flow_params / metrics / debitbrut are stored as JSON.
+CREATE TABLE IF NOT EXISTS overview_records (
+ filename VARCHAR PRIMARY KEY,
+ site_name VARCHAR REFERENCES sites(name),
+ housing VARCHAR,
+ mode VARCHAR,
+ t0 TIMESTAMP,
+ duration DOUBLE DEFAULT 0.0,
+ teb DOUBLE DEFAULT 0.0,
+ bp DOUBLE DEFAULT 0.0,
+ sources_overview VARCHAR[],
+ sources_archive VARCHAR[],
+ sources_pupitre VARCHAR[],
+ sources_default VARCHAR[],
+ sources_trigger VARCHAR[],
+ sources_spike VARCHAR[],
+ sources_hybrid_kHz VARCHAR[],
+ sources_hybrid_rms VARCHAR[],
+ sources_hybrid_trigger VARCHAR[],
+ sources_hybrid_vprocess VARCHAR[],
+ sources_pigbrother_runlog VARCHAR[],
+ sources_pupitre_runlog VARCHAR[],
+ signatures JSON DEFAULT '{}',
+ sync_info JSON DEFAULT '{}',
+ flow_params JSON DEFAULT '{}',
+ metrics JSON DEFAULT '{}',
+ debitbrut JSON DEFAULT '{}'
+);
+
+-- idempotent migration for databases that predate site_name
+ALTER TABLE overview_records ADD COLUMN IF NOT EXISTS site_name VARCHAR;
+
+-- ── Operational statistics tables ────────────────────────────────────────────
+
+-- Tracks which operationaldata files have been processed (idempotency guard).
+CREATE TABLE IF NOT EXISTS op_stats_processed (
+ operationaldata_id INTEGER PRIMARY KEY REFERENCES operationaldata(id),
+ processed_at TIMESTAMP DEFAULT now(),
+ n_rows INTEGER,
+ dt_median DOUBLE,
+ bin_config JSON
+);
+
+-- Per-run scalar quantities (not binned).
+-- Intended use cases:
+-- 'energy_j' = sum(Ptot * dt) electricity billing
+-- 'heat_extracted_j' = sum((tsb-teb) * Q_m3s * rho_cp * dt) fatal heat
+-- 'duration_s' = sum(dt) total run length
+-- 'duration_field_on_s' = sum(dt) where Field > threshold magnet-on time
+CREATE TABLE IF NOT EXISTS op_run_scalars (
+ operationaldata_id INTEGER REFERENCES operationaldata(id),
+ channel VARCHAR NOT NULL,
+ value DOUBLE NOT NULL,
+ PRIMARY KEY (operationaldata_id, channel)
+);
+
+-- Site-level field-bin distributions.
+-- One row per (file, field bin, channel).
+-- Channels: 'Pmagnet', 'Ptot', 'tsb', 'teb', 'debitbrut', ...
+-- Derived at query time:
+-- operating time (h) = SUM(sum_dt) / 3600
+-- time-weighted mean = SUM(sum_x_dt) / SUM(sum_dt)
+-- time-weighted stddev = sqrt(SUM(sum_x2_dt)/SUM(sum_dt) - mean^2)
+-- peak value = MAX(max_x)
+CREATE TABLE IF NOT EXISTS op_site_bin_stats (
+ operationaldata_id INTEGER REFERENCES operationaldata(id),
+ field_bin_low DOUBLE NOT NULL,
+ field_bin_high DOUBLE NOT NULL,
+ channel VARCHAR NOT NULL,
+ n_samples BIGINT NOT NULL,
+ sum_dt DOUBLE NOT NULL,
+ sum_x_dt DOUBLE,
+ sum_x2_dt DOUBLE,
+ min_x DOUBLE,
+ max_x DOUBLE,
+ PRIMARY KEY (operationaldata_id, field_bin_low, channel)
+);
+
+-- Per-part field-bin distributions.
+-- One row per (file, part, field bin, channel).
+-- Channels: 'Icoil', 'Ucoil', 'hoop_stress_proxy' (= I^2, proportional to sigma_theta)
+-- Only rows where |Icoil| > current_threshold are included.
+CREATE TABLE IF NOT EXISTS op_part_bin_stats (
+ operationaldata_id INTEGER REFERENCES operationaldata(id),
+ part_name VARCHAR REFERENCES parts(name),
+ field_bin_low DOUBLE NOT NULL,
+ field_bin_high DOUBLE NOT NULL,
+ channel VARCHAR NOT NULL,
+ n_samples BIGINT NOT NULL,
+ sum_dt DOUBLE NOT NULL,
+ sum_x_dt DOUBLE,
+ sum_x2_dt DOUBLE,
+ min_x DOUBLE,
+ max_x DOUBLE,
+ PRIMARY KEY (operationaldata_id, part_name, field_bin_low, channel)
+);
+
+-- ── Experiment statistics tables ─────────────────────────────────────────────
+
+-- Tracks which experiment files have been processed (idempotency guard).
+CREATE TABLE IF NOT EXISTS exp_stats_processed (
+ experiment_id INTEGER PRIMARY KEY REFERENCES experiments(id),
+ processed_at TIMESTAMP DEFAULT now(),
+ n_rows INTEGER,
+ dt_median DOUBLE,
+ bin_config JSON
+);
+
+-- Per-run scalar quantities for experiments (not binned).
+-- Same intended channels as op_run_scalars:
+-- 'energy_j', 'heat_extracted_j', 'duration_s', 'duration_field_on_s'
+CREATE TABLE IF NOT EXISTS exp_run_scalars (
+ experiment_id INTEGER REFERENCES experiments(id),
+ channel VARCHAR NOT NULL,
+ value DOUBLE NOT NULL,
+ PRIMARY KEY (experiment_id, channel)
+);
+
+-- Site-level field-bin distributions for experiments.
+-- One row per (experiment, field bin, channel).
+-- Derived at query time:
+-- operating time (h) = SUM(sum_dt) / 3600
+-- time-weighted mean = SUM(sum_x_dt) / SUM(sum_dt)
+-- time-weighted stddev = sqrt(SUM(sum_x2_dt)/SUM(sum_dt) - mean^2)
+-- peak value = MAX(max_x)
+CREATE TABLE IF NOT EXISTS exp_site_bin_stats (
+ experiment_id INTEGER REFERENCES experiments(id),
+ field_bin_low DOUBLE NOT NULL,
+ field_bin_high DOUBLE NOT NULL,
+ channel VARCHAR NOT NULL,
+ n_samples BIGINT NOT NULL,
+ sum_dt DOUBLE NOT NULL,
+ sum_x_dt DOUBLE,
+ sum_x2_dt DOUBLE,
+ min_x DOUBLE,
+ max_x DOUBLE,
+ PRIMARY KEY (experiment_id, field_bin_low, channel)
+);
+
+-- Per-part field-bin distributions for experiments.
+-- One row per (experiment, part, field bin, channel).
+-- Channels: 'Icoil', 'Ucoil', 'hoop_stress_proxy' (= I^2, proportional to sigma_theta)
+-- Only rows where |Icoil| > current_threshold are included.
+CREATE TABLE IF NOT EXISTS exp_part_bin_stats (
+ experiment_id INTEGER REFERENCES experiments(id),
+ part_name VARCHAR REFERENCES parts(name),
+ field_bin_low DOUBLE NOT NULL,
+ field_bin_high DOUBLE NOT NULL,
+ channel VARCHAR NOT NULL,
+ n_samples BIGINT NOT NULL,
+ sum_dt DOUBLE NOT NULL,
+ sum_x_dt DOUBLE,
+ sum_x2_dt DOUBLE,
+ min_x DOUBLE,
+ max_x DOUBLE,
+ PRIMARY KEY (experiment_id, part_name, field_bin_low, channel)
+);
+
+-- ── Hoop-stress statistics tables ────────────────────────────────────────────
+
+-- Idempotency guard: one row per (experiment, bin_config) pair.
+-- bin_config is the canonical edges string, e.g. "0.0,100.0,200.0,300.0,400.0,500.0,600.0".
+-- Using a composite PK allows re-running with different bin configs without data loss.
+-- parquet_path stores the path to the Parquet file with the full time series.
+CREATE TABLE IF NOT EXISTS hoop_stress_processed (
+ experiment_id INTEGER REFERENCES experiments(id),
+ bin_config VARCHAR NOT NULL,
+ processed_at TIMESTAMP DEFAULT now(),
+ magnet_type VARCHAR NOT NULL,
+ parquet_path VARCHAR,
+ PRIMARY KEY (experiment_id, bin_config)
+);
+
+-- Per-part stress-bin distributions.
+-- One row per (experiment, part_name, stress_bin_low).
+-- Derived at query time:
+-- operating time (h) = SUM(sum_dt) / 3600
+-- time-weighted mean = SUM(sum_x_dt) / SUM(sum_dt)
+-- time-weighted stddev = sqrt(SUM(sum_x2_dt)/SUM(sum_dt) - mean^2)
+-- peak stress = MAX(max_x)
+CREATE TABLE IF NOT EXISTS hoop_stress_bin_stats (
+ experiment_id INTEGER REFERENCES experiments(id),
+ part_name VARCHAR REFERENCES parts(name),
+ stress_bin_low DOUBLE NOT NULL,
+ stress_bin_high DOUBLE NOT NULL,
+ n_samples BIGINT NOT NULL,
+ sum_dt DOUBLE NOT NULL,
+ sum_x_dt DOUBLE,
+ sum_x2_dt DOUBLE,
+ min_x DOUBLE,
+ max_x DOUBLE,
+ PRIMARY KEY (experiment_id, part_name, stress_bin_low)
+);
+
+-- Per-part rainflow fatigue cycle counts.
+-- n_cycles: total number of counted half-cycles (rainflow)
+-- sum_range3: sum of (delta_sigma^3) — S-N fatigue proxy (Miner's rule with m=3)
+CREATE TABLE IF NOT EXISTS hoop_stress_fatigue (
+ experiment_id INTEGER REFERENCES experiments(id),
+ part_name VARCHAR REFERENCES parts(name),
+ n_cycles DOUBLE NOT NULL,
+ sum_range3 DOUBLE NOT NULL,
+ PRIMARY KEY (experiment_id, part_name)
+);
+"""
+
+
+def ensure_schema(con) -> None:
+ """Create all tables and apply idempotent migrations on *con*."""
+ con.execute(SCHEMA_SQL)
diff --git a/to_duckdb/schema_diagram.py b/to_duckdb/schema_diagram.py
new file mode 100644
index 0000000..b646709
--- /dev/null
+++ b/to_duckdb/schema_diagram.py
@@ -0,0 +1,462 @@
+#!/usr/bin/env python3
+"""
+schema_diagram.py
+=================
+Prints a text summary and/or renders a graphical ER diagram of the MagnetDB
+DuckDB schema.
+
+Usage
+-----
+ python schema_diagram.py [--db PATH] [--output PATH] [--text]
+
+Options
+-------
+--db PATH DuckDB file to introspect (default: magnetdb.duckdb in CWD).
+ If the file is not found, the schema is read from schema.py.
+--output PATH Save diagram to this file instead of opening a window
+ (PNG / SVG / PDF; format inferred from extension).
+ Default output name: schema_diagram.png
+--text Print a plain-text schema summary to stdout and exit.
+"""
+
+from __future__ import annotations
+
+import argparse
+import re
+import sys
+from dataclasses import dataclass, field
+from pathlib import Path
+
+
+# ── Data structures ───────────────────────────────────────────────────────────
+
+@dataclass
+class Column:
+ name: str
+ dtype: str
+ is_pk: bool = False
+ fk_table: str | None = None
+
+
+@dataclass
+class Table:
+ name: str
+ columns: list[Column] = field(default_factory=list)
+ pk_columns: list[str] = field(default_factory=list)
+
+
+@dataclass
+class ForeignKey:
+ src_table: str
+ src_col: str
+ dst_table: str
+ dst_col: str
+
+
+# ── Schema loading ─────────────────────────────────────────────────────────────
+
+def _load_from_db(db_path: str) -> tuple[list[Table], list[ForeignKey]]:
+ import duckdb
+ con = duckdb.connect(db_path, read_only=True)
+
+ table_names: list[str] = [
+ r[0] for r in con.execute(
+ "SELECT table_name FROM information_schema.tables "
+ "WHERE table_schema = 'main' AND table_type = 'BASE TABLE' "
+ "ORDER BY table_name"
+ ).fetchall()
+ ]
+
+ # Primary keys
+ pk_map: dict[str, list[str]] = {}
+ for tname, col_names in con.execute(
+ "SELECT table_name, constraint_column_names "
+ "FROM duckdb_constraints() "
+ "WHERE constraint_type = 'PRIMARY KEY' AND schema_name = 'main'"
+ ).fetchall():
+ pk_map[tname] = col_names
+
+ # Foreign keys (constraint_text = "FOREIGN KEY (col) REFERENCES tbl(col)")
+ fks: list[ForeignKey] = []
+ for tname, text in con.execute(
+ "SELECT table_name, constraint_text "
+ "FROM duckdb_constraints() "
+ "WHERE constraint_type = 'FOREIGN KEY' AND schema_name = 'main'"
+ ).fetchall():
+ m = re.match(r"FOREIGN KEY \((\w+)\) REFERENCES (\w+)\((\w+)\)", text or "")
+ if m:
+ fks.append(ForeignKey(tname, m.group(1), m.group(2), m.group(3)))
+
+ # Columns
+ fk_lookup: dict[str, dict[str, str]] = {}
+ for fk in fks:
+ fk_lookup.setdefault(fk.src_table, {})[fk.src_col] = fk.dst_table
+
+ tables: list[Table] = []
+ for tname in table_names:
+ rows = con.execute(
+ "SELECT column_name, data_type "
+ "FROM information_schema.columns "
+ "WHERE table_schema = 'main' AND table_name = ? "
+ "ORDER BY ordinal_position",
+ [tname],
+ ).fetchall()
+ pk_cols = pk_map.get(tname, [])
+ columns = [
+ Column(
+ name=cname,
+ dtype=dtype,
+ is_pk=(cname in pk_cols),
+ fk_table=fk_lookup.get(tname, {}).get(cname),
+ )
+ for cname, dtype in rows
+ ]
+ tables.append(Table(name=tname, columns=columns, pk_columns=pk_cols))
+
+ con.close()
+ return tables, fks
+
+
+def _load_from_sql() -> tuple[list[Table], list[ForeignKey]]:
+ sys.path.insert(0, str(Path(__file__).parent))
+ from schema import SCHEMA_SQL # noqa: PLC0415
+
+ tables: list[Table] = []
+ fks: list[ForeignKey] = []
+
+ for m in re.finditer(
+ r"CREATE TABLE IF NOT EXISTS (\w+)\s*\((.*?)\);",
+ SCHEMA_SQL,
+ re.DOTALL,
+ ):
+ tname = m.group(1)
+ body = m.group(2)
+
+ columns: list[Column] = []
+ composite_pk: list[str] = []
+ inline_pks: list[str] = []
+
+ for raw in body.splitlines():
+ line = raw.strip().rstrip(",")
+ if not line or line.startswith("--"):
+ continue
+
+ cpk = re.match(r"PRIMARY KEY\s*\((.+)\)", line)
+ if cpk:
+ composite_pk = [c.strip() for c in cpk.group(1).split(",")]
+ continue
+
+ cm = re.match(r"(\w+)\s+([\w\[\]()]+(?:\([^)]*\))?)", line)
+ if not cm:
+ continue
+ cname, dtype = cm.group(1), cm.group(2)
+ if cname.upper() in ("PRIMARY", "FOREIGN", "UNIQUE", "CHECK", "CONSTRAINT"):
+ continue
+
+ is_pk = bool(re.search(r"\bPRIMARY KEY\b", line))
+ if is_pk:
+ inline_pks.append(cname)
+
+ ref = re.search(r"REFERENCES\s+(\w+)\((\w+)\)", line)
+ if ref:
+ fks.append(ForeignKey(tname, cname, ref.group(1), ref.group(2)))
+
+ columns.append(Column(
+ name=cname,
+ dtype=dtype,
+ is_pk=is_pk,
+ fk_table=ref.group(1) if ref else None,
+ ))
+
+ pk_cols = composite_pk or inline_pks
+ tables.append(Table(name=tname, columns=columns, pk_columns=pk_cols))
+
+ return tables, fks
+
+
+def load_schema(db_path: str | None) -> tuple[list[Table], list[ForeignKey], str]:
+ if db_path and Path(db_path).exists():
+ return *_load_from_db(db_path), f"live DB: {db_path}"
+ fallback = str(Path(__file__).parent / "magnetdb.duckdb")
+ if Path(fallback).exists():
+ return *_load_from_db(fallback), f"live DB: {fallback}"
+ return *_load_from_sql(), "schema.py (no DB file found)"
+
+
+# ── Text output ───────────────────────────────────────────────────────────────
+
+def print_text(tables: list[Table], fks: list[ForeignKey]) -> None:
+ print(f"MagnetDB DuckDB schema — {len(tables)} tables, {len(fks)} FK relationships")
+ print("=" * 72)
+ for t in tables:
+ print(f"\n [{t.name}]")
+ pk_set = set(t.pk_columns)
+ for c in t.columns:
+ flags: list[str] = []
+ if c.is_pk or c.name in pk_set:
+ flags.append("PK")
+ if c.fk_table:
+ flags.append(f"→ {c.fk_table}")
+ tag = f" [{', '.join(flags)}]" if flags else ""
+ print(f" {c.name:<36} {c.dtype:<22}{tag}")
+ print("\n" + "=" * 72)
+ print("Foreign-key relationships:")
+ for fk in fks:
+ print(f" {fk.src_table}.{fk.src_col:<28} → {fk.dst_table}.{fk.dst_col}")
+
+
+# ── Diagram layout ────────────────────────────────────────────────────────────
+
+# (cx, cy) = top-centre of each table box in data units.
+# Rows are spaced ~3.2 units apart; columns ~4.5 units apart.
+_POSITIONS: dict[str, tuple[float, float]] = {
+ # ── row 0: reference / root ───────────────────────────────────────────────
+ "materials": ( 0.0, 9.6),
+ "housing_config": ( 9.0, 9.6),
+ # ── row 1: core assembly ─────────────────────────────────────────────────
+ "parts": ( 0.0, 6.4),
+ "magnets": ( 4.5, 6.4),
+ "sites": ( 9.0, 6.4),
+ # ── row 2: junction tables ────────────────────────────────────────────────
+ "magnet_parts": ( 2.25, 3.2),
+ "site_magnets": ( 6.75, 3.2),
+ # ── row 3: data / operational ────────────────────────────────────────────
+ "experiments": ( 0.0, 0.0),
+ "operationaldata": ( 4.5, 0.0),
+ "overview_records": ( 9.5, 0.0),
+ # ── row 4: idempotency guards ────────────────────────────────────────────
+ "exp_stats_processed": ( 0.0, -3.2),
+ "op_stats_processed": ( 4.5, -3.2),
+ "hoop_stress_processed": ( 9.0, -3.2),
+ # ── row 5: per-run scalars ───────────────────────────────────────────────
+ "exp_run_scalars": (-2.5, -6.4),
+ "op_run_scalars": ( 2.0, -6.4),
+ # ── row 6: per-bin stats ─────────────────────────────────────────────────
+ "exp_site_bin_stats": (-3.5, -9.6),
+ "exp_part_bin_stats": ( 0.0, -9.6),
+ "op_site_bin_stats": ( 3.5, -9.6),
+ "op_part_bin_stats": ( 6.5, -9.6),
+ "hoop_stress_bin_stats": ( 9.5, -9.6),
+ "hoop_stress_fatigue": (12.5, -9.6),
+}
+
+_COLORS: dict[str, str] = {
+ # reference
+ "materials": "#d4edda",
+ "housing_config": "#d4edda",
+ # assembly
+ "parts": "#cce5ff",
+ "magnets": "#cce5ff",
+ "sites": "#cce5ff",
+ "magnet_parts": "#cce5ff",
+ "site_magnets": "#cce5ff",
+ # data
+ "experiments": "#fff3cd",
+ "operationaldata": "#fff3cd",
+ "overview_records": "#fff3cd",
+}
+_DEFAULT_COLOR = "#f8d7da" # statistics tables
+
+_MAX_COLS = 7 # show at most this many column rows per box
+_TABLE_W = 2.9 # box width in data units
+_ROW_H = 0.27 # height per column row
+_HEADER_H = 0.38 # height of table-name header strip
+
+
+def _box_height(ncols: int) -> float:
+ visible = min(ncols, _MAX_COLS + 1) # +1 for the "… N more" row if needed
+ return _HEADER_H + visible * _ROW_H
+
+
+def _box_rect(cx: float, cy: float, ncols: int) -> tuple[float, float, float, float]:
+ """Return (x0, y0, w, h) where (cx, cy) is the top-centre."""
+ h = _box_height(ncols)
+ return cx - _TABLE_W / 2, cy - h, _TABLE_W, h
+
+
+def _centre(cx: float, cy: float, ncols: int) -> tuple[float, float]:
+ h = _box_height(ncols)
+ return cx, cy - h / 2
+
+
+def draw_diagram(
+ tables: list[Table],
+ fks: list[ForeignKey],
+ output: str | None,
+) -> None:
+ import matplotlib.pyplot as plt
+ import matplotlib.patches as mpatches
+
+ tmap = {t.name: t for t in tables}
+ ncols_map = {t.name: len(t.columns) for t in tables}
+
+ # ── figure bounds ─────────────────────────────────────────────────────────
+ xs = [cx for tname, (cx, cy) in _POSITIONS.items() if tname in tmap]
+ ys = [cy for tname, (cx, cy) in _POSITIONS.items() if tname in tmap]
+ margin = 1.5
+ x0_fig = min(xs) - _TABLE_W / 2 - margin
+ x1_fig = max(xs) + _TABLE_W / 2 + margin
+ y0_fig = min(ys) - max(_box_height(ncols_map.get(t, 1)) for t in _POSITIONS) - margin
+ y1_fig = max(ys) + margin
+
+ fig_w = (x1_fig - x0_fig) * 1.1
+ fig_h = (y1_fig - y0_fig) * 1.1
+ fig, ax = plt.subplots(figsize=(max(fig_w, 20), max(fig_h, 16)))
+ ax.set_xlim(x0_fig, x1_fig)
+ ax.set_ylim(y0_fig, y1_fig)
+ ax.axis("off")
+ ax.set_title(
+ "MagnetDB DuckDB — Entity Relationship Diagram",
+ fontsize=13, fontweight="bold", pad=10,
+ )
+
+ # ── pre-compute box centres for FK arrows ─────────────────────────────────
+ centres: dict[str, tuple[float, float]] = {}
+ for tname, (cx, cy) in _POSITIONS.items():
+ if tname in tmap:
+ centres[tname] = _centre(cx, cy, ncols_map[tname])
+
+ # ── FK arrows (drawn first, underneath boxes) ─────────────────────────────
+ # Structural FKs (darker) vs stats FKs (lighter)
+ _stats_tables = {
+ "op_stats_processed", "exp_stats_processed", "hoop_stress_processed",
+ "op_run_scalars", "exp_run_scalars",
+ "op_site_bin_stats", "op_part_bin_stats",
+ "exp_site_bin_stats", "exp_part_bin_stats",
+ "hoop_stress_bin_stats", "hoop_stress_fatigue",
+ }
+
+ for fk in fks:
+ if fk.src_table not in centres or fk.dst_table not in centres:
+ continue
+ is_stats = fk.src_table in _stats_tables
+ ax.annotate(
+ "",
+ xy=centres[fk.dst_table],
+ xytext=centres[fk.src_table],
+ arrowprops=dict(
+ arrowstyle="-|>",
+ color="#aaaaaa" if is_stats else "#555555",
+ lw=0.7 if is_stats else 1.0,
+ alpha=0.5 if is_stats else 0.8,
+ connectionstyle="arc3,rad=0.15",
+ ),
+ zorder=1,
+ )
+
+ # ── table boxes ───────────────────────────────────────────────────────────
+ for t in tables:
+ if t.name not in _POSITIONS:
+ continue
+ cx, cy = _POSITIONS[t.name]
+ x0, y0, w, h = _box_rect(cx, cy, len(t.columns))
+ color = _COLORS.get(t.name, _DEFAULT_COLOR)
+ pk_set = set(t.pk_columns)
+
+ # outer rounded rectangle
+ rect = mpatches.FancyBboxPatch(
+ (x0, y0), w, h,
+ boxstyle="round,pad=0.04",
+ linewidth=1.2, edgecolor="#333333", facecolor=color,
+ zorder=2,
+ )
+ ax.add_patch(rect)
+
+ # header background
+ header_rect = mpatches.FancyBboxPatch(
+ (x0, y0 + h - _HEADER_H), w, _HEADER_H,
+ boxstyle="round,pad=0.04",
+ linewidth=0, edgecolor="none",
+ facecolor="#00000015",
+ zorder=3,
+ )
+ ax.add_patch(header_rect)
+
+ # table name
+ ax.text(
+ x0 + w / 2, y0 + h - _HEADER_H / 2,
+ t.name,
+ ha="center", va="center",
+ fontsize=7, fontweight="bold",
+ zorder=4,
+ )
+ # header underline
+ ax.plot(
+ [x0, x0 + w], [y0 + h - _HEADER_H, y0 + h - _HEADER_H],
+ color="#333333", lw=0.8, zorder=4,
+ )
+
+ # column rows
+ visible_cols = t.columns[:_MAX_COLS]
+ extra = len(t.columns) - _MAX_COLS
+
+ for i, col in enumerate(visible_cols):
+ row_y = y0 + h - _HEADER_H - (i + 0.55) * _ROW_H
+ flags: list[str] = []
+ if col.is_pk or col.name in pk_set:
+ flags.append("PK")
+ if col.fk_table:
+ flags.append("FK")
+ tag = " [" + ",".join(flags) + "]" if flags else ""
+ ax.text(
+ x0 + 0.06, row_y,
+ col.name + tag,
+ ha="left", va="center", fontsize=5.5, color="#111111", zorder=4,
+ )
+ ax.text(
+ x0 + w - 0.06, row_y,
+ col.dtype,
+ ha="right", va="center", fontsize=4.8, color="#666666", zorder=4,
+ )
+
+ if extra > 0:
+ row_y = y0 + h - _HEADER_H - (_MAX_COLS + 0.55) * _ROW_H
+ ax.text(
+ x0 + w / 2, row_y,
+ f"… {extra} more column{'s' if extra > 1 else ''}",
+ ha="center", va="center", fontsize=5.0,
+ color="#888888", style="italic", zorder=4,
+ )
+
+ # ── legend ────────────────────────────────────────────────────────────────
+ legend_elements = [
+ mpatches.Patch(facecolor="#d4edda", edgecolor="#333333", label="Reference tables"),
+ mpatches.Patch(facecolor="#cce5ff", edgecolor="#333333", label="Assembly tables"),
+ mpatches.Patch(facecolor="#fff3cd", edgecolor="#333333", label="Data tables"),
+ mpatches.Patch(facecolor="#f8d7da", edgecolor="#333333", label="Statistics tables"),
+ ]
+ ax.legend(handles=legend_elements, loc="lower right", fontsize=8, framealpha=0.9)
+
+ plt.tight_layout(pad=0.5)
+ if output:
+ plt.savefig(output, dpi=150, bbox_inches="tight")
+ print(f"Diagram saved to: {output}")
+ else:
+ plt.show()
+
+
+# ── CLI entry point ────────────────────────────────────────────────────────────
+
+def main() -> None:
+ parser = argparse.ArgumentParser(
+ description=__doc__,
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ )
+ parser.add_argument("--db", default=None, help="DuckDB file path")
+ parser.add_argument("--output", default=None, help="Save diagram to file (PNG/SVG/PDF)")
+ parser.add_argument("--text", action="store_true", help="Print text summary only")
+ args = parser.parse_args()
+
+ tables, fks, source = load_schema(args.db)
+ print(f"Schema loaded from {source} ({len(tables)} tables, {len(fks)} FK relationships)")
+
+ if args.text:
+ print_text(tables, fks)
+ return
+
+ output = args.output or "schema_diagram.png"
+ draw_diagram(tables, fks, output)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/to_duckdb/seeds_to_duckdb.py b/to_duckdb/seeds_to_duckdb.py
deleted file mode 100644
index 844a57f..0000000
--- a/to_duckdb/seeds_to_duckdb.py
+++ /dev/null
@@ -1,548 +0,0 @@
-"""
-seeds_to_duckdb.py
-==================
-Build a student DuckDB database from MagnetDB seed files,
-WITHOUT requiring a running Django stack or PostgreSQL.
-
-Usage
------
- pip install duckdb
- python seeds_to_duckdb.py [--output student_magnetdb.duckdb] [--seeds all|bitters|M19061901|...]
-
-How it works
-------------
-The seed files (seeds-Bitters.py, seed-M19061901.py, …) call functions from
-`python_magnetdb.seeds.crud` which write to Django ORM / PostgreSQL.
-
-This script replaces that entire layer with lightweight stubs that capture
-every create_*/query_* call and redirect the data into DuckDB instead.
-No Django, no PostgreSQL, no MinIO needed.
-
-coil_index assignment
----------------------
-Parts are ordered in the `parts` list passed to `create_magnet()`.
-Only parts of type 'helix' or 'bitter' receive a coil_index (1-based,
-in their order of appearance). Parts of type 'ring' or 'lead' get NULL.
-This matches the Icoil_N column convention in operational records.
-"""
-
-import argparse
-import sys
-import types
-from pathlib import Path
-
-import duckdb
-
-# ---------------------------------------------------------------------------
-# Configuration
-# ---------------------------------------------------------------------------
-
-COIL_TYPES = {"helix", "bitter"} # these map to Icoil_N columns
-
-# ---------------------------------------------------------------------------
-# Lightweight mock objects returned by create_*/query_* stubs
-# ---------------------------------------------------------------------------
-
-
-class MockObject:
- """Minimal stand-in for a Django model instance."""
-
- def __init__(self, **kwargs):
- self.__dict__.update(kwargs)
-
- def __repr__(self):
- return f""
-
-
-# ---------------------------------------------------------------------------
-# In-memory registry (shared across all seed modules loaded in one run)
-# ---------------------------------------------------------------------------
-
-_materials: dict[str, dict] = {}
-_parts: dict[str, dict] = {}
-_magnets: dict[str, dict] = {}
-_sites: dict[str, dict] = {}
-_records: list[dict] = []
-
-
-# ---------------------------------------------------------------------------
-# Stub implementations of crud.py functions
-# ---------------------------------------------------------------------------
-
-
-def _create_material(obj: dict) -> MockObject:
- name = obj["name"]
- if name not in _materials:
- _materials[name] = {
- "name": name,
- "description": obj.get("description"),
- "nuance": obj.get("nuance"),
- "t_ref": obj.get("t_ref"),
- "volumic_mass": obj.get("volumic_mass"),
- "specific_heat": obj.get("specific_heat"),
- "alpha": obj.get("alpha"),
- "electrical_conductivity": obj.get("electrical_conductivity"),
- "thermal_conductivity": obj.get("thermal_conductivity"),
- "magnet_permeability": obj.get("magnet_permeability"),
- "young": obj.get("young"),
- "poisson": obj.get("poisson"),
- "expansion_coefficient": obj.get("expansion_coefficient"),
- "rpe": float(obj["rpe"]) if obj.get("rpe") is not None else None,
- }
- return MockObject(**_materials[name])
-
-
-def _create_part(obj: dict) -> MockObject:
- name = obj["name"]
- if name not in _parts:
- material = obj.get("material")
- material_name = material.name if isinstance(material, MockObject) else material
- _parts[name] = {
- "name": name,
- "type": obj.get("type"),
- "status": obj.get("status"),
- "material_name": material_name,
- "geometry": obj.get("geometry"),
- "cad": obj.get("cad"),
- "design_office_reference": obj.get("design_office_reference"),
- }
- return MockObject(**_parts[name])
-
-
-def _create_site(obj: dict) -> MockObject:
- name = obj["name"]
- if name not in _sites:
- _sites[name] = {
- "name": name,
- "status": obj.get("status"),
- "config": obj.get("config"),
- }
- return MockObject(**_sites[name])
-
-
-def _create_magnet(obj: dict) -> MockObject:
- name = obj["name"]
- if name not in _magnets:
- site = obj.get("site")
- site_name = site.name if isinstance(site, MockObject) else site
-
- parts = obj.get("parts", []) or []
-
- # Assign coil_index only to helix/bitter parts
- coil_counter = 0
- parts_list = []
- for rank, part in enumerate(parts):
- part_name = part.name if isinstance(part, MockObject) else part
- part_type = _parts.get(part_name, {}).get("type", "")
- if part_type in COIL_TYPES:
- coil_counter += 1
- coil_index = coil_counter
- else:
- coil_index = None
- parts_list.append(
- {
- "magnet_name": name,
- "part_name": part_name,
- "rank": rank,
- "coil_index": coil_index,
- }
- )
-
- # Normalise MagnetType enum → plain string
- mag_type = obj.get("type")
- if hasattr(mag_type, "value"):
- mag_type = mag_type.value
- elif hasattr(mag_type, "name"):
- mag_type = mag_type.name.lower()
-
- _magnets[name] = {
- "name": name,
- "type": str(mag_type) if mag_type else None,
- "status": obj.get("status"),
- "geometry": obj.get("geometry"),
- "site_name": site_name,
- "design_office_reference": obj.get("design_office_reference"),
- "_parts": parts_list,
- }
- return MockObject(**{k: v for k, v in _magnets[name].items() if k != "_parts"})
-
-
-def _create_record(obj: dict) -> None:
- site = obj.get("site")
- site_name = site.name if isinstance(site, MockObject) else site
- _records.append(
- {
- "record_file": obj.get("file"),
- "site_name": site_name,
- }
- )
-
-
-def _query_material(name: str) -> MockObject | None:
- return MockObject(**_materials[name]) if name in _materials else None
-
-
-def _query_part(name: str) -> MockObject | None:
- return MockObject(**_parts[name]) if name in _parts else None
-
-
-def _query_magnet(name: str) -> MockObject | None:
- return MockObject(**_magnets[name]) if name in _magnets else None
-
-
-def _query_site(name: str) -> MockObject | None:
- return MockObject(**_sites[name]) if name in _sites else None
-
-
-# ---------------------------------------------------------------------------
-# Stub module: replaces python_magnetdb.seeds.crud
-# ---------------------------------------------------------------------------
-
-
-def _make_crud_module() -> types.ModuleType:
- mod = types.ModuleType("python_magnetdb.seeds.crud")
- mod.create_material = _create_material
- mod.create_part = _create_part
- mod.create_site = _create_site
- mod.create_magnet = _create_magnet
- mod.create_record = _create_record
- mod.query_material = _query_material
- mod.query_part = _query_part
- mod.query_magnet = _query_magnet
- mod.query_site = _query_site
- # Some seeds also import these names directly
- mod.upload_attachment = lambda *a, **kw: None
- return mod
-
-
-# ---------------------------------------------------------------------------
-# Stub module: replaces python_magnetdb.models.magnet (for MagnetType enum)
-# ---------------------------------------------------------------------------
-
-
-def _make_models_module() -> types.ModuleType:
- from enum import Enum
-
- class MagnetType(str, Enum):
- INSERT = "insert"
- BITTERS = "bitters"
- SUPRA = "supra"
- HYBRID = "hybrid"
-
- mod = types.ModuleType("python_magnetdb.models.magnet")
- mod.MagnetType = MagnetType
- return mod
-
-
-# ---------------------------------------------------------------------------
-# Inject stubs into sys.modules before any seed is imported
-# ---------------------------------------------------------------------------
-
-
-def _install_stubs() -> None:
- # Ensure parent packages exist as empty modules so Python is happy
- for pkg in [
- "python_magnetdb",
- "python_magnetdb.models",
- "python_magnetdb.seeds",
- ]:
- if pkg not in sys.modules:
- sys.modules[pkg] = types.ModuleType(pkg)
-
- sys.modules["python_magnetdb.seeds.crud"] = _make_crud_module()
- sys.modules["python_magnetdb.models.magnet"] = _make_models_module()
-
- # Silence getenv("DATA_DIR") calls in seeds — not needed here
- import os
-
- os.environ.setdefault("DATA_DIR", "/tmp/dummy_data_dir")
-
-
-# ---------------------------------------------------------------------------
-# Load seed modules by name
-# ---------------------------------------------------------------------------
-
-SEED_MODULES = {
- "bitters": "python_magnetdb.seeds.seeds-Bitters",
- "M19061901": "python_magnetdb.seeds.seed-M19061901",
- "M19071101": "python_magnetdb.seeds.seed-M19071101",
- "M18110501": "python_magnetdb.seeds.seed-M18110501",
- "M20022001": "python_magnetdb.seeds.seed-M20022001",
- "M22011801": "python_magnetdb.seeds.seed-M22011801",
- "records": "python_magnetdb.seeds.seed-records",
-}
-
-
-def _load_seed(key: str, repo_root: Path) -> None:
- """
- Import a seed module from the repo without requiring it to be installed.
- We load it as a regular file using importlib.util so that relative imports
- (from .crud import …) work by virtue of the stubs already being in sys.modules.
- """
- import importlib.util
-
- # Map dotted name → file path
- # e.g. "python_magnetdb.seeds.seeds-Bitters" → repo_root/python_magnetdb/seeds/seeds-Bitters.py
- module_name = SEED_MODULES[key]
- rel_path = Path(*module_name.split(".")).with_suffix(".py")
- file_path = repo_root / rel_path
-
- if not file_path.exists():
- print(f" [SKIP] {file_path} not found")
- return
-
- print(f" Loading {file_path} …")
- spec = importlib.util.spec_from_file_location(module_name, file_path)
- mod = importlib.util.module_from_spec(spec)
- sys.modules[module_name] = mod
- try:
- spec.loader.exec_module(mod)
- except Exception as exc:
- print(f" [WARN] Error in {file_path.name}: {exc}")
-
-
-# ---------------------------------------------------------------------------
-# Write collected data to DuckDB
-# ---------------------------------------------------------------------------
-
-SCHEMA_SQL = """
-CREATE TABLE IF NOT EXISTS materials (
- name VARCHAR PRIMARY KEY,
- description VARCHAR,
- nuance VARCHAR,
- t_ref DOUBLE,
- volumic_mass DOUBLE,
- specific_heat DOUBLE,
- alpha DOUBLE,
- electrical_conductivity DOUBLE,
- thermal_conductivity DOUBLE,
- magnet_permeability DOUBLE,
- young DOUBLE,
- poisson DOUBLE,
- expansion_coefficient DOUBLE,
- rpe DOUBLE -- Pa (elastic limit)
-);
-
-CREATE TABLE IF NOT EXISTS parts (
- name VARCHAR PRIMARY KEY,
- type VARCHAR, -- 'helix' | 'ring' | 'bitter' | 'lead'
- status VARCHAR,
- material_name VARCHAR REFERENCES materials(name),
- geometry VARCHAR, -- geometry YAML stem (no extension)
- geometry_data JSON, -- python_magnetgeo object serialized as JSON
- cad VARCHAR, -- CAD file stem
- design_office_reference VARCHAR
-);
-
-CREATE TABLE IF NOT EXISTS sites (
- name VARCHAR PRIMARY KEY,
- status VARCHAR,
- config VARCHAR -- .conf filename if available
-);
-
-CREATE TABLE IF NOT EXISTS magnets (
- name VARCHAR PRIMARY KEY,
- type VARCHAR, -- 'insert' | 'bitters' | 'supra' | 'hybrid'
- status VARCHAR,
- geometry VARCHAR,
- geometry_data JSON, -- python_magnetgeo object serialized as JSON
- site_name VARCHAR REFERENCES sites(name),
- design_office_reference VARCHAR
-);
-
--- Migration: add geometry_data to existing databases (no-op if already present)
-ALTER TABLE parts ADD COLUMN IF NOT EXISTS geometry_data JSON;
-ALTER TABLE magnets ADD COLUMN IF NOT EXISTS geometry_data JSON;
-
-CREATE TABLE IF NOT EXISTS magnet_parts (
- magnet_name VARCHAR REFERENCES magnets(name),
- part_name VARCHAR REFERENCES parts(name),
- rank INTEGER, -- 0-based position in original parts list
- coil_index INTEGER, -- 1-based index among helix/bitter parts; NULL for rings/leads
- PRIMARY KEY (magnet_name, part_name)
-);
-
-CREATE TABLE IF NOT EXISTS experiments (
- id INTEGER PRIMARY KEY,
- site_name VARCHAR REFERENCES sites(name),
- record_file VARCHAR,
- status VARCHAR DEFAULT 'pending'
-);
-"""
-
-
-def _write_to_duckdb(output_path: Path) -> None:
- print(f"\nWriting to {output_path} …")
- con = duckdb.connect(str(output_path))
- con.execute(SCHEMA_SQL)
-
- # Materials
- for m in _materials.values():
- con.execute(
- """
- INSERT OR REPLACE INTO materials VALUES (?,?,?,?,?,?,?,?,?,?,?,?,?,?)
- """,
- [
- m["name"],
- m["description"],
- m["nuance"],
- m["t_ref"],
- m["volumic_mass"],
- m["specific_heat"],
- m["alpha"],
- m["electrical_conductivity"],
- m["thermal_conductivity"],
- m["magnet_permeability"],
- m["young"],
- m["poisson"],
- m["expansion_coefficient"],
- m["rpe"],
- ],
- )
-
- # Parts
- for p in _parts.values():
- con.execute(
- """
- INSERT OR REPLACE INTO parts
- (name, type, status, material_name, geometry, geometry_data, cad, design_office_reference)
- VALUES (?,?,?,?,?,NULL,?,?)
- """,
- [
- p["name"],
- p["type"],
- p["status"],
- p["material_name"],
- p["geometry"],
- p["cad"],
- p["design_office_reference"],
- ],
- )
-
- # Sites
- for s in _sites.values():
- con.execute(
- "INSERT OR REPLACE INTO sites VALUES (?,?,?)", [s["name"], s["status"], s["config"]]
- )
-
- # Magnets + magnet_parts
- for m in _magnets.values():
- con.execute(
- """
- INSERT OR REPLACE INTO magnets
- (name, type, status, geometry, geometry_data, site_name, design_office_reference)
- VALUES (?,?,?,?,NULL,?,?)
- """,
- [
- m["name"],
- m["type"],
- m["status"],
- m["geometry"],
- m["site_name"],
- m["design_office_reference"],
- ],
- )
- for mp in m["_parts"]:
- con.execute(
- """
- INSERT OR REPLACE INTO magnet_parts VALUES (?,?,?,?)
- """,
- [mp["magnet_name"], mp["part_name"], mp["rank"], mp["coil_index"]],
- )
-
- # Experiments (from seed-records)
- for i, r in enumerate(_records):
- con.execute(
- """
- INSERT OR REPLACE INTO experiments VALUES (?,?,?,'pending')
- """,
- [i + 1, r["site_name"], r["record_file"]],
- )
-
- con.close()
-
- _print_summary(output_path)
-
-
-def _print_summary(output_path: Path) -> None:
- con = duckdb.connect(str(output_path), read_only=True)
- print("\n── Database summary ──────────────────────────────────")
- for table in ["materials", "parts", "sites", "magnets", "magnet_parts", "experiments"]:
- n = con.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0]
- print(f" {table:<20} {n:>4} rows")
-
- print("\n── coil_index distribution ───────────────────────────")
- rows = con.execute(
- """
- SELECT m.name AS magnet, p.type, mp.coil_index, mp.part_name
- FROM magnet_parts mp
- JOIN parts p ON p.name = mp.part_name
- JOIN magnets m ON m.name = mp.magnet_name
- WHERE mp.coil_index IS NOT NULL
- ORDER BY m.name, mp.coil_index
- """
- ).fetchall()
- current_magnet = None
- for magnet, ptype, ci, pname in rows:
- if magnet != current_magnet:
- print(f"\n {magnet}")
- current_magnet = magnet
- print(f" Icoil{ci:<3} {ptype:<8} {pname}")
- con.close()
-
-
-# ---------------------------------------------------------------------------
-# CLI entry point
-# ---------------------------------------------------------------------------
-
-
-def main() -> None:
- parser = argparse.ArgumentParser(
- description=__doc__, formatter_class=argparse.RawDescriptionHelpFormatter
- )
- parser.add_argument(
- "--output",
- default="student_magnetdb.duckdb",
- help="Output DuckDB file path (default: student_magnetdb.duckdb)",
- )
- parser.add_argument(
- "--seeds",
- default="all",
- help=(
- "Comma-separated list of seeds to load, or 'all'. "
- f"Known keys: {', '.join(SEED_MODULES)}"
- ),
- )
- parser.add_argument(
- "--repo", default=".", help="Path to the magnetdb repo root (default: current directory)"
- )
- args = parser.parse_args()
-
- repo_root = Path(args.repo).resolve()
- output = Path(args.output)
-
- keys = list(SEED_MODULES) if args.seeds == "all" else [k.strip() for k in args.seeds.split(",")]
-
- unknown = [k for k in keys if k not in SEED_MODULES]
- if unknown:
- print(f"Unknown seed keys: {unknown}. Available: {list(SEED_MODULES)}")
- sys.exit(1)
-
- print("Installing Django/crud stubs …")
- _install_stubs()
-
- print(f"\nLoading seeds from {repo_root}:")
- for key in keys:
- _load_seed(key, repo_root)
-
- print(
- f"\nCollected: {len(_materials)} materials, {len(_parts)} parts, "
- f"{len(_sites)} sites, {len(_magnets)} magnets, {len(_records)} experiments"
- )
-
- _write_to_duckdb(output)
- print(f"\nDone → {output.resolve()}")
-
-
-if __name__ == "__main__":
- main()
diff --git a/to_duckdb/stress_map.py b/to_duckdb/stress_map.py
new file mode 100644
index 0000000..6e2b1e7
--- /dev/null
+++ b/to_duckdb/stress_map.py
@@ -0,0 +1,1729 @@
+"""
+stress_map.py
+=============
+Hoop-stress analysis for a site using DuckDB + YAML geometry files.
+
+Replaces the Django/ORM data-access layer of the MagnetDB production chain
+with DuckDB queries; everything from magnet_setup() onwards is identical.
+
+Public API
+----------
+ load_site_config_from_duckdb(site_name, db_path)
+ prepare_geometry_directory(site_name, magnets, geometries_dir, tempdir)
+ load_magnettools(config, tempdir, debug)
+ compute_hoop_at_currents(data, i_h, i_b, i_s)
+ annotate_with_rpe(result, site_name, db_path)
+ compute_stress_stats(df)
+ compute_fatigue(df, col)
+ plot_stress_map(df, magnet_name, i_h)
+ plot_stress_history(df, site_name)
+ plot_fatigue(df, cycles_df, site_name, col, bins)
+
+CLI (also accessible via ``magnetdb.py hoop-stress``)
+-----------------------------------------------------
+ python stress_map.py barchart [--i-h ...] [--i-b ...] [--i-s ...]
+ python stress_map.py history [--pupitre ...] [--use-mrun]
+ python stress_map.py stats [--pupitre ...] [--output ...]
+ python stress_map.py fatigue [--pupitre ...] [--bins ...]
+
+Note on Rpe units
+-----------------
+Rpe is stored as-is from the seed files (Pa in some, MPa in others).
+Verify the unit for your dataset before interpreting ratio_rpe values.
+"""
+
+import argparse
+import enum
+import glob as _glob
+import json
+import re
+import shutil
+import tempfile
+from pathlib import Path
+
+import duckdb
+import matplotlib.pyplot as plt
+import numpy as np
+import pandas as pd
+
+import magnettools.Bmap as bmap
+import magnettools.magnettools as mt
+from config import DEFAULT_DB
+from populate import _RECORDS_BASE as _DEFAULT_RECORDS_BASE, _SRV_SUBDIR as _DEFAULT_SRV_SUBDIR
+from python_magnetrun.magnetdata import load_magnetdata
+from python_magnetrun.runetl import prepareData
+from python_magnetrun.utils.timestamps import parse_filename_timestamp
+from python_magnetsetup.ana import msite_setup
+from python_magnetsetup.config import appenv
+
+
+class PartType(str, enum.Enum):
+ SUPRA = "supra"
+ HELIX = "helix"
+ RING = "ring"
+ SCREEN = "screen"
+ LEAD = "lead"
+ BITTER = "bitter"
+
+ @classmethod
+ def choices(cls):
+ return [(item.value, item.name) for item in cls]
+
+
+class MagnetType(str, enum.Enum):
+ INSERT = "insert"
+ BITTERS = "bitters"
+ SUPRAS = "supras"
+ HYBRID = "hybrid"
+
+ @classmethod
+ def choices(cls):
+ return [(item.value, item.name) for item in cls]
+
+
+# ---------------------------------------------------------------------------
+# Step 1 — Build config dict from DuckDB
+# Replicates generate_magnet_config() in generate_simulation_config.py
+# ---------------------------------------------------------------------------
+
+
+def _format_material_row(row: dict) -> dict:
+ """Map DuckDB column names to the format expected by magnet_setup().
+ Mirrors format_material() in generate_simulation_config.py exactly.
+ """
+ return {
+ "Tref": row["t_ref"],
+ "VolumicMass": row["volumic_mass"],
+ "alpha": row["alpha"],
+ "ElectricalConductivity": row["electrical_conductivity"],
+ "MagnetPermeability": row["magnet_permeability"],
+ "Poisson": row["poisson"],
+ "Rpe": row["rpe"], # unit: see module docstring
+ "SpecificHeat": row["specific_heat"],
+ "ThermalConductivity": row["thermal_conductivity"],
+ "Young": row["young"],
+ "CoefDilatation": row["expansion_coefficient"],
+ "nuance": row["nuance"],
+ }
+
+
+def load_site_config_from_duckdb(
+ site_name: str,
+ db_path: str,
+ magnet_override: str | None = None,
+) -> tuple[str, list[tuple[str, dict, str | None]]]:
+ """
+ Return (housing, [(magnet_name, config, geometry_data), ...]) for every magnet at a site.
+
+ Resolve the site → magnet mapping and load the full part/material config
+ in a single DB connection. All magnets are returned regardless of
+ commissioned/decommissioned status, ordered by commissioned_at DESC.
+
+ Parameters
+ ----------
+ site_name : Site name registered in DuckDB (e.g. "M9")
+ db_path : Path to the DuckDB file
+ magnet_override : Explicit magnet name; returns only that magnet.
+ A warning is printed if it is not linked to the site.
+
+ Returns
+ -------
+ housing : from sites.housing (e.g. "M9")
+ magnets : list of (magnet_name, config, geometry_data) triples — config is a
+ dict ready for magnet_setup() / prepare_geometry_directory();
+ geometry_data is the JSON-serialised python_magnetgeo object stored
+ in magnets.geometry_data (None if not yet imported with --geometry).
+
+ Raises
+ ------
+ ValueError : site not found, no magnet linked, MAT_ISOLANT missing,
+ or no magnet has parts in the DB.
+ """
+ con = duckdb.connect(db_path, read_only=True)
+
+ # ── 1. Site housing ───────────────────────────────────────────────────────
+ site_row = con.execute(
+ "SELECT housing FROM sites WHERE name = ?", [site_name]
+ ).fetchone()
+ if site_row is None:
+ con.close()
+ raise ValueError(
+ f"Site '{site_name}' not found in DB. "
+ "Check the site name and ensure seeds are loaded."
+ )
+ housing = site_row[0]
+
+ # ── 2. Resolve magnet list ────────────────────────────────────────────────
+ rows = con.execute(
+ """
+ SELECT magnet_name
+ FROM site_magnets
+ WHERE site_name = ?
+ ORDER BY commissioned_at DESC NULLS LAST
+ """,
+ [site_name],
+ ).fetchall()
+ if not rows:
+ con.close()
+ raise ValueError(
+ f"No magnet linked to site '{site_name}'. "
+ "Check the site name and ensure seeds are loaded."
+ )
+ magnet_names = [r[0] for r in rows]
+
+ # ── 3. Insulator material (shared by every part entry) ────────────────────
+ isolant_row = con.execute("""
+ SELECT t_ref, volumic_mass, alpha, electrical_conductivity,
+ magnet_permeability, poisson, rpe, specific_heat,
+ thermal_conductivity, young, expansion_coefficient, nuance
+ FROM materials WHERE name = 'MAT_ISOLANT'
+ """).fetchone()
+ if isolant_row is None:
+ con.close()
+ raise ValueError(
+ "MAT_ISOLANT not found in the database. "
+ "Run seeds_to_duckdb.py to populate structural data first."
+ )
+ insulator_payload = _format_material_row(
+ dict(
+ zip(
+ [
+ "t_ref",
+ "volumic_mass",
+ "alpha",
+ "electrical_conductivity",
+ "magnet_permeability",
+ "poisson",
+ "rpe",
+ "specific_heat",
+ "thermal_conductivity",
+ "young",
+ "expansion_coefficient",
+ "nuance",
+ ],
+ isolant_row,
+ )
+ )
+ )
+
+ # ── 4. Build config per magnet ────────────────────────────────────────────
+ col_names = [
+ "part_name",
+ "part_type",
+ "rank",
+ "t_ref",
+ "volumic_mass",
+ "alpha",
+ "electrical_conductivity",
+ "magnet_permeability",
+ "poisson",
+ "rpe",
+ "specific_heat",
+ "thermal_conductivity",
+ "young",
+ "expansion_coefficient",
+ "nuance",
+ ]
+ results: list[tuple[str, dict, str | None]] = []
+ for magnet_name in magnet_names:
+ parts = con.execute(
+ """
+ SELECT
+ p.name AS part_name,
+ p.type AS part_type,
+ mp.rank,
+ mat.t_ref, mat.volumic_mass, mat.alpha,
+ mat.electrical_conductivity, mat.magnet_permeability,
+ mat.poisson, mat.rpe, mat.specific_heat,
+ mat.thermal_conductivity, mat.young,
+ mat.expansion_coefficient, mat.nuance
+ FROM magnet_parts mp
+ JOIN parts p ON p.name = mp.part_name
+ JOIN magnets m ON m.name = mp.magnet_name
+ LEFT JOIN materials mat ON mat.name = p.material_name
+ WHERE m.name = ?
+ ORDER BY mp.rank
+ """,
+ [magnet_name],
+ ).fetchall()
+
+ if not parts:
+ print(f" [WARN] Magnet '{magnet_name}' has no parts in the DB — skipping.")
+ continue
+
+ geo_row = con.execute(
+ "SELECT geometry_data FROM magnets WHERE name = ?", [magnet_name]
+ ).fetchone()
+ geometry_data: str | None = geo_row[0] if geo_row else None
+
+ config: dict = {"geom": f"{magnet_name}.yaml"}
+ for row in parts:
+ d = dict(zip(col_names, row))
+ key = d["part_type"].capitalize() # "Helix", "Ring", "Bitter", "Lead"
+ if key not in config:
+ config[key] = []
+ config[key].append(
+ {
+ "geom": f"{d['part_name']}.yaml",
+ "material": _format_material_row(d),
+ "insulator": insulator_payload,
+ }
+ )
+ results.append((magnet_name, config, geometry_data))
+
+ con.close()
+
+ if not results:
+ raise ValueError(
+ f"No magnet with parts found for site '{site_name}'. "
+ "Check the magnet names and ensure seeds are loaded."
+ )
+
+ return housing, results
+
+
+# ---------------------------------------------------------------------------
+# Step 1b — Generate MSite YAML from DuckDB geometry_data + site offsets
+# Mirrors Site.geometry_config_to_json() in python_magnetdb/models.py
+# ---------------------------------------------------------------------------
+
+
+def geometry_config_to_yaml(
+ site_name: str,
+ db_path: str,
+ output_dir: str | Path | None = None,
+ geometries_dir: str | Path | None = None,
+) -> str:
+ """
+ Build a python_magnetgeo MSite from the site's magnet geometry_data and
+ site_magnets positional offsets, then return its YAML representation.
+
+ Mirrors ``Site.geometry_config_to_json()`` in python_magnetdb/models.py,
+ replacing the Django ORM with DuckDB queries.
+
+ Each magnet's assembly geometry is resolved in this order:
+
+ 1. ``magnets.geometry_data`` — JSON-serialised python_magnetgeo object stored
+ at import time via ``magnetdb.py magnet add --geometry ``.
+ 2. ``geometries_dir`` fallback — load ``{magnet_name}.yaml`` from this
+ directory (for DBs populated without ``--geometry``).
+
+ Parameters
+ ----------
+ site_name : Site name as registered in DuckDB (e.g. ``"M9_M19061901_0"``)
+ db_path : Path to the DuckDB file
+ output_dir : If given, also write ``.yaml`` to this directory
+ via ``MSite.write_to_yaml()``. The YAML string is returned
+ regardless.
+ geometries_dir : Fallback directory containing ``{magnet_name}.yaml``
+ assembly-level files (Insert, Bitters, …) for magnets that
+ were imported without ``--geometry``.
+
+ Returns
+ -------
+ str
+ YAML representation of the ``MSite``.
+
+ Raises
+ ------
+ ValueError
+ If the site is not found, has no magnets, or a magnet's assembly
+ geometry cannot be resolved from either the DB or *geometries_dir*.
+ """
+ import yaml as _yaml
+ from python_magnetgeo.MSite import MSite
+
+ print(f" ── Preparing geometry directory for site '{site_name}' …")
+ geo_dir = Path(geometries_dir) if geometries_dir else None
+
+ con = duckdb.connect(db_path, read_only=True)
+
+ if (
+ con.execute("SELECT 1 FROM sites WHERE name = ?", [site_name]).fetchone()
+ is None
+ ):
+ con.close()
+ raise ValueError(f"Site '{site_name}' not found in DB.")
+
+ rows = con.execute(
+ """
+ SELECT m.name, m.geometry_data, sm.z_offset, sm.r_offset, sm.parallax
+ FROM site_magnets sm
+ JOIN magnets m ON m.name = sm.magnet_name
+ WHERE sm.site_name = ?
+ ORDER BY sm.commissioned_at DESC NULLS LAST, m.name
+ """,
+ [site_name],
+ ).fetchall()
+ con.close()
+
+ if not rows:
+ raise ValueError(f"No magnets linked to site '{site_name}'.")
+
+ magnets = []
+ z_offset: list[float] = []
+ r_offset: list[float] = []
+ paralax: list[float] = []
+
+ for magnet_name, geometry_data, z, r, p in rows:
+ print(f"\t- Processing magnet '{magnet_name}' …")
+ yaml_str = magnet_geometry_config_to_yaml(
+ magnet_name, db_path, output_dir=geo_dir
+ )
+ magnet_obj = _yaml.load(yaml_str, Loader=_yaml.FullLoader)
+ if output_dir is not None:
+ magnet_obj.write_to_yaml(str(output_dir))
+ print(f" Written {Path(output_dir) / magnet_name}.yaml")
+
+ magnets.append(magnet_obj)
+ z_offset.append(float(z or 0.0))
+ r_offset.append(float(r or 0.0))
+ paralax.append(float(p or 0.0))
+
+ obj = MSite(
+ name=site_name,
+ magnets=magnets,
+ screens=[],
+ z_offset=z_offset,
+ r_offset=r_offset,
+ paralax=paralax,
+ )
+
+ if output_dir is not None:
+ obj.write_to_yaml(str(output_dir))
+ print(f" Written {Path(output_dir) / site_name}.yaml")
+
+ return obj.to_yaml()
+
+
+# ---------------------------------------------------------------------------
+# Step 1c — Generate magnet assembly YAML from DuckDB geometry_data
+# Mirrors Magnet.geometry_config_to_yaml() in python_magnetdb/models.py
+# ---------------------------------------------------------------------------
+
+
+def magnet_geometry_config_to_yaml(
+ magnet_name: str,
+ db_path: str,
+ output_dir: str | Path | None = None,
+) -> str:
+ """
+ Build a python_magnetgeo assembly object from a magnet's parts and return
+ its YAML representation.
+
+ Mirrors ``Magnet.geometry_config_to_yaml()`` in python_magnetdb/models.py,
+ replacing the Django ORM with DuckDB queries. The assembly object
+ (Insert, Bitters, or Supras) is reconstructed from the individual part
+ geometry stored in ``parts.geometry_data``, exactly as the Django method
+ builds it from ``magnet_part.part.geometry_config``.
+
+ Because the DuckDB schema does not store ``angle``, ``inner_bore``, or
+ ``outer_bore``, angles default to 0 and bore values are derived
+ automatically from the parts' geometry (Insert/Bitters/Supras auto-compute
+ when passed ``innerbore=0``/``outerbore=0``).
+
+ Parameters
+ ----------
+ magnet_name : Magnet name as registered in DuckDB (e.g. ``"M19061901"``)
+ db_path : Path to the DuckDB file
+ output_dir : If given, also write ``.yaml`` to this directory
+ via ``write_to_yaml()``. The YAML string is returned regardless.
+
+ Returns
+ -------
+ str
+ YAML representation of the magnet assembly object.
+
+ Raises
+ ------
+ ValueError
+ If the magnet is not found, has no parts, or a part has no geometry_data.
+ """
+ import copy
+ import json as _json
+ from python_magnetgeo.deserialize import unserialize_object
+ from python_magnetgeo.Insert import Insert
+ from python_magnetgeo.Bitters import Bitters
+ from python_magnetgeo.Supras import Supras
+
+ print(
+ f" ── Generating magnet assembly YAML for '{magnet_name}' in output directory '{output_dir}' …",
+ flush=True,
+ )
+
+ con = duckdb.connect(db_path, read_only=True)
+
+ magnet_row = con.execute(
+ "SELECT type FROM magnets WHERE name = ?", [magnet_name]
+ ).fetchone()
+ if magnet_row is None:
+ con.close()
+ raise ValueError(f"Magnet '{magnet_name}' not found in DB.")
+ magnet_type = magnet_row[0]
+
+ parts_rows = con.execute(
+ """
+ SELECT p.name, p.type, p.geometry_data
+ FROM magnet_parts mp
+ JOIN parts p ON p.name = mp.part_name
+ WHERE mp.magnet_name = ?
+ ORDER BY mp.rank
+ """,
+ [magnet_name],
+ ).fetchall()
+ con.close()
+
+ if not parts_rows:
+ raise ValueError(f"Magnet '{magnet_name}' has no parts in DB.")
+
+ print(
+ f" Processing {magnet_type.upper()} magnet '{magnet_name}' "
+ f"with {len(parts_rows)} part(s) …"
+ )
+
+ if magnet_type == MagnetType.INSERT:
+ helices, hangles, rings, rangles, currentleads = [], [], [], [], []
+ for part_name, part_type, geometry_data in parts_rows:
+ if not geometry_data:
+ raise ValueError(
+ f"Part '{part_name}' has no geometry_data. "
+ "Re-import with 'magnetdb.py magnet add --geometry'."
+ )
+ config = copy.deepcopy(_json.loads(geometry_data))
+ config["name"] = part_name
+ obj = unserialize_object(config)
+ if part_type == PartType.HELIX:
+ helices.append(obj)
+ hangles.append(0)
+ elif part_type == PartType.RING:
+ rings.append(obj)
+ rangles.append(0)
+ elif part_type == PartType.LEAD:
+ currentleads.append(obj)
+ else:
+ raise ValueError(
+ f"Unsupported part type '{part_type}' for '{part_name}' in "
+ f"INSERT magnet '{magnet_name}'. Expected HELIX, RING, or LEAD."
+ )
+ assembly = Insert(
+ name=magnet_name,
+ helices=helices,
+ rings=rings,
+ currentleads=currentleads,
+ hangles=hangles,
+ rangles=rangles,
+ innerbore=0,
+ outerbore=0,
+ )
+
+ elif magnet_type == MagnetType.BITTERS:
+ magnets, currentleads = [], []
+ for part_name, part_type, geometry_data in parts_rows:
+ if not geometry_data:
+ raise ValueError(
+ f"Part '{part_name}' has no geometry_data. "
+ "Re-import with 'magnetdb.py magnet add --geometry'."
+ )
+ config = copy.deepcopy(_json.loads(geometry_data))
+ config["name"] = part_name
+ obj = unserialize_object(config)
+ if part_type == PartType.BITTER:
+ magnets.append(obj)
+ elif part_type == PartType.LEAD:
+ currentleads.append(obj)
+ else:
+ raise ValueError(
+ f"Unsupported part type '{part_type}' for '{part_name}' in "
+ f"BITTERS magnet '{magnet_name}'. Expected BITTER or LEAD."
+ )
+ assembly = Bitters(
+ name=magnet_name,
+ magnets=magnets,
+ innerbore=0,
+ outerbore=0,
+ )
+
+ elif magnet_type == MagnetType.SUPRAS:
+ magnets, currentleads = [], []
+ for part_name, part_type, geometry_data in parts_rows:
+ if not geometry_data:
+ raise ValueError(
+ f"Part '{part_name}' has no geometry_data. "
+ "Re-import with 'magnetdb.py magnet add --geometry'."
+ )
+ config = copy.deepcopy(_json.loads(geometry_data))
+ config["name"] = part_name
+ obj = unserialize_object(config)
+ if part_type == PartType.SUPRA:
+ magnets.append(obj)
+ elif part_type == PartType.LEAD:
+ currentleads.append(obj)
+ else:
+ raise ValueError(
+ f"Unsupported part type '{part_type}' for '{part_name}' in "
+ f"SUPRAS magnet '{magnet_name}'. Expected SUPRA or LEAD."
+ )
+ assembly = Supras(
+ name=magnet_name,
+ magnets=magnets,
+ innerbore=0,
+ outerbore=0,
+ )
+
+ else:
+ raise ValueError(
+ f"Unsupported magnet type '{magnet_type}' for '{magnet_name}'. "
+ f"Expected one of: {[t.value for t in MagnetType if t != MagnetType.HYBRID]}."
+ )
+
+ if output_dir is not None:
+ assembly.write_to_yaml(str(output_dir))
+ print(f" Written {Path(output_dir) / magnet_name}.yaml")
+
+ print(f" Generated assembly YAML for magnet '{magnet_name}'.")
+ # print(f" Assembly summary: {assembly.to_yaml()}")
+ return assembly.to_yaml()
+
+
+# ---------------------------------------------------------------------------
+# Step 2 — Prepare geometry directory on disk
+# Replicates generate_site_directory() without Django
+# ---------------------------------------------------------------------------
+
+
+def prepare_geometry_directory(
+ site_name: str, config: dict, db_path: str, geometries_dir: str | Path | None = None
+) -> Path:
+ """
+ Build a temporary directory tree that magnet_setup() can read:
+
+ /
+ ├── config.json
+ └── data/
+ ├── geometries/
+ │ ├── {magnet_name}.yaml ← top-level insert/bitters geometry
+ │ ├── {part_name}.yaml ← one file per part
+ │ └── ...
+ └── cad/
+
+ The magnet name is derived from config["geom"] (e.g. "M19061901.yaml" → "M19061901").
+ site_name is used only for the temp-directory prefix.
+
+ Geometry YAML files are written from one of three sources (tried in order):
+ 1. ``geometry_data`` argument — JSON already fetched by load_site_config_from_duckdb;
+ no extra DB connection needed.
+ 2. ``geometry_data`` column in DuckDB — fetched via geometry_config_to_yaml when
+ geometry_data argument is None.
+ 3. ``geometries_dir`` fallback — a directory of pre-extracted YAML files
+ (used for seed-based data that pre-dates geometry_data storage).
+
+ Returns the Path of the created temp directory (caller should clean up).
+ """
+
+ print(f"\n── Preparing geometry directory for magnet '{config.keys()}' …")
+
+ src_dir = Path(geometries_dir) if geometries_dir else None
+ if src_dir is not None and not src_dir.is_dir():
+ print(
+ f" [WARN] geometries_dir not found: {src_dir} — will rely on DB-stored geometry_data."
+ )
+ src_dir = None
+
+ tempdir = Path(tempfile.mkdtemp(prefix=f"magnetdb_student_{site_name}_"))
+ data_geom = tempdir / "data" / "geometries"
+ data_geom.mkdir(parents=True)
+ (tempdir / "data" / "cad").mkdir()
+
+ geometry_data = geometry_config_to_yaml(
+ site_name, db_path, output_dir=data_geom, geometries_dir=src_dir
+ )
+ with open(data_geom / f"{site_name}.yaml", "w") as f:
+ f.write(geometry_data)
+
+ # TODO: add save per magnet
+
+ # Write config.json alongside the data/ tree
+ with open(tempdir / "config.json", "w") as f:
+ json.dump(config, f, indent=2)
+
+ return tempdir
+
+
+# ---------------------------------------------------------------------------
+# Step 3 — Load MagnetTools objects
+# Replicates get_magnet_data() in object_geometries.py without Django
+# ---------------------------------------------------------------------------
+
+
+def load_magnettools(config: dict, tempdir: Path, debug: bool = False) -> tuple:
+ """
+ Call magnet_setup() from python_magnetsetup with the prepared directory,
+ returning (Tubes, Helices, OHelices, BMagnets, UMagnets, Shims).
+
+ This is identical to the body of get_magnet_data() in object_geometries.py.
+ """
+ data_dir = str(tempdir / "data")
+ env = appenv(
+ envfile=None,
+ url_api=data_dir,
+ yaml_repo=f"{data_dir}/geometries",
+ cad_repo=f"{data_dir}/cad",
+ mesh_repo=data_dir,
+ simage_repo=data_dir,
+ mrecord_repo=data_dir,
+ optim_repo=data_dir,
+ )
+ # print(f"load_magnettools: env={env}, config={config}")
+ return msite_setup(env, config, debug)
+
+
+# ---------------------------------------------------------------------------
+# Step 4 — Compute hoop stress time series from a pupitre file
+# Fast vectorised alternative to the row-by-row compute_stress_map_chart
+# ---------------------------------------------------------------------------
+
+
+def validate_fast_from_pupitre(
+ data: tuple,
+ pupitre_file: str,
+ housing: str,
+ magnet_type: str = "H",
+ check: bool = False,
+ use_mrun: bool = False,
+ site: str = "",
+) -> pd.DataFrame:
+ """
+ Fast vectorised hoop-stress computation over a pupitre time series.
+
+ Precomputes, at unit current (1 A), for each tube i:
+ - r[i] : inner radius of the tube
+ - j_unit[i] : current density at inner radius for IH = 1 A
+ - Bz_tubes[i] : Bz at (r[i], 0) produced by all tubes at IH = 1 A
+ - Bz_bmag[i] : Bz at (r[i], 0) produced by all BMagnets at IB = 1 A
+ - Bz_umag[i] : Bz at (r[i], 0) produced by all UMagnets at IS = 1 A
+
+ Hoop stress estimate for tube i at time step k:
+ sigma_i(k) = r_i * j_unit_i * IH(k)
+ * (Bz_tubes_i * IH(k) + Bz_bmag_i * IB(k) + Bz_umag_i * IS(k))
+
+ All per-timestep work is pure NumPy — no C++ calls inside the time loop.
+
+ Parameters
+ ----------
+ data : MagnetTools tuple from load_magnettools()
+ pupitre_file : Path to the pupitre file (.txt, .tdms, or .csv)
+ housing : Housing name (e.g. "M9")
+ magnet_type : which coil type(s) to compute hoop stress for:
+ "H" — insert helices only (columns H1_fast, H2_fast, …)
+ "B" — bitter plates only (columns B1_fast, B2_fast, …)
+ "S" — supras only (columns Supra1_fast, Supra2_fast, …)
+ "all" — all present types (H + B + S columns combined)
+ Also controls which reference magnet type is used in the
+ bmap.getHoop sanity check (ignored when check=False).
+ check : If True, validate fast results against bmap.getHoop row by row
+ (only supported for single types "H", "B", "S", not "all")
+ use_mrun : If True, load via python_magnetrun.MagnetRun.load_mrun() instead
+ of load_magnetdata() + prepareData(); supports .tdms in addition
+ to .txt/.csv and handles path auto-resolution.
+ site : Site name forwarded to load_mrun() (ignored when use_mrun=False)
+
+ Returns
+ -------
+ DataFrame with time series columns: t, IH, IB, [IS,] and a subset of
+ H1_fast…HN_fast, B1_fast…BM_fast, Supra1_fast…Supra K_fast
+ depending on magnet_type and which magnet groups are present in *data*.
+ """
+ Tubes, Helices, OHelices, BMagnets, UMagnets, Shims = data
+ icurrents = mt.get_currents(Tubes, Helices, BMagnets, UMagnets)
+ n_tubes = len(Tubes)
+ n_bmag = len(BMagnets)
+ n_umag = len(UMagnets)
+
+ # Which types to compute (gate early so we skip unnecessary work)
+ _do_h = (magnet_type in ("H", "all")) and n_tubes > 0
+ _do_b = (magnet_type in ("B", "all")) and n_bmag > 0
+ _do_s = (magnet_type in ("S", "all")) and n_umag > 0
+
+ # ------------------------------------------------------------------
+ # 1. Precompute unit-current quantities for every magnet type
+ #
+ # Inner radii are pure geometry — extract before any set_currents call.
+ # Current densities require set_currents(group=1 A).
+ # Bz contributions are evaluated at ALL requested positions in each
+ # single-group pass so no extra set_currents calls are needed.
+ # ------------------------------------------------------------------
+ r_h = np.array([Tube.get_R_int() for Tube in Tubes]) if n_tubes else np.zeros(0)
+ r_b = np.array([BMag.get_R_int() for BMag in BMagnets]) if n_bmag else np.zeros(0)
+ r_s = np.array([UMag.get_R_int() for UMag in UMagnets]) if n_umag else np.zeros(0)
+
+ j_unit_h = np.zeros(n_tubes)
+ j_unit_b = np.zeros(n_bmag)
+ j_unit_s = np.zeros(n_umag)
+
+ # Bz[src_at_tgt]: Bz at *tgt* inner radii when *src* current = 1 A, rest = 0
+ Bz_h_at_rh = np.zeros(n_tubes)
+ Bz_b_at_rh = np.zeros(n_tubes)
+ Bz_s_at_rh = np.zeros(n_tubes)
+ Bz_h_at_rb = np.zeros(n_bmag)
+ Bz_b_at_rb = np.zeros(n_bmag)
+ Bz_s_at_rb = np.zeros(n_bmag)
+ Bz_h_at_rs = np.zeros(n_umag)
+ Bz_b_at_rs = np.zeros(n_umag)
+ Bz_s_at_rs = np.zeros(n_umag)
+
+ def _zero_vcurrents():
+ v = mt.DoubleVector(icurrents)
+ for i in range(len(v)):
+ v[i] = 0.0
+ return v
+
+ def _bz_at(radii):
+ return np.array(
+ [
+ mt.MagneticField(Tubes, Helices, BMagnets, UMagnets, r, 0)[1]
+ for r in radii
+ ]
+ )
+
+ num = 0
+ if n_tubes:
+ v = _zero_vcurrents()
+ v[num] = 1.0 # IH = 1 A
+ mt.set_currents(Tubes, Helices, BMagnets, UMagnets, OHelices, v)
+ for i, Tube in enumerate(Tubes):
+ n_elem = Tube.get_n_elem()
+ mid_elem = int(n_elem / 2) if (n_elem % 2) == 0 else int((n_elem + 1) / 2)
+ j_unit_h[i] = Helices[mid_elem + Tube.get_index()].get_CurrentDensity()
+ if _do_h:
+ Bz_h_at_rh = _bz_at(r_h)
+ if _do_b:
+ Bz_h_at_rb = _bz_at(r_b)
+ if _do_s:
+ Bz_h_at_rs = _bz_at(r_s)
+ num += 1
+
+ if n_bmag:
+ v = _zero_vcurrents()
+ v[num] = 1.0 # IB = 1 A
+ mt.set_currents(Tubes, Helices, BMagnets, UMagnets, OHelices, v)
+ for j, BMag in enumerate(BMagnets):
+ j_unit_b[j] = BMag.get_CurrentDensity()
+ if _do_h:
+ Bz_b_at_rh = _bz_at(r_h)
+ if _do_b:
+ Bz_b_at_rb = _bz_at(r_b)
+ if _do_s:
+ Bz_b_at_rs = _bz_at(r_s)
+ num += 1
+
+ if n_umag:
+ v = _zero_vcurrents()
+ v[num] = 1.0 # IS = 1 A
+ mt.set_currents(Tubes, Helices, BMagnets, UMagnets, OHelices, v)
+ for k, UMag in enumerate(UMagnets):
+ j_unit_s[k] = UMag.get_CurrentDensity()
+ if _do_h:
+ Bz_s_at_rh = _bz_at(r_h)
+ if _do_b:
+ Bz_s_at_rb = _bz_at(r_b)
+ if _do_s:
+ Bz_s_at_rs = _bz_at(r_s)
+
+ print(
+ f" Precomputed unit-current quantities: "
+ f"{n_tubes} helix tube(s), {n_bmag} bitter plate(s), {n_umag} supra(s)."
+ )
+
+ # ------------------------------------------------------------------
+ # 2. Load pupitre data
+ # ------------------------------------------------------------------
+ print(f"\n── Loading pupitre data: {pupitre_file} …")
+ if use_mrun:
+ from python_magnetrun.MagnetRun import load_mrun
+
+ mrun = load_mrun(pupitre_file, housing=housing, site=site)
+ df = mrun.MagnetData.Data
+ else:
+ mdata = load_magnetdata(pupitre_file)
+ prepareData(mdata, housing)
+ df = mdata.Data
+
+ # Drop rows where all current columns are NaN — they would propagate NaN
+ # into the stress computation and produce broken plots.
+ current_cols = [c for c in ("IH", "IB", "IS") if c in df.columns]
+ if current_cols:
+ n_before = len(df)
+ df = df.dropna(subset=current_cols, how="all").reset_index(drop=True)
+ n_dropped = n_before - len(df)
+ if n_dropped:
+ print(f" [warn] dropped {n_dropped}/{n_before} rows with all-NaN currents")
+
+ n_t = len(df)
+ IH_arr = df["IH"].to_numpy() if "IH" in df.columns else np.zeros(n_t)
+ IB_arr = df["IB"].to_numpy() if "IB" in df.columns else np.zeros(n_t)
+ IS_arr = df["IS"].to_numpy() if "IS" in df.columns else np.zeros(n_t)
+
+ # ------------------------------------------------------------------
+ # 3. Vectorised hoop stress — (N, 1) broadcast against (1, T)
+ #
+ # For each magnet group X ∈ {H, B, S} with driver current I_X:
+ # sigma_X[j, k] = r_X[j] * j_unit_X[j] * I_X[k]
+ # * (Bz_h_at_rX[j]*IH[k]
+ # + Bz_b_at_rX[j]*IB[k]
+ # + Bz_s_at_rX[j]*IS[k])
+ # ------------------------------------------------------------------
+ IH = IH_arr[np.newaxis, :] # (1, T)
+ IB = IB_arr[np.newaxis, :]
+ IS = IS_arr[np.newaxis, :]
+
+ sigma_h: np.ndarray | None = None
+ sigma_b: np.ndarray | None = None
+ sigma_s: np.ndarray | None = None
+
+ if _do_h:
+ _Bz = (
+ Bz_h_at_rh[:, np.newaxis] * IH
+ + Bz_b_at_rh[:, np.newaxis] * IB
+ + Bz_s_at_rh[:, np.newaxis] * IS
+ )
+ sigma_h = (
+ r_h[:, np.newaxis] * (j_unit_h[:, np.newaxis] * IH) * _Bz * 1e-6
+ ) # MPa
+
+ if _do_b:
+ _Bz = (
+ Bz_h_at_rb[:, np.newaxis] * IH
+ + Bz_b_at_rb[:, np.newaxis] * IB
+ + Bz_s_at_rb[:, np.newaxis] * IS
+ )
+ sigma_b = (
+ r_b[:, np.newaxis] * (j_unit_b[:, np.newaxis] * IB) * _Bz * 1e-6
+ ) # MPa
+
+ if _do_s:
+ _Bz = (
+ Bz_h_at_rs[:, np.newaxis] * IH
+ + Bz_b_at_rs[:, np.newaxis] * IB
+ + Bz_s_at_rs[:, np.newaxis] * IS
+ )
+ sigma_s = (
+ r_s[:, np.newaxis] * (j_unit_s[:, np.newaxis] * IS) * _Bz * 1e-6
+ ) # MPa
+
+ # ------------------------------------------------------------------
+ # 3b. Optional sanity check: fast sigma vs bmap.getHoop row by row.
+ # Skipped for magnet_type="all" — run single-type checks instead.
+ # ------------------------------------------------------------------
+ if check:
+ if magnet_type == "all":
+ print(
+ "\n── Sanity check skipped for magnet_type='all' — run H/B/S separately."
+ )
+ else:
+ print("\n── Sanity check: fast vs bmap.getHoop …")
+ _sigma_check = {"H": sigma_h, "B": sigma_b, "S": sigma_s}[magnet_type]
+ _n_check = {"H": n_tubes, "B": n_bmag, "S": n_umag}[magnet_type]
+ _label_prefix = {"H": "H", "B": "B", "S": "Supra"}[magnet_type]
+ max_err = np.zeros(_n_check)
+
+ for k, row in enumerate(df.itertuples(index=False)):
+ v = _zero_vcurrents()
+ _cnum = 0
+ if n_tubes:
+ v[_cnum] = getattr(row, "IH", 0.0)
+ _cnum += 1
+ if n_bmag:
+ v[_cnum] = getattr(row, "IB", 0.0)
+ _cnum += 1
+ if n_umag:
+ v[_cnum] = getattr(row, "IS", 0.0)
+ mt.set_currents(Tubes, Helices, BMagnets, UMagnets, OHelices, v)
+
+ headers, hoop_values = bmap.getHoop(Tubes, Helices, BMagnets, UMagnets)
+ ref_df = pd.DataFrame.from_records(hoop_values, columns=headers)
+ # Filter to rows belonging to the selected type (by label prefix)
+ mask = ref_df["label"].str.startswith(_label_prefix)
+ ref_hoop = ref_df.loc[mask, "Hoop[MPa]"].to_numpy()
+
+ for i in range(_n_check):
+ if i < len(ref_hoop):
+ max_err[i] = max(
+ max_err[i], abs(_sigma_check[i, k] - ref_hoop[i])
+ )
+
+ col_prefix = {"H": "H", "B": "B", "S": "Supra"}[magnet_type]
+ print(f" Max absolute error per {magnet_type} element [MPa]:")
+ for i in range(_n_check):
+ print(f" {col_prefix}{i+1}: {max_err[i]:.4e} MPa")
+
+ # ------------------------------------------------------------------
+ # 4. Store results in DataFrame
+ # ------------------------------------------------------------------
+ if _do_h and sigma_h is not None:
+ for i in range(n_tubes):
+ df[f"H{i+1}_fast"] = sigma_h[i, :]
+
+ if _do_b and sigma_b is not None:
+ for j in range(n_bmag):
+ df[f"B{j+1}_fast"] = sigma_b[j, :]
+
+ if _do_s and sigma_s is not None:
+ for k in range(n_umag):
+ df[f"Supra{k+1}_fast"] = sigma_s[k, :]
+
+ return df
+
+
+def _expand_pupitre_pattern(
+ pattern: str, pupitre_datadir: str, housing: str
+) -> list[str]:
+ """Expand a glob pattern to matching pupitre file paths.
+
+ For patterns with an explicit directory component, glob them directly.
+ For bare names or bare glob patterns, search in order:
+ 1. cwd
+ 2. pupitre_datadir
+ 3. pupitre_datadir / housing
+
+ Returns all matches from the first directory that yields any result.
+ Falls back to [pattern] unchanged if nothing matches anywhere.
+ """
+ p = Path(pattern)
+ if p.is_absolute() or p.parent != Path("."):
+ matches = sorted(_glob.glob(str(p)))
+ return matches if matches else [pattern]
+
+ search_dirs: list[Path] = [Path.cwd()]
+ if pupitre_datadir:
+ search_dirs.append(Path(pupitre_datadir))
+ if housing and housing not in ("notdefined", ""):
+ search_dirs.append(Path(pupitre_datadir) / housing)
+
+ for base in search_dirs:
+ matches = sorted(_glob.glob(str(base / pattern)))
+ if matches:
+ return matches
+
+ return [pattern]
+
+
+def resolve_pupitre_files(
+ site_name: str,
+ db_path: str,
+ files: list[str] | None = None,
+ pupitre_datadir: str = "",
+ housing: str = "",
+) -> list[str]:
+ """
+ Return the ordered list of pupitre files to process for a site.
+
+ Parameters
+ ----------
+ site_name : Site name registered in DuckDB (e.g. "M9")
+ db_path : Path to the DuckDB file
+ files : Explicit file list from --pupitre.
+ - None or empty → fetch all experiment files for the site.
+ - Non-empty → validate each against the experiments table;
+ files absent from the table trigger a warning
+ but are still included.
+ pupitre_datadir: Root directory for pupitre files (records_base / srv_subdir).
+ Used to resolve bare filenames from the DB.
+ housing : Housing name (e.g. "M9") appended as a subdirectory fallback.
+
+ Returns
+ -------
+ Non-empty list of resolved file paths, sorted by experiment id (DB order) when
+ auto-discovered, or preserving the user's order otherwise.
+
+ Raises
+ ------
+ ValueError if no files can be returned (empty table and no explicit list).
+ """
+ con = duckdb.connect(db_path, read_only=True)
+
+ if not files:
+ rows = con.execute(
+ "SELECT file FROM experiments "
+ "WHERE site_name = ? AND file IS NOT NULL "
+ "ORDER BY id",
+ [site_name],
+ ).fetchall()
+ con.close()
+ result = [r[0] for r in rows if r[0]]
+ if not result:
+ raise ValueError(
+ f"No experiment files found for site '{site_name}'. "
+ "Populate the experiments table or pass --pupitre explicitly."
+ )
+ print(f" Found {len(result)} experiment file(s) for site '{site_name}'.")
+ resolved: list[str] = []
+ for f in result:
+ resolved.extend(_expand_pupitre_pattern(f, pupitre_datadir, housing))
+ return resolved
+
+ # Expand each pattern, then validate each resolved file against the experiments table.
+ # Match by exact path OR by basename — the DB may store absolute paths.
+ resolved = []
+ for pattern in files:
+ expanded = _expand_pupitre_pattern(pattern, pupitre_datadir, housing)
+ for f in expanded:
+ basename = Path(f).name
+ row = con.execute(
+ "SELECT 1 FROM experiments "
+ "WHERE site_name = ? AND (file = ? OR file LIKE ?)",
+ [site_name, f, f"%/{basename}"],
+ ).fetchone()
+ if row is None:
+ print(
+ f" [WARN] '{f}' not found in experiments for site '{site_name}'."
+ )
+ resolved.extend(expanded)
+ con.close()
+ return resolved
+
+
+# ---------------------------------------------------------------------------
+# Step 5 — Annotate with Rpe from DuckDB and print summary
+# ---------------------------------------------------------------------------
+
+
+def annotate_with_rpe(result: dict, site_name: str, db_path: str) -> pd.DataFrame:
+ """
+ Join hoop stress results with Rpe values from DuckDB to compute
+ σ/Rpe safety ratios.
+
+ All coil parts (helix, bitter, supra) are fetched for the site, ordered
+ helices first then bitters then supras (by rank within each type) to match
+ the output order of bmap.getHoop, and aligned positionally with result["x"].
+ """
+ con = duckdb.connect(db_path, read_only=True)
+ rpe_df = con.execute(
+ """
+ SELECT p.name AS part, mat.rpe, mat.nuance
+ FROM magnet_parts mp
+ JOIN parts p ON p.name = mp.part_name
+ JOIN magnets m ON m.name = mp.magnet_name
+ JOIN site_magnets sm ON sm.magnet_name = m.name
+ LEFT JOIN materials mat ON mat.name = p.material_name
+ WHERE sm.site_name = ?
+ AND p.type IN ('helix', 'bitter', 'supra')
+ ORDER BY
+ CASE p.type WHEN 'helix' THEN 0 WHEN 'bitter' THEN 1 ELSE 2 END,
+ mp.rank
+ """,
+ [site_name],
+ ).df()
+ con.close()
+ print(f"rpe: {rpe_df}")
+
+ df = pd.DataFrame(
+ {
+ "coil": result["x"],
+ "hoop_MPa": result["y"],
+ "hoop_max_MPa": result["ymax"],
+ }
+ )
+ df = pd.concat([df, rpe_df.reset_index(drop=True)], axis=1)
+
+ df["rpe"] = df["rpe"] / 1e6 # Pa → MPa
+ df["ratio_rpe"] = df["hoop_MPa"] / df["rpe"]
+ df["ratio_rpe_max"] = df["hoop_max_MPa"] / df["rpe"]
+ return df
+
+
+# ---------------------------------------------------------------------------
+# Step 6 — Plot (matches the chart displayed in the MagnetDB web interface)
+# ---------------------------------------------------------------------------
+
+
+def plot_stress_map(df: pd.DataFrame, magnet_name: str, i_h: float) -> None:
+ x = np.arange(len(df))
+ fig, ax = plt.subplots(figsize=(10, 5))
+ ax.bar(
+ x - 0.2,
+ df["hoop_MPa"],
+ width=0.4,
+ label=f"Hoop stress at I={i_h/1e3:.1f} kA",
+ color="steelblue",
+ )
+ ax.bar(
+ x + 0.2,
+ df["hoop_max_MPa"],
+ width=0.4,
+ label="Hoop stress at I=31 kA (max)",
+ color="tomato",
+ alpha=0.7,
+ )
+ if df["rpe"].notna().any():
+ ax.step(
+ x,
+ df["rpe"],
+ where="mid",
+ color="black",
+ linestyle="--",
+ linewidth=1.5,
+ label="Rpe",
+ )
+ ax.set_xlabel("Coil")
+ ax.set_ylabel("Hoop stress [MPa]")
+ ax.set_title(f"Hoop stress map — {magnet_name}")
+ ax.set_xticks(x)
+ ax.set_xticklabels(df["coil"])
+ ax.legend()
+ ax.grid(axis="y", alpha=0.4)
+ plt.tight_layout()
+ plt.savefig(f"stress_map_{magnet_name}.png", dpi=150)
+ print(f"\nPlot saved to stress_map_{magnet_name}.png")
+ plt.show()
+
+
+# ---------------------------------------------------------------------------
+# Step 4b — Single-point hoop stress for barchart subcommand
+# Restored from the original compute_stress_map logic
+# ---------------------------------------------------------------------------
+
+
+def compute_hoop_at_currents(
+ data: tuple,
+ i_h: float,
+ i_b: float,
+ i_s: float,
+) -> dict:
+ """
+ Compute hoop stress at given currents and at maximum current (31 kA).
+
+ Returns
+ -------
+ dict with keys:
+ x : coil numbers
+ y : hoop stress [MPa] at (i_h, i_b, i_s)
+ ymax : hoop stress [MPa] at maximum current (31 kA)
+ Bz0 : central field [T] at (i_h, i_b, i_s)
+ Bz0_max : central field [T] at 31 kA
+ """
+ print(
+ f"\n── Computing hoop stress at currents IH={i_h} A, IB={i_b} A, IS={i_s} A …"
+ )
+ print(f" MagnetTools data: {type(data)}, {len(data)} elements")
+ Tubes, Helices, OHelices, BMagnets, UMagnets, Shims = data
+
+ def _set_currents(ih, ib, is_):
+ icurrents = mt.get_currents(Tubes, Helices, BMagnets, UMagnets)
+ vcurrents = mt.DoubleVector(icurrents)
+ num = 0
+ if len(Tubes):
+ vcurrents[num] = ih
+ num += 1
+ if len(BMagnets):
+ vcurrents[num] = ib
+ num += 1
+ if len(UMagnets):
+ vcurrents[num] = is_
+ mt.set_currents(
+ Tubes, Helices, BMagnets, UMagnets, OHelices, mt.DoubleVector(vcurrents)
+ )
+
+ def _get_hoop():
+ mdata_type = {"H": Helices, "B": BMagnets, "S": UMagnets}
+ headers, values = bmap.getHoop(Tubes, Helices, BMagnets, UMagnets)
+ hdf = pd.DataFrame.from_records(values, columns=headers)
+ return hdf["num"].tolist(), hdf["Hoop[MPa]"].tolist()
+
+ _set_currents(i_h, i_b, i_s)
+ Bz0 = mt.MagneticField(Tubes, Helices, BMagnets, UMagnets, 0, 0)[1]
+ x, y = _get_hoop()
+
+ _set_currents(31e3, 31e3, 0)
+ Bz0_max = mt.MagneticField(Tubes, Helices, BMagnets, UMagnets, 0, 0)[1]
+ _, ymax = _get_hoop()
+
+ return {"x": x, "y": y, "ymax": ymax, "Bz0": Bz0, "Bz0_max": Bz0_max}
+
+
+# ---------------------------------------------------------------------------
+# Step 5b — Stats from hoop stress history
+# ---------------------------------------------------------------------------
+
+
+def compute_stress_stats(df: pd.DataFrame) -> pd.DataFrame:
+ """Return per-coil descriptive statistics from a validate_fast_from_pupitre DataFrame."""
+ fast_cols = [c for c in df.columns if re.match(r"(H|B|Supra)\d+_fast", c)]
+ rows = []
+ for col in fast_cols:
+ s = df[col]
+ rows.append(
+ {
+ "coil": col,
+ "min": s.min(),
+ "max": s.max(),
+ "mean": s.mean(),
+ "std": s.std(),
+ "p50": s.quantile(0.50),
+ "p95": s.quantile(0.95),
+ "p99": s.quantile(0.99),
+ }
+ )
+ return pd.DataFrame(rows)
+
+
+# ---------------------------------------------------------------------------
+# Step 5c — Rainflow fatigue counting
+# ---------------------------------------------------------------------------
+
+
+def compute_fatigue(df: pd.DataFrame, col: str) -> pd.DataFrame:
+ """
+ Apply rainflow cycle counting to one hoop-stress time series column.
+
+ Requires the ``rainflow`` package (pip install rainflow).
+
+ Returns
+ -------
+ DataFrame with columns: range, mean, count, i_start, i_end
+ """
+ import rainflow
+
+ sigma = df[col].to_numpy()
+ cycles = list(rainflow.count_cycles(sigma))
+ return pd.DataFrame(cycles, columns=["range", "mean", "count", "i_start", "i_end"])
+
+
+def plot_fatigue(
+ df: pd.DataFrame,
+ cycles_df: pd.DataFrame,
+ magnet_name: str,
+ col: str,
+ bins: int = 15,
+ output_png: str | None = None,
+) -> None:
+ """Two-panel plot: hoop stress time series + rainflow amplitude histogram."""
+ x = df["t"] if "t" in df.columns else df.index
+ fig, (ax1, ax2) = plt.subplots(2, 1, figsize=(12, 10))
+
+ ax1.plot(x, df[col], color="steelblue", linewidth=1)
+ ax1.set_title(f"Hoop stress time series — {col} ({magnet_name})")
+ ax1.set_xlabel("t [s]" if "t" in df.columns else "index")
+ ax1.set_ylabel("Hoop stress [MPa]")
+ ax1.grid(True, alpha=0.3)
+
+ amplitudes = cycles_df["range"].to_numpy()
+ ax2.hist(amplitudes, bins=bins, color="orange", edgecolor="black", alpha=0.8)
+ ax2.set_title(f"Rainflow fatigue analysis — {col} ({len(cycles_df)} cycles)")
+ ax2.set_xlabel("Cycle amplitude [MPa]")
+ ax2.set_ylabel("Occurrences")
+ ax2.grid(axis="y", linestyle="--", alpha=0.5)
+
+ plt.tight_layout()
+ if output_png is None:
+ output_png = f"fatigue_{col}_{magnet_name}.png"
+ plt.savefig(output_png, dpi=150)
+ print(f"\nPlot saved to {output_png}")
+ plt.close()
+
+
+# ---------------------------------------------------------------------------
+# Step 7 — Normalized time-series plot (matches validate_fast_from_pupitre output)
+# ---------------------------------------------------------------------------
+
+
+def plot_stress_history(
+ df: pd.DataFrame, magnet_name: str, output_png: str | None = None
+) -> None:
+ fast_cols = [c for c in df.columns if re.match(r"H\d+_fast", c)]
+ plot_cols = [c for c in ("IH", "IB") if c in df.columns] + fast_cols
+
+ # Report and drop rows where every plotted column is NaN.
+ nan_counts = {c: int(df[c].isna().sum()) for c in plot_cols if df[c].isna().any()}
+ if nan_counts:
+ print(f" [plot] NaN counts per column: {nan_counts}")
+ mask = df[plot_cols].notna().any(axis=1)
+ n_dropped = int((~mask).sum())
+ if n_dropped:
+ print(f" [plot] dropping {n_dropped} all-NaN rows before plotting")
+ df = df[mask].reset_index(drop=True)
+
+ def _normalize(s: pd.Series) -> pd.Series:
+ lo = s.min(skipna=True)
+ hi = s.max(skipna=True)
+ if pd.isna(lo) or pd.isna(hi) or hi == lo:
+ return pd.Series(np.zeros(len(s)), index=s.index)
+ return (s - lo) / (hi - lo)
+
+ x = (
+ df["t_abs"]
+ if "t_abs" in df.columns
+ else (df["t"] if "t" in df.columns else df.index)
+ )
+
+ plt.figure(figsize=(10, 5))
+ if "IH" in df.columns:
+ plt.plot(
+ x,
+ _normalize(df["IH"]),
+ label=f"IH (max={df['IH'].max(skipna=True):.0f} A)",
+ linewidth=2,
+ )
+ if "IB" in df.columns:
+ plt.plot(
+ x,
+ _normalize(df["IB"]),
+ label=f"IB (max={df['IB'].max(skipna=True):.0f} A)",
+ linewidth=2,
+ )
+ for col in fast_cols:
+ plt.plot(
+ x,
+ _normalize(df[col]),
+ label=f"{col} (max={df[col].max(skipna=True):.2f} MPa)",
+ linewidth=2,
+ )
+ plt.xlabel("t [s]" if "t_abs" in df.columns or "t" in df.columns else "index")
+ plt.ylabel("Normalized value")
+ plt.title(f"Normalized currents and hoop stress — {magnet_name}")
+ plt.grid(True, alpha=0.3)
+ plt.legend()
+ plt.tight_layout()
+ if output_png is None:
+ output_png = f"stress_history_{magnet_name}.png"
+ plt.savefig(output_png, dpi=150)
+ print(f"\nPlot saved to {output_png}")
+ plt.close()
+
+
+# ---------------------------------------------------------------------------
+# Main — subcommand dispatcher
+# ---------------------------------------------------------------------------
+
+
+def _add_shared_args(p: argparse.ArgumentParser) -> None:
+ """Add arguments common to every subcommand."""
+ p.add_argument("site_name", help="Site name as registered in DuckDB (e.g. M9)")
+ p.add_argument(
+ "--db",
+ default=DEFAULT_DB,
+ help=f"Path to the DuckDB file (default: {DEFAULT_DB})",
+ )
+ p.add_argument(
+ "--geometries",
+ default="geometries",
+ help="Directory of YAML geometry files (default: geometries/)",
+ )
+ p.add_argument(
+ "--debug", action="store_true", help="Enable debug output from magnet_setup()"
+ )
+
+
+def _add_pupitre_args(p: argparse.ArgumentParser) -> None:
+ """Add arguments for subcommands that read a pupitre time-series file."""
+ p.add_argument(
+ "--pupitre",
+ nargs="*",
+ default=None,
+ metavar="FILE",
+ help="Pupitre file(s) (.txt, .tdms, .csv). "
+ "Omit to use all experiment files registered for the site.",
+ )
+ p.add_argument(
+ "--records-base",
+ default=str(_DEFAULT_RECORDS_BASE),
+ dest="records_base",
+ metavar="DIR",
+ help=(
+ "Root of the records tree. pupitre files are resolved under "
+ "records-base/srv-subdir[/]. "
+ f"(default: {_DEFAULT_RECORDS_BASE!r})"
+ ),
+ )
+ p.add_argument(
+ "--srv-subdir",
+ default=_DEFAULT_SRV_SUBDIR,
+ dest="srv_subdir",
+ help=f"Subdirectory of records-base for pupitre TXT files "
+ f"(default: {_DEFAULT_SRV_SUBDIR!r})",
+ )
+ p.add_argument(
+ "--use-mrun",
+ action="store_true",
+ help="Load via python_magnetrun.MagnetRun.load_mrun() "
+ "(supports .tdms and path auto-resolution)",
+ )
+ p.add_argument(
+ "--check",
+ action="store_true",
+ help="Validate fast results against bmap.getHoop row by row",
+ )
+ p.add_argument(
+ "--magnet-type",
+ default="all",
+ choices=["H", "B", "S", "all"],
+ help=(
+ "Coil type(s) to compute hoop stress for: "
+ "H (insert helices), B (bitter plates), S (supras), "
+ "all (H + B + S combined). Also selects the reference type for "
+ "--check validation (ignored when magnet-type=all). Default: all"
+ ),
+ )
+
+
+def _load_site(
+ args: argparse.Namespace,
+) -> tuple[list[tuple[tuple, object, str]], str]:
+ """
+ Resolve site → all magnets, prepare geometry directories, and load
+ MagnetTools objects for each.
+
+ Returns ([(data, tempdir, magnet_name), ...], housing).
+ """
+ print(f"\n── Loading site '{args.site_name}' from DB '{args.db}' …")
+ housing, magnets = load_site_config_from_duckdb(args.site_name, args.db)
+ # print(f"magnets: {magnets}")
+ # print(type(magnets[0]))
+
+ site_config = {
+ "name": args.site_name,
+ "magnets": [config for magnet_name, config, _ in magnets],
+ }
+ tempdir = prepare_geometry_directory(
+ args.site_name,
+ site_config,
+ args.db,
+ geometries_dir=args.geometries,
+ )
+
+ for magnet_name, config, _ in magnets:
+ print(
+ f" Prepared geometry directory for magnet '{magnet_name}' at {tempdir} ({config.keys()})"
+ )
+
+ print("\n── Loading MagnetTools objects …")
+ data = load_magnettools(site_config, tempdir, debug=args.debug)
+ Tubes, Helices, OHelices, BMagnets, UMagnets, Shims = data
+ print(
+ f"Tubes: {len(Tubes)} Helices: {len(Helices)} "
+ f"BMagnets: {len(BMagnets)} UMagnets: {len(UMagnets)}"
+ )
+
+ return tempdir, data, magnets, housing
+
+
+def _load_history(args: argparse.Namespace, data: tuple, housing: str) -> pd.DataFrame:
+ """
+ Resolve pupitre files, compute hoop stress for each, and return a single
+ concatenated DataFrame.
+
+ File resolution:
+ - args.pupitre is None or [] → all experiment files for the site (DB order)
+ - args.pupitre is a list → validated against experiments table (warn on miss)
+ """
+ if not housing:
+ raise ValueError(
+ "Housing could not be determined from the site. "
+ "Check that sites.housing is set in the DB."
+ )
+
+ records_base = getattr(args, "records_base", "")
+ srv_subdir = getattr(args, "srv_subdir", _DEFAULT_SRV_SUBDIR)
+ pupitre_datadir = (
+ str(Path(records_base) / srv_subdir) if records_base else ""
+ )
+ files = resolve_pupitre_files(
+ args.site_name,
+ args.db,
+ args.pupitre or None,
+ pupitre_datadir=pupitre_datadir,
+ housing=housing,
+ )
+ print(
+ f"\n── Computing hoop stress time series (housing={housing}, "
+ f"{len(files)} file(s)) …"
+ )
+
+ dfs: list[pd.DataFrame] = []
+ file_starts: list[float | None] = []
+ for f in files:
+ print(f" Processing {f} …")
+ df = validate_fast_from_pupitre(
+ data,
+ f,
+ housing,
+ magnet_type=args.magnet_type,
+ check=args.check,
+ use_mrun=args.use_mrun,
+ site=args.site_name,
+ )
+ dt = parse_filename_timestamp(f)
+ file_starts.append(dt.timestamp() if dt is not None else None)
+ dfs.append(df)
+
+ # Build t_abs: seconds from the first file's start time.
+ # This keeps each file's trace at its real position on the time axis
+ # so multiple files don't overlap at t=0.
+ if len(dfs) > 1 and "t" in dfs[0].columns:
+ t0 = next((s for s in file_starts if s is not None), None)
+ for df, fs in zip(dfs, file_starts):
+ offset = (fs - t0) if (fs is not None and t0 is not None) else 0.0
+ df["t_abs"] = df["t"] + offset
+ result = (
+ pd.concat(dfs, ignore_index=True)
+ .sort_values("t_abs")
+ .reset_index(drop=True)
+ )
+ else:
+ result = dfs[0] if len(dfs) == 1 else pd.concat(dfs, ignore_index=True)
+ if "t" in result.columns:
+ result["t_abs"] = result["t"]
+
+ fast_cols = [c for c in result.columns if re.match(r"H\d+_fast", c)]
+ show_cols = [c for c in ["t", "IH", "IB"] if c in result.columns] + fast_cols
+ print(result[show_cols].head().to_string(index=False))
+ return result
+
+
+def cmd_barchart(args: argparse.Namespace) -> None:
+ tempdir, data, magnets, housing = _load_site(args)
+ try:
+ print(f"\n── Computing hoop stress at Ih={args.i_h/1e3:.1f} kA …")
+ result = compute_hoop_at_currents(data, args.i_h, args.i_b, args.i_s)
+ print(f" Bz0 at requested current : {result['Bz0']:.3f} T")
+ print(f" Bz0 at max current (31kA): {result['Bz0_max']:.3f} T")
+ print(
+ pd.DataFrame(
+ {
+ "coil": result["x"],
+ "hoop_MPa": result["y"],
+ "hoop_max_MPa": result["ymax"],
+ }
+ ).to_string(index=False)
+ )
+
+ print("\n── Annotating with Rpe …")
+ df = annotate_with_rpe(result, args.site_name, args.db)
+ print(
+ df[
+ [
+ "coil",
+ "part",
+ "nuance",
+ "hoop_MPa",
+ "hoop_max_MPa",
+ "rpe",
+ "ratio_rpe_max",
+ ]
+ ].to_string(index=False)
+ )
+
+ print(f"\n── Plotting … (df: {list(df.keys())})")
+ plot_stress_map(df, args.site_name, args.i_h)
+ finally:
+ shutil.rmtree(tempdir, ignore_errors=True)
+
+
+def cmd_history(args: argparse.Namespace) -> None:
+ tempdir, data, magnets, housing = _load_site(args)
+
+ try:
+ df = _load_history(args, data, housing)
+ print("\n── Plotting …")
+ plot_stress_history(df, args.site_name)
+ finally:
+ shutil.rmtree(tempdir, ignore_errors=True)
+
+
+def cmd_stats(args: argparse.Namespace) -> None:
+ tempdir, data, magnets, housing = _load_site(args)
+
+ try:
+ df = _load_history(args, data, housing)
+ print("\n── Statistics …")
+ stats = compute_stress_stats(df)
+ print(stats.to_string(index=False))
+ if args.output:
+ stats.to_csv(args.output, index=False)
+ print(f"\nStats saved to {args.output}")
+ finally:
+ shutil.rmtree(tempdir, ignore_errors=True)
+
+
+def cmd_fatigue(args: argparse.Namespace) -> None:
+ tempdir, data, magnets, housing = _load_site(args)
+ try:
+ df = _load_history(args, data, housing)
+ fast_cols = [c for c in df.columns if re.match(r"H\d+_fast", c)]
+ print(f"\n── Rainflow fatigue analysis ({len(fast_cols)} coil(s)) …")
+ for col in fast_cols:
+ cycles_df = compute_fatigue(df, col)
+ print(f"\n {col}: {len(cycles_df)} cycles detected")
+ print(cycles_df.describe().to_string())
+ plot_fatigue(df, cycles_df, args.site_name, col, bins=args.bins)
+ finally:
+ shutil.rmtree(tempdir, ignore_errors=True)
+
+
+def main():
+ parser = argparse.ArgumentParser(
+ description="Hoop stress analysis for a site using DuckDB + YAML files.",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog=__doc__,
+ )
+ subparsers = parser.add_subparsers(
+ dest="command",
+ required=True,
+ metavar="{barchart,history,stats,fatigue}",
+ )
+
+ # ── barchart ──────────────────────────────────────────────────────────────
+ p_bar = subparsers.add_parser(
+ "barchart",
+ help="Bar chart of hoop stress at given currents vs Rpe",
+ )
+ _add_shared_args(p_bar)
+ p_bar.add_argument(
+ "--i-h", type=float, default=20000.0, help="Helix current [A] (default: 20000)"
+ )
+ p_bar.add_argument(
+ "--i-b", type=float, default=0.0, help="Bitter current [A] (default: 0)"
+ )
+ p_bar.add_argument(
+ "--i-s", type=float, default=0.0, help="Supra current [A] (default: 0)"
+ )
+ p_bar.set_defaults(func=cmd_barchart)
+
+ # ── history ───────────────────────────────────────────────────────────────
+ p_hist = subparsers.add_parser(
+ "history",
+ help="Hoop stress vs time from a pupitre file (normalised plot)",
+ )
+ _add_shared_args(p_hist)
+ _add_pupitre_args(p_hist)
+ p_hist.set_defaults(func=cmd_history)
+
+ # ── stats ─────────────────────────────────────────────────────────────────
+ p_stats = subparsers.add_parser(
+ "stats",
+ help="Descriptive statistics of hoop stress time series",
+ )
+ _add_shared_args(p_stats)
+ _add_pupitre_args(p_stats)
+ p_stats.add_argument(
+ "--output", default=None, help="Save stats table to CSV (default: print only)"
+ )
+ p_stats.set_defaults(func=cmd_stats)
+
+ # ── fatigue ───────────────────────────────────────────────────────────────
+ p_fat = subparsers.add_parser(
+ "fatigue",
+ help="Rainflow cycle counting on hoop stress time series",
+ )
+ _add_shared_args(p_fat)
+ _add_pupitre_args(p_fat)
+ p_fat.add_argument(
+ "--bins", type=int, default=15, help="Number of histogram bins (default: 15)"
+ )
+ p_fat.set_defaults(func=cmd_fatigue)
+
+ args = parser.parse_args()
+ args.func(args)
+
+
+if __name__ == "__main__":
+ main()
diff --git a/to_duckdb/student_queries.py b/to_duckdb/student_queries.py
deleted file mode 100644
index f6aabe8..0000000
--- a/to_duckdb/student_queries.py
+++ /dev/null
@@ -1,161 +0,0 @@
-"""
-student_queries.py
-==================
-Example queries a student can run against the student DuckDB.
-Copy these cells into a Jupyter notebook.
-
-Requirements:
- pip install duckdb pandas
-"""
-
-import duckdb
-import pandas as pd
-
-DB_PATH = "student_magnetdb.duckdb"
-
-con = duckdb.connect(DB_PATH, read_only=True)
-
-# ── 1. Full site hierarchy ─────────────────────────────────────────────────
-print("=== Site hierarchy ===")
-hierarchy = con.execute("""
- SELECT
- s.name AS site,
- m.name AS magnet,
- m.type AS magnet_type,
- p.type AS part_type,
- mp.coil_index, -- Icoil_N column in records (NULL for rings/leads)
- mp.rank, -- position in magnet assembly
- p.name AS part,
- p.geometry,
- mat.nuance,
- mat.rpe / 1e6 AS rpe_MPa
- FROM sites s
- JOIN magnets m ON m.site_name = s.name
- JOIN magnet_parts mp ON mp.magnet_name = m.name
- JOIN parts p ON p.name = mp.part_name
- LEFT JOIN materials mat ON mat.name = p.material_name
- ORDER BY s.name, mp.rank
-""").df()
-print(hierarchy.to_string())
-
-# ── 2. Icoil → part mapping for a specific magnet ─────────────────────────
-print("\n=== Icoil → part mapping for M19061901 ===")
-coil_map = con.execute("""
- SELECT
- 'Icoil' || mp.coil_index AS column_name,
- p.name AS part_name,
- p.type,
- p.geometry,
- mat.nuance,
- mat.rpe / 1e6 AS rpe_MPa,
- mat.electrical_conductivity / 1e6 AS sigma_MS_per_m
- FROM magnet_parts mp
- JOIN parts p ON p.name = mp.part_name
- JOIN magnets m ON m.name = mp.magnet_name
- LEFT JOIN materials mat ON mat.name = p.material_name
- WHERE m.name = 'M19061901'
- AND mp.coil_index IS NOT NULL
- ORDER BY mp.coil_index
-""").df()
-print(coil_map.to_string())
-
-# ── 3. All records for a site ─────────────────────────────────────────────
-print("\n=== Records for M9_M19061901 ===")
-records = con.execute("""
- SELECT id, record_file, status
- FROM experiments
- WHERE site_name = 'M9_M19061901'
- ORDER BY record_file
-""").df()
-print(records.to_string())
-
-# ── 4. Material comparison across all helices ────────────────────────────
-print("\n=== Helix materials summary ===")
-helix_mats = con.execute("""
- SELECT DISTINCT
- mat.name AS material,
- mat.nuance,
- mat.rpe / 1e6 AS rpe_MPa,
- mat.electrical_conductivity / 1e6 AS sigma_MS_per_m,
- mat.young / 1e9 AS E_GPa
- FROM parts p
- JOIN materials mat ON mat.name = p.material_name
- WHERE p.type = 'helix'
- ORDER BY mat.rpe DESC
-""").df()
-print(helix_mats.to_string())
-
-# ── 5. How many coil channels does each magnet have? ─────────────────────
-print("\n=== Coil channel count per magnet ===")
-channels = con.execute("""
- SELECT
- m.name AS magnet,
- m.type,
- COUNT(CASE WHEN mp.coil_index IS NOT NULL THEN 1 END) AS n_coils,
- COUNT(CASE WHEN p.type = 'ring' THEN 1 END) AS n_rings,
- COUNT(CASE WHEN p.type = 'lead' THEN 1 END) AS n_leads
- FROM magnets m
- JOIN magnet_parts mp ON mp.magnet_name = m.name
- JOIN parts p ON p.name = mp.part_name
- GROUP BY m.name, m.type
- ORDER BY m.type, m.name
-""").df()
-print(channels.to_string())
-
-# ── 6. Parts shared across multiple magnets (reused helices/rings) ────────
-print("\n=== Parts used in more than one magnet ===")
-shared = con.execute("""
- SELECT
- p.name, p.type,
- COUNT(DISTINCT mp.magnet_name) AS n_magnets,
- STRING_AGG(mp.magnet_name, ', ' ORDER BY mp.magnet_name) AS in_magnets
- FROM magnet_parts mp
- JOIN parts p ON p.name = mp.part_name
- GROUP BY p.name, p.type
- HAVING COUNT(DISTINCT mp.magnet_name) > 1
- ORDER BY n_magnets DESC, p.type
-""").df()
-print(shared.to_string())
-
-# ── 7. All sites in which a magnet has been used, sorted by commission date ─
-print("\n=== Sites where magnet M19071101 has been used ===")
-magnet_sites = con.execute("""
- SELECT
- s.name AS site,
- s.housing,
- s.status,
- s.commissioned_at,
- s.decommissioned_at
- FROM site_magnets sm
- JOIN sites s ON s.name = sm.site_name
- WHERE sm.magnet_name = 'M19071101'
- ORDER BY s.commissioned_at ASC NULLS LAST
-""").df()
-print(magnet_sites.to_string())
-
-# ── 8. All magnets and sites in which a part has been used,
-# sorted by site commission date ─────────────────────────────────────
-print("\n=== Sites and magnets where part H15101601 has been used ===")
-part_history = con.execute("""
- SELECT
- p.name AS part,
- p.type,
- mp.coil_index,
- m.name AS magnet,
- m.type AS magnet_type,
- s.name AS site,
- s.housing,
- s.commissioned_at,
- s.decommissioned_at
- FROM magnet_parts mp
- JOIN parts p ON p.name = mp.part_name
- JOIN magnets m ON m.name = mp.magnet_name
- JOIN site_magnets sm ON sm.magnet_name = m.name
- JOIN sites s ON s.name = sm.site_name
- WHERE p.name = 'H15101601'
- AND p.type IN ('helix', 'bitter')
- ORDER BY s.commissioned_at ASC NULLS LAST
-""").df()
-print(part_history.to_string())
-
-con.close()
diff --git a/to_duckdb/student_statheures_note.md b/to_duckdb/student_statheures_note.md
deleted file mode 100644
index 627770e..0000000
--- a/to_duckdb/student_statheures_note.md
+++ /dev/null
@@ -1,275 +0,0 @@
-# Student Note — Field-Time Statistics with DuckDB
-
-> This note explains how to apply the `statheures` statistics plan
-> (`statheures_stats_implementation.md`) using the student DuckDB database
-> and the TSV record files shipped alongside it.
->
-> You do **not** need `python_magnetrun` or `PandasMagnetData` for this work.
-> Load record files directly with `pandas.read_csv`.
-
----
-
-## What you already have
-
-```
-student_data/
-├── student_magnetdb.duckdb ← structural metadata + experiment index
-└── records/
- ├── M10_2025.11.13---09:14:21.txt
- ├── M10_2025.11.13---13:08:27.txt
- └── ... ← one TSV file per operational run
-```
-
-The DuckDB database gives you:
-
-- `sites` — hall, status, commissioning dates
-- `magnets`, `parts`, `materials` — magnet configuration hierarchy
-- `site_magnets` — which magnets operated in each site
-- `experiments` — one row per record file, with the filename that locates the TSV
-
----
-
-## What `PandasMagnetData` does (and how to replace it)
-
-In the full MagnetDB codebase, `PandasMagnetData` is a class from
-`python_magnetrun` that wraps loading a record file into a pandas DataFrame.
-Its three key methods are:
-
-| `PandasMagnetData` method | What it returns | Student equivalent |
-|---|---|---|
-| `run.getData()` | pandas DataFrame of the record | `pd.read_csv(filepath, sep='\t')` |
-| `run.getRunRef()` | Run identifier string | `experiments.name` from DuckDB |
-| `run.getMagnetRef()` | Magnet/site reference string | `experiments.site_name` from DuckDB |
-
-### Loading a record file
-
-```python
-import pandas as pd
-
-df = pd.read_csv("student_data/records/M10_2025.11.13---09:14:21.txt", sep='\t')
-print(df.columns.tolist())
-# Typical columns: t, Field, Icoil1, Icoil2, ..., Tin1, Tout, ...
-```
-
-Key columns for the statheures statistics:
-
-| Column | Description | Unit |
-|--------|-------------|------|
-| `t` | Elapsed time since start of run | s |
-| `Field` | Central magnetic field (Hall probe) | T |
-| `Icoil1`…`IcoilN` | Currents per power supply | A |
-| `timestamp` | Wall-clock datetime (if present) | — |
-
-> **Sampling interval**: each row is one sample. The sampling interval is
-> typically 10 seconds, but verify with `df['t'].diff().median()` on your
-> actual files. The conversion factor `COUNT(*) × dt / 3600` gives hours,
-> where `dt` is the interval in seconds.
-
----
-
-## Mapping the plan to your DuckDB workflow
-
-The plan in `statheures_stats_implementation.md` assumes all data is already
-in a single DataFrame indexed by datetime. With individual TSV files and DuckDB,
-the workflow has one extra step: **look up which files belong to which site
-before loading them**.
-
-### Full adapted workflow
-
-```
-DuckDB (experiments table)
- │ query: SELECT file FROM experiments WHERE site_name = '...'
- │
- ▼
-Record file list
- │ for each file: pd.read_csv(records_dir / file, sep='\t')
- │
- ▼
-pandas DataFrame (one per file)
- │ bin Field column → field_bin
- │ count rows × dt / 3600 → hours
- │
- ▼ incremental accumulation (additive — see Section 4 of the plan)
-Accumulated bin counts
- │
- ▼ (optional) write back to DuckDB
-field_bin_counts table → yearly_hours(), compare_intervals(), ...
-```
-
-The key insight from Section 4 of the plan is that **bin counts are additive**:
-you never need all files in memory at once. Accumulate counts file by file,
-convert to hours only at the end.
-
----
-
-## Concrete implementation
-
-See `student_statheures_demo.py` for a full working script. The main functions are:
-
-### 1. Get experiments for a site from DuckDB
-
-```python
-import duckdb
-
-def get_experiments(site_name: str, db_path: str, records_dir: str) -> list[dict]:
- """Return list of {name, file, path} for all experiments at a site."""
- con = duckdb.connect(db_path, read_only=True)
- rows = con.execute("""
- SELECT name, file FROM experiments
- WHERE site_name = ? ORDER BY name
- """, [site_name]).fetchall()
- con.close()
- return [
- {"name": name, "file": file,
- "path": str(Path(records_dir) / file)}
- for name, file in rows
- ]
-```
-
-### 2. Compute bin counts for one file (Section 3 of the plan)
-
-```python
-def bin_counts(df: pd.DataFrame, step=1.0, champmin=0.0, champmax=36.0,
- field_col='Field') -> pd.Series:
- """
- Return Series: field_bin (lower edge, T) → sample COUNT.
- Store counts, not hours — hours are computed at query time.
- Mirrors bin_counts() from Section 4 of the plan.
- """
- mask = df[field_col].between(champmin, champmax)
- bins = (df.loc[mask, field_col] // step) * step
- return bins.value_counts().sort_index().rename('count')
-```
-
-### 3. Accumulate across all files for a site
-
-```python
-from pathlib import Path
-import pandas as pd
-import numpy as np
-
-def compute_site_hours(site_name, db_path, records_dir,
- step=1.0, champmin=0.0, champmax=36.0):
- experiments = get_experiments(site_name, db_path, records_dir)
- accumulated = pd.Series(dtype=float)
-
- for exp in experiments:
- if not Path(exp["path"]).exists():
- print(f" [SKIP] {exp['file']} not found")
- continue
- df = pd.read_csv(exp["path"], sep='\t')
- if 'Field' not in df.columns:
- print(f" [SKIP] {exp['file']} has no Field column")
- continue
-
- dt = df['t'].diff().median() if 't' in df.columns else 10.0
- counts = bin_counts(df, step, champmin, champmax)
- hours = counts * dt / 3600.0
-
- accumulated = accumulated.add(hours, fill_value=0)
-
- return accumulated.rename('heures').sort_index()
-```
-
-### 4. Two-interval comparison (Section 3 of the plan)
-
-With individual TSV files you filter by the experiment name (which encodes
-the run date) rather than a datetime index:
-
-```python
-def compute_site_hours_for_year(site_name, year, db_path, records_dir, step=1.0):
- """Hours per field bin for a specific year, using filename date."""
- con = duckdb.connect(db_path, read_only=True)
- rows = con.execute("""
- SELECT name, file FROM experiments
- WHERE site_name = ?
- AND CAST(SUBSTRING(file, 4, 4) AS INTEGER) = ?
- ORDER BY name
- """, [site_name, year]).fetchall()
- con.close()
-
- accumulated = pd.Series(dtype=float)
- for name, file in rows:
- path = Path(records_dir) / file
- if not path.exists():
- continue
- df = pd.read_csv(path, sep='\t')
- dt = df['t'].diff().median() if 't' in df.columns else 10.0
- accumulated = accumulated.add(
- bin_counts(df) * dt / 3600.0, fill_value=0
- )
- return accumulated.rename('heures').sort_index()
-
-# Two-year comparison — same pattern as Section 3 of the plan
-h2024 = compute_site_hours_for_year('M10_M19071101_13', 2025, ...)
-h2025 = compute_site_hours_for_year('M10_M19071101_13', 2026, ...)
-comparison = pd.concat([h2024.rename('2025'), h2025.rename('2026')], axis=1).fillna(0)
-```
-
----
-
-## Optional: persist bin counts back to DuckDB
-
-If you want to follow the full Section 6 schema from the plan (storing pre-computed
-counts to avoid re-reading TSV files), you can add two tables to the existing
-student DuckDB. This lets you query hours instantly without reading any TSV files.
-
-```python
-STATS_SCHEMA = """
-CREATE TABLE IF NOT EXISTS processed_experiments (
- file VARCHAR PRIMARY KEY,
- site_name VARCHAR,
- n_samples INTEGER,
- dt_seconds DOUBLE,
- processed_at TIMESTAMP DEFAULT now()
-);
-
-CREATE TABLE IF NOT EXISTS field_bin_counts (
- site_name VARCHAR,
- file VARCHAR,
- year INTEGER,
- month INTEGER,
- field_bin DOUBLE,
- sample_count BIGINT,
- PRIMARY KEY (site_name, file, year, month, field_bin)
-);
-"""
-```
-
-See the demo script for `process_and_store()` which populates these tables,
-and `query_yearly_hours()` / `query_compare_intervals()` which read from them.
-
----
-
-## Differences from the original plan
-
-| Plan assumption | Student reality | Adaptation |
-|---|---|---|
-| `PandasMagnetData(filepath).getData()` | `pd.read_csv(path, sep='\t')` | Direct load — no wrapper needed |
-| `run.getMagnetRef()` | `experiments.site_name` in DuckDB | Query DuckDB for site context |
-| `run.getRunRef()` | `experiments.name` in DuckDB | Already in the index |
-| Files in a single folder, glob `*.csv` | Files listed in `experiments` table | Query DuckDB to get file list |
-| `timestamp` column as index | `t` column (elapsed seconds) | Use filename to extract run date; use `t` for duration |
-| Sampling always 10 s | Verify with `df['t'].diff().median()` | Use actual `dt` per file |
-
----
-
-## Exercises
-
-1. **Basic histogram**: compute and plot hours per field bin (1 T steps) for one site
- across all available records. Use `matplotlib` bar chart.
-
-2. **Year comparison**: compare 2025 vs 2026 operations for site `M10_M19071101_13`
- using the two-interval pattern from Section 3.
-
-3. **Per-magnet breakdown**: the site has two magnets (`M19071101` insert and
- `M10Bitters`). The `Field` column reflects the combined field. Explore whether
- the `Icoil1`…`IcoilN` channel currents correlate with the field bins — do
- higher field bins correspond to higher currents on all helices proportionally?
-
-4. **Persistence**: implement `process_and_store()` to populate `field_bin_counts`,
- then verify that querying the table gives the same result as the direct
- file-by-file computation.
-
-5. **Bin width sensitivity**: repeat the histogram with `step = 0.5 T` and `step = 2 T`.
- How does the choice of bin width affect the interpretation?
diff --git a/to_duckdb/student_stress_map.py b/to_duckdb/student_stress_map.py
deleted file mode 100644
index c7421f8..0000000
--- a/to_duckdb/student_stress_map.py
+++ /dev/null
@@ -1,563 +0,0 @@
-"""
-student_stress_map.py
-=====================
-Demonstrates how to compute a hoop stress map for a magnet using the
-student DuckDB database and local YAML geometry files, without any
-Django or MagnetDB infrastructure.
-
-This script replicates the full chain of:
-
- python_magnetdb/actions/compute_stress_map_chart.py
- python_magnetdb/actions/generate_simulation_config.py
- python_magnetdb/actions/generate_magnet_directory.py
- python_magnetdb/actions/object_geometries.py
-
-replacing only the Django/ORM data access layer with DuckDB queries.
-Everything from magnet_setup() onwards is identical to the production code.
-
-MagnetDB production chain
---------------------------
- Django ORM (Magnet model)
- │
- ├── generate_magnet_config(magnet_id)
- │ → config dict {"geom": ..., "Helix": [...], "Ring": [...]}
- │
- ├── generate_magnet_directory(magnet_id, tempdir)
- │ → writes {part_name}.yaml files to tempdir/data/geometries/
- │
- ├── appenv(yaml_repo=..., ...)
- │ → environment object pointing at file locations
- │
- ├── magnet_setup(env, config, debug)
- │ → (Tubes, Helices, OHelices, BMagnets, UMagnets, Shims)
- │
- └── compute_stress_map_chart(data, i_h, i_b, i_s, magnet_type)
- → {"x": [...], "y": [...], "ymax": [...]}
-
-Student chain (this script)
------------------------------
- DuckDB + YAML files on disk
- │
- ├── load_magnet_config_from_duckdb(magnet_name) ← replaces generate_magnet_config
- │
- ├── prepare_geometry_directory(magnet_name, ...) ← replaces generate_magnet_directory
- │
- ├── appenv(...) ← identical
- │
- ├── magnet_setup(env, config, debug) ← identical
- │
- └── compute_stress_map(data, i_h, i_b, i_s) ← identical logic
-
-Required files on disk (shipped with the student dataset)
-----------------------------------------------------------
- student_data/
- ├── student_magnetdb.duckdb
- ├── geometries/ ← YAML files from python_magnetsetup/data/geometries/
- │ ├── HL-31.yaml
- │ ├── HL-31_H1.yaml
- │ ├── ...
- │ ├── Ring-H1H2.yaml
- │ └── ...
- └── records/
- └── *.txt
-
-Requirements
-------------
- pip install duckdb pandas matplotlib
- # Plus system packages:
- # python3-magnettools (provides magnettools.magnettools, magnettools.Bmap)
- # python_magnetsetup (provides python_magnetsetup.ana, python_magnetsetup.config)
-
-Note on Rpe units
------------------
-In the DuckDB database, Rpe is stored as-is from the seed files.
-Some seed files store it in Pa (e.g. 481e6), others in MPa (e.g. 481).
-The config passed to magnet_setup() carries this value unchanged, exactly
-as generate_simulation_config.py does. Verify the unit for your specific
-dataset before interpreting ratio_rpe values.
-"""
-
-import argparse
-import json
-import shutil
-import tempfile
-from pathlib import Path
-
-import duckdb
-import matplotlib.pyplot as plt
-import pandas as pd
-
-import magnettools.Bmap as bmap
-import magnettools.magnettools as mt
-from python_magnetsetup.ana import magnet_setup
-from python_magnetsetup.config import appenv
-
-# ---------------------------------------------------------------------------
-# Step 1 — Build config dict from DuckDB
-# Replicates generate_magnet_config() in generate_simulation_config.py
-# ---------------------------------------------------------------------------
-
-def _format_material_row(row: dict) -> dict:
- """Map DuckDB column names to the format expected by magnet_setup().
- Mirrors format_material() in generate_simulation_config.py exactly.
- """
- return {
- "Tref": row["t_ref"],
- "VolumicMass": row["volumic_mass"],
- "alpha": row["alpha"],
- "ElectricalConductivity": row["electrical_conductivity"],
- "MagnetPermeability": row["magnet_permeability"],
- "Poisson": row["poisson"],
- "Rpe": row["rpe"], # unit: see module docstring
- "SpecificHeat": row["specific_heat"],
- "ThermalConductivity": row["thermal_conductivity"],
- "Young": row["young"],
- "CoefDilatation": row["expansion_coefficient"],
- "nuance": row["nuance"],
- }
-
-
-def load_magnet_config_from_duckdb(magnet_name: str, db_path: str) -> dict:
- """
- Build the config dict that magnet_setup() expects, reading from DuckDB
- instead of the Django ORM.
-
- Produces a dict with the same structure as generate_magnet_config():
- {
- "geom": "M19061901.yaml",
- "Helix": [
- {"geom": "H15101601.yaml", "material": {...}, "insulator": {...}},
- ...
- ],
- "Ring": [
- {"geom": "M19061901_R1.yaml", "material": {...}, "insulator": {...}},
- ...
- ]
- }
-
- Notes
- -----
- - "geom" keys use {part.name}.yaml, matching generate_magnet_directory()
- which writes files named after parts, not geometry stems.
- - Part sections are keyed by capitalised type: Helix, Ring, Bitter, Lead.
- - Parts are ordered by magnet_parts.rank, preserving assembly order.
- - MAT_ISOLANT must be present in the DB (loaded via seeds_to_duckdb.py).
- """
- con = duckdb.connect(db_path, read_only=True)
-
- # Fetch insulator (MAT_ISOLANT) — required for every part entry
- isolant_rows = con.execute("""
- SELECT t_ref, volumic_mass, alpha, electrical_conductivity,
- magnet_permeability, poisson, rpe, specific_heat,
- thermal_conductivity, young, expansion_coefficient, nuance
- FROM materials WHERE name = 'MAT_ISOLANT'
- """).fetchall()
-
- if not isolant_rows:
- raise ValueError(
- "MAT_ISOLANT not found in the database. "
- "Run seeds_to_duckdb.py to populate structural data first."
- )
- insulator_payload = _format_material_row(dict(zip(
- ["t_ref", "volumic_mass", "alpha", "electrical_conductivity",
- "magnet_permeability", "poisson", "rpe", "specific_heat",
- "thermal_conductivity", "young", "expansion_coefficient", "nuance"],
- isolant_rows[0]
- )))
-
- # Fetch all parts for this magnet, ordered by assembly rank
- parts = con.execute("""
- SELECT
- p.name AS part_name,
- p.type AS part_type,
- mp.rank,
- mat.t_ref, mat.volumic_mass, mat.alpha,
- mat.electrical_conductivity, mat.magnet_permeability,
- mat.poisson, mat.rpe, mat.specific_heat,
- mat.thermal_conductivity, mat.young,
- mat.expansion_coefficient, mat.nuance
- FROM magnet_parts mp
- JOIN parts p ON p.name = mp.part_name
- JOIN magnets m ON m.name = mp.magnet_name
- LEFT JOIN materials mat ON mat.name = p.material_name
- WHERE m.name = ?
- ORDER BY mp.rank
- """, [magnet_name]).fetchall()
-
- con.close()
-
- if not parts:
- raise ValueError(
- f"Magnet '{magnet_name}' not found in DB or has no parts. "
- f"Check the magnet name and ensure seeds are loaded."
- )
-
- col_names = [
- "part_name", "part_type", "rank",
- "t_ref", "volumic_mass", "alpha",
- "electrical_conductivity", "magnet_permeability",
- "poisson", "rpe", "specific_heat",
- "thermal_conductivity", "young",
- "expansion_coefficient", "nuance",
- ]
-
- config = {"geom": f"{magnet_name}.yaml"}
-
- for row in parts:
- d = dict(zip(col_names, row))
- key = d["part_type"].capitalize() # "Helix", "Ring", "Bitter", "Lead"
- if key not in config:
- config[key] = []
- config[key].append({
- "geom": f"{d['part_name']}.yaml",
- "material": _format_material_row(d),
- "insulator": insulator_payload,
- })
-
- return config
-
-
-# ---------------------------------------------------------------------------
-# Step 2 — Prepare geometry directory on disk
-# Replicates generate_magnet_directory() without Django
-# ---------------------------------------------------------------------------
-
-def prepare_geometry_directory(
- magnet_name: str,
- config: dict,
- db_path: str,
- geometries_dir: str | Path | None = None,
-) -> Path:
- """
- Build a temporary directory tree that magnet_setup() can read:
-
- /
- ├── config.json
- └── data/
- ├── geometries/
- │ ├── {magnet_name}.yaml ← top-level insert/bitters geometry
- │ ├── {part_name}.yaml ← one file per part
- │ └── ...
- └── cad/
-
- Geometry YAML files are written from one of two sources (tried in order):
- 1. ``geometry_data`` column in DuckDB — JSON-serialized python_magnetgeo object
- stored by add_magnet.py at import time. No external files needed.
- 2. ``geometries_dir`` fallback — a directory of pre-extracted YAML files
- (used for seed-based data that pre-dates geometry_data storage).
-
- Returns the Path of the created temp directory (caller should clean up).
- """
- src_dir = Path(geometries_dir) if geometries_dir else None
- if src_dir is not None and not src_dir.is_dir():
- print(f" [WARN] geometries_dir not found: {src_dir} — will rely on DB-stored geometry_data.")
- src_dir = None
-
- tempdir = Path(tempfile.mkdtemp(prefix=f"magnetdb_student_{magnet_name}_"))
- data_geom = tempdir / "data" / "geometries"
- data_geom.mkdir(parents=True)
- (tempdir / "data" / "cad").mkdir()
-
- # Look up {part_name} → {geometry_stem, geometry_data} and magnet geometry from DuckDB
- con = duckdb.connect(db_path, read_only=True)
- part_rows = con.execute("""
- SELECT p.name, p.geometry, p.geometry_data
- FROM magnet_parts mp
- JOIN parts p ON p.name = mp.part_name
- JOIN magnets m ON m.name = mp.magnet_name
- WHERE m.name = ?
- """, [magnet_name]).fetchall()
- magnet_row = con.execute(
- "SELECT geometry, geometry_data FROM magnets WHERE name = ?", [magnet_name]
- ).fetchone()
- con.close()
-
- # Write top-level magnet geometry: stem/geometry_data → {magnet_name}.yaml
- magnet_geom_stem = magnet_row[0] if magnet_row else magnet_name
- magnet_geom_data = magnet_row[1] if magnet_row else None
- _write_yaml(src_dir, magnet_geom_stem, magnet_geom_data, data_geom, magnet_name)
-
- # Write per-part geometries: stem/geometry_data → {part_name}.yaml
- for part_name, geom_stem, geom_data in part_rows:
- _write_yaml(src_dir, geom_stem, geom_data, data_geom, part_name)
-
- # Write config.json alongside the data/ tree
- with open(tempdir / "config.json", "w") as f:
- json.dump(config, f, indent=2)
-
- return tempdir
-
-
-def _yaml_from_geometry_data(geometry_data_json: str, dst_path: Path) -> bool:
- """
- Reconstruct a python_magnetgeo object from its DB-stored JSON and write it
- as a YAML file at dst_path. Returns True on success.
-
- The JSON is produced by add_magnet.py at import time via
- python_magnetgeo.deserialize.serialize_instance. This function reverses
- that: JSON → python_magnetgeo object → YAML string → file.
- """
- try:
- import json as _json
- import yaml as _yaml
- from python_magnetgeo.deserialize import unserialize_object
- d = _json.loads(geometry_data_json)
- obj = unserialize_object(d)
- dst_path.write_text(_yaml.dump(obj, default_flow_style=False, sort_keys=False))
- return True
- except Exception as exc:
- print(f" [WARN] Could not reconstruct geometry from DB JSON for {dst_path.name}: {exc}")
- return False
-
-
-def _write_yaml(
- src_dir: Path,
- stem: str | None,
- geometry_data: str | None,
- dst_dir: Path,
- dst_stem: str,
-) -> None:
- """
- Write a geometry YAML file named ``{dst_stem}.yaml`` into dst_dir.
-
- Strategy (in order):
- 1. If geometry_data (JSON) is available in the DB, reconstruct the
- python_magnetgeo object and dump it as YAML — no external files needed.
- 2. Otherwise fall back to copying ``{stem}.yaml`` from src_dir (legacy
- behaviour for seed-based data that has a geometries directory).
- """
- dst = dst_dir / f"{dst_stem}.yaml"
- if geometry_data:
- if _yaml_from_geometry_data(geometry_data, dst):
- return
- # Fallback: copy from geometries directory
- if stem and src_dir:
- # stem may be a full path (from add_magnet) or a bare stem (from seeds)
- src = src_dir / f"{Path(stem).stem}.yaml"
- if src.exists():
- shutil.copy(src, dst)
- return
- print(f" [WARN] No geometry source found for {dst_stem}.yaml")
-
-
-# ---------------------------------------------------------------------------
-# Step 3 — Load MagnetTools objects
-# Replicates get_magnet_data() in object_geometries.py without Django
-# ---------------------------------------------------------------------------
-
-def load_magnettools(config: dict, tempdir: Path, debug: bool = False) -> tuple:
- """
- Call magnet_setup() from python_magnetsetup with the prepared directory,
- returning (Tubes, Helices, OHelices, BMagnets, UMagnets, Shims).
-
- This is identical to the body of get_magnet_data() in object_geometries.py.
- """
- data_dir = str(tempdir / "data")
- env = appenv(
- envfile=None,
- url_api=data_dir,
- yaml_repo=f"{data_dir}/geometries",
- cad_repo=f"{data_dir}/cad",
- mesh_repo=data_dir,
- simage_repo=data_dir,
- mrecord_repo=data_dir,
- optim_repo=data_dir,
- )
- return magnet_setup(env, config, debug)
-
-
-# ---------------------------------------------------------------------------
-# Step 4 — Compute hoop stress map
-# Direct port of compute_stress_map_chart() in compute_stress_map_chart.py
-# ---------------------------------------------------------------------------
-
-def compute_stress_map(
- data: tuple,
- i_h: float,
- i_b: float,
- i_s: float,
- magnet_type: str = "H",
-) -> dict:
- """
- Compute hoop stress at given currents and at maximum current (31 kA).
-
- Parameters
- ----------
- data : MagnetTools tuple from load_magnettools()
- i_h : helix current [A]
- i_b : bitter current [A]
- i_s : supra current [A]
- magnet_type : "H" for insert helices, "B" for bitters
-
- Returns
- -------
- dict with keys:
- x : part numbers (coil indices)
- y : hoop stress [MPa] at (i_h, i_b, i_s)
- ymax : hoop stress [MPa] at maximum current (31 kA)
- Bz0 : central field [T] at (i_h, i_b, i_s)
- Bz0_max : central field [T] at maximum current
- """
- (Tubes, Helices, OHelices, BMagnets, UMagnets, Shims) = data
-
- def _set_currents(ih, ib, is_):
- icurrents = mt.get_currents(Tubes, Helices, BMagnets, UMagnets)
- vcurrents = list(icurrents)
- num = 0
- if len(Tubes) != 0: vcurrents[num] = ih; num += 1
- if len(BMagnets) != 0: vcurrents[num] = ib; num += 1
- if len(UMagnets) != 0: vcurrents[num] = is_; num += 1
- mt.set_currents(Tubes, Helices, BMagnets, UMagnets, OHelices,
- mt.DoubleVector(vcurrents))
-
- def _get_hoop() -> tuple[list, list]:
- mdata = {"H": Helices, "B": BMagnets, "S": UMagnets}
- (headers, values) = bmap.getHoop(
- mdata[magnet_type], Tubes, Helices, BMagnets, UMagnets, magnet_type
- )
- df = pd.DataFrame.from_records(values)
- df.columns = headers
- return df["num"].tolist(), df["Hoop[MPa]"].tolist()
-
- # At requested currents
- _set_currents(i_h, i_b, i_s)
- Bz0 = mt.MagneticField(Tubes, Helices, BMagnets, UMagnets, 0, 0)[1]
- x, y = _get_hoop()
-
- # At maximum current (31 kA) — same logic as compute_max() in original
- _set_currents(31e3, 31e3, 0)
- Bz0_max = mt.MagneticField(Tubes, Helices, BMagnets, UMagnets, 0, 0)[1]
- _, ymax = _get_hoop()
-
- return {"x": x, "y": y, "ymax": ymax, "Bz0": Bz0, "Bz0_max": Bz0_max}
-
-
-# ---------------------------------------------------------------------------
-# Step 5 — Annotate with Rpe from DuckDB and print summary
-# ---------------------------------------------------------------------------
-
-def annotate_with_rpe(result: dict, magnet_name: str, db_path: str) -> pd.DataFrame:
- """
- Join hoop stress results with Rpe values from DuckDB to compute
- σ/Rpe safety ratios.
- """
- con = duckdb.connect(db_path, read_only=True)
- rpe_df = con.execute("""
- SELECT mp.coil_index, p.name AS part, mat.rpe, mat.nuance
- FROM magnet_parts mp
- JOIN parts p ON p.name = mp.part_name
- JOIN magnets m ON m.name = mp.magnet_name
- LEFT JOIN materials mat ON mat.name = p.material_name
- WHERE m.name = ? AND mp.coil_index IS NOT NULL
- ORDER BY mp.coil_index
- """, [magnet_name]).df()
- con.close()
-
- df = pd.DataFrame({
- "coil_index": result["x"],
- "hoop_MPa": result["y"],
- "hoop_max_MPa": result["ymax"],
- })
- df = df.merge(rpe_df, on="coil_index", how="left")
-
- # ratio_rpe is only meaningful if rpe is in the same unit as hoop_MPa.
- # See the module docstring for the unit caveat.
- df["ratio_rpe"] = df["hoop_MPa"] / df["rpe"]
- df["ratio_rpe_max"] = df["hoop_max_MPa"] / df["rpe"]
- return df
-
-
-# ---------------------------------------------------------------------------
-# Step 6 — Plot (matches the chart displayed in the MagnetDB web interface)
-# ---------------------------------------------------------------------------
-
-def plot_stress_map(df: pd.DataFrame, magnet_name: str, i_h: float) -> None:
- fig, ax = plt.subplots(figsize=(10, 5))
- ax.bar(df["coil_index"] - 0.2, df["hoop_MPa"], width=0.4,
- label=f"Hoop stress at I={i_h/1e3:.1f} kA", color="steelblue")
- ax.bar(df["coil_index"] + 0.2, df["hoop_max_MPa"], width=0.4,
- label="Hoop stress at I=31 kA (max)", color="tomato", alpha=0.7)
- if df["rpe"].notna().any():
- ax.step(df["coil_index"], df["rpe"], where="mid",
- color="black", linestyle="--", linewidth=1.5, label="Rpe")
- ax.set_xlabel("Coil index (Icoil_N)")
- ax.set_ylabel("Hoop stress [MPa]")
- ax.set_title(f"Hoop stress map — {magnet_name}")
- ax.set_xticks(df["coil_index"])
- ax.legend()
- ax.grid(axis="y", alpha=0.4)
- plt.tight_layout()
- plt.savefig(f"stress_map_{magnet_name}.png", dpi=150)
- print(f"\nPlot saved to stress_map_{magnet_name}.png")
- plt.show()
-
-
-# ---------------------------------------------------------------------------
-# Main
-# ---------------------------------------------------------------------------
-
-def main():
- parser = argparse.ArgumentParser(
- description="Compute hoop stress map for a magnet using DuckDB + YAML files.",
- formatter_class=argparse.RawDescriptionHelpFormatter,
- epilog=__doc__,
- )
- parser.add_argument("magnet_name",
- help="Magnet name as registered in DuckDB (e.g. M19061901)")
- parser.add_argument("--db", default="student_magnetdb.duckdb",
- help="Path to the student DuckDB (default: student_magnetdb.duckdb)")
- parser.add_argument("--geometries", default="geometries",
- help="Directory of YAML geometry files (default: geometries/)")
- parser.add_argument("--i-h", type=float, default=20000.0,
- help="Helix current in A (default: 20000 A)")
- parser.add_argument("--i-b", type=float, default=0.0,
- help="Bitter current in A (default: 0 A)")
- parser.add_argument("--i-s", type=float, default=0.0,
- help="Supra current in A (default: 0 A)")
- parser.add_argument("--magnet-type", default="H", choices=["H", "B", "S"],
- help="Part type to compute hoop stress for (default: H)")
- parser.add_argument("--debug", action="store_true",
- help="Enable debug output from magnet_setup()")
- args = parser.parse_args()
-
- print(f"\n── Loading config from DuckDB for '{args.magnet_name}' …")
- config = load_magnet_config_from_duckdb(args.magnet_name, args.db)
- n_helices = len(config.get("Helix", []))
- n_rings = len(config.get("Ring", []))
- n_bitters = len(config.get("Bitter", []))
- print(f" Helix: {n_helices} Ring: {n_rings} Bitter: {n_bitters}")
-
- print(f"\n── Preparing geometry directory …")
- tempdir = prepare_geometry_directory(
- args.magnet_name, config, args.geometries, args.db
- )
- print(f" Temp dir: {tempdir}")
-
- try:
- print(f"\n── Loading MagnetTools objects …")
- data = load_magnettools(config, tempdir, debug=args.debug)
- (Tubes, Helices, OHelices, BMagnets, UMagnets, Shims) = data
- print(f" Tubes: {len(Tubes)} Helices: {len(Helices)} "
- f"BMagnets: {len(BMagnets)} UMagnets: {len(UMagnets)}")
-
- print(f"\n── Computing stress map at I_h={args.i_h/1e3:.1f} kA …")
- result = compute_stress_map(
- data, args.i_h, args.i_b, args.i_s, args.magnet_type
- )
- print(f" Bz0 at requested current : {result['Bz0']:.3f} T")
- print(f" Bz0 at max current (31kA): {result['Bz0_max']:.3f} T")
-
- print(f"\n── Annotating with Rpe …")
- df = annotate_with_rpe(result, args.magnet_name, args.db)
- print(df[["coil_index", "part", "nuance", "hoop_MPa",
- "hoop_max_MPa", "rpe", "ratio_rpe_max"]].to_string(index=False))
-
- print(f"\n── Plotting …")
- plot_stress_map(df, args.magnet_name, args.i_h)
-
- finally:
- shutil.rmtree(tempdir, ignore_errors=True)
-
-
-if __name__ == "__main__":
- main()
diff --git a/to_duckdb/tests/conftest.py b/to_duckdb/tests/conftest.py
new file mode 100644
index 0000000..de03088
--- /dev/null
+++ b/to_duckdb/tests/conftest.py
@@ -0,0 +1,151 @@
+"""
+Shared fixtures and test-data constants for the to_duckdb test suite.
+"""
+
+import pytest
+import duckdb
+
+from schema import ensure_schema
+
+# ---------------------------------------------------------------------------
+# Minimal, self-consistent test data
+# ---------------------------------------------------------------------------
+
+MATERIAL_COPPER = {
+ "name": "MAT_COPPER",
+ "description": "Copper alloy",
+ "nuance": "CuAg2.75",
+ "t_ref": 293.0,
+ "volumic_mass": 9000.0,
+ "specific_heat": 385.0,
+ "alpha": 0.0036,
+ "electrical_conductivity": 52_900_000.0,
+ "thermal_conductivity": 380.0,
+ "magnet_permeability": 1.0,
+ "young": 117e9,
+ "poisson": 0.33,
+ "expansion_coefficient": 1.8e-5,
+ "rpe": 490e6,
+}
+
+MATERIAL_STEEL = {
+ **MATERIAL_COPPER,
+ "name": "MAT_STEEL",
+ "nuance": "SS316L",
+ "electrical_conductivity": 1_380_000.0,
+ "thermal_conductivity": 13.0,
+ "rpe": 200e6,
+}
+
+PART_HELIX = {
+ "name": "HELIX_01",
+ "type": "helix",
+ "status": "in_operation",
+ "material_name": "MAT_COPPER",
+ "geometry": None,
+ "cad": None,
+ "design_office_reference": "HL-TEST",
+}
+
+PART_RING = {
+ "name": "RING_01",
+ "type": "ring",
+ "status": "in_operation",
+ "material_name": "MAT_STEEL",
+ "geometry": None,
+ "cad": None,
+ "design_office_reference": "",
+}
+
+MAGNET_DATA = {
+ "name": "MAG_01",
+ "status": "in_operation",
+ "design_office_reference": "MAG-TEST-001",
+ "geometry": None,
+}
+
+SITE_DATA = {
+ "name": "SITE_01",
+ "description": "Test site",
+ "status": "in_operation",
+ "housing": "M10",
+ "commissioned_at": "2025-01-01 00:00:00",
+ "decommissioned_at": None,
+}
+
+# Full magnet JSON (as exported from MagnetDB) with two parts: one helix, one ring
+MAGNET_JSON = {
+ "name": "MAG_JSON",
+ "status": "in_operation",
+ "design_office_reference": "",
+ "parts": [
+ {
+ "name": "H_JSON_01",
+ "type": "helix",
+ "status": "in_operation",
+ "design_office_reference": "",
+ "geometry": None,
+ "material": {**MATERIAL_COPPER, "name": "MAT_JSON_CU"},
+ },
+ {
+ "name": "R_JSON_01",
+ "type": "ring",
+ "status": "in_operation",
+ "design_office_reference": "",
+ "geometry": None,
+ "material": {**MATERIAL_STEEL, "name": "MAT_JSON_SS"},
+ },
+ ],
+}
+
+SITE_JSON = {
+ "name": "SITE_JSON_01",
+ "description": "",
+ "status": "in_operation",
+ "housing": "M10",
+ "commissioned_at": "2025-01-01 00:00:00",
+ "decommissioned_at": "None",
+ "magnets": ["MAG_JSON"],
+ "records": [
+ {
+ "name": "M10_2025.01.01---00:00:00.txt",
+ "description": "",
+ "file": "M10_2025.01.01---00:00:00.txt",
+ }
+ ],
+}
+
+
+# ---------------------------------------------------------------------------
+# Fixtures
+# ---------------------------------------------------------------------------
+
+
+@pytest.fixture
+def con():
+ """Fresh in-memory DuckDB connection with the canonical schema applied."""
+ c = duckdb.connect(":memory:")
+ ensure_schema(c)
+ yield c
+ c.close()
+
+
+@pytest.fixture
+def con_populated(con):
+ """Connection with two materials, two parts, one magnet, and one site pre-loaded."""
+ from crud import (
+ insert_magnet,
+ insert_magnet_part_row,
+ insert_material,
+ insert_part,
+ insert_site,
+ )
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ insert_material(con, MATERIAL_STEEL, verbose=False)
+ insert_part(con, PART_HELIX, verbose=False)
+ insert_part(con, PART_RING, verbose=False)
+ insert_magnet(con, MAGNET_DATA, "insert", verbose=False)
+ insert_magnet_part_row(con, "MAG_01", "HELIX_01", 0, 1)
+ insert_magnet_part_row(con, "MAG_01", "RING_01", 1, None)
+ insert_site(con, SITE_DATA, verbose=False)
+ return con
diff --git a/to_duckdb/tests/test_add_magnet.py b/to_duckdb/tests/test_add_magnet.py
new file mode 100644
index 0000000..6909d8b
--- /dev/null
+++ b/to_duckdb/tests/test_add_magnet.py
@@ -0,0 +1,190 @@
+"""Integration tests for add_magnet.py."""
+
+import json
+import copy
+
+import duckdb
+import pytest
+
+import magnetdb
+from magnetdb import _add_magnet as add_magnet, _validate_magnet
+from schema import ensure_schema
+from tests.conftest import MAGNET_JSON
+
+
+# ---------------------------------------------------------------------------
+# Helpers
+# ---------------------------------------------------------------------------
+
+
+def _count(db_path, table):
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ return con.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0]
+
+
+def _fetch_one(db_path, sql, params=None):
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ return con.execute(sql, params or []).fetchone()
+
+
+# ---------------------------------------------------------------------------
+# Happy path
+# ---------------------------------------------------------------------------
+
+
+def test_add_magnet_creates_magnet_row(tmp_path):
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db)
+ row = _fetch_one(db, "SELECT name, type, status FROM magnets WHERE name = 'MAG_JSON'")
+ assert row == ("MAG_JSON", "insert", "in_operation")
+
+
+def test_add_magnet_creates_all_parts(tmp_path):
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db)
+ count = _count(db, "parts")
+ assert count == len(MAGNET_JSON["parts"])
+
+
+def test_add_magnet_creates_all_materials(tmp_path):
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db)
+ assert _count(db, "materials") == 2 # one per part (CU + SS)
+
+
+def test_add_magnet_links_parts_to_magnet(tmp_path):
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db)
+ count = _fetch_one(
+ db,
+ "SELECT COUNT(*) FROM magnet_parts WHERE magnet_name = 'MAG_JSON'",
+ )[0]
+ assert count == 2
+
+
+def test_add_magnet_assigns_coil_index_to_helix_only(tmp_path):
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db)
+ rows = duckdb.connect(str(db), read_only=True).execute(
+ "SELECT p.type, mp.coil_index FROM magnet_parts mp "
+ "JOIN parts p ON p.name = mp.part_name "
+ "WHERE mp.magnet_name = 'MAG_JSON' ORDER BY mp.rank"
+ ).fetchall()
+ assert rows[0] == ("helix", 1) # first part is a helix → coil_index 1
+ assert rows[1] == ("ring", None) # second part is a ring → NULL
+
+
+# ---------------------------------------------------------------------------
+# Idempotency
+# ---------------------------------------------------------------------------
+
+
+def test_add_magnet_is_idempotent(tmp_path):
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db)
+ add_magnet(MAGNET_JSON, db) # second call must not raise or duplicate rows
+ assert _count(db, "magnets") == 1
+ assert _count(db, "parts") == 2
+ assert _count(db, "materials") == 2
+
+
+def test_add_magnet_shared_material_inserted_once(tmp_path):
+ """Two parts referencing the same material must not cause a duplicate key error."""
+ data = copy.deepcopy(MAGNET_JSON)
+ # Make both parts share the same material
+ data["parts"][1]["material"] = copy.deepcopy(data["parts"][0]["material"])
+ data["parts"][1]["material"]["name"] = "MAT_JSON_CU" # same as part 0
+
+ db = tmp_path / "test.duckdb"
+ add_magnet(data, db)
+ assert _count(db, "materials") == 1
+
+
+# ---------------------------------------------------------------------------
+# Dry run
+# ---------------------------------------------------------------------------
+
+
+def test_add_magnet_dry_run_writes_nothing(tmp_path):
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db, dry_run=True)
+ assert not db.exists()
+
+
+def test_add_magnet_dry_run_prints_summary(tmp_path, capsys):
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db, dry_run=True)
+ out = capsys.readouterr().out
+ assert "[dry-run]" in out
+ assert "MAG_JSON" in out
+
+
+# ---------------------------------------------------------------------------
+# Validation
+# ---------------------------------------------------------------------------
+
+
+def test_add_magnet_validate_missing_name(tmp_path):
+ data = {**MAGNET_JSON, "name": ""}
+ with pytest.raises(SystemExit):
+ add_magnet(data, tmp_path / "test.duckdb")
+
+
+def test_add_magnet_validate_missing_parts(tmp_path):
+ data = {**MAGNET_JSON, "parts": []}
+ with pytest.raises(SystemExit):
+ add_magnet(data, tmp_path / "test.duckdb")
+
+
+def test_add_magnet_validate_part_missing_type(tmp_path):
+ data = copy.deepcopy(MAGNET_JSON)
+ del data["parts"][0]["type"]
+ errors = _validate_magnet(data)
+ assert any("type" in e for e in errors)
+
+
+def test_add_magnet_validate_part_missing_material(tmp_path):
+ data = copy.deepcopy(MAGNET_JSON)
+ data["parts"][0]["material"] = {}
+ errors = _validate_magnet(data)
+ assert any("material" in e for e in errors)
+
+
+# ---------------------------------------------------------------------------
+# Type inference
+# ---------------------------------------------------------------------------
+
+
+@pytest.mark.parametrize("part_types,expected_magnet_type", [
+ (["helix", "ring"], "insert"),
+ (["bitter", "bitter"], "bitters"),
+ (["helix", "bitter"], "hybrid"),
+])
+def test_add_magnet_infers_type(tmp_path, part_types, expected_magnet_type):
+ data = copy.deepcopy(MAGNET_JSON)
+ # Rebuild parts list with the desired types, reusing the first material
+ template_part = data["parts"][0]
+ data["parts"] = [
+ {**template_part, "name": f"P_{i:02d}", "type": t}
+ for i, t in enumerate(part_types)
+ ]
+ db = tmp_path / "test.duckdb"
+ add_magnet(data, db)
+ row = _fetch_one(db, "SELECT type FROM magnets WHERE name = 'MAG_JSON'")
+ assert row[0] == expected_magnet_type
+
+
+# ---------------------------------------------------------------------------
+# CLI entry point smoke test
+# ---------------------------------------------------------------------------
+
+
+def test_add_magnet_cli(tmp_path, monkeypatch, capsys):
+ json_path = tmp_path / "MAG_JSON.json"
+ json_path.write_text(json.dumps(MAGNET_JSON))
+ db_path = tmp_path / "cli.duckdb"
+
+ monkeypatch.setattr("sys.argv", ["magnetdb.py", "magnet", "add", str(json_path), "--db", str(db_path)])
+ magnetdb.main()
+
+ assert _count(db_path, "magnets") == 1
diff --git a/to_duckdb/tests/test_add_site.py b/to_duckdb/tests/test_add_site.py
new file mode 100644
index 0000000..e33b961
--- /dev/null
+++ b/to_duckdb/tests/test_add_site.py
@@ -0,0 +1,216 @@
+"""Integration tests for add_site.py."""
+
+import copy
+import json
+
+import duckdb
+import pytest
+
+import magnetdb
+from magnetdb import _add_magnet as add_magnet, _add_site as add_site, _validate_site
+from schema import ensure_schema
+from tests.conftest import MAGNET_JSON, SITE_JSON
+
+
+# ---------------------------------------------------------------------------
+# Helpers
+# ---------------------------------------------------------------------------
+
+
+def _count(db_path, table):
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ return con.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0]
+
+
+def _fetch_one(db_path, sql, params=None):
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ return con.execute(sql, params or []).fetchone()
+
+
+def _db_with_magnet(tmp_path):
+ """Return a db_path that already contains MAG_JSON."""
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db)
+ return db
+
+
+def _empty_db(tmp_path):
+ """Return a db_path for an empty but schema-initialised database."""
+ db = tmp_path / "test.duckdb"
+ with duckdb.connect(str(db)) as con:
+ ensure_schema(con)
+ return db
+
+
+# ---------------------------------------------------------------------------
+# Happy path
+# ---------------------------------------------------------------------------
+
+
+def test_add_site_creates_site_row(tmp_path):
+ db = _db_with_magnet(tmp_path)
+ add_site(SITE_JSON, db)
+ row = _fetch_one(db, "SELECT name, housing, status FROM sites WHERE name = 'SITE_JSON_01'")
+ assert row == ("SITE_JSON_01", "M10", "in_operation")
+
+
+def test_add_site_links_magnets(tmp_path):
+ db = _db_with_magnet(tmp_path)
+ add_site(SITE_JSON, db)
+ count = _fetch_one(
+ db,
+ "SELECT COUNT(*) FROM site_magnets WHERE site_name = 'SITE_JSON_01'",
+ )[0]
+ assert count == 1
+
+
+def test_add_site_creates_experiments(tmp_path):
+ db = _db_with_magnet(tmp_path)
+ add_site(SITE_JSON, db)
+ count = _count(db, "experiments")
+ assert count == len(SITE_JSON["records"])
+
+
+def test_add_site_string_magnet_entry_uses_default_offsets(tmp_path):
+ db = _db_with_magnet(tmp_path)
+ add_site(SITE_JSON, db)
+ row = _fetch_one(
+ db,
+ "SELECT z_offset, r_offset, parallax FROM site_magnets WHERE magnet_name = 'MAG_JSON'",
+ )
+ assert row == (0.0, 0.0, 0.0)
+
+
+def test_add_site_dict_magnet_entry_stores_offsets(tmp_path):
+ db = _db_with_magnet(tmp_path)
+ data = copy.deepcopy(SITE_JSON)
+ data["magnets"] = [{"name": "MAG_JSON", "z_offset": 12.5, "r_offset": 0.3, "parallax": 0.1}]
+ add_site(data, db)
+ row = _fetch_one(
+ db,
+ "SELECT z_offset, r_offset, parallax FROM site_magnets WHERE magnet_name = 'MAG_JSON'",
+ )
+ assert row == (12.5, 0.3, 0.1)
+
+
+# ---------------------------------------------------------------------------
+# Idempotency
+# ---------------------------------------------------------------------------
+
+
+def test_add_site_is_idempotent(tmp_path):
+ db = _db_with_magnet(tmp_path)
+ add_site(SITE_JSON, db)
+ add_site(SITE_JSON, db) # second call must not raise or duplicate rows
+ assert _count(db, "sites") == 1
+ assert _count(db, "site_magnets") == 1
+ assert _count(db, "experiments") == len(SITE_JSON["records"])
+
+
+# ---------------------------------------------------------------------------
+# Auto-load missing magnets
+# ---------------------------------------------------------------------------
+
+
+def test_add_site_auto_loads_magnet_from_json(tmp_path):
+ """add_site must load a missing magnet from a JSON file in magnet_dir."""
+ db = _empty_db(tmp_path)
+ (tmp_path / "MAG_JSON.json").write_text(json.dumps(MAGNET_JSON))
+
+ add_site(SITE_JSON, db, magnet_dir=tmp_path)
+
+ assert _count(db, "magnets") == 1
+ assert _count(db, "sites") == 1
+
+
+def test_add_site_fails_when_magnet_json_missing(tmp_path):
+ """add_site must exit when a referenced magnet is absent from DB and disk."""
+ db = _empty_db(tmp_path)
+ # No magnet JSON file placed in tmp_path
+ with pytest.raises(SystemExit):
+ add_site(SITE_JSON, db, magnet_dir=tmp_path)
+
+
+# ---------------------------------------------------------------------------
+# Dry run
+# ---------------------------------------------------------------------------
+
+
+def test_add_site_dry_run_writes_nothing(tmp_path):
+ db = _db_with_magnet(tmp_path)
+ sites_before = _count(db, "sites")
+ add_site(SITE_JSON, db, dry_run=True)
+ assert _count(db, "sites") == sites_before
+
+
+def test_add_site_dry_run_prints_summary(tmp_path, capsys):
+ db = _db_with_magnet(tmp_path)
+ add_site(SITE_JSON, db, dry_run=True)
+ out = capsys.readouterr().out
+ assert "[dry-run]" in out
+ assert "SITE_JSON_01" in out
+
+
+# ---------------------------------------------------------------------------
+# Validation
+# ---------------------------------------------------------------------------
+
+
+def test_add_site_fails_when_db_missing(tmp_path):
+ db = tmp_path / "nonexistent.duckdb"
+ with pytest.raises(SystemExit):
+ add_site(SITE_JSON, db)
+
+
+def test_add_site_validate_missing_name(tmp_path):
+ errors = _validate_site({**SITE_JSON, "name": ""})
+ assert any("name" in e.lower() for e in errors)
+
+
+def test_add_site_validate_missing_magnets(tmp_path):
+ errors = _validate_site({**SITE_JSON, "magnets": []})
+ assert any("magnet" in e.lower() for e in errors)
+
+
+# ---------------------------------------------------------------------------
+# CLI: update-magnet subcommand
+# ---------------------------------------------------------------------------
+
+
+def test_update_magnet_cli(tmp_path, monkeypatch):
+ db = _db_with_magnet(tmp_path)
+ add_site(SITE_JSON, db)
+
+ monkeypatch.setattr(
+ "sys.argv",
+ [
+ "magnetdb.py",
+ "site", "update-magnet",
+ "SITE_JSON_01",
+ "MAG_JSON",
+ "--db", str(db),
+ "--z-offset", "7.5",
+ ],
+ )
+ magnetdb.main()
+
+ row = _fetch_one(db, "SELECT z_offset FROM site_magnets WHERE magnet_name = 'MAG_JSON'")
+ assert row[0] == 7.5
+
+
+def test_update_magnet_cli_missing_row_exits(tmp_path, monkeypatch):
+ db = _db_with_magnet(tmp_path) # site not added → no site_magnets row
+
+ monkeypatch.setattr(
+ "sys.argv",
+ [
+ "magnetdb.py",
+ "site", "update-magnet",
+ "NONEXISTENT_SITE",
+ "MAG_JSON",
+ "--db", str(db),
+ "--z-offset", "1.0",
+ ],
+ )
+ with pytest.raises(SystemExit):
+ magnetdb.main()
diff --git a/to_duckdb/tests/test_crud.py b/to_duckdb/tests/test_crud.py
new file mode 100644
index 0000000..42b39bc
--- /dev/null
+++ b/to_duckdb/tests/test_crud.py
@@ -0,0 +1,482 @@
+"""Unit tests for crud.py — one function per concern."""
+
+import pytest
+
+from crud import (
+ delete_magnet,
+ delete_site,
+ exists,
+ infer_magnet_type,
+ insert_experiments,
+ insert_magnet,
+ insert_magnet_part_row,
+ insert_magnet_parts,
+ insert_material,
+ insert_part,
+ insert_site,
+ insert_site_magnets,
+ parse_timestamp,
+ update_site_magnet,
+ view_magnet,
+ view_magnets,
+ view_site,
+ view_sites,
+)
+from tests.conftest import (
+ MAGNET_DATA,
+ MATERIAL_COPPER,
+ MATERIAL_STEEL,
+ PART_HELIX,
+ PART_RING,
+ SITE_DATA,
+)
+
+
+# ---------------------------------------------------------------------------
+# exists()
+# ---------------------------------------------------------------------------
+
+
+def test_exists_returns_false_before_insert(con):
+ assert exists(con, "materials", "NONEXISTENT") is False
+
+
+def test_exists_returns_true_after_insert(con):
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ assert exists(con, "materials", "MAT_COPPER") is True
+
+
+# ---------------------------------------------------------------------------
+# insert_material()
+# ---------------------------------------------------------------------------
+
+
+def test_insert_material_creates_row(con):
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ row = con.execute("SELECT nuance FROM materials WHERE name = 'MAT_COPPER'").fetchone()
+ assert row is not None
+ assert row[0] == "CuAg2.75"
+
+
+def test_insert_material_skips_duplicate(con):
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ count = con.execute("SELECT COUNT(*) FROM materials WHERE name = 'MAT_COPPER'").fetchone()[0]
+ assert count == 1
+
+
+def test_insert_material_stores_null_for_missing_optional_fields(con):
+ minimal = {"name": "MAT_MINIMAL", "nuance": "Cu", "rpe": None}
+ insert_material(con, minimal, verbose=False)
+ row = con.execute("SELECT description FROM materials WHERE name = 'MAT_MINIMAL'").fetchone()
+ assert row[0] is None
+
+
+# ---------------------------------------------------------------------------
+# insert_part()
+# ---------------------------------------------------------------------------
+
+
+def test_insert_part_creates_row(con):
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ insert_part(con, PART_HELIX, verbose=False)
+ row = con.execute("SELECT type, material_name FROM parts WHERE name = 'HELIX_01'").fetchone()
+ assert row == ("helix", "MAT_COPPER")
+
+
+def test_insert_part_skips_duplicate(con):
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ insert_part(con, PART_HELIX, verbose=False)
+ insert_part(con, PART_HELIX, verbose=False)
+ count = con.execute("SELECT COUNT(*) FROM parts WHERE name = 'HELIX_01'").fetchone()[0]
+ assert count == 1
+
+
+def test_insert_part_accepts_nested_material_dict(con):
+ """Part dict may carry the full material under 'material' instead of 'material_name'."""
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ part_with_nested = {**PART_HELIX, "name": "H_NESTED", "material_name": None,
+ "material": {"name": "MAT_COPPER"}}
+ insert_part(con, part_with_nested, verbose=False)
+ row = con.execute("SELECT material_name FROM parts WHERE name = 'H_NESTED'").fetchone()
+ assert row[0] == "MAT_COPPER"
+
+
+# ---------------------------------------------------------------------------
+# infer_magnet_type()
+# ---------------------------------------------------------------------------
+
+
+@pytest.mark.parametrize("parts,expected", [
+ ([{"type": "helix"}, {"type": "helix"}, {"type": "ring"}], "insert"),
+ ([{"type": "bitter"}, {"type": "bitter"}], "bitters"),
+ ([{"type": "helix"}, {"type": "bitter"}], "hybrid"),
+ ([{"type": "ring"}, {"type": "lead"}], "unknown"),
+ ([], "unknown"),
+])
+def test_infer_magnet_type(parts, expected):
+ assert infer_magnet_type(parts) == expected
+
+
+# ---------------------------------------------------------------------------
+# insert_magnet()
+# ---------------------------------------------------------------------------
+
+
+def test_insert_magnet_creates_row(con):
+ insert_magnet(con, MAGNET_DATA, "insert", verbose=False)
+ row = con.execute("SELECT type, status FROM magnets WHERE name = 'MAG_01'").fetchone()
+ assert row == ("insert", "in_operation")
+
+
+def test_insert_magnet_skips_duplicate(con):
+ insert_magnet(con, MAGNET_DATA, "insert", verbose=False)
+ insert_magnet(con, MAGNET_DATA, "insert", verbose=False)
+ count = con.execute("SELECT COUNT(*) FROM magnets WHERE name = 'MAG_01'").fetchone()[0]
+ assert count == 1
+
+
+# ---------------------------------------------------------------------------
+# insert_magnet_parts()
+# ---------------------------------------------------------------------------
+
+
+def test_insert_magnet_parts_assigns_coil_index(con):
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ insert_material(con, MATERIAL_STEEL, verbose=False)
+ insert_part(con, PART_HELIX, verbose=False)
+ insert_part(con, PART_RING, verbose=False)
+ insert_magnet(con, MAGNET_DATA, "insert", verbose=False)
+
+ parts = [{"name": "HELIX_01", "type": "helix"}, {"name": "RING_01", "type": "ring"}]
+ insert_magnet_parts(con, "MAG_01", parts, verbose=False)
+
+ rows = con.execute(
+ "SELECT part_name, rank, coil_index FROM magnet_parts WHERE magnet_name = 'MAG_01' ORDER BY rank"
+ ).fetchall()
+ assert rows[0] == ("HELIX_01", 0, 1) # helix → coil_index 1
+ assert rows[1] == ("RING_01", 1, None) # ring → NULL
+
+
+def test_insert_magnet_parts_skips_duplicate(con):
+ insert_material(con, MATERIAL_COPPER, verbose=False)
+ insert_part(con, PART_HELIX, verbose=False)
+ insert_magnet(con, MAGNET_DATA, "insert", verbose=False)
+
+ parts = [{"name": "HELIX_01", "type": "helix"}]
+ insert_magnet_parts(con, "MAG_01", parts, verbose=False)
+ insert_magnet_parts(con, "MAG_01", parts, verbose=False)
+
+ count = con.execute("SELECT COUNT(*) FROM magnet_parts WHERE magnet_name = 'MAG_01'").fetchone()[0]
+ assert count == 1
+
+
+def test_insert_magnet_parts_multiple_coil_channels(con):
+ """Three helices must get sequential coil_index 1, 2, 3."""
+ mats = {**MATERIAL_COPPER}
+ insert_material(con, mats, verbose=False)
+ for i in range(1, 4):
+ insert_part(con, {**PART_HELIX, "name": f"H_{i:02d}"}, verbose=False)
+ insert_magnet(con, MAGNET_DATA, "insert", verbose=False)
+
+ parts = [{"name": f"H_{i:02d}", "type": "helix"} for i in range(1, 4)]
+ insert_magnet_parts(con, "MAG_01", parts, verbose=False)
+
+ indexes = con.execute(
+ "SELECT coil_index FROM magnet_parts WHERE magnet_name = 'MAG_01' ORDER BY rank"
+ ).fetchall()
+ assert [r[0] for r in indexes] == [1, 2, 3]
+
+
+# ---------------------------------------------------------------------------
+# insert_magnet_part_row()
+# ---------------------------------------------------------------------------
+
+
+def test_insert_magnet_part_row_inserts(con_populated):
+ count = con_populated.execute(
+ "SELECT COUNT(*) FROM magnet_parts WHERE magnet_name = 'MAG_01'"
+ ).fetchone()[0]
+ assert count == 2 # HELIX_01 + RING_01 from fixture
+
+
+def test_insert_magnet_part_row_skips_duplicate(con_populated):
+ insert_magnet_part_row(con_populated, "MAG_01", "HELIX_01", 0, 1)
+ count = con_populated.execute(
+ "SELECT COUNT(*) FROM magnet_parts WHERE magnet_name = 'MAG_01' AND part_name = 'HELIX_01'"
+ ).fetchone()[0]
+ assert count == 1
+
+
+# ---------------------------------------------------------------------------
+# parse_timestamp()
+# ---------------------------------------------------------------------------
+
+
+@pytest.mark.parametrize("value,expected", [
+ (None, None),
+ ("None", None),
+ ("null", None),
+ ("NULL", None),
+ ("", None),
+ ("2025-01-01 00:00:00", "2025-01-01 00:00:00"),
+ ("2025-11-12", "2025-11-12"),
+])
+def test_parse_timestamp(value, expected):
+ assert parse_timestamp(value) == expected
+
+
+# ---------------------------------------------------------------------------
+# insert_site()
+# ---------------------------------------------------------------------------
+
+
+def test_insert_site_creates_row(con):
+ insert_site(con, SITE_DATA, verbose=False)
+ row = con.execute(
+ "SELECT housing, status FROM sites WHERE name = 'SITE_01'"
+ ).fetchone()
+ assert row == ("M10", "in_operation")
+
+
+def test_insert_site_skips_duplicate(con):
+ insert_site(con, SITE_DATA, verbose=False)
+ insert_site(con, SITE_DATA, verbose=False)
+ count = con.execute("SELECT COUNT(*) FROM sites WHERE name = 'SITE_01'").fetchone()[0]
+ assert count == 1
+
+
+def test_insert_site_null_decommissioned(con):
+ insert_site(con, {**SITE_DATA, "decommissioned_at": None}, verbose=False)
+ row = con.execute("SELECT decommissioned_at FROM sites WHERE name = 'SITE_01'").fetchone()
+ assert row[0] is None
+
+
+# ---------------------------------------------------------------------------
+# insert_site_magnets()
+# ---------------------------------------------------------------------------
+
+
+def test_insert_site_magnets_creates_row(con_populated):
+ insert_site_magnets(con_populated, "SITE_01", ["MAG_01"], verbose=False)
+ row = con_populated.execute(
+ "SELECT z_offset FROM site_magnets WHERE site_name = 'SITE_01' AND magnet_name = 'MAG_01'"
+ ).fetchone()
+ assert row is not None
+ assert row[0] == 0.0
+
+
+def test_insert_site_magnets_stores_offsets(con_populated):
+ entry = {"name": "MAG_01", "z_offset": 1.5, "r_offset": 0.3, "parallax": 0.01}
+ insert_site_magnets(con_populated, "SITE_01", [entry], verbose=False)
+ row = con_populated.execute(
+ "SELECT z_offset, r_offset, parallax FROM site_magnets "
+ "WHERE site_name = 'SITE_01' AND magnet_name = 'MAG_01'"
+ ).fetchone()
+ assert row == (1.5, 0.3, 0.01)
+
+
+def test_insert_site_magnets_skips_duplicate(con_populated):
+ insert_site_magnets(con_populated, "SITE_01", ["MAG_01"], verbose=False)
+ insert_site_magnets(con_populated, "SITE_01", ["MAG_01"], verbose=False)
+ count = con_populated.execute(
+ "SELECT COUNT(*) FROM site_magnets WHERE site_name = 'SITE_01' AND magnet_name = 'MAG_01'"
+ ).fetchone()[0]
+ assert count == 1
+
+
+# ---------------------------------------------------------------------------
+# insert_experiments()
+# ---------------------------------------------------------------------------
+
+
+def test_insert_experiments_creates_rows(con_populated):
+ records = [
+ {"name": "run_001.txt", "file": "run_001.txt", "description": ""},
+ {"name": "run_002.txt", "file": "run_002.txt", "description": ""},
+ ]
+ insert_experiments(con_populated, "SITE_01", records, verbose=False)
+ count = con_populated.execute(
+ "SELECT COUNT(*) FROM experiments WHERE site_name = 'SITE_01'"
+ ).fetchone()[0]
+ assert count == 2
+
+
+def test_insert_experiments_skips_duplicate_file(con_populated):
+ records = [{"name": "run_001.txt", "file": "run_001.txt"}]
+ insert_experiments(con_populated, "SITE_01", records, verbose=False)
+ insert_experiments(con_populated, "SITE_01", records, verbose=False)
+ count = con_populated.execute(
+ "SELECT COUNT(*) FROM experiments WHERE file = 'run_001.txt'"
+ ).fetchone()[0]
+ assert count == 1
+
+
+# ---------------------------------------------------------------------------
+# update_site_magnet()
+# ---------------------------------------------------------------------------
+
+
+def test_update_site_magnet_updates_offset(con_populated):
+ insert_site_magnets(con_populated, "SITE_01", ["MAG_01"], verbose=False)
+ update_site_magnet(con_populated, "SITE_01", "MAG_01", z_offset=12.5)
+ row = con_populated.execute(
+ "SELECT z_offset FROM site_magnets WHERE site_name = 'SITE_01' AND magnet_name = 'MAG_01'"
+ ).fetchone()
+ assert row[0] == 12.5
+
+
+def test_update_site_magnet_updates_only_passed_fields(con_populated):
+ insert_site_magnets(con_populated, "SITE_01", [{"name": "MAG_01", "r_offset": 0.5}], verbose=False)
+ update_site_magnet(con_populated, "SITE_01", "MAG_01", z_offset=3.0)
+ row = con_populated.execute(
+ "SELECT z_offset, r_offset FROM site_magnets WHERE site_name = 'SITE_01' AND magnet_name = 'MAG_01'"
+ ).fetchone()
+ assert row[0] == 3.0
+ assert row[1] == 0.5 # unchanged
+
+
+def test_update_site_magnet_raises_when_row_missing(con_populated):
+ with pytest.raises(ValueError, match="No link"):
+ update_site_magnet(con_populated, "SITE_01", "NONEXISTENT", z_offset=1.0)
+
+
+def test_update_site_magnet_nothing_to_update(con_populated, capsys):
+ insert_site_magnets(con_populated, "SITE_01", ["MAG_01"], verbose=False)
+ update_site_magnet(con_populated, "SITE_01", "MAG_01")
+ captured = capsys.readouterr()
+ assert "Nothing to update" in captured.out
+
+
+# ---------------------------------------------------------------------------
+# view_magnets() / view_magnet()
+# ---------------------------------------------------------------------------
+
+
+def test_view_magnets_empty(con, capsys):
+ view_magnets(con)
+ assert "No magnets" in capsys.readouterr().out
+
+
+def test_view_magnets_lists_row(con_populated, capsys):
+ view_magnets(con_populated)
+ out = capsys.readouterr().out
+ assert "MAG_01" in out
+ assert "insert" in out
+
+
+def test_view_magnet_not_found(con, capsys):
+ view_magnet(con, "NONEXISTENT")
+ assert "not found" in capsys.readouterr().out
+
+
+def test_view_magnet_shows_name_and_parts(con_populated, capsys):
+ view_magnet(con_populated, "MAG_01")
+ out = capsys.readouterr().out
+ assert "MAG_01" in out
+ assert "HELIX_01" in out
+ assert "RING_01" in out
+
+
+def test_view_magnet_shows_coil_index(con_populated, capsys):
+ view_magnet(con_populated, "MAG_01")
+ out = capsys.readouterr().out
+ assert "coil#1" in out
+
+
+# ---------------------------------------------------------------------------
+# view_sites() / view_site()
+# ---------------------------------------------------------------------------
+
+
+def test_view_sites_empty(con, capsys):
+ view_sites(con)
+ assert "No sites" in capsys.readouterr().out
+
+
+def test_view_sites_lists_row(con_populated, capsys):
+ view_sites(con_populated)
+ out = capsys.readouterr().out
+ assert "SITE_01" in out
+ assert "M10" in out
+
+
+def test_view_site_not_found(con, capsys):
+ view_site(con, "NONEXISTENT")
+ assert "not found" in capsys.readouterr().out
+
+
+def test_view_site_shows_detail(con_populated, capsys):
+ insert_site_magnets(con_populated, "SITE_01", ["MAG_01"], verbose=False)
+ records = [{"name": "run.txt", "file": "run.txt"}]
+ insert_experiments(con_populated, "SITE_01", records, verbose=False)
+ view_site(con_populated, "SITE_01")
+ out = capsys.readouterr().out
+ assert "SITE_01" in out
+ assert "M10" in out
+ assert "MAG_01" in out
+ assert "experiments: 1" in out
+
+
+# ---------------------------------------------------------------------------
+# delete_magnet()
+# ---------------------------------------------------------------------------
+
+
+def test_delete_magnet_removes_magnet_row(con_populated):
+ delete_magnet(con_populated, "MAG_01")
+ assert not exists(con_populated, "magnets", "MAG_01")
+
+
+def test_delete_magnet_removes_part_links(con_populated):
+ delete_magnet(con_populated, "MAG_01")
+ count = con_populated.execute(
+ "SELECT COUNT(*) FROM magnet_parts WHERE magnet_name = 'MAG_01'"
+ ).fetchone()[0]
+ assert count == 0
+
+
+def test_delete_magnet_not_found(con, capsys):
+ delete_magnet(con, "NONEXISTENT")
+ assert "not found" in capsys.readouterr().out
+
+
+def test_delete_magnet_leaves_parts_table_intact(con_populated):
+ """Deleting a magnet must not cascade-delete the parts themselves."""
+ delete_magnet(con_populated, "MAG_01")
+ assert exists(con_populated, "parts", "HELIX_01")
+ assert exists(con_populated, "parts", "RING_01")
+
+
+# ---------------------------------------------------------------------------
+# delete_site()
+# ---------------------------------------------------------------------------
+
+
+def test_delete_site_removes_site_row(con_populated):
+ delete_site(con_populated, "SITE_01")
+ assert not exists(con_populated, "sites", "SITE_01")
+
+
+def test_delete_site_removes_site_magnet_links(con_populated):
+ insert_site_magnets(con_populated, "SITE_01", ["MAG_01"], verbose=False)
+ delete_site(con_populated, "SITE_01")
+ count = con_populated.execute(
+ "SELECT COUNT(*) FROM site_magnets WHERE site_name = 'SITE_01'"
+ ).fetchone()[0]
+ assert count == 0
+
+
+def test_delete_site_removes_experiments(con_populated):
+ records = [{"name": "run.txt", "file": "run.txt"}]
+ insert_experiments(con_populated, "SITE_01", records, verbose=False)
+ delete_site(con_populated, "SITE_01")
+ count = con_populated.execute(
+ "SELECT COUNT(*) FROM experiments WHERE site_name = 'SITE_01'"
+ ).fetchone()[0]
+ assert count == 0
+
+
+def test_delete_site_not_found(con, capsys):
+ delete_site(con, "NONEXISTENT")
+ assert "not found" in capsys.readouterr().out
diff --git a/to_duckdb/tests/test_housing_config_db.py b/to_duckdb/tests/test_housing_config_db.py
new file mode 100644
index 0000000..c628327
--- /dev/null
+++ b/to_duckdb/tests/test_housing_config_db.py
@@ -0,0 +1,373 @@
+"""Tests for the housing_config DuckDB table (schema.py + crud.py).
+
+The bundled reference JSON files from python_magnetrun are used as ground
+truth. They are opened read-only and are never modified — all file writes
+go to pytest's tmp_path.
+"""
+
+import json
+from pathlib import Path
+
+import duckdb
+import pytest
+
+from schema import ensure_schema
+from crud import (
+ _derive_housing_config_dict,
+ insert_housing_config,
+ export_housing_config_json,
+)
+
+# ---------------------------------------------------------------------------
+# Reference JSON files (read-only)
+# ---------------------------------------------------------------------------
+
+_MAGNETRUN_PKG = (
+ Path(__file__).parent.parent.parent / "python_magnetrun" / "python_magnetrun"
+)
+
+_REF_FILES: dict[str, Path] = {
+ "M8": _MAGNETRUN_PKG / "M8-housing-config.json",
+ "M9": _MAGNETRUN_PKG / "M9-housing-config.json",
+ "M10": _MAGNETRUN_PKG / "M10-housing-config.json",
+}
+
+
+def _load_ref(name: str) -> dict:
+ return json.loads(_REF_FILES[name].read_text())
+
+
+def _coil_assignment_from_ref(ref: dict) -> dict[str, str]:
+ """Infer {coil_type: GR_name} from a reference JSON dict."""
+ suffix_to_coil = {"H": "Insert", "B": "Bitter"}
+ s1 = ref["reference_gr1_current"][-1] # "H" or "B"
+ s2 = ref["reference_gr2_current"][-1]
+ return {suffix_to_coil[s1]: "GR1", suffix_to_coil[s2]: "GR2"}
+
+
+def _extra_config_from_ref(ref: dict) -> dict | None:
+ """Extract hybrid/extra fields present in a reference JSON dict."""
+ keys = [
+ "reference_gr1_hybrid", "reference_gr2_hybrid",
+ "hybrid_formula_map", "hybrid_voltage_mask_map",
+ ]
+ extras = {k: ref[k] for k in keys if k in ref and ref[k]}
+ return extras or None
+
+
+# Fields that must be derived correctly from coil_assignment alone.
+_DERIVED_FIELDS = [
+ "reference_gr1_current", "reference_gr2_current",
+ "reference_gr1_flow", "reference_gr2_flow",
+ "reference_gr1_rpm", "reference_gr2_rpm",
+ "reference_gr1_pin", "reference_gr2_pin",
+ "reference_gr1_voltage", "reference_gr2_voltage",
+ "voltage_channels_gr1", "voltage_channels_gr2",
+]
+
+# ---------------------------------------------------------------------------
+# Fixtures
+# ---------------------------------------------------------------------------
+
+
+@pytest.fixture()
+def con():
+ """In-memory DuckDB connection with the full schema applied."""
+ conn = duckdb.connect(":memory:")
+ ensure_schema(conn)
+ yield conn
+ conn.close()
+
+
+@pytest.fixture()
+def populated_con(con):
+ """Connection pre-loaded with M8, M9, M10 from the reference JSON files."""
+ for name, path in _REF_FILES.items():
+ ref = json.loads(path.read_text())
+ insert_housing_config(con, {
+ "name": name,
+ "coil_assignment": _coil_assignment_from_ref(ref),
+ "formats": ref["formats"],
+ "extra_config": _extra_config_from_ref(ref),
+ }, verbose=False)
+ return con
+
+
+# ---------------------------------------------------------------------------
+# Schema
+# ---------------------------------------------------------------------------
+
+
+class TestSchema:
+ def test_housing_config_table_exists(self, con):
+ rows = con.execute(
+ "SELECT table_name FROM information_schema.tables "
+ "WHERE table_name = 'housing_config'"
+ ).fetchall()
+ assert rows, "housing_config table not found after ensure_schema()"
+
+ def test_housing_config_has_required_columns(self, con):
+ cols = {
+ row[0]
+ for row in con.execute(
+ "SELECT column_name FROM information_schema.columns "
+ "WHERE table_name = 'housing_config'"
+ ).fetchall()
+ }
+ assert {"name", "coil_assignment", "formats", "extra_config"} <= cols
+
+ def test_ensure_schema_is_idempotent(self, con):
+ """Calling ensure_schema twice must not raise."""
+ ensure_schema(con)
+
+
+# ---------------------------------------------------------------------------
+# insert_housing_config
+# ---------------------------------------------------------------------------
+
+
+class TestInsertHousingConfig:
+ def test_insert_m9_name(self, con):
+ ref = _load_ref("M9")
+ insert_housing_config(con, {
+ "name": "M9",
+ "coil_assignment": _coil_assignment_from_ref(ref),
+ "formats": ref["formats"],
+ "extra_config": None,
+ }, verbose=False)
+ row = con.execute(
+ "SELECT name FROM housing_config WHERE name = 'M9'"
+ ).fetchone()
+ assert row is not None and row[0] == "M9"
+
+ def test_insert_stores_coil_assignment(self, con):
+ ref = _load_ref("M9")
+ ca = _coil_assignment_from_ref(ref)
+ insert_housing_config(con, {
+ "name": "M9", "coil_assignment": ca,
+ "formats": ref["formats"], "extra_config": None,
+ }, verbose=False)
+ row = con.execute(
+ "SELECT coil_assignment FROM housing_config WHERE name = 'M9'"
+ ).fetchone()
+ assert dict(row[0]) == ca
+
+ def test_insert_stores_formats(self, con):
+ ref = _load_ref("M9")
+ insert_housing_config(con, {
+ "name": "M9", "coil_assignment": _coil_assignment_from_ref(ref),
+ "formats": ref["formats"], "extra_config": None,
+ }, verbose=False)
+ row = con.execute(
+ "SELECT formats FROM housing_config WHERE name = 'M9'"
+ ).fetchone()
+ assert list(row[0]) == ref["formats"]
+
+ def test_insert_stores_extra_config_for_m8(self, con):
+ ref = _load_ref("M8")
+ ec = _extra_config_from_ref(ref)
+ insert_housing_config(con, {
+ "name": "M8", "coil_assignment": _coil_assignment_from_ref(ref),
+ "formats": ref["formats"], "extra_config": ec,
+ }, verbose=False)
+ row = con.execute(
+ "SELECT extra_config FROM housing_config WHERE name = 'M8'"
+ ).fetchone()
+ stored = json.loads(row[0])
+ assert stored["reference_gr1_hybrid"] == ref["reference_gr1_hybrid"]
+ assert stored["reference_gr2_hybrid"] == ref["reference_gr2_hybrid"]
+
+ def test_insert_replace_is_idempotent(self, con):
+ """Inserting the same name twice (OR REPLACE) must not raise."""
+ base = {
+ "name": "M9",
+ "coil_assignment": {"Insert": "GR1", "Bitter": "GR2"},
+ "formats": ["pupitre"],
+ "extra_config": None,
+ }
+ insert_housing_config(con, base, verbose=False)
+ updated = dict(base, formats=["pupitre", "pigbrother"])
+ insert_housing_config(con, updated, verbose=False)
+ row = con.execute(
+ "SELECT formats FROM housing_config WHERE name = 'M9'"
+ ).fetchone()
+ assert list(row[0]) == ["pupitre", "pigbrother"]
+
+ def test_all_three_housings_inserted(self, populated_con):
+ count = populated_con.execute(
+ "SELECT COUNT(*) FROM housing_config"
+ ).fetchone()[0]
+ assert count == 3
+
+ @pytest.mark.parametrize("housing", ["M8", "M9", "M10"])
+ def test_m9_coil_assignment_is_insert_gr1(self, con, housing):
+ """M9 wires Insert to GR1; M8/M10 wire Insert to GR2."""
+ ref = _load_ref(housing)
+ ca = _coil_assignment_from_ref(ref)
+ insert_housing_config(con, {
+ "name": housing, "coil_assignment": ca,
+ "formats": ref["formats"], "extra_config": None,
+ }, verbose=False)
+ row = con.execute(
+ "SELECT coil_assignment FROM housing_config WHERE name = ?",
+ [housing],
+ ).fetchone()
+ stored = dict(row[0])
+ expected_gr1 = "GR1" if housing == "M9" else "GR2"
+ assert stored["Insert"] == expected_gr1
+
+
+# ---------------------------------------------------------------------------
+# _derive_housing_config_dict — correctness vs reference JSONs
+# ---------------------------------------------------------------------------
+
+
+@pytest.mark.parametrize("housing", ["M8", "M9", "M10"])
+class TestDeriveMatchesReference:
+ def test_reference_fields(self, housing):
+ ref = _load_ref(housing)
+ derived = _derive_housing_config_dict(
+ housing,
+ _coil_assignment_from_ref(ref),
+ ref["formats"],
+ _extra_config_from_ref(ref),
+ )
+ for field in _DERIVED_FIELDS:
+ assert derived[field] == ref[field], (
+ f"{housing}.{field}: got {derived[field]!r}, "
+ f"expected {ref[field]!r}"
+ )
+
+ def test_formats(self, housing):
+ ref = _load_ref(housing)
+ derived = _derive_housing_config_dict(
+ housing,
+ _coil_assignment_from_ref(ref),
+ ref["formats"],
+ _extra_config_from_ref(ref),
+ )
+ assert derived["formats"] == ref["formats"]
+
+ def test_pupitre_formula_map(self, housing):
+ ref = _load_ref(housing)
+ derived = _derive_housing_config_dict(
+ housing,
+ _coil_assignment_from_ref(ref),
+ ref["formats"],
+ _extra_config_from_ref(ref),
+ )
+ assert derived["pupitre_formula_map"] == ref["pupitre_formula_map"]
+
+ def test_pigbrother_formula_map(self, housing):
+ ref = _load_ref(housing)
+ derived = _derive_housing_config_dict(
+ housing,
+ _coil_assignment_from_ref(ref),
+ ref["formats"],
+ _extra_config_from_ref(ref),
+ )
+ assert derived["pigbrother_formula_map"] == ref["pigbrother_formula_map"]
+
+
+class TestDeriveM8HybridFields:
+ def test_hybrid_formula_map(self):
+ ref = _load_ref("M8")
+ derived = _derive_housing_config_dict(
+ "M8",
+ _coil_assignment_from_ref(ref),
+ ref["formats"],
+ _extra_config_from_ref(ref),
+ )
+ assert derived["hybrid_formula_map"] == ref["hybrid_formula_map"]
+
+ def test_hybrid_voltage_mask_map(self):
+ ref = _load_ref("M8")
+ derived = _derive_housing_config_dict(
+ "M8",
+ _coil_assignment_from_ref(ref),
+ ref["formats"],
+ _extra_config_from_ref(ref),
+ )
+ assert derived["hybrid_voltage_mask_map"] == ref["hybrid_voltage_mask_map"]
+
+ def test_reference_gr1_hybrid(self):
+ ref = _load_ref("M8")
+ derived = _derive_housing_config_dict(
+ "M8",
+ _coil_assignment_from_ref(ref),
+ ref["formats"],
+ _extra_config_from_ref(ref),
+ )
+ assert derived["reference_gr1_hybrid"] == ref["reference_gr1_hybrid"]
+
+ def test_reference_gr2_hybrid(self):
+ ref = _load_ref("M8")
+ derived = _derive_housing_config_dict(
+ "M8",
+ _coil_assignment_from_ref(ref),
+ ref["formats"],
+ _extra_config_from_ref(ref),
+ )
+ assert derived["reference_gr2_hybrid"] == ref["reference_gr2_hybrid"]
+
+
+# ---------------------------------------------------------------------------
+# export_housing_config_json
+# ---------------------------------------------------------------------------
+
+
+class TestExportHousingConfigJson:
+ def test_creates_file(self, populated_con, tmp_path):
+ path = export_housing_config_json(populated_con, "M9", tmp_path)
+ assert path.exists()
+
+ def test_filename_convention(self, populated_con, tmp_path):
+ path = export_housing_config_json(populated_con, "M9", tmp_path)
+ assert path.name == "M9-housing-config.json"
+
+ def test_output_is_valid_json(self, populated_con, tmp_path):
+ path = export_housing_config_json(populated_con, "M9", tmp_path)
+ data = json.loads(path.read_text())
+ assert isinstance(data, dict)
+
+ @pytest.mark.parametrize("housing", ["M8", "M9", "M10"])
+ def test_derived_fields_match_reference(self, populated_con, tmp_path, housing):
+ path = export_housing_config_json(populated_con, housing, tmp_path)
+ exported = json.loads(path.read_text())
+ ref = _load_ref(housing)
+ for field in _DERIVED_FIELDS:
+ assert exported[field] == ref[field], (
+ f"{housing}.{field}: got {exported[field]!r}, "
+ f"expected {ref[field]!r}"
+ )
+
+ @pytest.mark.parametrize("housing", ["M8", "M9", "M10"])
+ def test_formula_maps_match_reference(self, populated_con, tmp_path, housing):
+ path = export_housing_config_json(populated_con, housing, tmp_path)
+ exported = json.loads(path.read_text())
+ ref = _load_ref(housing)
+ assert exported["pupitre_formula_map"] == ref["pupitre_formula_map"]
+ assert exported["pigbrother_formula_map"] == ref["pigbrother_formula_map"]
+
+ def test_m8_hybrid_fields_match_reference(self, populated_con, tmp_path):
+ path = export_housing_config_json(populated_con, "M8", tmp_path)
+ exported = json.loads(path.read_text())
+ ref = _load_ref("M8")
+ assert exported["hybrid_formula_map"] == ref["hybrid_formula_map"]
+ assert exported["hybrid_voltage_mask_map"] == ref["hybrid_voltage_mask_map"]
+ assert exported["reference_gr1_hybrid"] == ref["reference_gr1_hybrid"]
+ assert exported["reference_gr2_hybrid"] == ref["reference_gr2_hybrid"]
+
+ def test_missing_housing_raises(self, con, tmp_path):
+ with pytest.raises(ValueError, match="No housing_config row"):
+ export_housing_config_json(con, "INVALID", tmp_path)
+
+ def test_reference_files_are_never_modified(self, populated_con, tmp_path):
+ """Exporting to tmp_path must leave the original reference files untouched."""
+ originals = {name: path.read_text() for name, path in _REF_FILES.items()}
+ for name in _REF_FILES:
+ export_housing_config_json(populated_con, name, tmp_path)
+ for name, path in _REF_FILES.items():
+ assert path.read_text() == originals[name], (
+ f"Reference file {path.name} was modified!"
+ )
diff --git a/to_duckdb/tests/test_magnetdb.py b/to_duckdb/tests/test_magnetdb.py
new file mode 100644
index 0000000..a040075
--- /dev/null
+++ b/to_duckdb/tests/test_magnetdb.py
@@ -0,0 +1,238 @@
+"""Integration tests for magnetdb.py — the unified CLI entry point."""
+
+import json
+
+import duckdb
+import pytest
+
+import magnetdb as cli_module
+from magnetdb import main
+from magnetdb import _add_magnet as add_magnet, _add_site as add_site
+from schema import ensure_schema
+from tests.conftest import MAGNET_JSON, SITE_JSON
+
+
+# ---------------------------------------------------------------------------
+# Helpers
+# ---------------------------------------------------------------------------
+
+
+def _count(db_path, table):
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ return con.execute(f"SELECT COUNT(*) FROM {table}").fetchone()[0]
+
+
+def _fetch_one(db_path, sql, params=None):
+ with duckdb.connect(str(db_path), read_only=True) as con:
+ return con.execute(sql, params or []).fetchone()
+
+
+def _db_with_magnet(tmp_path):
+ db = tmp_path / "test.duckdb"
+ add_magnet(MAGNET_JSON, db)
+ return db
+
+
+def _db_with_site(tmp_path):
+ db = _db_with_magnet(tmp_path)
+ add_site(SITE_JSON, db)
+ return db
+
+
+def _run(monkeypatch, *argv):
+ monkeypatch.setattr("sys.argv", ["magnetdb", *argv])
+ main()
+
+
+# ---------------------------------------------------------------------------
+# magnet add
+# ---------------------------------------------------------------------------
+
+
+def test_cli_magnet_add_creates_magnet(tmp_path, monkeypatch):
+ json_path = tmp_path / "MAG_JSON.json"
+ json_path.write_text(json.dumps(MAGNET_JSON))
+ db_path = tmp_path / "test.duckdb"
+
+ _run(monkeypatch, "magnet", "add", str(json_path), "--db", str(db_path))
+
+ assert _count(db_path, "magnets") == 1
+ assert _count(db_path, "parts") == 2
+ assert _count(db_path, "materials") == 2
+
+
+def test_cli_magnet_add_dry_run_writes_nothing(tmp_path, monkeypatch):
+ json_path = tmp_path / "MAG_JSON.json"
+ json_path.write_text(json.dumps(MAGNET_JSON))
+ db_path = tmp_path / "test.duckdb"
+
+ _run(monkeypatch, "magnet", "add", str(json_path), "--db", str(db_path), "--dry-run")
+
+ assert not db_path.exists()
+
+
+def test_cli_magnet_add_missing_json_exits(tmp_path, monkeypatch):
+ with pytest.raises(SystemExit):
+ _run(monkeypatch, "magnet", "add", str(tmp_path / "NOPE.json"),
+ "--db", str(tmp_path / "test.duckdb"))
+
+
+# ---------------------------------------------------------------------------
+# magnet view
+# ---------------------------------------------------------------------------
+
+
+def test_cli_magnet_view_list_all(tmp_path, monkeypatch, capsys):
+ db = _db_with_magnet(tmp_path)
+ _run(monkeypatch, "magnet", "view", "--db", str(db))
+ assert "MAG_JSON" in capsys.readouterr().out
+
+
+def test_cli_magnet_view_one(tmp_path, monkeypatch, capsys):
+ db = _db_with_magnet(tmp_path)
+ _run(monkeypatch, "magnet", "view", "MAG_JSON", "--db", str(db))
+ out = capsys.readouterr().out
+ assert "MAG_JSON" in out
+ assert "H_JSON_01" in out
+
+
+def test_cli_magnet_view_missing_db_exits(tmp_path, monkeypatch):
+ with pytest.raises(SystemExit):
+ _run(monkeypatch, "magnet", "view", "--db", str(tmp_path / "nope.duckdb"))
+
+
+# ---------------------------------------------------------------------------
+# magnet delete
+# ---------------------------------------------------------------------------
+
+
+def test_cli_magnet_delete_removes_magnet(tmp_path, monkeypatch):
+ db = _db_with_magnet(tmp_path)
+ _run(monkeypatch, "magnet", "delete", "MAG_JSON", "--db", str(db))
+ assert _count(db, "magnets") == 0
+ assert _count(db, "magnet_parts") == 0
+
+
+def test_cli_magnet_delete_missing_db_exits(tmp_path, monkeypatch):
+ with pytest.raises(SystemExit):
+ _run(monkeypatch, "magnet", "delete", "MAG_JSON",
+ "--db", str(tmp_path / "nope.duckdb"))
+
+
+# ---------------------------------------------------------------------------
+# site add
+# ---------------------------------------------------------------------------
+
+
+def test_cli_site_add_creates_site(tmp_path, monkeypatch):
+ db = _db_with_magnet(tmp_path)
+ json_path = tmp_path / "SITE_JSON_01.json"
+ json_path.write_text(json.dumps(SITE_JSON))
+
+ _run(monkeypatch, "site", "add", str(json_path), "--db", str(db))
+
+ assert _count(db, "sites") == 1
+ assert _count(db, "site_magnets") == 1
+ assert _count(db, "experiments") == len(SITE_JSON["records"])
+
+
+def test_cli_site_add_dry_run_writes_nothing(tmp_path, monkeypatch):
+ db = _db_with_magnet(tmp_path)
+ json_path = tmp_path / "SITE_JSON_01.json"
+ json_path.write_text(json.dumps(SITE_JSON))
+
+ _run(monkeypatch, "site", "add", str(json_path), "--db", str(db), "--dry-run")
+
+ assert _count(db, "sites") == 0
+
+
+def test_cli_site_add_missing_json_exits(tmp_path, monkeypatch):
+ db = _db_with_magnet(tmp_path)
+ with pytest.raises(SystemExit):
+ _run(monkeypatch, "site", "add", str(tmp_path / "NOPE.json"), "--db", str(db))
+
+
+# ---------------------------------------------------------------------------
+# site view
+# ---------------------------------------------------------------------------
+
+
+def test_cli_site_view_list_all(tmp_path, monkeypatch, capsys):
+ db = _db_with_site(tmp_path)
+ _run(monkeypatch, "site", "view", "--db", str(db))
+ assert "SITE_JSON_01" in capsys.readouterr().out
+
+
+def test_cli_site_view_one(tmp_path, monkeypatch, capsys):
+ db = _db_with_site(tmp_path)
+ _run(monkeypatch, "site", "view", "SITE_JSON_01", "--db", str(db))
+ out = capsys.readouterr().out
+ assert "SITE_JSON_01" in out
+ assert "M10" in out
+
+
+def test_cli_site_view_missing_db_exits(tmp_path, monkeypatch):
+ with pytest.raises(SystemExit):
+ _run(monkeypatch, "site", "view", "--db", str(tmp_path / "nope.duckdb"))
+
+
+# ---------------------------------------------------------------------------
+# site delete
+# ---------------------------------------------------------------------------
+
+
+def test_cli_site_delete_removes_site_and_related(tmp_path, monkeypatch):
+ db = _db_with_site(tmp_path)
+ _run(monkeypatch, "site", "delete", "SITE_JSON_01", "--db", str(db))
+ assert _count(db, "sites") == 0
+ assert _count(db, "site_magnets") == 0
+ assert _count(db, "experiments") == 0
+
+
+def test_cli_site_delete_missing_db_exits(tmp_path, monkeypatch):
+ with pytest.raises(SystemExit):
+ _run(monkeypatch, "site", "delete", "SITE_JSON_01",
+ "--db", str(tmp_path / "nope.duckdb"))
+
+
+# ---------------------------------------------------------------------------
+# site update-magnet
+# ---------------------------------------------------------------------------
+
+
+def test_cli_site_update_magnet_changes_offset(tmp_path, monkeypatch):
+ db = _db_with_site(tmp_path)
+
+ _run(monkeypatch, "site", "update-magnet",
+ "SITE_JSON_01", "MAG_JSON",
+ "--db", str(db),
+ "--z-offset", "9.5")
+
+ row = _fetch_one(db, "SELECT z_offset FROM site_magnets WHERE magnet_name = 'MAG_JSON'")
+ assert row[0] == 9.5
+
+
+def test_cli_site_update_magnet_invalid_metadata_exits(tmp_path, monkeypatch):
+ db = _db_with_site(tmp_path)
+ with pytest.raises(SystemExit):
+ _run(monkeypatch, "site", "update-magnet",
+ "SITE_JSON_01", "MAG_JSON",
+ "--db", str(db),
+ "--metadata", "NOT_JSON")
+
+
+def test_cli_site_update_magnet_missing_row_exits(tmp_path, monkeypatch):
+ db = _db_with_magnet(tmp_path) # site not added → no site_magnets row
+ with pytest.raises(SystemExit):
+ _run(monkeypatch, "site", "update-magnet",
+ "NONEXISTENT_SITE", "MAG_JSON",
+ "--db", str(db),
+ "--z-offset", "1.0")
+
+
+def test_cli_site_update_magnet_missing_db_exits(tmp_path, monkeypatch):
+ with pytest.raises(SystemExit):
+ _run(monkeypatch, "site", "update-magnet",
+ "SITE_JSON_01", "MAG_JSON",
+ "--db", str(tmp_path / "nope.duckdb"),
+ "--z-offset", "1.0")
diff --git a/to_duckdb/tests/test_material_db.py b/to_duckdb/tests/test_material_db.py
new file mode 100644
index 0000000..69abb25
--- /dev/null
+++ b/to_duckdb/tests/test_material_db.py
@@ -0,0 +1,258 @@
+"""Tests for material CRUD operations (schema.py + crud.py).
+
+Reference JSON files from hifimagnet-projects/magnetdb.json are used as
+ground truth. They are opened read-only and are never modified.
+"""
+
+import json
+from pathlib import Path
+
+import duckdb
+import pytest
+
+from schema import ensure_schema
+from crud import (
+ delete_material,
+ exists,
+ insert_material,
+ insert_part,
+ view_material,
+ view_materials,
+)
+
+# ---------------------------------------------------------------------------
+# Reference JSON files (read-only)
+# ---------------------------------------------------------------------------
+
+_MAGNETDB_JSON = (
+ Path(__file__).parent.parent.parent.parent
+ / "hifimagnet-projects" / "magnetdb.json"
+)
+
+_REF_FILES: dict[str, Path] = {
+ "MA20072304": _MAGNETDB_JSON / "MA20072304.json",
+ "MA15011202": _MAGNETDB_JSON / "MA15011202.json",
+ "MA25031201": _MAGNETDB_JSON / "MA25031201.json",
+}
+
+_EXPECTED: dict[str, dict] = {}
+for _name, _path in _REF_FILES.items():
+ if _path.exists():
+ _EXPECTED[_name] = json.loads(_path.read_text())
+
+
+def _ref_available(name: str):
+ return pytest.mark.skipif(
+ name not in _EXPECTED,
+ reason=f"Reference file for {name} not found",
+ )
+
+
+# ---------------------------------------------------------------------------
+# Fixtures
+# ---------------------------------------------------------------------------
+
+
+@pytest.fixture()
+def con():
+ """Fresh in-memory DuckDB connection with the full schema."""
+ conn = duckdb.connect(":memory:")
+ ensure_schema(conn)
+ yield conn
+ conn.close()
+
+
+@pytest.fixture()
+def populated_con(con):
+ """Connection pre-loaded with all available reference materials."""
+ for data in _EXPECTED.values():
+ insert_material(con, data, verbose=False)
+ return con
+
+
+# ---------------------------------------------------------------------------
+# Schema
+# ---------------------------------------------------------------------------
+
+
+class TestMaterialsTable:
+ def test_table_exists(self, con):
+ rows = con.execute(
+ "SELECT table_name FROM information_schema.tables "
+ "WHERE table_name = 'materials'"
+ ).fetchall()
+ assert rows, "materials table not found after ensure_schema()"
+
+ def test_required_columns_present(self, con):
+ cols = {
+ row[0]
+ for row in con.execute(
+ "SELECT column_name FROM information_schema.columns "
+ "WHERE table_name = 'materials'"
+ ).fetchall()
+ }
+ required = {
+ "name", "description", "nuance", "t_ref", "volumic_mass",
+ "specific_heat", "alpha", "electrical_conductivity",
+ "thermal_conductivity", "magnet_permeability",
+ "young", "poisson", "expansion_coefficient", "rpe",
+ }
+ assert required <= cols
+
+ def test_ensure_schema_idempotent(self, con):
+ ensure_schema(con)
+
+
+# ---------------------------------------------------------------------------
+# insert_material
+# ---------------------------------------------------------------------------
+
+
+class TestInsertMaterial:
+ @_ref_available("MA20072304")
+ def test_inserts_row(self, con):
+ insert_material(con, _EXPECTED["MA20072304"], verbose=False)
+ assert exists(con, "materials", "MA20072304")
+
+ @_ref_available("MA20072304")
+ def test_nuance_stored(self, con):
+ insert_material(con, _EXPECTED["MA20072304"], verbose=False)
+ row = con.execute(
+ "SELECT nuance FROM materials WHERE name = 'MA20072304'"
+ ).fetchone()
+ assert row[0] == _EXPECTED["MA20072304"]["nuance"]
+
+ @_ref_available("MA20072304")
+ def test_rpe_stored(self, con):
+ insert_material(con, _EXPECTED["MA20072304"], verbose=False)
+ row = con.execute(
+ "SELECT rpe FROM materials WHERE name = 'MA20072304'"
+ ).fetchone()
+ assert row[0] == pytest.approx(_EXPECTED["MA20072304"]["rpe"])
+
+ @_ref_available("MA20072304")
+ def test_all_numeric_fields_stored(self, con):
+ data = _EXPECTED["MA20072304"]
+ insert_material(con, data, verbose=False)
+ row = con.execute(
+ "SELECT t_ref, volumic_mass, specific_heat, alpha, "
+ "electrical_conductivity, thermal_conductivity, "
+ "magnet_permeability, young, poisson, expansion_coefficient, rpe "
+ "FROM materials WHERE name = 'MA20072304'"
+ ).fetchone()
+ fields = [
+ "t_ref", "volumic_mass", "specific_heat", "alpha",
+ "electrical_conductivity", "thermal_conductivity",
+ "magnet_permeability", "young", "poisson", "expansion_coefficient", "rpe",
+ ]
+ for value, field in zip(row, fields):
+ assert value == pytest.approx(data[field]), f"{field} mismatch"
+
+ @_ref_available("MA20072304")
+ def test_idempotent_second_insert_skipped(self, con):
+ insert_material(con, _EXPECTED["MA20072304"], verbose=False)
+ insert_material(con, _EXPECTED["MA20072304"], verbose=False)
+ count = con.execute(
+ "SELECT COUNT(*) FROM materials WHERE name = 'MA20072304'"
+ ).fetchone()[0]
+ assert count == 1
+
+ @pytest.mark.parametrize("name", list(_EXPECTED))
+ def test_all_ref_materials_insert(self, con, name):
+ insert_material(con, _EXPECTED[name], verbose=False)
+ assert exists(con, "materials", name)
+
+ def test_minimal_material_name_only(self, con):
+ insert_material(con, {"name": "MAT_MINIMAL"}, verbose=False)
+ assert exists(con, "materials", "MAT_MINIMAL")
+
+
+# ---------------------------------------------------------------------------
+# view_materials / view_material
+# ---------------------------------------------------------------------------
+
+
+class TestViewMaterials:
+ def test_empty_database(self, con, capsys):
+ view_materials(con)
+ assert "No materials" in capsys.readouterr().out
+
+ def test_lists_all_inserted(self, populated_con, capsys):
+ view_materials(populated_con)
+ out = capsys.readouterr().out
+ for name in _EXPECTED:
+ assert name in out
+
+ @_ref_available("MA20072304")
+ def test_nuance_in_listing(self, populated_con, capsys):
+ view_materials(populated_con)
+ out = capsys.readouterr().out
+ assert _EXPECTED["MA20072304"]["nuance"] in out
+
+
+class TestViewMaterial:
+ @_ref_available("MA20072304")
+ def test_shows_name(self, populated_con, capsys):
+ view_material(populated_con, "MA20072304")
+ out = capsys.readouterr().out
+ assert "MA20072304" in out
+
+ @_ref_available("MA20072304")
+ def test_shows_nuance(self, populated_con, capsys):
+ view_material(populated_con, "MA20072304")
+ out = capsys.readouterr().out
+ assert _EXPECTED["MA20072304"]["nuance"] in out
+
+ @_ref_available("MA20072304")
+ def test_shows_rpe(self, populated_con, capsys):
+ view_material(populated_con, "MA20072304")
+ out = capsys.readouterr().out
+ assert "rpe" in out
+
+ def test_not_found_message(self, con, capsys):
+ view_material(con, "NONEXISTENT")
+ out = capsys.readouterr().out
+ assert "not found" in out.lower()
+
+
+# ---------------------------------------------------------------------------
+# delete_material
+# ---------------------------------------------------------------------------
+
+
+class TestDeleteMaterial:
+ @_ref_available("MA20072304")
+ def test_deletes_existing(self, con):
+ insert_material(con, _EXPECTED["MA20072304"], verbose=False)
+ delete_material(con, "MA20072304")
+ assert not exists(con, "materials", "MA20072304")
+
+ def test_not_found_message(self, con, capsys):
+ delete_material(con, "NONEXISTENT")
+ out = capsys.readouterr().out
+ assert "not found" in out.lower()
+
+ @_ref_available("MA20072304")
+ def test_blocked_when_part_references_material(self, con, capsys):
+ insert_material(con, _EXPECTED["MA20072304"], verbose=False)
+ insert_part(con, {
+ "name": "PART_REF_TEST",
+ "type": "helix",
+ "status": "in_operation",
+ "material_name": "MA20072304",
+ }, verbose=False)
+ delete_material(con, "MA20072304")
+ out = capsys.readouterr().out
+ assert "referenced" in out.lower() or "error" in out.lower()
+ assert exists(con, "materials", "MA20072304"), (
+ "Material must NOT be deleted when a part references it"
+ )
+
+ @_ref_available("MA20072304")
+ def test_reference_files_unmodified(self):
+ """Reference JSON files must never be written to."""
+ originals = {n: p.read_text() for n, p in _REF_FILES.items() if p.exists()}
+ # (no DB writes happen here; this just re-reads the files)
+ for name, path in _REF_FILES.items():
+ if path.exists():
+ assert path.read_text() == originals[name]
diff --git a/to_duckdb/tests/test_mysql_connect.py b/to_duckdb/tests/test_mysql_connect.py
new file mode 100644
index 0000000..b7eee2b
--- /dev/null
+++ b/to_duckdb/tests/test_mysql_connect.py
@@ -0,0 +1,674 @@
+"""
+tests/test_mysql_connect.py
+===========================
+Tests for mysql_connect.py — three categories:
+
+Unit No external dependencies. Tests pure-Python/DuckDB helper functions.
+Smoke Uses in-memory DuckDB; no MySQL required. Tests CLI arg parsing.
+Integration Require a live MySQL server. Skipped unless MYSQL_TEST_HOST,
+ MYSQL_TEST_USER, MYSQL_TEST_PASSWORD, and MYSQL_TEST_DB are set.
+ Run with: pytest -m integration
+"""
+
+import os
+import sys
+
+import duckdb
+import pytest
+
+from mysql_connect import (
+ _auto_x_field,
+ _build_dsn,
+ _build_export_select,
+ _build_poll_query,
+ _env,
+ _fetch_poll,
+ _is_numeric_type,
+ _is_timestamp_type,
+ _parse_plot_options,
+ _resolve_groups,
+ _safe_widget_id,
+ parse_args,
+)
+
+# ---------------------------------------------------------------------------
+# Integration skip marker
+# ---------------------------------------------------------------------------
+
+_INTEGRATION_VARS = (
+ "MYSQL_TEST_HOST", "MYSQL_TEST_USER",
+ "MYSQL_TEST_PASSWORD", "MYSQL_TEST_DB",
+)
+
+integration = pytest.mark.skipif(
+ not all(os.getenv(v) for v in _INTEGRATION_VARS),
+ reason=(
+ "Set MYSQL_TEST_HOST / MYSQL_TEST_USER / "
+ "MYSQL_TEST_PASSWORD / MYSQL_TEST_DB to run integration tests"
+ ),
+)
+
+# ---------------------------------------------------------------------------
+# Smoke fixture
+# ---------------------------------------------------------------------------
+
+
+@pytest.fixture
+def mem_con():
+ """Plain in-memory DuckDB connection — no mysqldb attachment, no schema."""
+ con = duckdb.connect(":memory:")
+ yield con
+ con.close()
+
+
+# ============================================================================
+# UNIT TESTS — pure Python, no DuckDB extension, no MySQL
+# ============================================================================
+
+
+class TestIsNumericType:
+ @pytest.mark.parametrize("col_type", [
+ "FLOAT", "DOUBLE", "DECIMAL(10,2)", "NUMERIC(8,4)", "REAL",
+ "INTEGER", "INT", "BIGINT", "SMALLINT", "TINYINT",
+ "HUGEINT", "UBIGINT", "UINTEGER", "USMALLINT", "UTINYINT",
+ "float", # lower-case
+ "integer",
+ "double precision", # PostgreSQL alias sometimes seen
+ ])
+ def test_recognized_as_numeric(self, col_type):
+ assert _is_numeric_type(col_type)
+
+ @pytest.mark.parametrize("col_type", [
+ "VARCHAR", "TIMESTAMP", "DATE", "BOOLEAN", "BLOB",
+ "JSON", "TEXT", "CHAR(10)", "DATETIME",
+ ])
+ def test_not_numeric(self, col_type):
+ assert not _is_numeric_type(col_type)
+
+ def test_leading_whitespace_tolerated(self):
+ assert _is_numeric_type(" FLOAT ")
+
+ def test_empty_string_not_numeric(self):
+ assert not _is_numeric_type("")
+
+
+class TestIsTimestampType:
+ @pytest.mark.parametrize("col_type", [
+ "TIMESTAMP", "TIMESTAMPTZ", "DATE", "DATETIME",
+ "timestamp", "date", "datetime",
+ ])
+ def test_recognized_as_timestamp(self, col_type):
+ assert _is_timestamp_type(col_type)
+
+ @pytest.mark.parametrize("col_type", [
+ "FLOAT", "INTEGER", "VARCHAR", "BOOLEAN", "BLOB",
+ ])
+ def test_not_timestamp(self, col_type):
+ assert not _is_timestamp_type(col_type)
+
+ def test_leading_whitespace_tolerated(self):
+ assert _is_timestamp_type(" TIMESTAMP ")
+
+
+class TestAutoXField:
+ def test_returns_first_timestamp_column(self):
+ cols = [("id", "INTEGER"), ("ts", "TIMESTAMP"), ("val", "FLOAT")]
+ assert _auto_x_field(cols) == "ts"
+
+ def test_returns_none_when_no_timestamp(self):
+ cols = [("id", "INTEGER"), ("val", "FLOAT")]
+ assert _auto_x_field(cols) is None
+
+ def test_returns_none_for_empty_list(self):
+ assert _auto_x_field([]) is None
+
+ def test_picks_first_of_multiple_timestamp_columns(self):
+ cols = [("t1", "DATE"), ("t2", "TIMESTAMP"), ("val", "FLOAT")]
+ assert _auto_x_field(cols) == "t1"
+
+ def test_datetime_counts_as_timestamp(self):
+ cols = [("id", "INTEGER"), ("created", "DATETIME")]
+ assert _auto_x_field(cols) == "created"
+
+
+class TestBuildDSN:
+ def test_all_fields_present(self):
+ dsn = _build_dsn("myhost", 3306, "user", "pass", "mydb")
+ assert "host=myhost" in dsn
+ assert "port=3306" in dsn
+ assert "user=user" in dsn
+ assert "password=pass" in dsn
+ assert "database=mydb" in dsn
+
+ def test_non_default_port(self):
+ dsn = _build_dsn("h", 5555, "u", "p", "d")
+ assert "port=5555" in dsn
+
+ def test_returns_string(self):
+ assert isinstance(_build_dsn("h", 3306, "u", "p", "d"), str)
+
+
+class TestBuildPollQuery:
+ def test_select_star_when_no_fields(self):
+ sql = _build_poll_query("t", [], None, 100, None)
+ assert "SELECT *" in sql
+ assert "FROM mysqldb.t" in sql
+ assert "LIMIT 100" in sql
+
+ def test_specific_fields(self):
+ sql = _build_poll_query("t", ["a", "b"], None, 50, None)
+ assert "SELECT a, b" in sql
+
+ def test_where_clause_included(self):
+ sql = _build_poll_query("t", ["x"], "x > 0", 10, None)
+ assert "WHERE (x > 0)" in sql
+
+ def test_no_where_when_none(self):
+ sql = _build_poll_query("t", ["x"], None, 10, None)
+ assert "WHERE" not in sql
+
+ def test_order_by_included(self):
+ sql = _build_poll_query("t", ["ts", "x"], None, 10, "ts")
+ assert "ORDER BY ts" in sql
+
+ def test_no_order_by_when_none(self):
+ sql = _build_poll_query("t", ["x"], None, 10, None)
+ assert "ORDER BY" not in sql
+
+ def test_limit_at_end_of_query(self):
+ sql = _build_poll_query("t", ["x"], "x>0", 77, "x")
+ assert sql.endswith("LIMIT 77")
+
+ def test_table_name_embedded(self):
+ sql = _build_poll_query("measurements", [], None, 10, None)
+ assert "mysqldb.measurements" in sql
+
+
+class TestBuildExportSelect:
+ def test_all_columns_no_filter(self):
+ sql = _build_export_select("t", [], None, None, None)
+ assert sql == "SELECT * FROM mysqldb.t"
+
+ def test_specific_columns(self):
+ sql = _build_export_select("t", ["a", "b"], None, None, None)
+ assert "SELECT a, b" in sql
+ assert "FROM mysqldb.t" in sql
+
+ def test_start_only(self):
+ sql = _build_export_select("t", [], "ts", "2024-01-01", None)
+ assert "WHERE" in sql
+ assert "2024-01-01" in sql
+ assert "CAST" in sql
+ assert ">=" in sql
+
+ def test_end_only(self):
+ sql = _build_export_select("t", [], "ts", None, "2024-12-31")
+ assert "WHERE" in sql
+ assert "2024-12-31" in sql
+ assert "<=" in sql
+
+ def test_start_and_end_joined_by_and(self):
+ sql = _build_export_select("t", [], "ts", "2024-01-01", "2024-12-31")
+ assert "AND" in sql
+ assert "2024-01-01" in sql
+ assert "2024-12-31" in sql
+
+ def test_no_where_when_time_field_missing(self):
+ sql = _build_export_select("t", [], None, "2024-01-01", "2024-12-31")
+ assert "WHERE" not in sql
+
+ def test_no_where_when_both_bounds_none(self):
+ sql = _build_export_select("t", [], "ts", None, None)
+ assert "WHERE" not in sql
+
+ def test_timestamp_cast_syntax(self):
+ sql = _build_export_select("t", [], "created", "2024-06-01 00:00:00", None)
+ assert "CAST('2024-06-01 00:00:00' AS TIMESTAMP)" in sql
+
+
+class TestResolveGroups:
+ def test_subplots_default_one_group_per_field(self):
+ groups = _resolve_groups(["a", "b", "c"], {"layout": "subplots"})
+ assert groups == [["a"], ["b"], ["c"]]
+
+ def test_overlay_single_group_all_fields(self):
+ groups = _resolve_groups(["a", "b"], {"layout": "overlay"})
+ assert groups == [["a", "b"]]
+
+ def test_groups_user_defined(self):
+ opts = {"layout": "groups", "groups": [["a", "b"], ["c"]]}
+ groups = _resolve_groups(["a", "b", "c"], opts)
+ assert groups == [["a", "b"], ["c"]]
+
+ def test_groups_unknown_field_exits(self):
+ opts = {"layout": "groups", "groups": [["x", "NONEXISTENT"]]}
+ with pytest.raises(SystemExit) as exc:
+ _resolve_groups(["x"], opts)
+ assert exc.value.code == 1
+
+ def test_groups_empty_list_falls_back_to_subplots(self):
+ groups = _resolve_groups(["a", "b"], {"layout": "groups", "groups": []})
+ assert groups == [["a"], ["b"]]
+
+ def test_unknown_layout_falls_back_to_subplots(self):
+ groups = _resolve_groups(["a", "b"], {"layout": "unknown_layout"})
+ assert groups == [["a"], ["b"]]
+
+ def test_single_field_overlay(self):
+ groups = _resolve_groups(["x"], {"layout": "overlay"})
+ assert groups == [["x"]]
+
+ def test_missing_layout_key_defaults_to_subplots(self):
+ groups = _resolve_groups(["a", "b"], {})
+ assert groups == [["a"], ["b"]]
+
+
+class TestParseOptions:
+ def test_defaults_when_none(self):
+ opts = _parse_plot_options(None)
+ assert opts["type"] == "line"
+ assert opts["layout"] == "subplots"
+ assert opts["colors"] == []
+ assert opts["font"] is None
+ assert opts["fontsize"] is None
+ assert opts["figsize"] == [12, 6]
+
+ def test_user_values_override_defaults(self):
+ opts = _parse_plot_options('{"type":"scatter","fontsize":12}')
+ assert opts["type"] == "scatter"
+ assert opts["fontsize"] == 12
+ assert opts["layout"] == "subplots" # untouched default
+
+ def test_partial_override_preserves_other_defaults(self):
+ opts = _parse_plot_options('{"font":"Arial"}')
+ assert opts["font"] == "Arial"
+ assert opts["type"] == "line"
+ assert opts["figsize"] == [12, 6]
+
+ def test_invalid_json_exits(self):
+ with pytest.raises(SystemExit) as exc:
+ _parse_plot_options("{not valid json}")
+ assert exc.value.code == 1
+
+ def test_non_object_json_exits(self):
+ with pytest.raises(SystemExit) as exc:
+ _parse_plot_options("[1, 2, 3]")
+ assert exc.value.code == 1
+
+ def test_groups_key_passed_through(self):
+ opts = _parse_plot_options('{"layout":"groups","groups":[["a","b"]]}')
+ assert opts["groups"] == [["a", "b"]]
+
+
+class TestSafeWidgetId:
+ def test_plain_name_unchanged(self):
+ assert _safe_widget_id("Icoil") == "Icoil"
+
+ def test_spaces_replaced_with_underscore(self):
+ assert _safe_widget_id("Timestamp Field") == "Timestamp_Field"
+
+ def test_dots_replaced(self):
+ assert _safe_widget_id("m.Icoil") == "m_Icoil"
+
+ def test_mixed_special_chars(self):
+ result = _safe_widget_id("field (A)")
+ for bad in (" ", "(", ")"):
+ assert bad not in result
+
+ def test_digits_preserved(self):
+ assert _safe_widget_id("ch1_val") == "ch1_val"
+
+ def test_empty_string(self):
+ assert _safe_widget_id("") == ""
+
+ def test_all_special_chars_replaced(self):
+ result = _safe_widget_id("a-b+c/d")
+ assert result == "a_b_c_d"
+
+
+class TestEnv:
+ def test_returns_env_var_value(self, monkeypatch):
+ monkeypatch.setenv("TEST_MC_KEY", "hello")
+ assert _env("TEST_MC_KEY") == "hello"
+
+ def test_returns_default_when_not_set(self, monkeypatch):
+ monkeypatch.delenv("TEST_MC_MISSING", raising=False)
+ assert _env("TEST_MC_MISSING", "fallback") == "fallback"
+
+ def test_returns_none_when_not_set_and_no_default(self, monkeypatch):
+ monkeypatch.delenv("TEST_MC_MISSING", raising=False)
+ assert _env("TEST_MC_MISSING") is None
+
+
+# ============================================================================
+# SMOKE TESTS — in-memory DuckDB, no MySQL
+# ============================================================================
+
+
+class TestFetchPollSmoke:
+ def test_returns_column_names_and_rows(self, mem_con):
+ mem_con.execute("CREATE TABLE t AS SELECT 1.5 AS x, 2.5 AS y")
+ cols, rows = _fetch_poll(mem_con, "SELECT x, y FROM t")
+ assert cols == ["x", "y"]
+ assert len(rows) == 1
+ assert rows[0] == (1.5, 2.5)
+
+ def test_empty_result_returns_empty_rows(self, mem_con):
+ mem_con.execute("CREATE TABLE empty_t (x FLOAT)")
+ cols, rows = _fetch_poll(mem_con, "SELECT x FROM empty_t")
+ assert cols == ["x"]
+ assert rows == []
+
+ def test_multiple_rows(self, mem_con):
+ mem_con.execute(
+ "CREATE TABLE multi AS "
+ "SELECT UNNEST([1.0, 2.0, 3.0]) AS v"
+ )
+ cols, rows = _fetch_poll(mem_con, "SELECT v FROM multi")
+ assert cols == ["v"]
+ assert len(rows) == 3
+
+ def test_integer_column(self, mem_con):
+ mem_con.execute("CREATE TABLE ints AS SELECT 42 AS n")
+ cols, rows = _fetch_poll(mem_con, "SELECT n FROM ints")
+ assert cols == ["n"]
+ assert rows[0][0] == 42
+
+ def test_limit_honoured(self, mem_con):
+ mem_con.execute(
+ "CREATE TABLE big AS "
+ "SELECT UNNEST(range(100)) AS i"
+ )
+ _, rows = _fetch_poll(mem_con, "SELECT i FROM big LIMIT 10")
+ assert len(rows) == 10
+
+
+class TestParseArgsSmoke:
+ """Test CLI argument parsing without connecting to MySQL."""
+
+ _CONN = ["--user", "u", "--password", "p", "--database", "db"]
+
+ def _parse(self, monkeypatch, extra: list):
+ # Clear MySQL env vars so they don't satisfy the "missing" check
+ for v in ("MYSQL_USER", "MYSQL_PASSWORD", "MYSQL_DB"):
+ monkeypatch.delenv(v, raising=False)
+ sys.argv = ["mysql_connect.py"] + self._CONN + extra
+ return parse_args()
+
+ def test_default_mode_is_live(self, monkeypatch):
+ args = self._parse(monkeypatch, [])
+ assert args.mode == "live"
+
+ def test_export_mode(self, monkeypatch):
+ args = self._parse(monkeypatch, ["--mode", "export"])
+ assert args.mode == "export"
+ assert args.fmt == "csv"
+
+ def test_export_duckdb_format(self, monkeypatch):
+ args = self._parse(monkeypatch, ["--mode", "export", "--format", "duckdb"])
+ assert args.fmt == "duckdb"
+
+ def test_export_parquet_format(self, monkeypatch):
+ args = self._parse(monkeypatch, ["--mode", "export", "--format", "parquet"])
+ assert args.fmt == "parquet"
+
+ def test_export_fields_and_time_range(self, monkeypatch):
+ args = self._parse(monkeypatch, [
+ "--mode", "export", "--tables", "measurements",
+ "--export-fields", "Icoil", "Ucoil",
+ "--start", "2024-01-01",
+ "--end", "2024-12-31",
+ ])
+ assert args.export_fields == ["Icoil", "Ucoil"]
+ assert args.start == "2024-01-01"
+ assert args.end == "2024-12-31"
+
+ def test_poll_with_table(self, monkeypatch):
+ args = self._parse(monkeypatch, ["--mode", "poll", "--table", "measurements"])
+ assert args.mode == "poll"
+ assert args.table == "measurements"
+
+ def test_poll_with_query(self, monkeypatch):
+ args = self._parse(monkeypatch, ["--mode", "poll", "--query", "SELECT 1"])
+ assert args.query == "SELECT 1"
+
+ def test_poll_list_tables_requires_no_table(self, monkeypatch):
+ args = self._parse(monkeypatch, ["--mode", "poll", "--list-tables"])
+ assert args.list_tables is True
+
+ def test_poll_list_fields(self, monkeypatch):
+ args = self._parse(monkeypatch, [
+ "--mode", "poll", "--table", "t", "--list-fields",
+ ])
+ assert args.list_fields is True
+
+ def test_poll_defaults(self, monkeypatch):
+ args = self._parse(monkeypatch, ["--mode", "poll", "--table", "t"])
+ assert args.interval == 5.0
+ assert args.limit is None
+ assert args.count == 0
+ assert args.plot == "matplotlib"
+
+ def test_poll_custom_interval_and_limit(self, monkeypatch):
+ args = self._parse(monkeypatch, [
+ "--mode", "poll", "--table", "t",
+ "--interval", "10.5", "--limit", "500",
+ ])
+ assert args.interval == 10.5
+ assert args.limit == 500
+
+ @pytest.mark.parametrize("backend", ["matplotlib", "plotly", "textual", "dash"])
+ def test_poll_plot_backends(self, monkeypatch, backend):
+ args = self._parse(monkeypatch, [
+ "--mode", "poll", "--table", "t", "--plot", backend,
+ ])
+ assert args.plot == backend
+
+ def test_poll_dash_host_port(self, monkeypatch):
+ args = self._parse(monkeypatch, [
+ "--mode", "poll", "--table", "t",
+ "--plot", "dash",
+ "--dash-host", "0.0.0.0",
+ "--dash-port", "9000",
+ ])
+ assert args.dash_host == "0.0.0.0"
+ assert args.dash_port == 9000
+
+ def test_plot_options_stored_as_raw_string(self, monkeypatch):
+ raw = '{"type":"scatter","fontsize":11}'
+ args = self._parse(monkeypatch, [
+ "--mode", "poll", "--table", "t",
+ "--plot-options", raw,
+ ])
+ assert args.plot_options == raw
+
+ def test_where_clause_stored(self, monkeypatch):
+ args = self._parse(monkeypatch, [
+ "--mode", "poll", "--table", "t",
+ "--where", "status='active'",
+ ])
+ assert args.where == "status='active'"
+
+ def test_verbose_flag(self, monkeypatch):
+ args = self._parse(monkeypatch, ["--verbose"])
+ assert args.verbose is True
+
+ def test_error_missing_all_credentials(self, monkeypatch):
+ for v in ("MYSQL_USER", "MYSQL_PASSWORD", "MYSQL_DB"):
+ monkeypatch.delenv(v, raising=False)
+ sys.argv = ["mysql_connect.py"]
+ with pytest.raises(SystemExit) as exc:
+ parse_args()
+ assert exc.value.code == 2
+
+ def test_error_table_and_query_mutually_exclusive(self, monkeypatch):
+ with pytest.raises(SystemExit) as exc:
+ self._parse(monkeypatch, [
+ "--mode", "poll",
+ "--table", "t",
+ "--query", "SELECT 1",
+ ])
+ assert exc.value.code == 2
+
+ def test_error_poll_without_table_or_query(self, monkeypatch):
+ with pytest.raises(SystemExit) as exc:
+ self._parse(monkeypatch, ["--mode", "poll"])
+ assert exc.value.code == 2
+
+ def test_error_invalid_plot_backend(self, monkeypatch):
+ with pytest.raises(SystemExit) as exc:
+ self._parse(monkeypatch, [
+ "--mode", "poll", "--table", "t",
+ "--plot", "gnuplot",
+ ])
+ assert exc.value.code == 2
+
+ def test_view_mode_with_table(self, monkeypatch):
+ args = self._parse(monkeypatch, ["--mode", "view", "--table", "measurements"])
+ assert args.mode == "view"
+ assert args.table == "measurements"
+
+ def test_view_mode_with_query(self, monkeypatch):
+ args = self._parse(monkeypatch, [
+ "--mode", "view", "--query", "SELECT 1 AS n",
+ ])
+ assert args.mode == "view"
+ assert args.query == "SELECT 1 AS n"
+
+ def test_view_mode_with_where_and_limit(self, monkeypatch):
+ args = self._parse(monkeypatch, [
+ "--mode", "view", "--table", "t",
+ "--where", "status='active'", "--limit", "50",
+ ])
+ assert args.where == "status='active'"
+ assert args.limit == 50
+
+ def test_view_mode_limit_zero_allowed(self, monkeypatch):
+ args = self._parse(monkeypatch, [
+ "--mode", "view", "--table", "t", "--limit", "0",
+ ])
+ assert args.limit == 0
+
+ def test_error_view_without_table_or_query(self, monkeypatch):
+ with pytest.raises(SystemExit) as exc:
+ self._parse(monkeypatch, ["--mode", "view"])
+ assert exc.value.code == 2
+
+ def test_error_view_table_and_query_mutually_exclusive(self, monkeypatch):
+ with pytest.raises(SystemExit) as exc:
+ self._parse(monkeypatch, [
+ "--mode", "view",
+ "--table", "t", "--query", "SELECT 1",
+ ])
+ assert exc.value.code == 2
+
+
+# ============================================================================
+# INTEGRATION TESTS — require a live MySQL server
+# ============================================================================
+
+
+@pytest.fixture(scope="module")
+def mysql_con():
+ """
+ DuckDB connection with a live MySQL database attached as 'mysqldb'.
+
+ Requires env vars:
+ MYSQL_TEST_HOST, MYSQL_TEST_USER, MYSQL_TEST_PASSWORD, MYSQL_TEST_DB
+ """
+ from mysql_connect import _attach_mysql, _build_dsn, _load_mysql_extension
+
+ host = os.environ["MYSQL_TEST_HOST"]
+ user = os.environ["MYSQL_TEST_USER"]
+ password = os.environ["MYSQL_TEST_PASSWORD"]
+ database = os.environ["MYSQL_TEST_DB"]
+ port = int(os.environ.get("MYSQL_TEST_PORT", "3306"))
+
+ dsn = _build_dsn(host, port, user, password, database)
+ con = duckdb.connect()
+ _load_mysql_extension(con)
+ _attach_mysql(con, dsn)
+ yield con, database
+ con.close()
+
+
+@pytest.mark.integration
+class TestIntegrationListTables:
+ def test_returns_non_empty_list(self, mysql_con):
+ con, database = mysql_con
+ from mysql_connect import list_mysql_tables
+ tables = list_mysql_tables(con, database)
+ assert isinstance(tables, list)
+ assert len(tables) > 0
+
+ def test_sorted_alphabetically(self, mysql_con):
+ con, database = mysql_con
+ from mysql_connect import list_mysql_tables
+ tables = list_mysql_tables(con, database)
+ assert tables == sorted(tables)
+
+ def test_all_entries_are_strings(self, mysql_con):
+ con, database = mysql_con
+ from mysql_connect import list_mysql_tables
+ for name in list_mysql_tables(con, database):
+ assert isinstance(name, str)
+
+
+@pytest.mark.integration
+class TestIntegrationDescribeTable:
+ def test_returns_list_of_tuples(self, mysql_con):
+ con, database = mysql_con
+ from mysql_connect import describe_table, list_mysql_tables
+ table = list_mysql_tables(con, database)[0]
+ cols = describe_table(con, table)
+ assert isinstance(cols, list)
+ assert len(cols) > 0
+ assert isinstance(cols[0], tuple)
+
+ def test_column_names_and_types_are_strings(self, mysql_con):
+ con, database = mysql_con
+ from mysql_connect import describe_table, list_mysql_tables
+ table = list_mysql_tables(con, database)[0]
+ for col in describe_table(con, table):
+ assert isinstance(col[0], str), f"column name not str: {col[0]!r}"
+ assert isinstance(col[1], str), f"column type not str: {col[1]!r}"
+
+
+@pytest.mark.integration
+class TestIntegrationListNumericColumns:
+ def test_returns_subset_of_all_columns(self, mysql_con):
+ con, database = mysql_con
+ from mysql_connect import describe_table, list_mysql_tables, list_numeric_columns
+ table = list_mysql_tables(con, database)[0]
+ all_names = {c[0] for c in describe_table(con, table)}
+ numeric_names = {c[0] for c in list_numeric_columns(con, table)}
+ assert numeric_names.issubset(all_names)
+
+ def test_all_returned_types_are_numeric(self, mysql_con):
+ con, database = mysql_con
+ from mysql_connect import list_mysql_tables, list_numeric_columns
+ table = list_mysql_tables(con, database)[0]
+ for name, col_type in list_numeric_columns(con, table):
+ assert _is_numeric_type(col_type), (
+ f"Column {name!r} has non-numeric type {col_type!r}"
+ )
+
+
+@pytest.mark.integration
+class TestIntegrationFetchPoll:
+ def test_fetch_returns_cols_and_rows(self, mysql_con):
+ con, database = mysql_con
+ from mysql_connect import list_mysql_tables
+ table = list_mysql_tables(con, database)[0]
+ cols, rows = _fetch_poll(con, f"SELECT * FROM mysqldb.{table} LIMIT 5")
+ assert isinstance(cols, list)
+ assert len(cols) > 0
+ assert isinstance(rows, list)
+ assert len(rows) <= 5
+
+ def test_limit_respected(self, mysql_con):
+ con, database = mysql_con
+ from mysql_connect import list_mysql_tables
+ table = list_mysql_tables(con, database)[0]
+ _, rows = _fetch_poll(con, f"SELECT * FROM mysqldb.{table} LIMIT 3")
+ assert len(rows) <= 3
diff --git a/to_duckdb/tests/test_schema.py b/to_duckdb/tests/test_schema.py
new file mode 100644
index 0000000..56dc3a3
--- /dev/null
+++ b/to_duckdb/tests/test_schema.py
@@ -0,0 +1,76 @@
+"""Tests for schema.py — DDL creation and idempotency."""
+
+import duckdb
+import pytest
+
+from schema import COIL_TYPES, ensure_schema
+
+EXPECTED_TABLES = {
+ "materials",
+ "parts",
+ "magnets",
+ "magnet_parts",
+ "sites",
+ "site_magnets",
+ "experiments",
+ "operationaldata",
+ "overview_records",
+ "housing_config",
+ "op_run_scalars",
+ "op_site_bin_stats",
+ "op_part_bin_stats",
+ "op_stats_processed",
+ "hoop_stress_processed",
+ "hoop_stress_bin_stats",
+ "hoop_stress_fatigue",
+}
+
+
+def _table_names(con) -> set[str]:
+ return {row[0] for row in con.execute("SHOW TABLES").fetchall()}
+
+
+def test_ensure_schema_creates_all_tables():
+ con = duckdb.connect(":memory:")
+ ensure_schema(con)
+ assert _table_names(con) == EXPECTED_TABLES
+ con.close()
+
+
+def test_ensure_schema_is_idempotent():
+ """Calling ensure_schema twice on the same connection must not raise."""
+ con = duckdb.connect(":memory:")
+ ensure_schema(con)
+ ensure_schema(con)
+ assert _table_names(con) == EXPECTED_TABLES
+ con.close()
+
+
+def test_ensure_schema_on_empty_file(tmp_path):
+ """ensure_schema must work on a freshly created file-backed database."""
+ db_path = tmp_path / "new.duckdb"
+ con = duckdb.connect(str(db_path))
+ ensure_schema(con)
+ assert _table_names(con) == EXPECTED_TABLES
+ con.close()
+
+
+def test_coil_types_contains_expected_values():
+ assert "helix" in COIL_TYPES
+ assert "bitter" in COIL_TYPES
+ assert "ring" not in COIL_TYPES
+ assert "lead" not in COIL_TYPES
+
+
+@pytest.mark.parametrize("table,fk_col,fk_table", [
+ ("parts", "material_name", "materials"),
+ ("magnet_parts", "magnet_name", "magnets"),
+ ("magnet_parts", "part_name", "parts"),
+ ("site_magnets", "site_name", "sites"),
+ ("site_magnets", "magnet_name", "magnets"),
+ ("experiments", "site_name", "sites"),
+])
+def test_foreign_key_columns_exist(con, table, fk_col, fk_table):
+ """Spot-check that FK columns are present (via PRAGMA table_info)."""
+ cols = {row[1] for row in con.execute(f"PRAGMA table_info({table})").fetchall()}
+ assert fk_col in cols, f"{table}.{fk_col} missing"
diff --git a/to_duckdb/tutorials/README.md b/to_duckdb/tutorials/README.md
new file mode 100644
index 0000000..da281ce
--- /dev/null
+++ b/to_duckdb/tutorials/README.md
@@ -0,0 +1,69 @@
+# Tutorials
+
+Standalone scripts and notes for exploring the student MagnetDB DuckDB
+without the full MagnetDB / Django infrastructure.
+
+All scripts can be run from the `to_duckdb/` directory and default to
+`magnetdb.duckdb` in that directory.
+
+---
+
+## Scripts
+
+| File | Description |
+|------|-------------|
+| `queries.py` | Ready-to-run DuckDB query examples — copy cells into a Jupyter notebook as a starting point |
+| `statheures_demo.py` | Field-time histogram demo: bin counts, annual comparisons, no `python_magnetrun` required |
+| `stress_map.py` | Backward-compatibility shim — delegates to `magnetdb.py hoop-stress` |
+
+---
+
+## Hoop-stress analysis
+
+The hoop-stress commands are now integrated into the main CLI.
+Run them from `to_duckdb/`:
+
+```bash
+python magnetdb.py hoop-stress barchart [--i-h A] [--i-b A] [--i-s A]
+python magnetdb.py hoop-stress history [--pupitre FILE ...] [--use-mrun]
+python magnetdb.py hoop-stress stats [--pupitre FILE ...] [--output CSV]
+python magnetdb.py hoop-stress fatigue [--pupitre FILE ...] [--bins N]
+```
+
+`stress_map.py` in this directory accepts the same arguments for
+backward compatibility. For a step-by-step explanation of how the analysis
+chain works, see:
+
+- [README_student_stress_map.md](README_student_stress_map.md)
+- [student_statheures_note.md](student_statheures_note.md)
+
+---
+
+## Query examples
+
+`queries.py` covers:
+
+- Full site → magnet → part → material hierarchy
+- Coil map for a specific magnet
+- Experiment records for a site
+- Helix material lookup
+- Per-magnet channel list
+- Shared-part detection
+- Site history for a part
+
+```bash
+python tutorials/queries.py
+```
+
+---
+
+## Field-time statistics demo
+
+`statheures_demo.py` demonstrates the `statheures` workflow:
+
+```bash
+python tutorials/statheures_demo.py
+python tutorials/statheures_demo.py --site M10_M19071101_13 --step 1.0
+python tutorials/statheures_demo.py --site M10_M19071101_13 --year 2025
+python tutorials/statheures_demo.py --site M10_M19071101_13 --compare 2025 2026
+```
diff --git a/to_duckdb/tutorials/queries.py b/to_duckdb/tutorials/queries.py
new file mode 100644
index 0000000..a997009
--- /dev/null
+++ b/to_duckdb/tutorials/queries.py
@@ -0,0 +1,170 @@
+"""
+queries.py
+==========
+Example queries against the MagnetDB DuckDB.
+
+Jupyter use: copy each numbered block as a separate cell.
+ Run the connection cell (DB_PATH + con = …) first.
+
+Requirements:
+ pip install duckdb pandas
+"""
+
+from pathlib import Path
+
+import duckdb
+import pandas as pd
+
+try:
+ DB_PATH = str(Path(__file__).resolve().parent.parent / "magnetdb.duckdb")
+except NameError: # __file__ is undefined in Jupyter
+ DB_PATH = "magnetdb.duckdb"
+
+if __name__ == "__main__":
+ con = duckdb.connect(DB_PATH, read_only=True)
+
+ # ── 1. Full site hierarchy ─────────────────────────────────────────────────
+ print("=== Site hierarchy ===")
+ hierarchy = con.execute("""
+ SELECT
+ s.name AS site,
+ m.name AS magnet,
+ m.type AS magnet_type,
+ p.type AS part_type,
+ mp.coil_index, -- Icoil_N column in records (NULL for rings/leads)
+ mp.rank, -- position in magnet assembly
+ p.name AS part,
+ p.geometry,
+ mat.nuance,
+ mat.rpe / 1e6 AS rpe_MPa
+ FROM sites s
+ JOIN site_magnets sm ON sm.site_name = s.name
+ JOIN magnets m ON m.name = sm.magnet_name
+ JOIN magnet_parts mp ON mp.magnet_name = m.name
+ JOIN parts p ON p.name = mp.part_name
+ LEFT JOIN materials mat ON mat.name = p.material_name
+ ORDER BY s.name, mp.rank
+ """).df()
+ print(hierarchy.to_string())
+
+ # ── 2. Icoil → part mapping for a specific magnet ─────────────────────────
+ print("\n=== Icoil → part mapping for M19061901 ===")
+ coil_map = con.execute("""
+ SELECT
+ 'Icoil' || mp.coil_index AS column_name,
+ p.name AS part_name,
+ p.type,
+ p.geometry,
+ mat.nuance,
+ mat.rpe / 1e6 AS rpe_MPa,
+ mat.electrical_conductivity / 1e6 AS sigma_MS_per_m
+ FROM magnet_parts mp
+ JOIN parts p ON p.name = mp.part_name
+ JOIN magnets m ON m.name = mp.magnet_name
+ LEFT JOIN materials mat ON mat.name = p.material_name
+ WHERE m.name = 'M19061901'
+ AND mp.coil_index IS NOT NULL
+ ORDER BY mp.coil_index
+ """).df()
+ print(coil_map.to_string())
+
+ # ── 3. All records for a site ─────────────────────────────────────────────
+ print("\n=== Records for M9_M19061901 ===")
+ records = con.execute("""
+ SELECT id, file, status
+ FROM experiments
+ WHERE site_name = 'M9_M19061901'
+ ORDER BY file
+ """).df()
+ print(records.to_string())
+
+ # ── 4. Material comparison across all helices ────────────────────────────
+ print("\n=== Helix materials summary ===")
+ helix_mats = con.execute("""
+ SELECT DISTINCT
+ mat.name AS material,
+ mat.nuance,
+ mat.rpe / 1e6 AS rpe_MPa,
+ mat.electrical_conductivity / 1e6 AS sigma_MS_per_m,
+ mat.young / 1e9 AS E_GPa
+ FROM parts p
+ JOIN materials mat ON mat.name = p.material_name
+ WHERE p.type = 'helix'
+ ORDER BY mat.rpe DESC
+ """).df()
+ print(helix_mats.to_string())
+
+ # ── 5. How many coil channels does each magnet have? ─────────────────────
+ print("\n=== Coil channel count per magnet ===")
+ channels = con.execute("""
+ SELECT
+ m.name AS magnet,
+ m.type,
+ COUNT(CASE WHEN mp.coil_index IS NOT NULL THEN 1 END) AS n_coils,
+ COUNT(CASE WHEN p.type = 'ring' THEN 1 END) AS n_rings,
+ COUNT(CASE WHEN p.type = 'lead' THEN 1 END) AS n_leads
+ FROM magnets m
+ JOIN magnet_parts mp ON mp.magnet_name = m.name
+ JOIN parts p ON p.name = mp.part_name
+ GROUP BY m.name, m.type
+ ORDER BY m.type, m.name
+ """).df()
+ print(channels.to_string())
+
+ # ── 6. Parts shared across multiple magnets (reused helices/rings) ────────
+ print("\n=== Parts used in more than one magnet ===")
+ shared = con.execute("""
+ SELECT
+ p.name, p.type,
+ COUNT(DISTINCT mp.magnet_name) AS n_magnets,
+ STRING_AGG(mp.magnet_name, ', ' ORDER BY mp.magnet_name) AS in_magnets
+ FROM magnet_parts mp
+ JOIN parts p ON p.name = mp.part_name
+ GROUP BY p.name, p.type
+ HAVING COUNT(DISTINCT mp.magnet_name) > 1
+ ORDER BY n_magnets DESC, p.type
+ """).df()
+ print(shared.to_string())
+
+ # ── 7. All sites in which a magnet has been used, sorted by commission date ─
+ print("\n=== Sites where magnet M19071101 has been used ===")
+ magnet_sites = con.execute("""
+ SELECT
+ s.name AS site,
+ s.housing,
+ s.status,
+ s.commissioned_at,
+ s.decommissioned_at
+ FROM site_magnets sm
+ JOIN sites s ON s.name = sm.site_name
+ WHERE sm.magnet_name = 'M19071101'
+ ORDER BY s.commissioned_at ASC NULLS LAST
+ """).df()
+ print(magnet_sites.to_string())
+
+ # ── 8. All magnets and sites in which a part has been used,
+ # sorted by site commission date ─────────────────────────────────────
+ print("\n=== Sites and magnets where part H15101601 has been used ===")
+ part_history = con.execute("""
+ SELECT
+ p.name AS part,
+ p.type,
+ mp.coil_index,
+ m.name AS magnet,
+ m.type AS magnet_type,
+ s.name AS site,
+ s.housing,
+ s.commissioned_at,
+ s.decommissioned_at
+ FROM magnet_parts mp
+ JOIN parts p ON p.name = mp.part_name
+ JOIN magnets m ON m.name = mp.magnet_name
+ JOIN site_magnets sm ON sm.magnet_name = m.name
+ JOIN sites s ON s.name = sm.site_name
+ WHERE p.name = 'H15101601'
+ AND p.type IN ('helix', 'bitter')
+ ORDER BY s.commissioned_at ASC NULLS LAST
+ """).df()
+ print(part_history.to_string())
+
+ con.close()
diff --git a/to_duckdb/tutorials/query_cumstats.py b/to_duckdb/tutorials/query_cumstats.py
new file mode 100644
index 0000000..cee988c
--- /dev/null
+++ b/to_duckdb/tutorials/query_cumstats.py
@@ -0,0 +1,638 @@
+"""
+query_cumstats.py
+=================
+Query and display cumulative operational and experiment statistics from DuckDB.
+
+All queries read only from the pre-computed tables (op_run_scalars,
+op_site_bin_stats, op_part_bin_stats, exp_run_scalars, exp_site_bin_stats,
+exp_part_bin_stats) — no raw record files are touched.
+
+Aggregation rules
+-----------------
+ operating time (h) = SUM(sum_dt) / 3600
+ time-weighted mean = SUM(sum_x_dt) / SUM(sum_dt)
+ time-weighted std = sqrt(SUM(sum_x2_dt)/SUM(sum_dt) - mean^2)
+ cumulative energy/etc = SUM(sum_x_dt) [for integral channels]
+ peak value = MAX(max_x)
+
+Usage
+-----
+ # Cumulative scalars for a site (operational data)
+ python query_cumstats.py --db magnetdb.duckdb --site M9_M19061901 scalars
+
+ # Field-bin histogram for a site (time + Ptot mean)
+ python query_cumstats.py --db magnetdb.duckdb --site M9_M19061901 site-bins
+
+ # Field-bin stats per magnet
+ python query_cumstats.py --db magnetdb.duckdb --magnet M9Bitters magnet-bins
+
+ # Field-bin stats per part
+ python query_cumstats.py --db magnetdb.duckdb --part M9Bi part-bins
+
+ # All of the above with plots
+ python query_cumstats.py --db magnetdb.duckdb --site M9_M19061901 site-bins --plot
+
+ # Same queries for experiment data
+ python query_cumstats.py --db magnetdb.duckdb --site M9_M19061901 exp-scalars
+ python query_cumstats.py --db magnetdb.duckdb --site M9_M19061901 exp-site-bins
+ python query_cumstats.py --db magnetdb.duckdb --magnet M9Bitters exp-magnet-bins
+ python query_cumstats.py --db magnetdb.duckdb --part M9Bi exp-part-bins
+
+ # Filter experiment queries by experiment name
+ python query_cumstats.py --db magnetdb.duckdb --site M9_M19061901 --experiment myrun exp-site-bins
+"""
+
+import argparse
+import sys
+from pathlib import Path
+
+import duckdb
+import pandas as pd
+
+sys.path.insert(0, str(Path(__file__).parent))
+from config import DEFAULT_DB
+
+# optional imports — used only for plotting
+try:
+ import matplotlib.pyplot as plt
+ _HAS_MPL = True
+except ImportError:
+ _HAS_MPL = False
+
+# ---------------------------------------------------------------------------
+# Scalar queries
+# ---------------------------------------------------------------------------
+
+def query_scalars(con, *, site_name: str | None = None,
+ magnet_name: str | None = None) -> pd.DataFrame:
+ """Total scalar stats across all processed files for a site or magnet."""
+ if site_name:
+ where = "od.site_name = ?"
+ params = [site_name]
+ elif magnet_name:
+ where = "sm.magnet_name = ?"
+ params = [magnet_name]
+ else:
+ raise ValueError("Provide site_name or magnet_name")
+
+ join = (
+ "JOIN site_magnets sm ON sm.site_name = od.site_name" if magnet_name else ""
+ )
+
+ return con.execute(f"""
+ SELECT
+ s.channel,
+ COUNT(DISTINCT s.operationaldata_id) AS n_files,
+ SUM(s.value) AS total
+ FROM op_run_scalars s
+ JOIN operationaldata od ON od.id = s.operationaldata_id
+ {join}
+ WHERE {where}
+ GROUP BY s.channel
+ ORDER BY s.channel
+ """, params).df()
+
+
+# ---------------------------------------------------------------------------
+# Site-level bin queries
+# ---------------------------------------------------------------------------
+
+def query_site_bins(
+ con,
+ site_name: str,
+ channels: list[str] | None = None,
+) -> pd.DataFrame:
+ """Cumulative field-bin stats for a site.
+
+ Returns one row per (field_bin_low, field_bin_high, channel) with:
+ hours, mean_x, std_x, min_x, max_x
+ """
+ ch_filter = ""
+ params: list = [site_name]
+ if channels:
+ placeholders = ",".join("?" * len(channels))
+ ch_filter = f"AND s.channel IN ({placeholders})"
+ params += channels
+
+ return con.execute(f"""
+ SELECT
+ s.field_bin_low,
+ s.field_bin_high,
+ s.channel,
+ SUM(s.sum_dt) / 3600 AS hours,
+ SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0) AS mean_x,
+ sqrt(
+ GREATEST(
+ SUM(s.sum_x2_dt) / NULLIF(SUM(s.sum_dt), 0)
+ - power(SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0), 2),
+ 0.0
+ )
+ ) AS std_x,
+ MIN(s.min_x) AS min_x,
+ MAX(s.max_x) AS max_x
+ FROM op_site_bin_stats s
+ JOIN operationaldata od ON od.id = s.operationaldata_id
+ WHERE od.site_name = ?
+ {ch_filter}
+ GROUP BY s.field_bin_low, s.field_bin_high, s.channel
+ ORDER BY s.channel, s.field_bin_low
+ """, params).df()
+
+
+# ---------------------------------------------------------------------------
+# Magnet-level bin queries
+# ---------------------------------------------------------------------------
+
+def query_magnet_bins(
+ con,
+ magnet_name: str,
+ channels: list[str] | None = None,
+) -> pd.DataFrame:
+ """Cumulative field-bin stats for all parts of a magnet."""
+ ch_filter = ""
+ params: list = [magnet_name]
+ if channels:
+ placeholders = ",".join("?" * len(channels))
+ ch_filter = f"AND s.channel IN ({placeholders})"
+ params += channels
+
+ return con.execute(f"""
+ SELECT
+ s.part_name,
+ s.field_bin_low,
+ s.field_bin_high,
+ s.channel,
+ SUM(s.sum_dt) / 3600 AS hours,
+ SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0) AS mean_x,
+ sqrt(
+ GREATEST(
+ SUM(s.sum_x2_dt) / NULLIF(SUM(s.sum_dt), 0)
+ - power(SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0), 2),
+ 0.0
+ )
+ ) AS std_x,
+ MIN(s.min_x) AS min_x,
+ MAX(s.max_x) AS max_x
+ FROM op_part_bin_stats s
+ JOIN operationaldata od ON od.id = s.operationaldata_id
+ JOIN site_magnets sm ON sm.site_name = od.site_name
+ JOIN magnet_parts mp ON mp.magnet_name = sm.magnet_name
+ AND mp.part_name = s.part_name
+ WHERE sm.magnet_name = ?
+ {ch_filter}
+ GROUP BY s.part_name, s.field_bin_low, s.field_bin_high, s.channel
+ ORDER BY s.part_name, s.channel, s.field_bin_low
+ """, params).df()
+
+
+# ---------------------------------------------------------------------------
+# Part-level bin queries
+# ---------------------------------------------------------------------------
+
+def query_part_bins(
+ con,
+ part_name: str,
+ channels: list[str] | None = None,
+) -> pd.DataFrame:
+ """Cumulative field-bin stats for a single part across all sites and runs."""
+ ch_filter = ""
+ params: list = [part_name]
+ if channels:
+ placeholders = ",".join("?" * len(channels))
+ ch_filter = f"AND s.channel IN ({placeholders})"
+ params += channels
+
+ return con.execute(f"""
+ SELECT
+ s.field_bin_low,
+ s.field_bin_high,
+ s.channel,
+ SUM(s.sum_dt) / 3600 AS hours,
+ SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0) AS mean_x,
+ sqrt(
+ GREATEST(
+ SUM(s.sum_x2_dt) / NULLIF(SUM(s.sum_dt), 0)
+ - power(SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0), 2),
+ 0.0
+ )
+ ) AS std_x,
+ MIN(s.min_x) AS min_x,
+ MAX(s.max_x) AS max_x
+ FROM op_part_bin_stats s
+ WHERE s.part_name = ?
+ {ch_filter}
+ GROUP BY s.field_bin_low, s.field_bin_high, s.channel
+ ORDER BY s.channel, s.field_bin_low
+ """, params).df()
+
+
+# ---------------------------------------------------------------------------
+# Experiment scalar queries
+# ---------------------------------------------------------------------------
+
+def query_exp_scalars(con, *, site_name: str | None = None,
+ magnet_name: str | None = None,
+ experiment_name: str | None = None) -> pd.DataFrame:
+ """Total scalar stats across all processed experiments for a site or magnet."""
+ if site_name:
+ where = "e.site_name = ?"
+ params: list = [site_name]
+ elif magnet_name:
+ where = "sm.magnet_name = ?"
+ params = [magnet_name]
+ else:
+ raise ValueError("Provide site_name or magnet_name")
+
+ join = (
+ "JOIN site_magnets sm ON sm.site_name = e.site_name" if magnet_name else ""
+ )
+ exp_filter = ""
+ if experiment_name:
+ exp_filter = "AND e.name = ?"
+ params.append(experiment_name)
+
+ return con.execute(f"""
+ SELECT
+ s.channel,
+ COUNT(DISTINCT s.experiment_id) AS n_experiments,
+ SUM(s.value) AS total
+ FROM exp_run_scalars s
+ JOIN experiments e ON e.id = s.experiment_id
+ {join}
+ WHERE {where}
+ {exp_filter}
+ GROUP BY s.channel
+ ORDER BY s.channel
+ """, params).df()
+
+
+# ---------------------------------------------------------------------------
+# Experiment site-level bin queries
+# ---------------------------------------------------------------------------
+
+def query_exp_site_bins(
+ con,
+ site_name: str,
+ channels: list[str] | None = None,
+ experiment_name: str | None = None,
+) -> pd.DataFrame:
+ """Cumulative field-bin stats for a site across all its experiments."""
+ params: list = [site_name]
+ ch_filter = ""
+ if channels:
+ placeholders = ",".join("?" * len(channels))
+ ch_filter = f"AND s.channel IN ({placeholders})"
+ params += channels
+ exp_filter = ""
+ if experiment_name:
+ exp_filter = "AND e.name = ?"
+ params.append(experiment_name)
+
+ return con.execute(f"""
+ SELECT
+ s.field_bin_low,
+ s.field_bin_high,
+ s.channel,
+ SUM(s.sum_dt) / 3600 AS hours,
+ SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0) AS mean_x,
+ sqrt(
+ GREATEST(
+ SUM(s.sum_x2_dt) / NULLIF(SUM(s.sum_dt), 0)
+ - power(SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0), 2),
+ 0.0
+ )
+ ) AS std_x,
+ MIN(s.min_x) AS min_x,
+ MAX(s.max_x) AS max_x
+ FROM exp_site_bin_stats s
+ JOIN experiments e ON e.id = s.experiment_id
+ WHERE e.site_name = ?
+ {ch_filter}
+ {exp_filter}
+ GROUP BY s.field_bin_low, s.field_bin_high, s.channel
+ ORDER BY s.channel, s.field_bin_low
+ """, params).df()
+
+
+# ---------------------------------------------------------------------------
+# Experiment magnet-level bin queries
+# ---------------------------------------------------------------------------
+
+def query_exp_magnet_bins(
+ con,
+ magnet_name: str,
+ channels: list[str] | None = None,
+ experiment_name: str | None = None,
+) -> pd.DataFrame:
+ """Cumulative field-bin stats for all parts of a magnet across its experiments."""
+ params: list = [magnet_name]
+ ch_filter = ""
+ if channels:
+ placeholders = ",".join("?" * len(channels))
+ ch_filter = f"AND s.channel IN ({placeholders})"
+ params += channels
+ exp_filter = ""
+ if experiment_name:
+ exp_filter = "AND e.name = ?"
+ params.append(experiment_name)
+
+ return con.execute(f"""
+ SELECT
+ s.part_name,
+ s.field_bin_low,
+ s.field_bin_high,
+ s.channel,
+ SUM(s.sum_dt) / 3600 AS hours,
+ SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0) AS mean_x,
+ sqrt(
+ GREATEST(
+ SUM(s.sum_x2_dt) / NULLIF(SUM(s.sum_dt), 0)
+ - power(SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0), 2),
+ 0.0
+ )
+ ) AS std_x,
+ MIN(s.min_x) AS min_x,
+ MAX(s.max_x) AS max_x
+ FROM exp_part_bin_stats s
+ JOIN experiments e ON e.id = s.experiment_id
+ JOIN site_magnets sm ON sm.site_name = e.site_name
+ JOIN magnet_parts mp ON mp.magnet_name = sm.magnet_name
+ AND mp.part_name = s.part_name
+ WHERE sm.magnet_name = ?
+ {ch_filter}
+ {exp_filter}
+ GROUP BY s.part_name, s.field_bin_low, s.field_bin_high, s.channel
+ ORDER BY s.part_name, s.channel, s.field_bin_low
+ """, params).df()
+
+
+# ---------------------------------------------------------------------------
+# Experiment part-level bin queries
+# ---------------------------------------------------------------------------
+
+def query_exp_part_bins(
+ con,
+ part_name: str,
+ channels: list[str] | None = None,
+ experiment_name: str | None = None,
+) -> pd.DataFrame:
+ """Cumulative field-bin stats for a single part across all experiments."""
+ params: list = [part_name]
+ ch_filter = ""
+ if channels:
+ placeholders = ",".join("?" * len(channels))
+ ch_filter = f"AND s.channel IN ({placeholders})"
+ params += channels
+ exp_filter = ""
+ if experiment_name:
+ exp_filter = "AND e.name = ?"
+ params.append(experiment_name)
+
+ join = "JOIN experiments e ON e.id = s.experiment_id" if experiment_name else ""
+
+ return con.execute(f"""
+ SELECT
+ s.field_bin_low,
+ s.field_bin_high,
+ s.channel,
+ SUM(s.sum_dt) / 3600 AS hours,
+ SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0) AS mean_x,
+ sqrt(
+ GREATEST(
+ SUM(s.sum_x2_dt) / NULLIF(SUM(s.sum_dt), 0)
+ - power(SUM(s.sum_x_dt) / NULLIF(SUM(s.sum_dt), 0), 2),
+ 0.0
+ )
+ ) AS std_x,
+ MIN(s.min_x) AS min_x,
+ MAX(s.max_x) AS max_x
+ FROM exp_part_bin_stats s
+ {join}
+ WHERE s.part_name = ?
+ {ch_filter}
+ {exp_filter}
+ GROUP BY s.field_bin_low, s.field_bin_high, s.channel
+ ORDER BY s.channel, s.field_bin_low
+ """, params).df()
+
+
+# ---------------------------------------------------------------------------
+# Printing helpers
+# ---------------------------------------------------------------------------
+
+_SCALAR_LABELS = {
+ "duration_s": ("Total duration", "h", 1/3600),
+ "duration_field_on_s": ("Field-on duration", "h", 1/3600),
+ "energy_j": ("Electrical energy", "MWh", 1/3.6e9),
+ "heat_extracted_j": ("Heat extracted", "MWh", 1/3.6e9),
+}
+
+
+def print_scalars(df: pd.DataFrame, scope: str) -> None:
+ print(f"\n{'─'*55}")
+ print(f" Scalar statistics — {scope}")
+ print(f"{'─'*55}")
+ for _, row in df.iterrows():
+ ch = row["channel"]
+ label, unit, scale = _SCALAR_LABELS.get(ch, (ch, "", 1.0))
+ val = row["total"] * scale
+ print(f" {label:<30} {val:>12.3f} {unit} ({int(row['n_files'])} files)")
+
+
+def print_bins(df: pd.DataFrame, scope: str) -> None:
+ for ch, grp in df.groupby("channel"):
+ print(f"\n{'─'*70}")
+ print(f" {ch} — {scope}")
+ print(f" {'Bin (T)':<15} {'Hours':>9} {'Mean':>12} {'Std':>10} {'Min':>10} {'Max':>10}")
+ print(f"{'─'*70}")
+ for _, r in grp.iterrows():
+ label = f"{r['field_bin_low']:.1f}–{r['field_bin_high']:.1f}"
+ mean = r["mean_x"] if pd.notna(r["mean_x"]) else float("nan")
+ std = r["std_x"] if pd.notna(r["std_x"]) else float("nan")
+ print(
+ f" {label:<15} {r['hours']:>9.3f} {mean:>12.3f} "
+ f"{std:>10.3f} {r['min_x']:>10.3f} {r['max_x']:>10.3f}"
+ )
+
+
+# ---------------------------------------------------------------------------
+# Plotting
+# ---------------------------------------------------------------------------
+
+def _bar_bins(ax, grp: pd.DataFrame, label: str, color: str) -> None:
+ widths = grp["field_bin_high"] - grp["field_bin_low"]
+ ax.bar(
+ grp["field_bin_low"], grp["hours"],
+ width=widths * 0.85, align="edge",
+ label=label, color=color, edgecolor="white", alpha=0.85,
+ )
+
+
+def plot_site_bins(df: pd.DataFrame, site_name: str) -> None:
+ if not _HAS_MPL:
+ print("matplotlib not available — skipping plots")
+ return
+ channels = df["channel"].unique()
+ fig, axes = plt.subplots(1, len(channels), figsize=(7 * len(channels), 5), squeeze=False)
+ colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
+ for ax, ch in zip(axes[0], channels):
+ grp = df[df["channel"] == ch]
+ _bar_bins(ax, grp, ch, colors[0])
+ ax.set_xlabel("Magnetic field (T)")
+ ax.set_ylabel("Hours")
+ ax.set_title(f"{site_name} — {ch}")
+ ax.grid(axis="y", alpha=0.4)
+ plt.tight_layout()
+ fname = f"cumstats_site_{site_name}.png"
+ plt.savefig(fname, dpi=150)
+ print(f"Saved {fname}")
+ plt.show()
+
+
+def plot_part_bins(df: pd.DataFrame, scope: str, label_col: str = "channel") -> None:
+ if not _HAS_MPL:
+ print("matplotlib not available — skipping plots")
+ return
+ channels = df["channel"].unique()
+ parts = df["part_name"].unique() if "part_name" in df.columns else [None]
+ colors = plt.rcParams["axes.prop_cycle"].by_key()["color"]
+
+ for ch in channels:
+ sub = df[df["channel"] == ch]
+ fig, ax = plt.subplots(figsize=(10, 5))
+ for idx, part in enumerate(parts if parts[0] is not None else [None]):
+ grp = sub[sub["part_name"] == part] if part else sub
+ if grp.empty:
+ continue
+ widths = grp["field_bin_high"] - grp["field_bin_low"]
+ offset = idx * widths.mean() * 0.4 if len(parts) > 1 else 0
+ ax.bar(
+ grp["field_bin_low"] + offset, grp["hours"],
+ width=widths * 0.85 / max(len(parts), 1),
+ align="edge", label=str(part), color=colors[idx % len(colors)],
+ edgecolor="white", alpha=0.85,
+ )
+ ax.set_xlabel("Magnetic field (T)")
+ ax.set_ylabel("Hours")
+ ax.set_title(f"{scope} — {ch}")
+ if parts[0] is not None and len(parts) > 1:
+ ax.legend(title="Part")
+ ax.grid(axis="y", alpha=0.4)
+ plt.tight_layout()
+ fname = f"cumstats_{scope.replace(' ', '_')}_{ch}.png"
+ plt.savefig(fname, dpi=150)
+ print(f"Saved {fname}")
+ plt.show()
+
+
+# ---------------------------------------------------------------------------
+# CLI
+# ---------------------------------------------------------------------------
+
+SUBCOMMANDS = {
+ "scalars": "Per-run scalar totals (energy, duration, heat) — operational data",
+ "site-bins": "Site-level field-bin distributions — operational data",
+ "magnet-bins": "Per-part field-bin distributions for a magnet — operational data",
+ "part-bins": "Field-bin distributions for a single part — operational data",
+ "exp-scalars": "Per-experiment scalar totals — experiment data",
+ "exp-site-bins": "Site-level field-bin distributions — experiment data",
+ "exp-magnet-bins": "Per-part field-bin distributions for a magnet — experiment data",
+ "exp-part-bins": "Field-bin distributions for a single part — experiment data",
+}
+
+
+def main() -> None:
+ parser = argparse.ArgumentParser(
+ description="Query cumulative operational statistics from DuckDB.",
+ formatter_class=argparse.RawDescriptionHelpFormatter,
+ epilog="\n".join(f" {k:<14} {v}" for k, v in SUBCOMMANDS.items()),
+ )
+ parser.add_argument("command", choices=list(SUBCOMMANDS))
+ parser.add_argument("--db", default=DEFAULT_DB)
+ parser.add_argument("--site", default=None, help="Site name")
+ parser.add_argument("--magnet", default=None, help="Magnet name")
+ parser.add_argument("--part", default=None, help="Part name")
+ parser.add_argument("--channels", default=None,
+ help="Comma-separated channel filter, e.g. 'Ptot,tsb'")
+ parser.add_argument("--experiment", default=None,
+ help="Filter by experiment name (exp-* commands only)")
+ parser.add_argument("--plot", action="store_true", help="Show and save plots")
+ args = parser.parse_args()
+
+ channels = [c.strip() for c in args.channels.split(",")] if args.channels else None
+
+ con = duckdb.connect(args.db, read_only=True)
+
+ if args.command == "scalars":
+ if not args.site and not args.magnet:
+ parser.error("scalars requires --site or --magnet")
+ df = query_scalars(con, site_name=args.site, magnet_name=args.magnet)
+ scope = args.site or args.magnet
+ print_scalars(df, scope)
+
+ elif args.command == "site-bins":
+ if not args.site:
+ parser.error("site-bins requires --site")
+ df = query_site_bins(con, args.site, channels)
+ print_bins(df, f"site {args.site}")
+ if args.plot:
+ plot_site_bins(df, args.site)
+
+ elif args.command == "magnet-bins":
+ if not args.magnet:
+ parser.error("magnet-bins requires --magnet")
+ df = query_magnet_bins(con, args.magnet, channels)
+ print_bins(df, f"magnet {args.magnet}")
+ if args.plot:
+ plot_part_bins(df, f"magnet {args.magnet}")
+
+ elif args.command == "part-bins":
+ if not args.part:
+ parser.error("part-bins requires --part")
+ df = query_part_bins(con, args.part, channels)
+ # no part_name column here — add it for the shared plot helper
+ df.insert(0, "part_name", args.part)
+ print_bins(df, f"part {args.part}")
+ if args.plot:
+ plot_part_bins(df, f"part {args.part}")
+
+ elif args.command == "exp-scalars":
+ if not args.site and not args.magnet:
+ parser.error("exp-scalars requires --site or --magnet")
+ df = query_exp_scalars(
+ con, site_name=args.site, magnet_name=args.magnet,
+ experiment_name=args.experiment,
+ )
+ scope = args.site or args.magnet
+ print_scalars(df, f"{scope} [experiments]")
+
+ elif args.command == "exp-site-bins":
+ if not args.site:
+ parser.error("exp-site-bins requires --site")
+ df = query_exp_site_bins(con, args.site, channels, args.experiment)
+ print_bins(df, f"site {args.site} [experiments]")
+ if args.plot:
+ plot_site_bins(df, args.site)
+
+ elif args.command == "exp-magnet-bins":
+ if not args.magnet:
+ parser.error("exp-magnet-bins requires --magnet")
+ df = query_exp_magnet_bins(con, args.magnet, channels, args.experiment)
+ print_bins(df, f"magnet {args.magnet} [experiments]")
+ if args.plot:
+ plot_part_bins(df, f"magnet {args.magnet} [experiments]")
+
+ elif args.command == "exp-part-bins":
+ if not args.part:
+ parser.error("exp-part-bins requires --part")
+ df = query_exp_part_bins(con, args.part, channels, args.experiment)
+ df.insert(0, "part_name", args.part)
+ print_bins(df, f"part {args.part} [experiments]")
+ if args.plot:
+ plot_part_bins(df, f"part {args.part} [experiments]")
+
+ con.close()
+
+
+if __name__ == "__main__":
+ main()
diff --git a/to_duckdb/student_statheures_demo.py b/to_duckdb/tutorials/statheures_demo.py
similarity index 96%
rename from to_duckdb/student_statheures_demo.py
rename to to_duckdb/tutorials/statheures_demo.py
index fe2f97c..2394f22 100644
--- a/to_duckdb/student_statheures_demo.py
+++ b/to_duckdb/tutorials/statheures_demo.py
@@ -1,20 +1,20 @@
"""
-student_statheures_demo.py
-==========================
+statheures_demo.py
+==================
Demonstrates the statheures field-time statistics workflow using the
-student DuckDB database and TSV record files, without python_magnetrun.
+MagnetDB DuckDB database and TSV record files, without python_magnetrun.
This script adapts the plan from statheures_stats_implementation.md:
- PandasMagnetData.getData() → pd.read_csv(filepath, sep='\\t')
- run.getMagnetRef() → experiments.site_name from DuckDB
- run.getRunRef() → experiments.name from DuckDB
-Usage
------
- python student_statheures_demo.py
- python student_statheures_demo.py --site M10_M19071101_13 --step 1.0
- python student_statheures_demo.py --site M10_M19071101_13 --year 2025
- python student_statheures_demo.py --site M10_M19071101_13 \\
+Usage (run from to_duckdb/)
+--------------------------
+ python tutorials/statheures_demo.py
+ python tutorials/statheures_demo.py --site M10_M19071101_13 --step 1.0
+ python tutorials/statheures_demo.py --site M10_M19071101_13 --year 2025
+ python tutorials/statheures_demo.py --site M10_M19071101_13 \\
--compare 2025 2026
Requirements
@@ -33,8 +33,9 @@
# ---------------------------------------------------------------------------
# Configuration — adjust to match your local paths
# ---------------------------------------------------------------------------
-DEFAULT_DB = "student_magnetdb.duckdb"
-DEFAULT_RECORDS = "records" # directory containing TSV files
+_HERE = Path(__file__).resolve().parent.parent
+DEFAULT_DB = str(_HERE / "magnetdb.duckdb")
+DEFAULT_RECORDS = str(_HERE / "records") # directory containing TSV files
DEFAULT_SITE = "M10_M19071101_13"
FIELD_COL = "Field" # column name for central field in T
TIME_COL = "t" # elapsed time column in seconds
diff --git a/to_duckdb/tutorials/stress_map.py b/to_duckdb/tutorials/stress_map.py
new file mode 100644
index 0000000..c97d3fb
--- /dev/null
+++ b/to_duckdb/tutorials/stress_map.py
@@ -0,0 +1,29 @@
+"""
+stress_map.py (tutorial shim)
+=======================================
+This script is kept for backward compatibility and tutorial use.
+The full implementation now lives in ../stress_map.py and is accessible
+through the unified CLI (run from the to_duckdb/ directory):
+
+ python magnetdb.py hoop-stress barchart [options]
+ python magnetdb.py hoop-stress history [options]
+ python magnetdb.py hoop-stress stats [options]
+ python magnetdb.py hoop-stress fatigue [options]
+
+Run ``python magnetdb.py hoop-stress --help`` for full usage.
+
+For a step-by-step explanation of how the chain works (DuckDB →
+geometry YAML → magnettools → stress computation), see:
+
+ README_student_stress_map.md
+ student_statheures_note.md
+"""
+import sys
+from pathlib import Path
+
+sys.path.insert(0, str(Path(__file__).resolve().parent.parent))
+
+from stress_map import main # noqa: E402
+
+if __name__ == "__main__":
+ main()
diff --git a/web/Dockerfile b/web/Dockerfile
index 15c1764..7bca324 100644
--- a/web/Dockerfile
+++ b/web/Dockerfile
@@ -1,4 +1,4 @@
-FROM node:18-bookworm AS builder
+FROM node:22-trixie AS builder
WORKDIR /app
@@ -13,8 +13,6 @@ ARG API_ENDPOINT
ENV NODE_ENV=$NODE_ENV
ENV VUE_APP_API_ENDPOINT=$API_ENDPOINT
-ENV NODE_OPTIONS=--openssl-legacy-provider
-
COPY . .
RUN npm run build
diff --git a/web/Dockerfile-dev b/web/Dockerfile-dev
index 6ef13f5..eacf89e 100644
--- a/web/Dockerfile-dev
+++ b/web/Dockerfile-dev
@@ -1,4 +1,4 @@
-FROM node:18-bookworm AS builder
+FROM node:22-trixie AS builder
ARG USERNAME=feelpp
ARG USER_UID=1001
@@ -36,8 +36,6 @@ ARG API_ENDPOINT
ENV NODE_ENV=$NODE_ENV
ENV VUE_APP_API_ENDPOINT=$API_ENDPOINT
-ENV NODE_OPTIONS=--openssl-legacy-provider
-
COPY . .
#RUN yarn build
diff --git a/web/config/nginx.conf b/web/config/nginx.conf
index 18076b0..c42aea0 100644
--- a/web/config/nginx.conf
+++ b/web/config/nginx.conf
@@ -1,5 +1,5 @@
user nginx;
-worker_processes 1;
+worker_processes auto;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
@@ -18,7 +18,17 @@ http {
access_log /var/log/nginx/access.log main;
sendfile on;
- keepalive_timeout 300;
+ tcp_nopush on;
+ tcp_nodelay on;
+ keepalive_timeout 65;
+ types_hash_max_size 2048;
+
+ # Enable gzip compression
+ gzip on;
+ gzip_vary on;
+ gzip_proxied any;
+ gzip_comp_level 6;
+ gzip_types text/plain text/css text/xml text/javascript application/json application/javascript application/xml+rss application/rss+xml font/truetype font/opentype application/vnd.ms-fontobject image/svg+xml;
gzip_disable "msie6";
server {
@@ -29,14 +39,27 @@ http {
index index.html index.htm;
server_name _;
+ # Security headers
+ add_header X-Frame-Options "SAMEORIGIN" always;
+ add_header X-Content-Type-Options "nosniff" always;
+ add_header X-XSS-Protection "1; mode=block" always;
+ add_header Referrer-Policy "no-referrer-when-downgrade" always;
+
location / {
try_files $uri $uri/ /index.html;
+ # Cache control for HTML - no cache
add_header Last-Modified $date_gmt;
- add_header Cache-Control 'no-store, no-cache';
+ add_header Cache-Control 'no-store, no-cache, must-revalidate, proxy-revalidate, max-age=0';
if_modified_since off;
expires off;
etag off;
}
+
+ # Cache static assets
+ location ~* \.(js|css|png|jpg|jpeg|gif|ico|svg|woff|woff2|ttf|eot)$ {
+ expires 1y;
+ add_header Cache-Control "public, immutable";
+ }
}
}
diff --git a/web/eslint.config.js b/web/eslint.config.js
new file mode 100644
index 0000000..6be0fda
--- /dev/null
+++ b/web/eslint.config.js
@@ -0,0 +1,27 @@
+const globals = require('globals')
+const js = require('@eslint/js')
+const pluginVue = require('eslint-plugin-vue')
+const babelParser = require('@babel/eslint-parser')
+
+module.exports = [
+ { ignores: ['dist/**', 'node_modules/**'] },
+ js.configs.recommended,
+ ...pluginVue.configs['flat/vue2-essential'],
+ {
+ languageOptions: {
+ globals: {
+ ...globals.browser,
+ ...globals.node,
+ },
+ parserOptions: {
+ parser: babelParser,
+ requireConfigFile: false,
+ },
+ },
+ rules: {
+ 'vue/multi-word-component-names': 'off',
+ 'vue/no-reserved-component-names': 'off',
+ 'vue/valid-v-slot': 'off',
+ },
+ },
+]
diff --git a/web/package-lock.json b/web/package-lock.json
index c0b18ff..4e65653 100644
--- a/web/package-lock.json
+++ b/web/package-lock.json
@@ -9,10 +9,9 @@
"version": "0.1.0",
"dependencies": {
"@guolao/vue-monaco-editor": "^1.5.4",
- "@tailwindcss/forms": "^0.3.4",
+ "@tailwindcss/forms": "^0.5.x",
"@vue-hero-icons/outline": "^1.7.2",
"@vue-hero-icons/solid": "^1.7.2",
- "@vue/composition-api": "^1.7.2",
"axios": "^1.8.3",
"chart.js": "^3.7.1",
"chartjs-plugin-zoom": "^1.2.0",
@@ -30,61 +29,91 @@
"yup": "^0.32.11"
},
"devDependencies": {
- "@tailwindcss/postcss7-compat": "^2.2.17",
- "@vue/cli-plugin-babel": "~4.5.0",
- "@vue/cli-plugin-eslint": "~4.5.0",
- "@vue/cli-service": "~4.5.0",
- "autoprefixer": "^9",
- "babel-eslint": "^10.1.0",
- "eslint": "^6.7.2",
- "eslint-plugin-vue": "^6.2.2",
- "postcss": "^7.0.39",
- "tailwindcss": "npm:@tailwindcss/postcss7-compat"
+ "@babel/eslint-parser": "^7.x",
+ "@vue/cli-plugin-babel": "~5.0.0",
+ "@vue/cli-plugin-eslint": "~5.0.0",
+ "@vue/cli-service": "~5.0.0",
+ "autoprefixer": "^10",
+ "eslint": "^9.0.0",
+ "eslint-plugin-vue": "^10.0.0",
+ "globals": "^16.0.0",
+ "tailwindcss": "^3.x"
+ }
+ },
+ "node_modules/@achrinza/node-ipc": {
+ "version": "9.2.10",
+ "resolved": "https://registry.npmjs.org/@achrinza/node-ipc/-/node-ipc-9.2.10.tgz",
+ "integrity": "sha512-rCkw57K82y1XA9KwBmuMrupFQr9VOS4Rn77vW2UD2j0+HjlP/npSON9COkUIfocd95B4wv5EpfWMr6lGD4lN3A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@node-ipc/js-queue": "2.0.3",
+ "event-pubsub": "4.3.0",
+ "js-message": "1.0.7"
+ },
+ "engines": {
+ "node": "8 || 9 || 10 || 11 || 12 || 13 || 14 || 15 || 16 || 17 || 18 || 19 || 20 || 21 || 22 || 23 || 24 || 25"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/@babel/code-frame": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.24.7.tgz",
- "integrity": "sha512-BcYH1CVJBO9tvyIZ2jVeXgSIMvGZ2FDRvDdOIVQyuklNKSsx+eppDEBq/g47Ayw+RqNFE+URvOShmf+f/qwAlA==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.29.0.tgz",
+ "integrity": "sha512-9NhCeYjq9+3uxgdtp20LSiJXJvN0FeCtNGpJxuMFZ1Kv3cWUNb6DOhJwUvcVCzKGR66cw4njwM6hrJLqgOwbcw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/highlight": "^7.24.7",
- "picocolors": "^1.0.0"
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "js-tokens": "^4.0.0",
+ "picocolors": "^1.1.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/compat-data": {
- "version": "7.16.4",
- "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.16.4.tgz",
- "integrity": "sha512-1o/jo7D+kC9ZjHX5v+EHrdjl3PhxMrLSOTGsOdHJ+KL8HCaEK6ehrVL2RS6oHDZp+L7xLirLrPmQtEng769J/Q==",
+ "version": "7.29.3",
+ "resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.29.3.tgz",
+ "integrity": "sha512-LIVqM46zQWZhj17qA8wb4nW/ixr2y1Nw+r1etiAWgRM6U1IqP+LNhL1yg440jYZR72jCWcWbLWzIosH+uP1fqg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/core": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.16.0.tgz",
- "integrity": "sha512-mYZEvshBRHGsIAiyH5PzCFTCfbWfoYbO/jcSdXQSUQu1/pW0xDZAUP7KEc32heqWTAfAHhV9j1vH8Sav7l+JNQ==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.16.0",
- "@babel/generator": "^7.16.0",
- "@babel/helper-compilation-targets": "^7.16.0",
- "@babel/helper-module-transforms": "^7.16.0",
- "@babel/helpers": "^7.16.0",
- "@babel/parser": "^7.16.0",
- "@babel/template": "^7.16.0",
- "@babel/traverse": "^7.16.0",
- "@babel/types": "^7.16.0",
- "convert-source-map": "^1.7.0",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/core/-/core-7.29.0.tgz",
+ "integrity": "sha512-CGOfOJqWjg2qW/Mb6zNsDm+u5vFQ8DxXfbM09z69p5Z6+mE1ikP2jUXw+j42Pf1XTYED2Rni5f95npYeuwMDQA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helpers": "^7.28.6",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@jridgewell/remapping": "^2.3.5",
+ "convert-source-map": "^2.0.0",
"debug": "^4.1.0",
"gensync": "^1.0.0-beta.2",
- "json5": "^2.1.2",
- "semver": "^6.3.0",
- "source-map": "^0.5.0"
+ "json5": "^2.2.3",
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
@@ -94,76 +123,86 @@
"url": "https://opencollective.com/babel"
}
},
- "node_modules/@babel/generator": {
- "version": "7.24.10",
- "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.24.10.tgz",
- "integrity": "sha512-o9HBZL1G2129luEUlG1hB4N/nlYNWHnpwlND9eOMclRqqu1YDy2sSYVCFUZwl8I1Gxh+QSRrP2vD7EpUmFVXxg==",
+ "node_modules/@babel/eslint-parser": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/eslint-parser/-/eslint-parser-7.28.6.tgz",
+ "integrity": "sha512-QGmsKi2PBO/MHSQk+AAgA9R6OHQr+VqnniFE0eMWZcVcfBZoA2dKn2hUsl3Csg/Plt9opRUWdY7//VXsrIlEiA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.24.9",
- "@jridgewell/gen-mapping": "^0.3.5",
- "@jridgewell/trace-mapping": "^0.3.25",
- "jsesc": "^2.5.1"
+ "@nicolo-ribaudo/eslint-scope-5-internals": "5.1.1-v1",
+ "eslint-visitor-keys": "^2.1.0",
+ "semver": "^6.3.1"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^10.13.0 || ^12.13.0 || >=14.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.11.0",
+ "eslint": "^7.5.0 || ^8.0.0 || ^9.0.0"
}
},
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.16.0.tgz",
- "integrity": "sha512-ItmYF9vR4zA8cByDocY05o0LGUkp1zhbTQOH1NFyl5xXEqlTJQCEJjieriw+aFpxo16swMxUnUiKS7a/r4vtHg==",
+ "node_modules/@babel/generator": {
+ "version": "7.29.1",
+ "resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.29.1.tgz",
+ "integrity": "sha512-qsaF+9Qcm2Qv8SRIMMscAvG4O3lJ0F1GuMo5HR/Bp02LopNgnZBC/EkbevHFeGs4ls/oPz9v+Bsmzbkbe+0dUw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.16.0"
+ "@babel/parser": "^7.29.0",
+ "@babel/types": "^7.29.0",
+ "@jridgewell/gen-mapping": "^0.3.12",
+ "@jridgewell/trace-mapping": "^0.3.28",
+ "jsesc": "^3.0.2"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-builder-binary-assignment-operator-visitor": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-builder-binary-assignment-operator-visitor/-/helper-builder-binary-assignment-operator-visitor-7.16.0.tgz",
- "integrity": "sha512-9KuleLT0e77wFUku6TUkqZzCEymBdtuQQ27MhEKzf9UOOJu3cYj98kyaDAzxpC7lV6DGiZFuC8XqDsq8/Kl6aQ==",
+ "node_modules/@babel/helper-annotate-as-pure": {
+ "version": "7.27.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.27.3.tgz",
+ "integrity": "sha512-fXSwMQqitTGeHLBC08Eq5yXz2m37E4pJX1qAU1+2cNedz/ifv/bVXft90VeSav5nFO61EcNgwr0aJxbyPaWBPg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-explode-assignable-expression": "^7.16.0",
- "@babel/types": "^7.16.0"
+ "@babel/types": "^7.27.3"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-compilation-targets": {
- "version": "7.16.3",
- "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.16.3.tgz",
- "integrity": "sha512-vKsoSQAyBmxS35JUOOt+07cLc6Nk/2ljLIHwmq2/NM6hdioUaqEXq/S+nXvbvXbZkNDlWOymPanJGOc4CBjSJA==",
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.28.6.tgz",
+ "integrity": "sha512-JYtls3hqi15fcx5GaSNL7SCTJ2MNmjrkHXg4FSpOA/grxK8KwyZ5bubHsCq8FXCkua6xhuaaBit+3b7+VZRfcA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.16.0",
- "@babel/helper-validator-option": "^7.14.5",
- "browserslist": "^4.17.5",
- "semver": "^6.3.0"
+ "@babel/compat-data": "^7.28.6",
+ "@babel/helper-validator-option": "^7.27.1",
+ "browserslist": "^4.24.0",
+ "lru-cache": "^5.1.1",
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-create-class-features-plugin": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.16.0.tgz",
- "integrity": "sha512-XLwWvqEaq19zFlF5PTgOod4bUA+XbkR4WLQBct1bkzmxJGB0ZEJaoKF4c8cgH9oBtCDuYJ8BP5NB9uFiEgO5QA==",
+ "version": "7.29.3",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-class-features-plugin/-/helper-create-class-features-plugin-7.29.3.tgz",
+ "integrity": "sha512-RpLYy2sb51oNLjuu1iD3bwBqCBWUzjO0ocp+iaCP/lJtb2CPLcnC2Fftw+4sAzaMELGeWTgExSKADbdo0GFVzA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.16.0",
- "@babel/helper-function-name": "^7.16.0",
- "@babel/helper-member-expression-to-functions": "^7.16.0",
- "@babel/helper-optimise-call-expression": "^7.16.0",
- "@babel/helper-replace-supers": "^7.16.0",
- "@babel/helper-split-export-declaration": "^7.16.0"
+ "@babel/helper-annotate-as-pure": "^7.27.3",
+ "@babel/helper-member-expression-to-functions": "^7.28.5",
+ "@babel/helper-optimise-call-expression": "^7.27.1",
+ "@babel/helper-replace-supers": "^7.28.6",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+ "@babel/traverse": "^7.29.0",
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
@@ -173,13 +212,15 @@
}
},
"node_modules/@babel/helper-create-regexp-features-plugin": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.16.0.tgz",
- "integrity": "sha512-3DyG0zAFAZKcOp7aVr33ddwkxJ0Z0Jr5V99y3I690eYLpukJsJvAbzTy1ewoCqsML8SbIrjH14Jc/nSQ4TvNPA==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-create-regexp-features-plugin/-/helper-create-regexp-features-plugin-7.28.5.tgz",
+ "integrity": "sha512-N1EhvLtHzOvj7QQOUCCS3NrPJP8c5W6ZXCHDn7Yialuy1iu4r5EmIYkXlKNqT99Ciw+W0mDqWoR6HWMZlFP3hw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.16.0",
- "regexpu-core": "^4.7.1"
+ "@babel/helper-annotate-as-pure": "^7.27.3",
+ "regexpu-core": "^6.3.1",
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
@@ -189,357 +230,281 @@
}
},
"node_modules/@babel/helper-define-polyfill-provider": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.3.0.tgz",
- "integrity": "sha512-7hfT8lUljl/tM3h+izTX/pO3W3frz2ok6Pk+gzys8iJqDfZrZy2pXjRTZAvG2YmfHun1X4q8/UZRLatMfqc5Tg==",
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/@babel/helper-define-polyfill-provider/-/helper-define-polyfill-provider-0.6.8.tgz",
+ "integrity": "sha512-47UwBLPpQi1NoWzLuHNjRoHlYXMwIJoBf7MFou6viC/sIHWYygpvr0B6IAyh5sBdA2nr2LPIRww8lfaUVQINBA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-compilation-targets": "^7.13.0",
- "@babel/helper-module-imports": "^7.12.13",
- "@babel/helper-plugin-utils": "^7.13.0",
- "@babel/traverse": "^7.13.0",
- "debug": "^4.1.1",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "debug": "^4.4.3",
"lodash.debounce": "^4.0.8",
- "resolve": "^1.14.2",
- "semver": "^6.1.2"
+ "resolve": "^1.22.11"
},
"peerDependencies": {
- "@babel/core": "^7.4.0-0"
- }
- },
- "node_modules/@babel/helper-environment-visitor": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.24.7.tgz",
- "integrity": "sha512-DoiN84+4Gnd0ncbBOM9AZENV4a5ZiL39HYMyZJGZ/AZEykHYdJw0wW3kdcsh9/Kn+BRXHLkkklZ51ecPKmI1CQ==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.24.7"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-explode-assignable-expression": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-explode-assignable-expression/-/helper-explode-assignable-expression-7.16.0.tgz",
- "integrity": "sha512-Hk2SLxC9ZbcOhLpg/yMznzJ11W++lg5GMbxt1ev6TXUiJB0N42KPC+7w8a+eWGuqDnUYuwStJoZHM7RgmIOaGQ==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.16.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-function-name": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.24.7.tgz",
- "integrity": "sha512-FyoJTsj/PEUWu1/TYRiXTIHc8lbw+TDYkZuoE43opPS5TrI7MyONBE1oNvfguEXAD9yhQRrVBnXdXzSLQl9XnA==",
- "dev": true,
- "dependencies": {
- "@babel/template": "^7.24.7",
- "@babel/types": "^7.24.7"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
- "node_modules/@babel/helper-hoist-variables": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.24.7.tgz",
- "integrity": "sha512-MJJwhkoGy5c4ehfoRyrJ/owKeMl19U54h27YYftT0o2teQ3FJ3nQUf/I3LlJsX4l3qlw7WRXUmiyajvHXoTubQ==",
+ "node_modules/@babel/helper-globals": {
+ "version": "7.28.0",
+ "resolved": "https://registry.npmjs.org/@babel/helper-globals/-/helper-globals-7.28.0.tgz",
+ "integrity": "sha512-+W6cISkXFa1jXsDEdYA8HeevQT/FULhxzR99pxphltZcVaugps53THCeiWA8SguxxpSp3gKPiuYfSWopkLQ4hw==",
"dev": true,
- "dependencies": {
- "@babel/types": "^7.24.7"
- },
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-member-expression-to-functions": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.16.0.tgz",
- "integrity": "sha512-bsjlBFPuWT6IWhl28EdrQ+gTvSvj5tqVP5Xeftp07SEuz5pLnsXZuDkDD3Rfcxy0IsHmbZ+7B2/9SHzxO0T+sQ==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-member-expression-to-functions/-/helper-member-expression-to-functions-7.28.5.tgz",
+ "integrity": "sha512-cwM7SBRZcPCLgl8a7cY0soT1SptSzAlMH39vwiRpOQkJlh53r5hdHwLSCZpQdVLT39sZt+CRpNwYG4Y2v77atg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.16.0"
+ "@babel/traverse": "^7.28.5",
+ "@babel/types": "^7.28.5"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-imports": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.16.0.tgz",
- "integrity": "sha512-kkH7sWzKPq0xt3H1n+ghb4xEMP8k0U7XV3kkB+ZGy69kDk2ySFW1qPi06sjKzFY3t1j6XbJSqr4mF9L7CYVyhg==",
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-imports/-/helper-module-imports-7.28.6.tgz",
+ "integrity": "sha512-l5XkZK7r7wa9LucGw9LwZyyCUscb4x37JWTPz7swwFE/0FMQAGpiWUZn8u9DzkSBWEcK25jmvubfpw2dnAMdbw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.16.0"
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-module-transforms": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.16.0.tgz",
- "integrity": "sha512-My4cr9ATcaBbmaEa8M0dZNA74cfI6gitvUAskgDtAFmAqyFKDSHQo5YstxPbN+lzHl2D9l/YOEFqb2mtUh4gfA==",
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.28.6.tgz",
+ "integrity": "sha512-67oXFAYr2cDLDVGLXTEABjdBJZ6drElUSI7WKp70NrpyISso3plG9SAGEF6y7zbha/wOzUByWWTJvEDVNIUGcA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.16.0",
- "@babel/helper-replace-supers": "^7.16.0",
- "@babel/helper-simple-access": "^7.16.0",
- "@babel/helper-split-export-declaration": "^7.16.0",
- "@babel/helper-validator-identifier": "^7.15.7",
- "@babel/template": "^7.16.0",
- "@babel/traverse": "^7.16.0",
- "@babel/types": "^7.16.0"
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-optimise-call-expression": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.16.0.tgz",
- "integrity": "sha512-SuI467Gi2V8fkofm2JPnZzB/SUuXoJA5zXe/xzyPP2M04686RzFKFHPK6HDVN6JvWBIEW8tt9hPR7fXdn2Lgpw==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-optimise-call-expression/-/helper-optimise-call-expression-7.27.1.tgz",
+ "integrity": "sha512-URMGH08NzYFhubNSGJrpUEphGKQwMQYBySzat5cAByY1/YgIRkULnIy3tAMeszlL/so2HbeilYloUmSpd7GdVw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.16.0"
+ "@babel/types": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-plugin-utils": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.14.5.tgz",
- "integrity": "sha512-/37qQCE3K0vvZKwoK4XU/irIJQdIfCJuhU5eKnNxpFDsOkgFaUAwbv+RYw6eYgsC0E4hS7r5KqGULUogqui0fQ==",
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.28.6.tgz",
+ "integrity": "sha512-S9gzZ/bz83GRysI7gAD4wPT/AI3uCnY+9xn+Mx/KPs2JwHJIz1W8PZkg2cqyt3RNOBM8ejcXhV6y8Og7ly/Dug==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-remap-async-to-generator": {
- "version": "7.16.4",
- "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.16.4.tgz",
- "integrity": "sha512-vGERmmhR+s7eH5Y/cp8PCVzj4XEjerq8jooMfxFdA5xVtAk9Sh4AQsrWgiErUEBjtGrBtOFKDUcWQFW4/dFwMA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-remap-async-to-generator/-/helper-remap-async-to-generator-7.27.1.tgz",
+ "integrity": "sha512-7fiA521aVw8lSPeI4ZOD3vRFkoqkJcS+z4hFo82bFSH/2tNd6eJ5qCVMS5OzDmZh/kaHQeBaeyxK6wljcPtveA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.16.0",
- "@babel/helper-wrap-function": "^7.16.0",
- "@babel/types": "^7.16.0"
+ "@babel/helper-annotate-as-pure": "^7.27.1",
+ "@babel/helper-wrap-function": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-replace-supers": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.16.0.tgz",
- "integrity": "sha512-TQxuQfSCdoha7cpRNJvfaYxxxzmbxXw/+6cS7V02eeDYyhxderSoMVALvwupA54/pZcOTtVeJ0xccp1nGWladA==",
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-replace-supers/-/helper-replace-supers-7.28.6.tgz",
+ "integrity": "sha512-mq8e+laIk94/yFec3DxSjCRD2Z0TAjhVbEJY3UQrlwVo15Lmt7C2wAUbK4bjnTs4APkwsYLTahXRraQXhb1WCg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-member-expression-to-functions": "^7.16.0",
- "@babel/helper-optimise-call-expression": "^7.16.0",
- "@babel/traverse": "^7.16.0",
- "@babel/types": "^7.16.0"
+ "@babel/helper-member-expression-to-functions": "^7.28.5",
+ "@babel/helper-optimise-call-expression": "^7.27.1",
+ "@babel/traverse": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-simple-access": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.16.0.tgz",
- "integrity": "sha512-o1rjBT/gppAqKsYfUdfHq5Rk03lMQrkPHG1OWzHWpLgVXRH4HnMM9Et9CVdIqwkCQlobnGHEJMsgWP/jE1zUiw==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.16.0"
},
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
"node_modules/@babel/helper-skip-transparent-expression-wrappers": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.16.0.tgz",
- "integrity": "sha512-+il1gTy0oHwUsBQZyJvukbB4vPMdcYBrFHa0Uc4AizLxbq6BOYC51Rv4tWocX9BLBDLZ4kc6qUFpQ6HRgL+3zw==",
- "dev": true,
- "dependencies": {
- "@babel/types": "^7.16.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/helper-split-export-declaration": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.24.7.tgz",
- "integrity": "sha512-oy5V7pD+UvfkEATUKvIjvIAH/xCzfsFVw7ygW2SI6NClZzquT+mwdTfgfdbUiceh6iQO0CHtCPsyze/MZ2YbAA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-skip-transparent-expression-wrappers/-/helper-skip-transparent-expression-wrappers-7.27.1.tgz",
+ "integrity": "sha512-Tub4ZKEXqbPjXgWLl2+3JpQAYBJ8+ikpQ2Ocj/q/r0LwE3UhENh7EUabyHjz2kCEsrRY83ew2DQdHluuiDQFzg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/types": "^7.24.7"
+ "@babel/traverse": "^7.27.1",
+ "@babel/types": "^7.27.1"
},
"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==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-string-parser/-/helper-string-parser-7.27.1.tgz",
+ "integrity": "sha512-qMlSxKbpRlAridDExk92nSobyDdpPijUq2DW6oDnUqd0iOGxmQjyqhMIihI9+zv4LPyZdRje2cavWPbCbWm3eA==",
"license": "MIT",
"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==",
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-identifier/-/helper-validator-identifier-7.28.5.tgz",
+ "integrity": "sha512-qSs4ifwzKJSV39ucNjsvc6WVHs6b7S03sOh2OcHF9UHfVPqWWALUsNUVzhSBiItjRZoLHx7nIarVjqKVusUZ1Q==",
"license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-validator-option": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.14.5.tgz",
- "integrity": "sha512-OX8D5eeX4XwcroVW45NMvoYaIuFI+GQpA2a8Gi+X/U/cDUIRsV37qQfF905F0htTRCREQIB4KqPeaveRJUl3Ow==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.27.1.tgz",
+ "integrity": "sha512-YvjJow9FxbhFFKDSuFnVCe2WxXk1zWc22fFePVNEaWJEu8IrZVlda6N0uHwzZrUM1il7NC9Mlp4MaJYbYd9JSg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helper-wrap-function": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.16.0.tgz",
- "integrity": "sha512-VVMGzYY3vkWgCJML+qVLvGIam902mJW0FvT7Avj1zEe0Gn7D93aWdLblYARTxEw+6DhZmtzhBM2zv0ekE5zg1g==",
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/helper-wrap-function/-/helper-wrap-function-7.28.6.tgz",
+ "integrity": "sha512-z+PwLziMNBeSQJonizz2AGnndLsP2DeGHIxDAn+wdHOGuo4Fo1x1HBPPXeE9TAOPHNNWQKCSlA2VZyYyyibDnQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-function-name": "^7.16.0",
- "@babel/template": "^7.16.0",
- "@babel/traverse": "^7.16.0",
- "@babel/types": "^7.16.0"
+ "@babel/template": "^7.28.6",
+ "@babel/traverse": "^7.28.6",
+ "@babel/types": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/helpers": {
- "version": "7.16.3",
- "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.16.3.tgz",
- "integrity": "sha512-Xn8IhDlBPhvYTvgewPKawhADichOsbkZuzN7qz2BusOM0brChsyXMDJvldWaYMMUNiCQdQzNEioXTp3sC8Nt8w==",
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.29.2.tgz",
+ "integrity": "sha512-HoGuUs4sCZNezVEKdVcwqmZN8GoHirLUcLaYVNBK2J0DadGtdcqgr3BCbvH8+XUo4NGjNl3VOtSjEKNzqfFgKw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/template": "^7.16.0",
- "@babel/traverse": "^7.16.3",
- "@babel/types": "^7.16.0"
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0"
},
"engines": {
"node": ">=6.9.0"
}
},
- "node_modules/@babel/highlight": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.24.7.tgz",
- "integrity": "sha512-EStJpq4OuY8xYfhGVXngigBJRWxftKX9ksiGDnmlY3o7B/V7KIAc9X4oiK87uPJSc/vs5L869bem5fhZa8caZw==",
- "dev": true,
+ "node_modules/@babel/parser": {
+ "version": "7.29.3",
+ "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.29.3.tgz",
+ "integrity": "sha512-b3ctpQwp+PROvU/cttc4OYl4MzfJUWy6FZg+PMXfzmt/+39iHVF0sDfqay8TQM3JA2EUOyKcFZt75jWriQijsA==",
+ "license": "MIT",
"dependencies": {
- "@babel/helper-validator-identifier": "^7.24.7",
- "chalk": "^2.4.2",
- "js-tokens": "^4.0.0",
- "picocolors": "^1.0.0"
+ "@babel/types": "^7.29.0"
},
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/@babel/highlight/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
+ "bin": {
+ "parser": "bin/babel-parser.js"
},
"engines": {
- "node": ">=4"
+ "node": ">=6.0.0"
}
},
- "node_modules/@babel/highlight/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "node_modules/@babel/plugin-bugfix-firefox-class-in-computed-class-key": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-firefox-class-in-computed-class-key/-/plugin-bugfix-firefox-class-in-computed-class-key-7.28.5.tgz",
+ "integrity": "sha512-87GDMS3tsmMSi/3bWOte1UblL+YUTFMV8SZPZ2eSEL17s74Cw/l63rR6NmGVKMYW2GYi85nE+/d6Hw5N0bEk2Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.28.5"
},
"engines": {
- "node": ">=4"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/@babel/highlight/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/@babel/highlight/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/highlight/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "node_modules/@babel/plugin-bugfix-safari-class-field-initializer-scope": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-class-field-initializer-scope/-/plugin-bugfix-safari-class-field-initializer-scope-7.27.1.tgz",
+ "integrity": "sha512-qNeq3bCKnGgLkEXUuFry6dPlGfCdQNZbn7yUAPCInwAJHMU7THJfrBSozkcWq5sNM6RcF3S8XyQL2A52KNR9IA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-flag": "^3.0.0"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
- "node": ">=4"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/parser": {
- "version": "7.26.10",
- "resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.26.10.tgz",
- "integrity": "sha512-6aQR2zGE/QFi8JpDLjUZEPYOs7+mhKXm86VaKFiLP35JQwQb6bwUE+XbvkH0EptsYhbNBSUGaUBLKqxH1xSgsA==",
+ "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.27.1.tgz",
+ "integrity": "sha512-g4L7OYun04N1WyqMNjldFwlfPCLVkgB54A/YCXICZYBsvJJE3kByKv9c9+R/nAfmIfjl2rKYLNyMHboYbZaWaA==",
+ "dev": true,
"license": "MIT",
"dependencies": {
- "@babel/types": "^7.26.10"
- },
- "bin": {
- "parser": "bin/babel-parser.js"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
- "node": ">=6.0.0"
+ "node": ">=6.9.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": {
- "version": "7.16.2",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression/-/plugin-bugfix-safari-id-destructuring-collision-in-function-expression-7.16.2.tgz",
- "integrity": "sha512-h37CvpLSf8gb2lIJ2CgC3t+EjFbi0t8qS7LCS1xcJIlEXE4czlofwaW7W1HA8zpgOCzI9C1nmoqNR1zWkk0pQg==",
+ "node_modules/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": {
+ "version": "7.29.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-safari-rest-destructuring-rhs-array/-/plugin-bugfix-safari-rest-destructuring-rhs-array-7.29.3.tgz",
+ "integrity": "sha512-SRS46DFR4HqzUzCVgi90/xMoL+zeBDBvWdKYXSEzh79kXswNFEglUpMKxR04//dPqwYXWUBJ3mpUd933ru9Kmg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -549,14 +514,15 @@
}
},
"node_modules/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.16.0.tgz",
- "integrity": "sha512-4tcFwwicpWTrpl9qjf7UsoosaArgImF85AxqCRZlgc3IQDvkUHjJpruXAL58Wmj+T6fypWTC/BakfEkwIL/pwA==",
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining/-/plugin-bugfix-v8-spread-parameters-in-optional-chaining-7.27.1.tgz",
+ "integrity": "sha512-oO02gcONcD5O1iTLi/6frMJBIwWEHceWGSGqrpCmEL8nogiS6J9PBlE48CaK20/Jx1LuRml9aDftLgdjXT8+Cw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
- "@babel/plugin-proposal-optional-chaining": "^7.16.0"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1",
+ "@babel/plugin-transform-optional-chaining": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -565,33 +531,33 @@
"@babel/core": "^7.13.0"
}
},
- "node_modules/@babel/plugin-proposal-async-generator-functions": {
- "version": "7.16.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-async-generator-functions/-/plugin-proposal-async-generator-functions-7.16.4.tgz",
- "integrity": "sha512-/CUekqaAaZCQHleSK/9HajvcD/zdnJiKRiuUFq8ITE+0HsPzquf53cpFiqAwl/UfmJbR6n5uGPQSPdrmKOvHHg==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-async-generator-functions instead.",
+ "node_modules/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly/-/plugin-bugfix-v8-static-class-fields-redefine-readonly-7.28.6.tgz",
+ "integrity": "sha512-a0aBScVTlNaiUe35UtfxAN7A/tehvvG4/ByO6+46VPKTRSlfnAFsgKy0FUh+qAkQrDTmhDkT+IBOKlOoMUxQ0g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-remap-async-to-generator": "^7.16.4",
- "@babel/plugin-syntax-async-generators": "^7.8.4"
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/traverse": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
"node_modules/@babel/plugin-proposal-class-properties": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.16.0.tgz",
- "integrity": "sha512-mCF3HcuZSY9Fcx56Lbn+CGdT44ioBMMvjNVldpKtj8tpniETdLjnxdHI1+sDWXIM1nNt+EanJOZ3IG9lzVjs7A==",
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-properties/-/plugin-proposal-class-properties-7.18.6.tgz",
+ "integrity": "sha512-cumfXOF0+nzZrrN8Rf0t7M+tF6sZc7vhQwYQck9q1/5w2OExlD+b4v4RpMJFaV1Z7WcDRgO6FqvxqxGlwo+RHQ==",
"deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-properties instead.",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-create-class-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
@@ -600,34 +566,30 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-class-static-block": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-class-static-block/-/plugin-proposal-class-static-block-7.16.0.tgz",
- "integrity": "sha512-mAy3sdcY9sKAkf3lQbDiv3olOfiLqI51c9DR9b19uMoR2Z6r5pmGl7dfNFqEvqOyqbf1ta4lknK4gc5PJn3mfA==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-class-static-block instead.",
+ "node_modules/@babel/plugin-proposal-decorators": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.29.0.tgz",
+ "integrity": "sha512-CVBVv3VY/XRMxRYq5dwr2DS7/MvqPm23cOCjbwNnVrfOqcWlnefua1uUs0sjdKOGjvPUG633o07uWzJq4oI6dA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-class-static-block": "^7.14.5"
+ "@babel/helper-create-class-features-plugin": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/plugin-syntax-decorators": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.12.0"
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-decorators": {
- "version": "7.16.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-decorators/-/plugin-proposal-decorators-7.16.4.tgz",
- "integrity": "sha512-RESBNX16eNqnBeEVR5sCJpnW0mHiNLNNvGA8PrRuK/4ZJ4TO+6bHleRUuGQYDERVySOKtOhSya/C4MIhwAMAgg==",
+ "node_modules/@babel/plugin-proposal-private-property-in-object": {
+ "version": "7.21.0-placeholder-for-preset-env.2",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.21.0-placeholder-for-preset-env.2.tgz",
+ "integrity": "sha512-SOSkfJDddaM7mak6cPEpswyTRnuRltl429hMraQEglW+OkovnCzsiszTmsrlY//qLFjCpQDFRvjdm2wA5pPm9w==",
"dev": true,
- "dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-decorators": "^7.16.0"
- },
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
},
@@ -635,15 +597,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-dynamic-import": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-dynamic-import/-/plugin-proposal-dynamic-import-7.16.0.tgz",
- "integrity": "sha512-QGSA6ExWk95jFQgwz5GQ2Dr95cf7eI7TKutIXXTb7B1gCLTCz5hTjFTQGfLFBBiC5WSNi7udNwWsqbbMh1c4yQ==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-dynamic-import instead.",
+ "node_modules/@babel/plugin-syntax-decorators": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.28.6.tgz",
+ "integrity": "sha512-71EYI0ONURHJBL4rSFXnITXqXrrY8q4P0q006DPfN+Rk+ASM+++IBXem/ruokgBZR8YNEWZ8R6B+rCb8VcUTqA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -652,32 +613,27 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-export-namespace-from": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-export-namespace-from/-/plugin-proposal-export-namespace-from-7.16.0.tgz",
- "integrity": "sha512-CjI4nxM/D+5wCnhD11MHB1AwRSAYeDT+h8gCdcVJZ/OK7+wRzFsf7PFPWVpVpNRkHMmMkQWAHpTq+15IXQ1diA==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-export-namespace-from instead.",
+ "node_modules/@babel/plugin-syntax-dynamic-import": {
+ "version": "7.8.3",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
+ "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3"
- },
- "engines": {
- "node": ">=6.9.0"
+ "@babel/helper-plugin-utils": "^7.8.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-json-strings": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-json-strings/-/plugin-proposal-json-strings-7.16.0.tgz",
- "integrity": "sha512-kouIPuiv8mSi5JkEhzApg5Gn6hFyKPnlkO0a9YSzqRurH8wYzSlf6RJdzluAsbqecdW5pBvDJDfyDIUR/vLxvg==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-json-strings instead.",
+ "node_modules/@babel/plugin-syntax-import-assertions": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-assertions/-/plugin-syntax-import-assertions-7.28.6.tgz",
+ "integrity": "sha512-pSJUpFHdx9z5nqTSirOCMtYVP2wFgoWhP0p3g8ONK/4IHhLIBd0B9NYqAvIUAhq+OkhO4VM1tENCt0cjlsNShw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-json-strings": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -686,15 +642,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-logical-assignment-operators": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-logical-assignment-operators/-/plugin-proposal-logical-assignment-operators-7.16.0.tgz",
- "integrity": "sha512-pbW0fE30sVTYXXm9lpVQQ/Vc+iTeQKiXlaNRZPPN2A2VdlWyAtsUrsQ3xydSlDW00TFMK7a8m3cDTkBF5WnV3Q==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-logical-assignment-operators instead.",
+ "node_modules/@babel/plugin-syntax-import-attributes": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-attributes/-/plugin-syntax-import-attributes-7.28.6.tgz",
+ "integrity": "sha512-jiLC0ma9XkQT3TKJ9uYvlakm66Pamywo+qwL+oL8HJOvc6TWdZXVfhqJr8CCzbSGUAbDOzlGHJC1U+vRfLQDvw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -703,15 +658,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-nullish-coalescing-operator": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-nullish-coalescing-operator/-/plugin-proposal-nullish-coalescing-operator-7.16.0.tgz",
- "integrity": "sha512-3bnHA8CAFm7cG93v8loghDYyQ8r97Qydf63BeYiGgYbjKKB/XP53W15wfRC7dvKfoiJ34f6Rbyyx2btExc8XsQ==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-nullish-coalescing-operator instead.",
+ "node_modules/@babel/plugin-syntax-jsx": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.28.6.tgz",
+ "integrity": "sha512-wgEmr06G6sIpqr8YDwA2dSRTE3bJ+V0IfpzfSY3Lfgd7YWOaAdlykvJi13ZKBt8cZHfgH1IXN+CL656W3uUa4w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -720,35 +674,31 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-numeric-separator": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-numeric-separator/-/plugin-proposal-numeric-separator-7.16.0.tgz",
- "integrity": "sha512-FAhE2I6mjispy+vwwd6xWPyEx3NYFS13pikDBWUAFGZvq6POGs5eNchw8+1CYoEgBl9n11I3NkzD7ghn25PQ9Q==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-numeric-separator instead.",
+ "node_modules/@babel/plugin-syntax-unicode-sets-regex": {
+ "version": "7.18.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-unicode-sets-regex/-/plugin-syntax-unicode-sets-regex-7.18.6.tgz",
+ "integrity": "sha512-727YkEAPwSIQTv5im8QHz3upqp92JTWhidIC81Tdx4VJYIte/VndKf1qKrfnnhPLiPghStWfvC/iFaMCQu7Nqg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4"
+ "@babel/helper-create-regexp-features-plugin": "^7.18.6",
+ "@babel/helper-plugin-utils": "^7.18.6"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-proposal-object-rest-spread": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-object-rest-spread/-/plugin-proposal-object-rest-spread-7.16.0.tgz",
- "integrity": "sha512-LU/+jp89efe5HuWJLmMmFG0+xbz+I2rSI7iLc1AlaeSMDMOGzWlc5yJrMN1d04osXN4sSfpo4O+azkBNBes0jg==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-object-rest-spread instead.",
+ "node_modules/@babel/plugin-transform-arrow-functions": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.27.1.tgz",
+ "integrity": "sha512-8Z4TGic6xW70FKThA5HYEKKyBpOOsucTOD1DjU3fZxDg+K3zBJcXMFnt/4yQiZnf5+MiOMSXQ9PaEK/Ilh1DeA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/compat-data": "^7.16.0",
- "@babel/helper-compilation-targets": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-transform-parameters": "^7.16.0"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -757,15 +707,16 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-optional-catch-binding": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-catch-binding/-/plugin-proposal-optional-catch-binding-7.16.0.tgz",
- "integrity": "sha512-kicDo0A/5J0nrsCPbn89mTG3Bm4XgYi0CZtvex9Oyw7gGZE3HXGD0zpQNH+mo+tEfbo8wbmMvJftOwpmPy7aVw==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-catch-binding instead.",
+ "node_modules/@babel/plugin-transform-async-generator-functions": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-generator-functions/-/plugin-transform-async-generator-functions-7.29.0.tgz",
+ "integrity": "sha512-va0VdWro4zlBr2JsXC+ofCPB2iG12wPtVGTWFx2WLDOM3nYQZZIGP82qku2eW/JR83sD+k2k+CsNtyEbUqhU6w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/helper-remap-async-to-generator": "^7.27.1",
+ "@babel/traverse": "^7.29.0"
},
"engines": {
"node": ">=6.9.0"
@@ -774,16 +725,16 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-optional-chaining": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-optional-chaining/-/plugin-proposal-optional-chaining-7.16.0.tgz",
- "integrity": "sha512-Y4rFpkZODfHrVo70Uaj6cC1JJOt3Pp0MdWSwIKtb8z1/lsjl9AmnB7ErRFV+QNGIfcY1Eruc2UMx5KaRnXjMyg==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-optional-chaining instead.",
+ "node_modules/@babel/plugin-transform-async-to-generator": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.28.6.tgz",
+ "integrity": "sha512-ilTRcmbuXjsMmcZ3HASTe4caH5Tpo93PkTxF9oG2VZsSWsahydmcEHhix9Ik122RcTnZnUzPbmux4wh1swfv7g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3"
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/helper-remap-async-to-generator": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -792,15 +743,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-private-methods": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-methods/-/plugin-proposal-private-methods-7.16.0.tgz",
- "integrity": "sha512-IvHmcTHDFztQGnn6aWq4t12QaBXTKr1whF/dgp9kz84X6GUcwq9utj7z2wFCUfeOup/QKnOlt2k0zxkGFx9ubg==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-methods instead.",
+ "node_modules/@babel/plugin-transform-block-scoped-functions": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.27.1.tgz",
+ "integrity": "sha512-cnqkuOtZLapWYZUYM5rVIdv1nXYuFVIltZ6ZJ7nIj585QsjKM5dhL2Fu/lICXZ1OyIAFc7Qy+bvDAtTXqGrlhg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-create-class-features-plugin": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -809,17 +759,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-private-property-in-object": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-private-property-in-object/-/plugin-proposal-private-property-in-object-7.16.0.tgz",
- "integrity": "sha512-3jQUr/HBbMVZmi72LpjQwlZ55i1queL8KcDTQEkAHihttJnAPrcvG9ZNXIfsd2ugpizZo595egYV6xy+pv4Ofw==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-private-property-in-object instead.",
+ "node_modules/@babel/plugin-transform-block-scoping": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.28.6.tgz",
+ "integrity": "sha512-tt/7wOtBmwHPNMPu7ax4pdPz6shjFrmHDghvNC+FG9Qvj7D6mJcoRQIF5dy4njmxR941l6rgtvfSB2zX3VlUIw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.16.0",
- "@babel/helper-create-class-features-plugin": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -828,54 +775,70 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-proposal-unicode-property-regex": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-proposal-unicode-property-regex/-/plugin-proposal-unicode-property-regex-7.16.0.tgz",
- "integrity": "sha512-ti7IdM54NXv29cA4+bNNKEMS4jLMCbJgl+Drv+FgYy0erJLAxNAIXcNjNjrRZEcWq0xJHsNVwQezskMFpF8N9g==",
- "deprecated": "This proposal has been merged to the ECMAScript standard and thus this plugin is no longer maintained. Please use @babel/plugin-transform-unicode-property-regex instead.",
+ "node_modules/@babel/plugin-transform-class-properties": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-properties/-/plugin-transform-class-properties-7.28.6.tgz",
+ "integrity": "sha512-dY2wS3I2G7D697VHndN91TJr8/AAfXQNt5ynCTI/MpxMsSzHp+52uNivYT5wCPax3whc47DR8Ba7cmlQMg24bw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-create-class-features-plugin": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
- "node": ">=4"
+ "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
- "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
+ "node_modules/@babel/plugin-transform-class-static-block": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-class-static-block/-/plugin-transform-class-static-block-7.28.6.tgz",
+ "integrity": "sha512-rfQ++ghVwTWTqQ7w8qyDxL1XGihjBss4CmTgGRCTAC9RIbhVpyp4fOeZtta0Lbf+dTNIVJer6ych2ibHwkZqsQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "@babel/helper-create-class-features-plugin": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.12.0"
}
},
- "node_modules/@babel/plugin-syntax-class-properties": {
- "version": "7.12.13",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
- "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
+ "node_modules/@babel/plugin-transform-classes": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.28.6.tgz",
+ "integrity": "sha512-EF5KONAqC5zAqT783iMGuM2ZtmEBy+mJMOKl2BCvPZ2lVrwvXnB6o+OBWCS+CoeCCpVRF2sA2RBKUxvT8tQT5Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.12.13"
+ "@babel/helper-annotate-as-pure": "^7.27.3",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/helper-replace-supers": "^7.28.6",
+ "@babel/traverse": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-class-static-block": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-static-block/-/plugin-syntax-class-static-block-7.14.5.tgz",
- "integrity": "sha512-b+YyPmr6ldyNnM6sqYeMWE+bgJcJpO6yS4QD7ymxgH34GBPNDM/THBh8iunyvKIZztiwLH4CJZ0RxTk9emgpjw==",
+ "node_modules/@babel/plugin-transform-computed-properties": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.28.6.tgz",
+ "integrity": "sha512-bcc3k0ijhHbc2lEfpFHgx7eYw9KNXqOerKWfzbxEHUGKnS3sz9C4CNL9OiFN1297bDNfUiSO7DaLzbvHQQQ1BQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/template": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -884,13 +847,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-decorators": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-decorators/-/plugin-syntax-decorators-7.16.0.tgz",
- "integrity": "sha512-nxnnngZClvlY13nHJAIDow0S7Qzhq64fQ/NlqS+VER3kjW/4F0jLhXjeL8jcwSwz6Ca3rotT5NJD2T9I7lcv7g==",
+ "node_modules/@babel/plugin-transform-destructuring": {
+ "version": "7.28.5",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.28.5.tgz",
+ "integrity": "sha512-Kl9Bc6D0zTUcFUvkNuQh4eGXPKKNDOJQXVyyM4ZAQPMveniJdxi8XMJwLo+xSoW3MIq81bD33lcUe9kZpl0MCw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.28.5"
},
"engines": {
"node": ">=6.9.0"
@@ -899,136 +864,148 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-dynamic-import": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-dynamic-import/-/plugin-syntax-dynamic-import-7.8.3.tgz",
- "integrity": "sha512-5gdGbFon+PszYzqs83S3E5mpi7/y/8M9eC90MRTZfduQOYW76ig6SOSPNe41IG5LoP3FGBn2N0RjVDSQiS94kQ==",
+ "node_modules/@babel/plugin-transform-dotall-regex": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.28.6.tgz",
+ "integrity": "sha512-SljjowuNKB7q5Oayv4FoPzeB74g3QgLt8IVJw9ADvWy3QnUb/01aw8I4AVv8wYnPvQz2GDDZ/g3GhcNyDBI4Bg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "@babel/helper-create-regexp-features-plugin": "^7.28.5",
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-export-namespace-from": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-export-namespace-from/-/plugin-syntax-export-namespace-from-7.8.3.tgz",
- "integrity": "sha512-MXf5laXo6c1IbEbegDmzGPwGNTsHZmEy6QGznu5Sh2UCWvueywb2ee+CCE4zQiZstxU9BMoQO9i6zUFSY0Kj0Q==",
+ "node_modules/@babel/plugin-transform-duplicate-keys": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.27.1.tgz",
+ "integrity": "sha512-MTyJk98sHvSs+cvZ4nOauwTTG1JeonDjSGvGGUNHreGQns+Mpt6WX/dVzWBHgg+dYZhkC4X+zTDfkTU+Vy9y7Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.3"
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
- "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
+ "node_modules/@babel/plugin-transform-duplicate-named-capturing-groups-regex": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-named-capturing-groups-regex/-/plugin-transform-duplicate-named-capturing-groups-regex-7.29.0.tgz",
+ "integrity": "sha512-zBPcW2lFGxdiD8PUnPwJjag2J9otbcLQzvbiOzDxpYXyCuYX9agOwMPGn1prVH0a4qzhCKu24rlH4c1f7yA8rw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.16.0.tgz",
- "integrity": "sha512-8zv2+xiPHwly31RK4RmnEYY5zziuF3O7W2kIDW+07ewWDh6Oi0dRq8kwvulRkFgt6DB97RlKs5c1y068iPlCUg==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-create-regexp-features-plugin": "^7.28.5",
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
- "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
+ "node_modules/@babel/plugin-transform-dynamic-import": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dynamic-import/-/plugin-transform-dynamic-import-7.27.1.tgz",
+ "integrity": "sha512-MHzkWQcEmjzzVW9j2q8LGjwGWpG2mjwaaB0BNQwst3FIjqsg8Ct/mIZlvSPJvfi9y2AC8mi/ktxbFVL9pZ1I4A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dev": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
- "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
+ "node_modules/@babel/plugin-transform-explicit-resource-management": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-explicit-resource-management/-/plugin-transform-explicit-resource-management-7.28.6.tgz",
+ "integrity": "sha512-Iao5Konzx2b6g7EPqTy40UZbcdXE126tTxVFr/nAIj+WItNxjKSYTEw3RC+A2/ZetmdJsgueL1KhaMCQHkLPIg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/plugin-transform-destructuring": "^7.28.5"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
- "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
+ "node_modules/@babel/plugin-transform-exponentiation-operator": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.28.6.tgz",
+ "integrity": "sha512-WitabqiGjV/vJ0aPOLSFfNY1u9U3R7W36B03r5I2KoNix+a3sOhJ3pKFB3R5It9/UiK78NiO0KE9P21cMhlPkw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "@babel/helper-plugin-utils": "^7.28.6"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
+ "node_modules/@babel/plugin-transform-export-namespace-from": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-export-namespace-from/-/plugin-transform-export-namespace-from-7.27.1.tgz",
+ "integrity": "sha512-tQvHWSZ3/jH2xuq/vZDy0jNn+ZdXJeM8gHvX4lnJmsc3+50yPlWdZXIc5ay+umX+2/tJIqHqiEqcJvxlmIvRvQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "@babel/helper-plugin-utils": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
- "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
+ "node_modules/@babel/plugin-transform-for-of": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.27.1.tgz",
+ "integrity": "sha512-BfbWFFEJFQzLCQ5N8VocnCtA8J1CLkNTe2Ms2wocj75dd6VpiqS5Z5quTYcUoo4Yq+DN0rtikODccuv7RU81sw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
+ },
+ "engines": {
+ "node": ">=6.9.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-private-property-in-object": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-private-property-in-object/-/plugin-syntax-private-property-in-object-7.14.5.tgz",
- "integrity": "sha512-0wVnp9dxJ72ZUJDV27ZfbSj6iHLoytYZmh3rFcxNnvsJF3ktkzLDZPy/mA17HGsaQT3/DQsWYX1f1QGWkCoVUg==",
+ "node_modules/@babel/plugin-transform-function-name": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.27.1.tgz",
+ "integrity": "sha512-1bQeydJF9Nr1eBCMMbC+hdwmRlsv5XYOMu03YSWFwNs0HsAmtSxxF1fyuYPqemVldVyFmlCU7w8UE14LupUSZQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-compilation-targets": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/traverse": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1037,13 +1014,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-syntax-top-level-await": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
- "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
+ "node_modules/@babel/plugin-transform-json-strings": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-json-strings/-/plugin-transform-json-strings-7.28.6.tgz",
+ "integrity": "sha512-Nr+hEN+0geQkzhbdgQVPoqr47lZbm+5fCUmO70722xJZd0Mvb59+33QLImGj6F+DkK3xgDi1YVysP8whD6FQAw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1052,13 +1030,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-arrow-functions": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-arrow-functions/-/plugin-transform-arrow-functions-7.16.0.tgz",
- "integrity": "sha512-vIFb5250Rbh7roWARvCLvIJ/PtAU5Lhv7BtZ1u24COwpI9Ypjsh+bZcKk6rlIyalK+r0jOc1XQ8I4ovNxNrWrA==",
+ "node_modules/@babel/plugin-transform-literals": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.27.1.tgz",
+ "integrity": "sha512-0HCFSepIpLTkLcsi86GG3mTUzxV5jpmbv97hTETW3yzrAij8aqlD36toB1D0daVFJM8NK6GvKO0gslVQmm+zZA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1067,15 +1046,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-async-to-generator": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-async-to-generator/-/plugin-transform-async-to-generator-7.16.0.tgz",
- "integrity": "sha512-PbIr7G9kR8tdH6g8Wouir5uVjklETk91GMVSUq+VaOgiinbCkBP6Q7NN/suM/QutZkMJMvcyAriogcYAdhg8Gw==",
+ "node_modules/@babel/plugin-transform-logical-assignment-operators": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-logical-assignment-operators/-/plugin-transform-logical-assignment-operators-7.28.6.tgz",
+ "integrity": "sha512-+anKKair6gpi8VsM/95kmomGNMD0eLz1NQ8+Pfw5sAwWH9fGYXT50E55ZpV0pHUHWf6IUTWPM+f/7AAff+wr9A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-remap-async-to-generator": "^7.16.0"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1084,13 +1062,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-block-scoped-functions": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoped-functions/-/plugin-transform-block-scoped-functions-7.16.0.tgz",
- "integrity": "sha512-V14As3haUOP4ZWrLJ3VVx5rCnrYhMSHN/jX7z6FAt5hjRkLsb0snPCmJwSOML5oxkKO4FNoNv7V5hw/y2bjuvg==",
+ "node_modules/@babel/plugin-transform-member-expression-literals": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.27.1.tgz",
+ "integrity": "sha512-hqoBX4dcZ1I33jCSWcXrP+1Ku7kdqXf1oeah7ooKOIiAdKQ+uqftgCFNOSzA5AMS2XIHEYeGFg4cKRCdpxzVOQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1099,13 +1078,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-block-scoping": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-block-scoping/-/plugin-transform-block-scoping-7.16.0.tgz",
- "integrity": "sha512-27n3l67/R3UrXfizlvHGuTwsRIFyce3D/6a37GRxn28iyTPvNXaW4XvznexRh1zUNLPjbLL22Id0XQElV94ruw==",
+ "node_modules/@babel/plugin-transform-modules-amd": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.27.1.tgz",
+ "integrity": "sha512-iCsytMg/N9/oFq6n+gFTvUYDZQOMK5kEdeYxmxt91fcJGycfxVP9CnrxoliM0oumFERba2i8ZtwRUCMhvP1LnA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1114,19 +1095,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-classes": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-classes/-/plugin-transform-classes-7.16.0.tgz",
- "integrity": "sha512-HUxMvy6GtAdd+GKBNYDWCIA776byUQH8zjnfjxwT1P1ARv/wFu8eBDpmXQcLS/IwRtrxIReGiplOwMeyO7nsDQ==",
+ "node_modules/@babel/plugin-transform-modules-commonjs": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.28.6.tgz",
+ "integrity": "sha512-jppVbf8IV9iWWwWTQIxJMAJCWBuuKx71475wHwYytrRGQ2CWiDvYlADQno3tcYpS/T2UUWFQp3nVtYfK/YBQrA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-annotate-as-pure": "^7.16.0",
- "@babel/helper-function-name": "^7.16.0",
- "@babel/helper-optimise-call-expression": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-replace-supers": "^7.16.0",
- "@babel/helper-split-export-declaration": "^7.16.0",
- "globals": "^11.1.0"
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1135,13 +1112,17 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-computed-properties": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-computed-properties/-/plugin-transform-computed-properties-7.16.0.tgz",
- "integrity": "sha512-63l1dRXday6S8V3WFY5mXJwcRAnPYxvFfTlt67bwV1rTyVTM5zrp0DBBb13Kl7+ehkCVwIZPumPpFP/4u70+Tw==",
+ "node_modules/@babel/plugin-transform-modules-systemjs": {
+ "version": "7.29.4",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.29.4.tgz",
+ "integrity": "sha512-N7QmZ0xRZfjHOfZeQLJjwgX2zS9pdGHSVl/cjSGlo4dXMqvurfxXDMKY4RqEKzPozV78VMcd0lxyG13mlbKc4w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-module-transforms": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/helper-validator-identifier": "^7.28.5",
+ "@babel/traverse": "^7.29.0"
},
"engines": {
"node": ">=6.9.0"
@@ -1150,13 +1131,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-destructuring": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-destructuring/-/plugin-transform-destructuring-7.16.0.tgz",
- "integrity": "sha512-Q7tBUwjxLTsHEoqktemHBMtb3NYwyJPTJdM+wDwb0g8PZ3kQUIzNvwD5lPaqW/p54TXBc/MXZu9Jr7tbUEUM8Q==",
+ "node_modules/@babel/plugin-transform-modules-umd": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.27.1.tgz",
+ "integrity": "sha512-iQBE/xC5BV1OxJbp6WG7jq9IWiD+xxlZhLrdwpPkTX3ydmXdvoCpyfJN7acaIBZaOqTfr76pgzqBJflNbeRK+w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-module-transforms": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1165,29 +1148,31 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-dotall-regex": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-dotall-regex/-/plugin-transform-dotall-regex-7.16.0.tgz",
- "integrity": "sha512-FXlDZfQeLILfJlC6I1qyEwcHK5UpRCFkaoVyA1nk9A1L1Yu583YO4un2KsLBsu3IJb4CUbctZks8tD9xPQubLw==",
+ "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.29.0.tgz",
+ "integrity": "sha512-1CZQA5KNAD6ZYQLPw7oi5ewtDNxH/2vuCh+6SmvgDfhumForvs8a1o9n0UrEoBD8HU4djO2yWngTQlXl1NDVEQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-create-regexp-features-plugin": "^7.28.5",
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-transform-duplicate-keys": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-duplicate-keys/-/plugin-transform-duplicate-keys-7.16.0.tgz",
- "integrity": "sha512-LIe2kcHKAZOJDNxujvmp6z3mfN6V9lJxubU4fJIGoQCkKe3Ec2OcbdlYP+vW++4MpxwG0d1wSDOJtQW5kLnkZQ==",
+ "node_modules/@babel/plugin-transform-new-target": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.27.1.tgz",
+ "integrity": "sha512-f6PiYeqXQ05lYq3TIfIDu/MtliKUbNwkGApPUvyo6+tc7uaR4cPjPe7DFPr15Uyycg2lZU6btZ575CuQoYh7MQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1196,14 +1181,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-exponentiation-operator": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-exponentiation-operator/-/plugin-transform-exponentiation-operator-7.16.0.tgz",
- "integrity": "sha512-OwYEvzFI38hXklsrbNivzpO3fh87skzx8Pnqi4LoSYeav0xHlueSoCJrSgTPfnbyzopo5b3YVAJkFIcUpK2wsw==",
+ "node_modules/@babel/plugin-transform-nullish-coalescing-operator": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-nullish-coalescing-operator/-/plugin-transform-nullish-coalescing-operator-7.28.6.tgz",
+ "integrity": "sha512-3wKbRgmzYbw24mDJXT7N+ADXw8BC/imU9yo9c9X9NKaLF1fW+e5H1U5QjMUBe4Qo4Ox/o++IyUkl1sVCLgevKg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-builder-binary-assignment-operator-visitor": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1212,13 +1197,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-for-of": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-for-of/-/plugin-transform-for-of-7.16.0.tgz",
- "integrity": "sha512-5QKUw2kO+GVmKr2wMYSATCTTnHyscl6sxFRAY+rvN7h7WB0lcG0o4NoV6ZQU32OZGVsYUsfLGgPQpDFdkfjlJQ==",
+ "node_modules/@babel/plugin-transform-numeric-separator": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-numeric-separator/-/plugin-transform-numeric-separator-7.28.6.tgz",
+ "integrity": "sha512-SJR8hPynj8outz+SlStQSwvziMN4+Bq99it4tMIf5/Caq+3iOc0JtKyse8puvyXkk3eFRIA5ID/XfunGgO5i6w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1227,14 +1213,18 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-function-name": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-function-name/-/plugin-transform-function-name-7.16.0.tgz",
- "integrity": "sha512-lBzMle9jcOXtSOXUpc7tvvTpENu/NuekNJVova5lCCWCV9/U1ho2HH2y0p6mBg8fPm/syEAbfaaemYGOHCY3mg==",
+ "node_modules/@babel/plugin-transform-object-rest-spread": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-rest-spread/-/plugin-transform-object-rest-spread-7.28.6.tgz",
+ "integrity": "sha512-5rh+JR4JBC4pGkXLAcYdLHZjXudVxWMXbB6u6+E9lRL5TrGVbHt1TjxGbZ8CkmYw9zjkB7jutzOROArsqtncEA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-function-name": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/plugin-transform-destructuring": "^7.28.5",
+ "@babel/plugin-transform-parameters": "^7.27.7",
+ "@babel/traverse": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1243,13 +1233,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-literals": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-literals/-/plugin-transform-literals-7.16.0.tgz",
- "integrity": "sha512-gQDlsSF1iv9RU04clgXqRjrPyyoJMTclFt3K1cjLmTKikc0s/6vE3hlDeEVC71wLTRu72Fq7650kABrdTc2wMQ==",
+ "node_modules/@babel/plugin-transform-object-super": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.27.1.tgz",
+ "integrity": "sha512-SFy8S9plRPbIcxlJ8A6mT/CxFdJx/c04JEctz4jf8YZaVS2px34j7NXRrlGlHkN/M2gnpL37ZpGRGVFLd3l8Ng==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/helper-replace-supers": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1258,13 +1250,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-member-expression-literals": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-member-expression-literals/-/plugin-transform-member-expression-literals-7.16.0.tgz",
- "integrity": "sha512-WRpw5HL4Jhnxw8QARzRvwojp9MIE7Tdk3ez6vRyUk1MwgjJN0aNpRoXainLR5SgxmoXx/vsXGZ6OthP6t/RbUg==",
+ "node_modules/@babel/plugin-transform-optional-catch-binding": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-catch-binding/-/plugin-transform-optional-catch-binding-7.28.6.tgz",
+ "integrity": "sha512-R8ja/Pyrv0OGAvAXQhSTmWyPJPml+0TMqXlO5w+AsMEiwb2fg3WkOvob7UxFSL3OIttFSGSRFKQsOhJ/X6HQdQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1273,15 +1266,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-modules-amd": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-amd/-/plugin-transform-modules-amd-7.16.0.tgz",
- "integrity": "sha512-rWFhWbCJ9Wdmzln1NmSCqn7P0RAD+ogXG/bd9Kg5c7PKWkJtkiXmYsMBeXjDlzHpVTJ4I/hnjs45zX4dEv81xw==",
+ "node_modules/@babel/plugin-transform-optional-chaining": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-optional-chaining/-/plugin-transform-optional-chaining-7.28.6.tgz",
+ "integrity": "sha512-A4zobikRGJTsX9uqVFdafzGkqD30t26ck2LmOzAuLL8b2x6k3TIqRiT2xVvA9fNmFeTX484VpsdgmKNA0bS23w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "babel-plugin-dynamic-import-node": "^2.3.3"
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1290,16 +1283,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-modules-commonjs": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-commonjs/-/plugin-transform-modules-commonjs-7.16.0.tgz",
- "integrity": "sha512-Dzi+NWqyEotgzk/sb7kgQPJQf7AJkQBWsVp1N6JWc1lBVo0vkElUnGdr1PzUBmfsCCN5OOFya3RtpeHk15oLKQ==",
+ "node_modules/@babel/plugin-transform-parameters": {
+ "version": "7.27.7",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.27.7.tgz",
+ "integrity": "sha512-qBkYTYCb76RRxUM6CcZA5KRu8K4SM8ajzVeUgVdMVO9NN9uI/GaVmBg/WKJJGnNokV9SY8FxNOVWGXzqzUidBg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-simple-access": "^7.16.0",
- "babel-plugin-dynamic-import-node": "^2.3.3"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1308,17 +1299,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-modules-systemjs": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-systemjs/-/plugin-transform-modules-systemjs-7.16.0.tgz",
- "integrity": "sha512-yuGBaHS3lF1m/5R+6fjIke64ii5luRUg97N2wr+z1sF0V+sNSXPxXDdEEL/iYLszsN5VKxVB1IPfEqhzVpiqvg==",
+ "node_modules/@babel/plugin-transform-private-methods": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-methods/-/plugin-transform-private-methods-7.28.6.tgz",
+ "integrity": "sha512-piiuapX9CRv7+0st8lmuUlRSmX6mBcVeNQ1b4AYzJxfCMuBfB0vBXDiGSmm03pKJw1v6cZ8KSeM+oUnM6yAExg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-hoist-variables": "^7.16.0",
- "@babel/helper-module-transforms": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-validator-identifier": "^7.15.7",
- "babel-plugin-dynamic-import-node": "^2.3.3"
+ "@babel/helper-create-class-features-plugin": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1327,14 +1316,16 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-modules-umd": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-modules-umd/-/plugin-transform-modules-umd-7.16.0.tgz",
- "integrity": "sha512-nx4f6no57himWiHhxDM5pjwhae5vLpTK2zCnDH8+wNLJy0TVER/LJRHl2bkt6w9Aad2sPD5iNNoUpY3X9sTGDg==",
+ "node_modules/@babel/plugin-transform-private-property-in-object": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-private-property-in-object/-/plugin-transform-private-property-in-object-7.28.6.tgz",
+ "integrity": "sha512-b97jvNSOb5+ehyQmBpmhOCiUC5oVK4PMnpRvO7+ymFBoqYjeDHIU9jnrNUuwHOiL9RpGDoKBpSViarV+BU+eVA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-transforms": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-annotate-as-pure": "^7.27.3",
+ "@babel/helper-create-class-features-plugin": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1343,28 +1334,30 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-named-capturing-groups-regex": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-named-capturing-groups-regex/-/plugin-transform-named-capturing-groups-regex-7.16.0.tgz",
- "integrity": "sha512-LogN88uO+7EhxWc8WZuQ8vxdSyVGxhkh8WTC3tzlT8LccMuQdA81e9SGV6zY7kY2LjDhhDOFdQVxdGwPyBCnvg==",
+ "node_modules/@babel/plugin-transform-property-literals": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.27.1.tgz",
+ "integrity": "sha512-oThy3BCuCha8kDZ8ZkgOg2exvPYUlprMukKQXI1r1pJ47NCvxfkEy8vK+r/hT9nF0Aa4H1WUPZZjHTFtAhGfmQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.16.0"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0"
+ "@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-new-target": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-new-target/-/plugin-transform-new-target-7.16.0.tgz",
- "integrity": "sha512-fhjrDEYv2DBsGN/P6rlqakwRwIp7rBGLPbrKxwh7oVt5NNkIhZVOY2GRV+ULLsQri1bDqwDWnU3vhlmx5B2aCw==",
+ "node_modules/@babel/plugin-transform-regenerator": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.29.0.tgz",
+ "integrity": "sha512-FijqlqMA7DmRdg/aINBSs04y8XNTYw/lr1gJ2WsmBnnaNw1iS43EPkJW+zK7z65auG3AWRFXWj+NcTQwYptUog==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1373,29 +1366,31 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-object-super": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-object-super/-/plugin-transform-object-super-7.16.0.tgz",
- "integrity": "sha512-fds+puedQHn4cPLshoHcR1DTMN0q1V9ou0mUjm8whx9pGcNvDrVVrgw+KJzzCaiTdaYhldtrUps8DWVMgrSEyg==",
+ "node_modules/@babel/plugin-transform-regexp-modifiers": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regexp-modifiers/-/plugin-transform-regexp-modifiers-7.28.6.tgz",
+ "integrity": "sha512-QGWAepm9qxpaIs7UM9FvUSnCGlb8Ua1RhyM4/veAxLwt3gMat/LSGrZixyuj4I6+Kn9iwvqCyPTtbdxanYoWYg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-replace-supers": "^7.16.0"
+ "@babel/helper-create-regexp-features-plugin": "^7.28.5",
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-transform-parameters": {
- "version": "7.16.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-parameters/-/plugin-transform-parameters-7.16.3.tgz",
- "integrity": "sha512-3MaDpJrOXT1MZ/WCmkOFo7EtmVVC8H4EUZVrHvFOsmwkk4lOjQj8rzv8JKUZV4YoQKeoIgk07GO+acPU9IMu/w==",
+ "node_modules/@babel/plugin-transform-reserved-words": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.27.1.tgz",
+ "integrity": "sha512-V2ABPHIJX4kC7HegLkYoDpfg9PVmuWy/i6vUM5eGK22bx4YVFD3M5F0QQnWQoDs6AGsUWTVOopBiMFQgHaSkVw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1404,13 +1399,19 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-property-literals": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-property-literals/-/plugin-transform-property-literals-7.16.0.tgz",
- "integrity": "sha512-XLldD4V8+pOqX2hwfWhgwXzGdnDOThxaNTgqagOcpBgIxbUvpgU2FMvo5E1RyHbk756WYgdbS0T8y0Cj9FKkWQ==",
+ "node_modules/@babel/plugin-transform-runtime": {
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.29.0.tgz",
+ "integrity": "sha512-jlaRT5dJtMaMCV6fAuLbsQMSwz/QkvaHOHOSXRitGGwSpR1blCY4KUKoyP2tYO8vJcqYe8cEj96cqSztv3uF9w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-module-imports": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "babel-plugin-polyfill-corejs2": "^0.4.14",
+ "babel-plugin-polyfill-corejs3": "^0.13.0",
+ "babel-plugin-polyfill-regenerator": "^0.6.5",
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1419,13 +1420,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-regenerator": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-regenerator/-/plugin-transform-regenerator-7.16.0.tgz",
- "integrity": "sha512-JAvGxgKuwS2PihiSFaDrp94XOzzTUeDeOQlcKzVAyaPap7BnZXK/lvMDiubkPTdotPKOIZq9xWXWnggUMYiExg==",
+ "node_modules/@babel/plugin-transform-shorthand-properties": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.27.1.tgz",
+ "integrity": "sha512-N/wH1vcn4oYawbJ13Y/FxcQrWk63jhfNa7jef0ih7PHSIHX2LB7GWE1rkPrOnka9kwMxb6hMl19p7lidA+EHmQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "regenerator-transform": "^0.14.2"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1434,13 +1436,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-reserved-words": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-reserved-words/-/plugin-transform-reserved-words-7.16.0.tgz",
- "integrity": "sha512-Dgs8NNCehHSvXdhEhln8u/TtJxfVwGYCgP2OOr5Z3Ar+B+zXicEOKNTyc+eca2cuEOMtjW6m9P9ijOt8QdqWkg==",
+ "node_modules/@babel/plugin-transform-spread": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.28.6.tgz",
+ "integrity": "sha512-9U4QObUC0FtJl05AsUcodau/RWDytrU6uKgkxu09mLR9HLDAtUMoPuuskm5huQsoktmsYpI+bGmq+iapDcriKA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/helper-skip-transparent-expression-wrappers": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1449,18 +1453,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-runtime": {
- "version": "7.16.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-runtime/-/plugin-transform-runtime-7.16.4.tgz",
- "integrity": "sha512-pru6+yHANMTukMtEZGC4fs7XPwg35v8sj5CIEmE+gEkFljFiVJxEWxx/7ZDkTK+iZRYo1bFXBtfIN95+K3cJ5A==",
+ "node_modules/@babel/plugin-transform-sticky-regex": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.27.1.tgz",
+ "integrity": "sha512-lhInBO5bi/Kowe2/aLdBAawijx+q1pQzicSgnkB6dUPc1+RC8QmJHKf2OjvU+NZWitguJHEaEmbV6VWEouT58g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5",
- "babel-plugin-polyfill-corejs2": "^0.3.0",
- "babel-plugin-polyfill-corejs3": "^0.4.0",
- "babel-plugin-polyfill-regenerator": "^0.3.0",
- "semver": "^6.3.0"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1469,13 +1469,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-shorthand-properties": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-shorthand-properties/-/plugin-transform-shorthand-properties-7.16.0.tgz",
- "integrity": "sha512-iVb1mTcD8fuhSv3k99+5tlXu5N0v8/DPm2mO3WACLG6al1CGZH7v09HJyUb1TtYl/Z+KrM6pHSIJdZxP5A+xow==",
+ "node_modules/@babel/plugin-transform-template-literals": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.27.1.tgz",
+ "integrity": "sha512-fBJKiV7F2DxZUkg5EtHKXQdbsbURW3DZKQUWphDum0uRP6eHGGa/He9mc0mypL680pb+e/lDIthRohlv8NCHkg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1484,14 +1485,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-spread": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-spread/-/plugin-transform-spread-7.16.0.tgz",
- "integrity": "sha512-Ao4MSYRaLAQczZVp9/7E7QHsCuK92yHRrmVNRe/SlEJjhzivq0BSn8mEraimL8wizHZ3fuaHxKH0iwzI13GyGg==",
+ "node_modules/@babel/plugin-transform-typeof-symbol": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.27.1.tgz",
+ "integrity": "sha512-RiSILC+nRJM7FY5srIyc4/fGIwUhyDuuBSdWn4y6yT6gm652DpCHZjIipgn6B7MQ1ITOUnAKWixEUjQRIBIcLw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-skip-transparent-expression-wrappers": "^7.16.0"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1500,13 +1501,14 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-sticky-regex": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-sticky-regex/-/plugin-transform-sticky-regex-7.16.0.tgz",
- "integrity": "sha512-/ntT2NljR9foobKk4E/YyOSwcGUXtYWv5tinMK/3RkypyNBNdhHUaq6Orw5DWq9ZcNlS03BIlEALFeQgeVAo4Q==",
+ "node_modules/@babel/plugin-transform-unicode-escapes": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.27.1.tgz",
+ "integrity": "sha512-Ysg4v6AmF26k9vpfFuTZg8HRfVWzsh1kVfowA23y9j/Gu6dOuahdUVhkLqpObp3JIv27MLSii6noRnuKN8H0Mg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1515,13 +1517,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-template-literals": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-template-literals/-/plugin-transform-template-literals-7.16.0.tgz",
- "integrity": "sha512-Rd4Ic89hA/f7xUSJQk5PnC+4so50vBoBfxjdQAdvngwidM8jYIBVxBZ/sARxD4e0yMXRbJVDrYf7dyRtIIKT6Q==",
+ "node_modules/@babel/plugin-transform-unicode-property-regex": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-property-regex/-/plugin-transform-unicode-property-regex-7.28.6.tgz",
+ "integrity": "sha512-4Wlbdl/sIZjzi/8St0evF0gEZrgOswVO6aOzqxh1kDZOl9WmLrHq2HtGhnOJZmHZYKP8WZ1MDLCt5DAWwRo57A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-create-regexp-features-plugin": "^7.28.5",
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
@@ -1530,13 +1534,15 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-typeof-symbol": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-typeof-symbol/-/plugin-transform-typeof-symbol-7.16.0.tgz",
- "integrity": "sha512-++V2L8Bdf4vcaHi2raILnptTBjGEFxn5315YU+e8+EqXIucA+q349qWngCLpUYqqv233suJ6NOienIVUpS9cqg==",
+ "node_modules/@babel/plugin-transform-unicode-regex": {
+ "version": "7.27.1",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.27.1.tgz",
+ "integrity": "sha512-xvINq24TRojDuyt6JGtHmkVkrfVV3FPT16uytxImLeBZqW3/H52yN+kM1MGuyPkIQxrzKwPHs5U/MP3qKyzkGw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-create-regexp-features-plugin": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1545,29 +1551,101 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/plugin-transform-unicode-escapes": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-escapes/-/plugin-transform-unicode-escapes-7.16.0.tgz",
- "integrity": "sha512-VFi4dhgJM7Bpk8lRc5CMaRGlKZ29W9C3geZjt9beuzSUrlJxsNwX7ReLwaL6WEvsOf2EQkyIJEPtF8EXjB/g2A==",
+ "node_modules/@babel/plugin-transform-unicode-sets-regex": {
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-sets-regex/-/plugin-transform-unicode-sets-regex-7.28.6.tgz",
+ "integrity": "sha512-/wHc/paTUmsDYN7SZkpWxogTOBNnlx7nBQYfy6JJlCT7G3mVhltk3e++N7zV0XfgGsrqBxd4rJQt9H16I21Y1Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/helper-create-regexp-features-plugin": "^7.28.5",
+ "@babel/helper-plugin-utils": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0"
}
},
- "node_modules/@babel/plugin-transform-unicode-regex": {
- "version": "7.16.0",
- "resolved": "https://registry.npmjs.org/@babel/plugin-transform-unicode-regex/-/plugin-transform-unicode-regex-7.16.0.tgz",
- "integrity": "sha512-jHLK4LxhHjvCeZDWyA9c+P9XH1sOxRd1RO9xMtDVRAOND/PczPqizEtVdx4TQF/wyPaewqpT+tgQFYMnN/P94A==",
+ "node_modules/@babel/preset-env": {
+ "version": "7.29.5",
+ "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.29.5.tgz",
+ "integrity": "sha512-/69t2aEzGKHD76DyLbHysF/QH2LJOB8iFnYO37unDTKBTubzcMRv0f3H5EiN1Q6ajOd/eB7dAInF0qdFVS06kA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-create-regexp-features-plugin": "^7.16.0",
- "@babel/helper-plugin-utils": "^7.14.5"
+ "@babel/compat-data": "^7.29.3",
+ "@babel/helper-compilation-targets": "^7.28.6",
+ "@babel/helper-plugin-utils": "^7.28.6",
+ "@babel/helper-validator-option": "^7.27.1",
+ "@babel/plugin-bugfix-firefox-class-in-computed-class-key": "^7.28.5",
+ "@babel/plugin-bugfix-safari-class-field-initializer-scope": "^7.27.1",
+ "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.27.1",
+ "@babel/plugin-bugfix-safari-rest-destructuring-rhs-array": "^7.29.3",
+ "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.27.1",
+ "@babel/plugin-bugfix-v8-static-class-fields-redefine-readonly": "^7.28.6",
+ "@babel/plugin-proposal-private-property-in-object": "7.21.0-placeholder-for-preset-env.2",
+ "@babel/plugin-syntax-import-assertions": "^7.28.6",
+ "@babel/plugin-syntax-import-attributes": "^7.28.6",
+ "@babel/plugin-syntax-unicode-sets-regex": "^7.18.6",
+ "@babel/plugin-transform-arrow-functions": "^7.27.1",
+ "@babel/plugin-transform-async-generator-functions": "^7.29.0",
+ "@babel/plugin-transform-async-to-generator": "^7.28.6",
+ "@babel/plugin-transform-block-scoped-functions": "^7.27.1",
+ "@babel/plugin-transform-block-scoping": "^7.28.6",
+ "@babel/plugin-transform-class-properties": "^7.28.6",
+ "@babel/plugin-transform-class-static-block": "^7.28.6",
+ "@babel/plugin-transform-classes": "^7.28.6",
+ "@babel/plugin-transform-computed-properties": "^7.28.6",
+ "@babel/plugin-transform-destructuring": "^7.28.5",
+ "@babel/plugin-transform-dotall-regex": "^7.28.6",
+ "@babel/plugin-transform-duplicate-keys": "^7.27.1",
+ "@babel/plugin-transform-duplicate-named-capturing-groups-regex": "^7.29.0",
+ "@babel/plugin-transform-dynamic-import": "^7.27.1",
+ "@babel/plugin-transform-explicit-resource-management": "^7.28.6",
+ "@babel/plugin-transform-exponentiation-operator": "^7.28.6",
+ "@babel/plugin-transform-export-namespace-from": "^7.27.1",
+ "@babel/plugin-transform-for-of": "^7.27.1",
+ "@babel/plugin-transform-function-name": "^7.27.1",
+ "@babel/plugin-transform-json-strings": "^7.28.6",
+ "@babel/plugin-transform-literals": "^7.27.1",
+ "@babel/plugin-transform-logical-assignment-operators": "^7.28.6",
+ "@babel/plugin-transform-member-expression-literals": "^7.27.1",
+ "@babel/plugin-transform-modules-amd": "^7.27.1",
+ "@babel/plugin-transform-modules-commonjs": "^7.28.6",
+ "@babel/plugin-transform-modules-systemjs": "^7.29.4",
+ "@babel/plugin-transform-modules-umd": "^7.27.1",
+ "@babel/plugin-transform-named-capturing-groups-regex": "^7.29.0",
+ "@babel/plugin-transform-new-target": "^7.27.1",
+ "@babel/plugin-transform-nullish-coalescing-operator": "^7.28.6",
+ "@babel/plugin-transform-numeric-separator": "^7.28.6",
+ "@babel/plugin-transform-object-rest-spread": "^7.28.6",
+ "@babel/plugin-transform-object-super": "^7.27.1",
+ "@babel/plugin-transform-optional-catch-binding": "^7.28.6",
+ "@babel/plugin-transform-optional-chaining": "^7.28.6",
+ "@babel/plugin-transform-parameters": "^7.27.7",
+ "@babel/plugin-transform-private-methods": "^7.28.6",
+ "@babel/plugin-transform-private-property-in-object": "^7.28.6",
+ "@babel/plugin-transform-property-literals": "^7.27.1",
+ "@babel/plugin-transform-regenerator": "^7.29.0",
+ "@babel/plugin-transform-regexp-modifiers": "^7.28.6",
+ "@babel/plugin-transform-reserved-words": "^7.27.1",
+ "@babel/plugin-transform-shorthand-properties": "^7.27.1",
+ "@babel/plugin-transform-spread": "^7.28.6",
+ "@babel/plugin-transform-sticky-regex": "^7.27.1",
+ "@babel/plugin-transform-template-literals": "^7.27.1",
+ "@babel/plugin-transform-typeof-symbol": "^7.27.1",
+ "@babel/plugin-transform-unicode-escapes": "^7.27.1",
+ "@babel/plugin-transform-unicode-property-regex": "^7.28.6",
+ "@babel/plugin-transform-unicode-regex": "^7.27.1",
+ "@babel/plugin-transform-unicode-sets-regex": "^7.28.6",
+ "@babel/preset-modules": "0.1.6-no-external-plugins",
+ "babel-plugin-polyfill-corejs2": "^0.4.15",
+ "babel-plugin-polyfill-corejs3": "^0.14.0",
+ "babel-plugin-polyfill-regenerator": "^0.6.6",
+ "core-js-compat": "^3.48.0",
+ "semver": "^6.3.1"
},
"engines": {
"node": ">=6.9.0"
@@ -1576,164 +1654,86 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@babel/preset-env": {
- "version": "7.16.4",
- "resolved": "https://registry.npmjs.org/@babel/preset-env/-/preset-env-7.16.4.tgz",
- "integrity": "sha512-v0QtNd81v/xKj4gNKeuAerQ/azeNn/G1B1qMLeXOcV8+4TWlD2j3NV1u8q29SDFBXx/NBq5kyEAO+0mpRgacjA==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.16.4",
- "@babel/helper-compilation-targets": "^7.16.3",
- "@babel/helper-plugin-utils": "^7.14.5",
- "@babel/helper-validator-option": "^7.14.5",
- "@babel/plugin-bugfix-safari-id-destructuring-collision-in-function-expression": "^7.16.2",
- "@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining": "^7.16.0",
- "@babel/plugin-proposal-async-generator-functions": "^7.16.4",
- "@babel/plugin-proposal-class-properties": "^7.16.0",
- "@babel/plugin-proposal-class-static-block": "^7.16.0",
- "@babel/plugin-proposal-dynamic-import": "^7.16.0",
- "@babel/plugin-proposal-export-namespace-from": "^7.16.0",
- "@babel/plugin-proposal-json-strings": "^7.16.0",
- "@babel/plugin-proposal-logical-assignment-operators": "^7.16.0",
- "@babel/plugin-proposal-nullish-coalescing-operator": "^7.16.0",
- "@babel/plugin-proposal-numeric-separator": "^7.16.0",
- "@babel/plugin-proposal-object-rest-spread": "^7.16.0",
- "@babel/plugin-proposal-optional-catch-binding": "^7.16.0",
- "@babel/plugin-proposal-optional-chaining": "^7.16.0",
- "@babel/plugin-proposal-private-methods": "^7.16.0",
- "@babel/plugin-proposal-private-property-in-object": "^7.16.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.16.0",
- "@babel/plugin-syntax-async-generators": "^7.8.4",
- "@babel/plugin-syntax-class-properties": "^7.12.13",
- "@babel/plugin-syntax-class-static-block": "^7.14.5",
- "@babel/plugin-syntax-dynamic-import": "^7.8.3",
- "@babel/plugin-syntax-export-namespace-from": "^7.8.3",
- "@babel/plugin-syntax-json-strings": "^7.8.3",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.10.4",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.10.4",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-syntax-private-property-in-object": "^7.14.5",
- "@babel/plugin-syntax-top-level-await": "^7.14.5",
- "@babel/plugin-transform-arrow-functions": "^7.16.0",
- "@babel/plugin-transform-async-to-generator": "^7.16.0",
- "@babel/plugin-transform-block-scoped-functions": "^7.16.0",
- "@babel/plugin-transform-block-scoping": "^7.16.0",
- "@babel/plugin-transform-classes": "^7.16.0",
- "@babel/plugin-transform-computed-properties": "^7.16.0",
- "@babel/plugin-transform-destructuring": "^7.16.0",
- "@babel/plugin-transform-dotall-regex": "^7.16.0",
- "@babel/plugin-transform-duplicate-keys": "^7.16.0",
- "@babel/plugin-transform-exponentiation-operator": "^7.16.0",
- "@babel/plugin-transform-for-of": "^7.16.0",
- "@babel/plugin-transform-function-name": "^7.16.0",
- "@babel/plugin-transform-literals": "^7.16.0",
- "@babel/plugin-transform-member-expression-literals": "^7.16.0",
- "@babel/plugin-transform-modules-amd": "^7.16.0",
- "@babel/plugin-transform-modules-commonjs": "^7.16.0",
- "@babel/plugin-transform-modules-systemjs": "^7.16.0",
- "@babel/plugin-transform-modules-umd": "^7.16.0",
- "@babel/plugin-transform-named-capturing-groups-regex": "^7.16.0",
- "@babel/plugin-transform-new-target": "^7.16.0",
- "@babel/plugin-transform-object-super": "^7.16.0",
- "@babel/plugin-transform-parameters": "^7.16.3",
- "@babel/plugin-transform-property-literals": "^7.16.0",
- "@babel/plugin-transform-regenerator": "^7.16.0",
- "@babel/plugin-transform-reserved-words": "^7.16.0",
- "@babel/plugin-transform-shorthand-properties": "^7.16.0",
- "@babel/plugin-transform-spread": "^7.16.0",
- "@babel/plugin-transform-sticky-regex": "^7.16.0",
- "@babel/plugin-transform-template-literals": "^7.16.0",
- "@babel/plugin-transform-typeof-symbol": "^7.16.0",
- "@babel/plugin-transform-unicode-escapes": "^7.16.0",
- "@babel/plugin-transform-unicode-regex": "^7.16.0",
- "@babel/preset-modules": "^0.1.5",
- "@babel/types": "^7.16.0",
- "babel-plugin-polyfill-corejs2": "^0.3.0",
- "babel-plugin-polyfill-corejs3": "^0.4.0",
- "babel-plugin-polyfill-regenerator": "^0.3.0",
- "core-js-compat": "^3.19.1",
- "semver": "^6.3.0"
- },
- "engines": {
- "node": ">=6.9.0"
+ "node_modules/@babel/preset-env/node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.14.2",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.14.2.tgz",
+ "integrity": "sha512-coWpDLJ410R781Npmn/SIBZEsAetR4xVi0SxLMXPaMO4lSf1MwnkGYMtkFxew0Dn8B3/CpbpYxN0JCgg8mn67g==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-define-polyfill-provider": "^0.6.8",
+ "core-js-compat": "^3.48.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/@babel/preset-modules": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.5.tgz",
- "integrity": "sha512-A57th6YRG7oR3cq/yt/Y84MvGgE0eJG2F1JLhKuyG+jFxEgrd/HAMJatiFtmOiZurz+0DkrvbheCLaV5f2JfjA==",
+ "version": "0.1.6-no-external-plugins",
+ "resolved": "https://registry.npmjs.org/@babel/preset-modules/-/preset-modules-0.1.6-no-external-plugins.tgz",
+ "integrity": "sha512-HrcgcIESLm9aIR842yhJ5RWan/gebQUJ6E/E5+rf0y9o6oj7w0Br+sWuL6kEQ/o/AdfvR1Je9jG18/gnpwjEyA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/helper-plugin-utils": "^7.0.0",
- "@babel/plugin-proposal-unicode-property-regex": "^7.4.4",
- "@babel/plugin-transform-dotall-regex": "^7.4.4",
"@babel/types": "^7.4.4",
"esutils": "^2.0.2"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0-0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/@babel/runtime": {
- "version": "7.20.6",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.20.6.tgz",
- "integrity": "sha512-Q+8MqP7TiHMWzSfwiJwXCjyf4GYA4Dgw3emg/7xmwsdLJOZUp+nMqcOwOzzYheuM1rhDu8FSj2l0aoMygEuXuA==",
- "dependencies": {
- "regenerator-runtime": "^0.13.11"
- },
+ "version": "7.29.2",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.29.2.tgz",
+ "integrity": "sha512-JiDShH45zKHWyGe4ZNVRrCjBz8Nh9TMmZG1kh4QTK8hCBTWBi8Da+i7s1fJw7/lYpM4ccepSNfqzZ/QvABBi5g==",
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/template": {
- "version": "7.24.7",
- "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.24.7.tgz",
- "integrity": "sha512-jYqfPrU9JTF0PmPy1tLYHW4Mp4KlgxJD9l2nP9fD6yT/ICi554DmrWBAEYpIelzjHf1msDP3PxJIRt/nFNfBig==",
+ "version": "7.28.6",
+ "resolved": "https://registry.npmjs.org/@babel/template/-/template-7.28.6.tgz",
+ "integrity": "sha512-YA6Ma2KsCdGb+WC6UpBVFJGXL58MDA6oyONbjyF/+5sBgxY/dwkhLogbMT2GXXyU84/IhRw/2D1Os1B/giz+BQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.24.7",
- "@babel/parser": "^7.24.7",
- "@babel/types": "^7.24.7"
+ "@babel/code-frame": "^7.28.6",
+ "@babel/parser": "^7.28.6",
+ "@babel/types": "^7.28.6"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/traverse": {
- "version": "7.24.8",
- "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.24.8.tgz",
- "integrity": "sha512-t0P1xxAPzEDcEPmjprAQq19NWum4K0EQPjMwZQZbHt+GiZqvjCHjj755Weq1YRPVzBI+3zSfvScfpnuIecVFJQ==",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.24.7",
- "@babel/generator": "^7.24.8",
- "@babel/helper-environment-visitor": "^7.24.7",
- "@babel/helper-function-name": "^7.24.7",
- "@babel/helper-hoist-variables": "^7.24.7",
- "@babel/helper-split-export-declaration": "^7.24.7",
- "@babel/parser": "^7.24.8",
- "@babel/types": "^7.24.8",
- "debug": "^4.3.1",
- "globals": "^11.1.0"
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.29.0.tgz",
+ "integrity": "sha512-4HPiQr0X7+waHfyXPZpWPfWL/J7dcN1mx9gL6WdQVMbPnF3+ZhSMs8tCxN7oHddJE9fhNE7+lxdnlyemKfJRuA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@babel/code-frame": "^7.29.0",
+ "@babel/generator": "^7.29.0",
+ "@babel/helper-globals": "^7.28.0",
+ "@babel/parser": "^7.29.0",
+ "@babel/template": "^7.28.6",
+ "@babel/types": "^7.29.0",
+ "debug": "^4.3.1"
},
"engines": {
"node": ">=6.9.0"
}
},
"node_modules/@babel/types": {
- "version": "7.26.10",
- "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.26.10.tgz",
- "integrity": "sha512-emqcG3vHrpxUKTrxcblR36dcrcoRDvKmnL/dCL6ZsHaShW80qxCAcNhzQZrpeM765VzEos+xOi4s+r4IXzTwdQ==",
+ "version": "7.29.0",
+ "resolved": "https://registry.npmjs.org/@babel/types/-/types-7.29.0.tgz",
+ "integrity": "sha512-LwdZHpScM4Qz8Xw2iKSzS+cfglZzJGvofQICy7W7v4caru4EaAmyUuO6BGrbyQ2mYV11W0U8j5mBhd14dd3B0A==",
"license": "MIT",
"dependencies": {
- "@babel/helper-string-parser": "^7.25.9",
- "@babel/helper-validator-identifier": "^7.25.9"
+ "@babel/helper-string-parser": "^7.27.1",
+ "@babel/helper-validator-identifier": "^7.28.5"
},
"engines": {
"node": ">=6.9.0"
@@ -1743,6 +1743,7 @@
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/@choojs/findup/-/findup-0.2.1.tgz",
"integrity": "sha512-YstAqNb0MCN8PjdLCDfRsBcGVRN41f3vgLvaI0IrIcBp4AqILRSS0DeWNGkicC+f/zRIPJLc+9RURVSepwvfBw==",
+ "license": "MIT",
"dependencies": {
"commander": "^2.15.1"
},
@@ -1750,135 +1751,424 @@
"findup": "bin/findup.js"
}
},
- "node_modules/@guolao/vue-monaco-editor": {
- "version": "1.5.4",
- "resolved": "https://registry.npmjs.org/@guolao/vue-monaco-editor/-/vue-monaco-editor-1.5.4.tgz",
- "integrity": "sha512-eyBAqxJeDpV4mZYZSpNvh3xUgKCld5eEe0dBtjJhsy2+L0MB6PYFZ/FbPHNwskgp2RoIpfn1DLrIhXXE3lVbwQ==",
+ "node_modules/@choojs/findup/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "license": "MIT"
+ },
+ "node_modules/@discoveryjs/json-ext": {
+ "version": "0.5.7",
+ "resolved": "https://registry.npmjs.org/@discoveryjs/json-ext/-/json-ext-0.5.7.tgz",
+ "integrity": "sha512-dBVuXR082gk3jsFp7Rd/JI4kytwGHecnCoTtXFb7DB6CNHp4rg5k1bhg0nWdLGLnOV71lmDzGQaLMy8iPLY0pw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.0.0"
+ }
+ },
+ "node_modules/@eslint-community/eslint-utils": {
+ "version": "4.9.1",
+ "resolved": "https://registry.npmjs.org/@eslint-community/eslint-utils/-/eslint-utils-4.9.1.tgz",
+ "integrity": "sha512-phrYmNiYppR7znFEdqgfWHXR6NCkZEK7hwWDHZUjit/2/U0r6XvkDl0SYnoM51Hq7FhCGdLDT6zxCCOY1hexsQ==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "@monaco-editor/loader": "^1.4.0",
- "vue-demi": "latest"
+ "eslint-visitor-keys": "^3.4.3"
},
- "peerDependencies": {
- "@vue/composition-api": "^1.7.1",
- "monaco-editor": ">=0.43.0",
- "vue": "^2.6.14 || >=3.0.0"
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
},
- "peerDependenciesMeta": {
- "@vue/composition-api": {
- "optional": true
- }
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ },
+ "peerDependencies": {
+ "eslint": "^6.0.0 || ^7.0.0 || >=8.0.0"
}
},
- "node_modules/@hapi/address": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/@hapi/address/-/address-2.1.4.tgz",
- "integrity": "sha512-QD1PhQk+s31P1ixsX0H0Suoupp3VMXzIVMSwobR3F3MSUO2YCV0B7xqLcUw/Bh8yuvd3LhpyqLQWTNcRmp6IdQ==",
- "deprecated": "Moved to 'npm install @sideway/address'",
- "dev": true
- },
- "node_modules/@hapi/bourne": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@hapi/bourne/-/bourne-1.3.2.tgz",
- "integrity": "sha512-1dVNHT76Uu5N3eJNTYcvxee+jzX4Z9lfciqRRHCU27ihbUcYi+iSc2iml5Ke1LXe1SyJCLA0+14Jh4tXJgOppA==",
- "deprecated": "This version has been deprecated and is no longer supported or maintained",
- "dev": true
+ "node_modules/@eslint-community/eslint-utils/node_modules/eslint-visitor-keys": {
+ "version": "3.4.3",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-3.4.3.tgz",
+ "integrity": "sha512-wpc+LXeiyiisxPlEkUzU6svyS1frIO3Mgxj1fdy7Pm8Ygzguax2N3Fa/D/ag1WqbOprdI+uY6wMUl8/a2G+iag==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^12.22.0 || ^14.17.0 || >=16.0.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
},
- "node_modules/@hapi/hoek": {
- "version": "8.5.1",
- "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-8.5.1.tgz",
- "integrity": "sha512-yN7kbciD87WzLGc5539Tn0sApjyiGHAJgKvG9W8C7O+6c7qmoQMfVs0W4bX17eqz6C78QJqqFrtgdK5EWf6Qow==",
- "deprecated": "This version has been deprecated and is no longer supported or maintained",
- "dev": true
+ "node_modules/@eslint-community/regexpp": {
+ "version": "4.12.2",
+ "resolved": "https://registry.npmjs.org/@eslint-community/regexpp/-/regexpp-4.12.2.tgz",
+ "integrity": "sha512-EriSTlt5OC9/7SXkRSCAhfSxxoSUgBm33OH+IkwbdpgoqsSsUg7y3uh+IICI/Qg4BBWr3U2i39RpmycbxMq4ew==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": "^12.0.0 || ^14.0.0 || >=16.0.0"
+ }
},
- "node_modules/@hapi/joi": {
- "version": "15.1.1",
- "resolved": "https://registry.npmjs.org/@hapi/joi/-/joi-15.1.1.tgz",
- "integrity": "sha512-entf8ZMOK8sc+8YfeOlM8pCfg3b5+WZIKBfUaaJT8UsjAAPjartzxIYm3TIbjvA4u+u++KbcXD38k682nVHDAQ==",
- "deprecated": "Switch to 'npm install joi'",
+ "node_modules/@eslint/config-array": {
+ "version": "0.21.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-array/-/config-array-0.21.2.tgz",
+ "integrity": "sha512-nJl2KGTlrf9GjLimgIru+V/mzgSK0ABCDQRvxw5BjURL7WfH5uoWmizbH7QB6MmnMBd8cIC9uceWnezL1VZWWw==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@hapi/address": "2.x.x",
- "@hapi/bourne": "1.x.x",
- "@hapi/hoek": "8.x.x",
- "@hapi/topo": "3.x.x"
+ "@eslint/object-schema": "^2.1.7",
+ "debug": "^4.3.1",
+ "minimatch": "^3.1.5"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@hapi/topo": {
- "version": "3.1.6",
- "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-3.1.6.tgz",
- "integrity": "sha512-tAag0jEcjwH+P2quUfipd7liWCNX2F8NvYjQp2wtInsZxnMlypdw0FtAOLxtvvkO+GSRRbmNi8m/5y42PQJYCQ==",
- "deprecated": "This version has been deprecated and is no longer supported or maintained",
+ "node_modules/@eslint/config-helpers": {
+ "version": "0.4.2",
+ "resolved": "https://registry.npmjs.org/@eslint/config-helpers/-/config-helpers-0.4.2.tgz",
+ "integrity": "sha512-gBrxN88gOIf3R7ja5K9slwNayVcZgK6SOUORm2uBzTeIEfeVaIhOpCtTox3P6R7o2jLFwLFTLnC7kU/RGcYEgw==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@hapi/hoek": "^8.3.0"
+ "@eslint/core": "^0.17.0"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@intervolga/optimize-cssnano-plugin": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/@intervolga/optimize-cssnano-plugin/-/optimize-cssnano-plugin-1.0.6.tgz",
- "integrity": "sha512-zN69TnSr0viRSU6cEDIcuPcP67QcpQ6uHACg58FiN9PDrU6SLyGW3MR4tiISbYxy1kDWAVPwD+XwQTWE5cigAA==",
+ "node_modules/@eslint/core": {
+ "version": "0.17.0",
+ "resolved": "https://registry.npmjs.org/@eslint/core/-/core-0.17.0.tgz",
+ "integrity": "sha512-yL/sLrpmtDaFEiUj1osRP4TI2MDz1AddJL+jZ7KSqvBuliN4xqYY54IfdN8qD8Toa6g1iloph1fxQNkjOxrrpQ==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "cssnano": "^4.0.0",
- "cssnano-preset-default": "^4.0.0",
- "postcss": "^7.0.0"
+ "@types/json-schema": "^7.0.15"
},
- "peerDependencies": {
- "webpack": "^4.0.0"
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@jridgewell/gen-mapping": {
- "version": "0.3.5",
- "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.5.tgz",
- "integrity": "sha512-IzL8ZoEDIBRWEzlCcRhOaCupYyN5gdIK+Q6fbFdPDg6HqX6jpkItn7DFIpW9LQzXG6Df9sA7+OKnq0qlz/GaQg==",
+ "node_modules/@eslint/eslintrc": {
+ "version": "3.3.5",
+ "resolved": "https://registry.npmjs.org/@eslint/eslintrc/-/eslintrc-3.3.5.tgz",
+ "integrity": "sha512-4IlJx0X0qftVsN5E+/vGujTRIFtwuLbNsVUe7TO6zYPDR1O6nFwvwhIKEKSrl6dZchmYBITazxKoUYOjdtjlRg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@jridgewell/set-array": "^1.2.1",
- "@jridgewell/sourcemap-codec": "^1.4.10",
- "@jridgewell/trace-mapping": "^0.3.24"
+ "ajv": "^6.14.0",
+ "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.1",
+ "minimatch": "^3.1.5",
+ "strip-json-comments": "^3.1.1"
},
"engines": {
- "node": ">=6.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "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==",
+ "node_modules/@eslint/eslintrc/node_modules/globals": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-14.0.0.tgz",
+ "integrity": "sha512-oahGvuMGQlPw/ivIYBjVSrWAfWLBeku5tpPE2fOPLi+WHffIWbuh2tCjhyQhTBPMf5E9jDEH4FOmTYgYwbKwtQ==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=6.0.0"
+ "node": ">=18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "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==",
+ "node_modules/@eslint/js": {
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/@eslint/js/-/js-9.39.4.tgz",
+ "integrity": "sha512-nE7DEIchvtiFTwBw4Lfbu59PG+kCofhjsKaCWzxTpt4lfRjRMqG6uMBzKXuEcyXhOHoUp9riAm7/aWYGhXZ9cw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=6.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://eslint.org/donate"
}
},
- "node_modules/@jridgewell/sourcemap-codec": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.0.tgz",
- "integrity": "sha512-gv3ZRaISU3fjPAgNsriBRqGWQL6quFx04YMPW/zD8XMLsU32mhCCbfbO6KZFLjvYpCZ8zyDEgqsgf+PwPaM7GQ==",
- "dev": true
+ "node_modules/@eslint/object-schema": {
+ "version": "2.1.7",
+ "resolved": "https://registry.npmjs.org/@eslint/object-schema/-/object-schema-2.1.7.tgz",
+ "integrity": "sha512-VtAOaymWVfZcmZbp6E2mympDIHvyjXs/12LqWYjVw6qjrfF+VK+fyG33kChz3nnK+SU5/NeHOqrTEHS8sXO3OA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ }
},
- "node_modules/@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==",
+ "node_modules/@eslint/plugin-kit": {
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/@eslint/plugin-kit/-/plugin-kit-0.4.1.tgz",
+ "integrity": "sha512-43/qtrDUokr7LJqoF2c3+RInu/t4zfrpYdoSDfYyhg52rwLV6TnOvdG4fXm7IkSB3wErkcmJS9iEhjVtOSEjjA==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "@jridgewell/resolve-uri": "^3.1.0",
- "@jridgewell/sourcemap-codec": "^1.4.14"
+ "@eslint/core": "^0.17.0",
+ "levn": "^0.4.1"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
}
},
- "node_modules/@mapbox/geojson-rewind": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz",
+ "node_modules/@guolao/vue-monaco-editor": {
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/@guolao/vue-monaco-editor/-/vue-monaco-editor-1.6.0.tgz",
+ "integrity": "sha512-w2IiJ6eJGGeuIgCK6EKZOAfhHTTUB5aZwslzwGbZ5e89Hb4avx6++GkLTW8p84Sng/arFMjLPPxSBI56cFudyQ==",
+ "license": "MIT",
+ "dependencies": {
+ "@monaco-editor/loader": "^1.6.1",
+ "vue-demi": "latest"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.7.2",
+ "monaco-editor": ">=0.43.0",
+ "vue": "^2.6.14 || >=3.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@guolao/vue-monaco-editor/node_modules/vue-demi": {
+ "version": "0.14.10",
+ "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
+ "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
+ "hasInstallScript": true,
+ "license": "MIT",
+ "bin": {
+ "vue-demi-fix": "bin/vue-demi-fix.js",
+ "vue-demi-switch": "bin/vue-demi-switch.js"
+ },
+ "engines": {
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antfu"
+ },
+ "peerDependencies": {
+ "@vue/composition-api": "^1.0.0-rc.1",
+ "vue": "^3.0.0-0 || ^2.6.0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/composition-api": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/@hapi/hoek": {
+ "version": "9.3.0",
+ "resolved": "https://registry.npmjs.org/@hapi/hoek/-/hoek-9.3.0.tgz",
+ "integrity": "sha512-/c6rf4UJlmHlC9b5BaNvzAcFv7HZ2QHaV0D4/HNlBdvFnvQq8RI4kYdhyPCl7Xj+oWvTWQ8ujhqS53LIgAe6KQ==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@hapi/topo": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/@hapi/topo/-/topo-5.1.0.tgz",
+ "integrity": "sha512-foQZKJig7Ob0BMAYBfcJk8d77QtOe7Wo4ox7ff1lQYoNNAb6jwcY1ncdoy2e9wQZzvNy7ODZCYJkK8kzmcAnAg==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.0.0"
+ }
+ },
+ "node_modules/@humanfs/core": {
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/@humanfs/core/-/core-0.19.2.tgz",
+ "integrity": "sha512-UhXNm+CFMWcbChXywFwkmhqjs3PRCmcSa/hfBgLIb7oQ5HNb1wS0icWsGtSAUNgefHeI+eBrA8I1fxmbHsGdvA==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/types": "^0.15.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/node": {
+ "version": "0.16.8",
+ "resolved": "https://registry.npmjs.org/@humanfs/node/-/node-0.16.8.tgz",
+ "integrity": "sha512-gE1eQNZ3R++kTzFUpdGlpmy8kDZD/MLyHqDwqjkVQI0JMdI1D51sy1H958PNXYkM2rAac7e5/CnIKZrHtPh3BQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "dependencies": {
+ "@humanfs/core": "^0.19.2",
+ "@humanfs/types": "^0.15.0",
+ "@humanwhocodes/retry": "^0.4.0"
+ },
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "node_modules/@humanfs/types": {
+ "version": "0.15.0",
+ "resolved": "https://registry.npmjs.org/@humanfs/types/-/types-0.15.0.tgz",
+ "integrity": "sha512-ZZ1w0aoQkwuUuC7Yf+7sdeaNfqQiiLcSRbfI08oAxqLtpXQr9AIVX7Ay7HLDuiLYAaFPu8oBYNq/QIi9URHJ3Q==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18.0"
+ }
+ },
+ "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,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12.22"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@humanwhocodes/retry": {
+ "version": "0.4.3",
+ "resolved": "https://registry.npmjs.org/@humanwhocodes/retry/-/retry-0.4.3.tgz",
+ "integrity": "sha512-bV0Tgo9K4hfPCek+aMAn81RppFKv2ySDQeMoSZuvTASywNTnVJCArCZE2FWqpvIatKu7VMRLWlR1EazvVhDyhQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=18.18"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/nzakas"
+ }
+ },
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@sinclair/typebox": "^0.27.8"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.3.tgz",
+ "integrity": "sha512-u3UPsIilWKOM3F9CXtrG8LEJmNxwoCQC/XVj4IKYXvvpx7QIi/Kg1LI5uDmDpKlac62NUtX7eLjRh+jVZcLOzw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/schemas": "^29.6.3",
+ "@types/istanbul-lib-coverage": "^2.0.0",
+ "@types/istanbul-reports": "^3.0.0",
+ "@types/node": "*",
+ "@types/yargs": "^17.0.8",
+ "chalk": "^4.0.0"
+ },
+ "engines": {
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ }
+ },
+ "node_modules/@jest/types/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/@jridgewell/gen-mapping": {
+ "version": "0.3.13",
+ "resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.13.tgz",
+ "integrity": "sha512-2kkt/7niJ6MgEPxF0bYdQ6etZaA+fQvDcLKckhy1yIQOzaoKjBBjSj63/aLVjYE3qhRt5dvM+uUyfCg6UKCBbA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.0",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "node_modules/@jridgewell/remapping": {
+ "version": "2.3.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/remapping/-/remapping-2.3.5.tgz",
+ "integrity": "sha512-LI9u/+laYG4Ds1TDKSJW2YPrIlcVYOwi2fUC6xB43lueCjgxV4lffOCZCtYFiH6TNOX+tQKXx97T4IKHbhyHEQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.24"
+ }
+ },
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=6.0.0"
+ }
+ },
+ "node_modules/@jridgewell/source-map": {
+ "version": "0.3.11",
+ "resolved": "https://registry.npmjs.org/@jridgewell/source-map/-/source-map-0.3.11.tgz",
+ "integrity": "sha512-ZMp1V8ZFcPG5dIWnQLr3NSI1MiCU7UETdS/A0G8V/XWHvJv3ZsFqutJn1Y5RPmAPX6F3BiE397OqveU/9NCuIA==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/gen-mapping": "^0.3.5",
+ "@jridgewell/trace-mapping": "^0.3.25"
+ }
+ },
+ "node_modules/@jridgewell/sourcemap-codec": {
+ "version": "1.5.5",
+ "resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.5.5.tgz",
+ "integrity": "sha512-cYQ9310grqxueWbl+WuIUIaiUaDcj7WOq5fVhEljNVgRfOUhY9fy2zTvfoqWsnebh8Sl70VScFbICvJnLKB0Og==",
+ "license": "MIT"
+ },
+ "node_modules/@jridgewell/trace-mapping": {
+ "version": "0.3.31",
+ "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz",
+ "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==",
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/resolve-uri": "^3.1.0",
+ "@jridgewell/sourcemap-codec": "^1.4.14"
+ }
+ },
+ "node_modules/@leichtgewicht/ip-codec": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@leichtgewicht/ip-codec/-/ip-codec-2.0.5.tgz",
+ "integrity": "sha512-Vo+PSpZG2/fmgmiNzYK9qWRh8h/CHrwD0mo1h1DzL4yzHNSfWYujGTYsWGreD000gcgmZ7K4Ys6Tx9TxtsKdDw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@mapbox/geojson-rewind": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/@mapbox/geojson-rewind/-/geojson-rewind-0.5.2.tgz",
"integrity": "sha512-tJaT+RbYGJYStt7wI3cq4Nl4SXxG8W7JDG5DMJu97V25RnbNg3QtQtf+KD+VLjNpWKYsRvXDNmNrBgEETr1ifA==",
+ "license": "ISC",
"dependencies": {
"get-stream": "^6.0.1",
"minimist": "^1.2.6"
@@ -1891,6 +2181,7 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
"integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "license": "MIT",
"engines": {
"node": ">=10"
},
@@ -1901,7 +2192,8 @@
"node_modules/@mapbox/geojson-types": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/@mapbox/geojson-types/-/geojson-types-1.0.2.tgz",
- "integrity": "sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw=="
+ "integrity": "sha512-e9EBqHHv3EORHrSfbR9DqecPNn+AmuAoQxV6aL8Xu30bJMJR1o8PZLZzpk1Wq7/NfCbuhmakHTPYRhoqLsXRnw==",
+ "license": "ISC"
},
"node_modules/@mapbox/jsonlint-lines-primitives": {
"version": "2.0.2",
@@ -1915,6 +2207,7 @@
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/@mapbox/mapbox-gl-supported/-/mapbox-gl-supported-1.5.0.tgz",
"integrity": "sha512-/PT1P6DNf7vjEEiPkVIRJkvibbqWtqnyGaBz3nfRdcxclNSnSdaLU5tfAgcD7I8Yt5i+L19s406YLl1koLnLbg==",
+ "license": "BSD-3-Clause",
"peerDependencies": {
"mapbox-gl": ">=0.32.1 <2.0.0"
}
@@ -1922,22 +2215,26 @@
"node_modules/@mapbox/point-geometry": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
- "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ=="
+ "integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ==",
+ "license": "ISC"
},
"node_modules/@mapbox/tiny-sdf": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-1.2.5.tgz",
- "integrity": "sha512-cD8A/zJlm6fdJOk6DqPUV8mcpyJkRz2x2R+/fYcWDYG3oWbG7/L7Yl/WqQ1VZCjnL9OTIMAn6c+BC5Eru4sQEw=="
+ "integrity": "sha512-cD8A/zJlm6fdJOk6DqPUV8mcpyJkRz2x2R+/fYcWDYG3oWbG7/L7Yl/WqQ1VZCjnL9OTIMAn6c+BC5Eru4sQEw==",
+ "license": "BSD-2-Clause"
},
"node_modules/@mapbox/unitbezier": {
"version": "0.0.0",
"resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.0.tgz",
- "integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA=="
+ "integrity": "sha512-HPnRdYO0WjFjRTSwO3frz1wKaU649OBFPX3Zo/2WZvuRi6zMiRGui8SnPQiQABgqCf8YikDe5t3HViTVw1WUzA==",
+ "license": "BSD-2-Clause"
},
"node_modules/@mapbox/vector-tile": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/@mapbox/vector-tile/-/vector-tile-1.3.1.tgz",
"integrity": "sha512-MCEddb8u44/xfQ3oD+Srl/tNcQoqTw3goGk2oLsrFxOTc3dUp+kAnby3PvAeeBYSMSjSPD1nd1AJA6W49WnoUw==",
+ "license": "BSD-3-Clause",
"dependencies": {
"@mapbox/point-geometry": "~0.1.0"
}
@@ -1946,39 +2243,80 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@mapbox/whoots-js/-/whoots-js-3.1.0.tgz",
"integrity": "sha512-Es6WcD0nO5l+2BOQS4uLfNPYQaNDfbot3X1XUoloz+x0mPDS3eeORZJl06HXjwBG1fOGwCRnzK88LMdxKRrd6Q==",
+ "license": "ISC",
"engines": {
"node": ">=6.0.0"
}
},
+ "node_modules/@maplibre/maplibre-gl-style-spec": {
+ "version": "20.4.0",
+ "resolved": "https://registry.npmjs.org/@maplibre/maplibre-gl-style-spec/-/maplibre-gl-style-spec-20.4.0.tgz",
+ "integrity": "sha512-AzBy3095fTFPjDjmWpR2w6HVRAZJ6hQZUCwk5Plz6EyfnfuQW1odeW5i2Ai47Y6TBA2hQnC+azscjBSALpaWgw==",
+ "license": "ISC",
+ "dependencies": {
+ "@mapbox/jsonlint-lines-primitives": "~2.0.2",
+ "@mapbox/unitbezier": "^0.0.1",
+ "json-stringify-pretty-compact": "^4.0.0",
+ "minimist": "^1.2.8",
+ "quickselect": "^2.0.0",
+ "rw": "^1.3.3",
+ "tinyqueue": "^3.0.0"
+ },
+ "bin": {
+ "gl-style-format": "dist/gl-style-format.mjs",
+ "gl-style-migrate": "dist/gl-style-migrate.mjs",
+ "gl-style-validate": "dist/gl-style-validate.mjs"
+ }
+ },
+ "node_modules/@maplibre/maplibre-gl-style-spec/node_modules/@mapbox/unitbezier": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz",
+ "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/@maplibre/maplibre-gl-style-spec/node_modules/tinyqueue": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz",
+ "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==",
+ "license": "ISC"
+ },
"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==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.7.0.tgz",
+ "integrity": "sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA==",
+ "license": "MIT",
"dependencies": {
"state-local": "^1.0.6"
- },
- "peerDependencies": {
- "monaco-editor": ">= 0.21.0 < 1"
}
},
- "node_modules/@mrmlnc/readdir-enhanced": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/@mrmlnc/readdir-enhanced/-/readdir-enhanced-2.2.1.tgz",
- "integrity": "sha512-bPHp6Ji8b41szTOcaP63VlnbbO5Ny6dwAATtY6JTjh5N2OLrb5Qk/Th5cRkRQhkWCt+EJsYrNB0MiL+Gpn6e3g==",
+ "node_modules/@nicolo-ribaudo/eslint-scope-5-internals": {
+ "version": "5.1.1-v1",
+ "resolved": "https://registry.npmjs.org/@nicolo-ribaudo/eslint-scope-5-internals/-/eslint-scope-5-internals-5.1.1-v1.tgz",
+ "integrity": "sha512-54/JRvkLIzzDWshCWfuhadfrfZVPiElY8Fcgmg1HroEly/EDSszzhBAsarCux+D/kOslTRquNzuyGSmUSTTHGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "eslint-scope": "5.1.1"
+ }
+ },
+ "node_modules/@node-ipc/js-queue": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/@node-ipc/js-queue/-/js-queue-2.0.3.tgz",
+ "integrity": "sha512-fL1wpr8hhD5gT2dA1qifeVaoDFlQR5es8tFuKqjHX+kdOtdNHnxkVZbtIrR2rxnMFvehkjaZRNV2H/gPXlb0hw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-me-maybe": "^1.0.1",
- "glob-to-regexp": "^0.3.0"
+ "easy-stack": "1.0.1"
},
"engines": {
- "node": ">=4"
+ "node": ">=1.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,
+ "license": "MIT",
"dependencies": {
"@nodelib/fs.stat": "2.0.5",
"run-parallel": "^1.1.9"
@@ -1991,7 +2329,7 @@
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-2.0.5.tgz",
"integrity": "sha512-RkhPPp2zrqDAQA/2jNhnztcPAlv64XdhIp7a7454A5ovI7Bukxgt7MX7udwAu3zg1DcpPU0rz3VV1SeaqvY4+A==",
- "dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 8"
}
@@ -2000,7 +2338,7 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/@nodelib/fs.walk/-/fs.walk-1.2.8.tgz",
"integrity": "sha512-oGB+UxlgWcgQkgwo8GcEGwemoTFt3FIO9ababBmaGwXIoBKZ+GTy0pP185beGg7Llih/NSHSV2XAs1lnznocSg==",
- "dev": true,
+ "license": "MIT",
"dependencies": {
"@nodelib/fs.scandir": "2.1.5",
"fastq": "^1.6.0"
@@ -2010,14 +2348,16 @@
}
},
"node_modules/@plotly/d3": {
- "version": "3.8.1",
- "resolved": "https://registry.npmjs.org/@plotly/d3/-/d3-3.8.1.tgz",
- "integrity": "sha512-x49ThEu1FRA00kTso4Jdfyf2byaCPLBGmLjAYQz5OzaPyLUhHesX3/Nfv2OHEhynhdy2UB39DLXq6thYe2L2kg=="
+ "version": "3.8.2",
+ "resolved": "https://registry.npmjs.org/@plotly/d3/-/d3-3.8.2.tgz",
+ "integrity": "sha512-wvsNmh1GYjyJfyEBPKJLTMzgf2c2bEbSIL50lmqVUi+o1NHaLPi1Lb4v7VxXXJn043BhNyrxUrWI85Q+zmjOVA==",
+ "license": "BSD-3-Clause"
},
"node_modules/@plotly/d3-sankey": {
"version": "0.7.2",
"resolved": "https://registry.npmjs.org/@plotly/d3-sankey/-/d3-sankey-0.7.2.tgz",
"integrity": "sha512-2jdVos1N3mMp3QW0k2q1ph7Gd6j5PY1YihBrwpkFnKqO+cqtZq3AdEYUeSGXMeLsBDQYiqTVcihYfk8vr5tqhw==",
+ "license": "BSD-3-Clause",
"dependencies": {
"d3-array": "1",
"d3-collection": "1",
@@ -2028,6 +2368,7 @@
"version": "0.33.1",
"resolved": "https://registry.npmjs.org/@plotly/d3-sankey-circular/-/d3-sankey-circular-0.33.1.tgz",
"integrity": "sha512-FgBV1HEvCr3DV7RHhDsPXyryknucxtfnLwPtCKKxdolKyTFYoLX/ibEfX39iFYIL7DYbVeRtP43dbFcrHNE+KQ==",
+ "license": "MIT",
"dependencies": {
"d3-array": "^1.2.1",
"d3-collection": "^1.0.4",
@@ -2035,10 +2376,44 @@
"elementary-circuits-directed-graph": "^1.0.4"
}
},
+ "node_modules/@plotly/mapbox-gl": {
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/@plotly/mapbox-gl/-/mapbox-gl-1.13.4.tgz",
+ "integrity": "sha512-sR3/Pe5LqT/fhYgp4rT4aSFf1rTsxMbGiH6Hojc7PH36ny5Bn17iVFUjpzycafETURuFbLZUfjODO8LvSI+5zQ==",
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "dependencies": {
+ "@mapbox/geojson-rewind": "^0.5.2",
+ "@mapbox/geojson-types": "^1.0.2",
+ "@mapbox/jsonlint-lines-primitives": "^2.0.2",
+ "@mapbox/mapbox-gl-supported": "^1.5.0",
+ "@mapbox/point-geometry": "^0.1.0",
+ "@mapbox/tiny-sdf": "^1.1.1",
+ "@mapbox/unitbezier": "^0.0.0",
+ "@mapbox/vector-tile": "^1.3.1",
+ "@mapbox/whoots-js": "^3.1.0",
+ "csscolorparser": "~1.0.3",
+ "earcut": "^2.2.2",
+ "geojson-vt": "^3.2.1",
+ "gl-matrix": "^3.2.1",
+ "grid-index": "^1.1.0",
+ "murmurhash-js": "^1.0.0",
+ "pbf": "^3.2.1",
+ "potpack": "^1.0.1",
+ "quickselect": "^2.0.0",
+ "rw": "^1.3.3",
+ "supercluster": "^7.1.0",
+ "tinyqueue": "^2.0.3",
+ "vt-pbf": "^3.1.1"
+ },
+ "engines": {
+ "node": ">=6.4.0"
+ }
+ },
"node_modules/@plotly/point-cluster": {
"version": "3.1.9",
"resolved": "https://registry.npmjs.org/@plotly/point-cluster/-/point-cluster-3.1.9.tgz",
"integrity": "sha512-MwaI6g9scKf68Orpr1pHZ597pYx9uP8UEFXLPbsCmuw3a84obwz6pnMXGc90VhgDNeNiLEdlmuK7CPo+5PIxXw==",
+ "license": "MIT",
"dependencies": {
"array-bounds": "^1.0.1",
"binary-search-bounds": "^2.0.4",
@@ -2052,11 +2427,50 @@
"pick-by-alias": "^1.2.0"
}
},
+ "node_modules/@polka/url": {
+ "version": "1.0.0-next.29",
+ "resolved": "https://registry.npmjs.org/@polka/url/-/url-1.0.0-next.29.tgz",
+ "integrity": "sha512-wwQAWhWSuHaag8c4q/KN/vCoeOJYshAIvMQwD4GpSb3OiZklFfvAgmj0VCBBImRpuF/aFgIRzllXlVX93Jevww==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@sideway/address": {
+ "version": "4.1.5",
+ "resolved": "https://registry.npmjs.org/@sideway/address/-/address-4.1.5.tgz",
+ "integrity": "sha512-IqO/DUQHUkPeixNQ8n0JA6102hT9CmaljNTPmQ1u8MEhBo/R4Q8eKLN/vGZxuebwOroDB4cbpjheD4+/sKFK4Q==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.0.0"
+ }
+ },
+ "node_modules/@sideway/formula": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/@sideway/formula/-/formula-3.0.1.tgz",
+ "integrity": "sha512-/poHZJJVjx3L+zVD6g9KgHfYnb443oi7wLu/XKojDviHy6HOEOA6z1Trk5aR1dGcmPenJEgb2sK2I80LeS3MIg==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@sideway/pinpoint": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/@sideway/pinpoint/-/pinpoint-2.0.0.tgz",
+ "integrity": "sha512-RNiOoTPkptFtSVzQevY/yWtZwf/RxyVnPy/OcA9HBM3MlGDnBEYL5B41H0MTn0Uec8Hi+2qUtTfG2WWZBmMejQ==",
+ "dev": true,
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/@sinclair/typebox": {
+ "version": "0.27.10",
+ "resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.10.tgz",
+ "integrity": "sha512-MTBk/3jGLNB2tVxv6uLlFh1iu64iYOQ2PbdOSK3NW8JZsmlaOh2q6sdtKowBhfw8QFLmYNzTW4/oK4uATIi6ZA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@soda/friendly-errors-webpack-plugin": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/@soda/friendly-errors-webpack-plugin/-/friendly-errors-webpack-plugin-1.8.1.tgz",
"integrity": "sha512-h2ooWqP8XuFqTXT+NyAFbrArzfQA7R6HTezADrvD9Re8fxMLTPPniLdqVTdDaO0eIoLaAwKT+d6w+5GeTk7Vbg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"chalk": "^3.0.0",
"error-stack-parser": "^2.0.6",
@@ -2070,377 +2484,483 @@
"webpack": "^4.0.0 || ^5.0.0"
}
},
- "node_modules/@soda/friendly-errors-webpack-plugin/node_modules/chalk": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
- "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
+ "node_modules/@soda/get-current-script": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/@soda/get-current-script/-/get-current-script-1.0.2.tgz",
+ "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==",
"dev": true,
- "dependencies": {
- "ansi-styles": "^4.1.0",
- "supports-color": "^7.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@soda/get-current-script": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@soda/get-current-script/-/get-current-script-1.0.2.tgz",
- "integrity": "sha512-T7VNNlYVM1SgQ+VsMYhnDkcGmWhQdL0bDyGm5TlQ3GBXnJscEClUUOKduWTmm2zCnvNLC1hc3JpuXjs/nFOc5w==",
- "dev": true
- },
- "node_modules/@tailwindcss/forms": {
- "version": "0.3.4",
- "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.3.4.tgz",
- "integrity": "sha512-vlAoBifNJUkagB+PAdW4aHMe4pKmSLroH398UPgIogBFc91D2VlHUxe4pjxQhiJl0Nfw53sHSJSQBSTQBZP3vA==",
+ "license": "MIT"
+ },
+ "node_modules/@tailwindcss/forms": {
+ "version": "0.5.11",
+ "resolved": "https://registry.npmjs.org/@tailwindcss/forms/-/forms-0.5.11.tgz",
+ "integrity": "sha512-h9wegbZDPurxG22xZSoWtdzc41/OlNEUQERNqI/0fOwa2aVlWGu7C35E/x6LDyD3lgtztFSSjKZyuVM0hxhbgA==",
+ "license": "MIT",
"dependencies": {
"mini-svg-data-uri": "^1.2.3"
},
"peerDependencies": {
- "tailwindcss": ">=2.0.0"
- }
- },
- "node_modules/@tailwindcss/postcss7-compat": {
- "version": "2.2.17",
- "resolved": "https://registry.npmjs.org/@tailwindcss/postcss7-compat/-/postcss7-compat-2.2.17.tgz",
- "integrity": "sha512-3h2svqQAqYHxRZ1KjsJjZOVTQ04m29LjfrLjXyZZEJuvUuJN+BCIF9GI8vhE1s0plS0mogd6E6YLg6mu4Wv/Vw==",
- "dev": true,
- "dependencies": {
- "arg": "^5.0.1",
- "autoprefixer": "^9",
- "bytes": "^3.0.0",
- "chalk": "^4.1.2",
- "chokidar": "^3.5.2",
- "color": "^4.0.1",
- "cosmiconfig": "^7.0.1",
- "detective": "^5.2.0",
- "didyoumean": "^1.2.2",
- "dlv": "^1.1.3",
- "fast-glob": "^3.2.7",
- "fs-extra": "^10.0.0",
- "glob-parent": "^6.0.1",
- "html-tags": "^3.1.0",
- "is-color-stop": "^1.1.0",
- "is-glob": "^4.0.1",
- "lodash": "^4.17.21",
- "lodash.topath": "^4.5.2",
- "modern-normalize": "^1.1.0",
- "node-emoji": "^1.11.0",
- "normalize-path": "^3.0.0",
- "object-hash": "^2.2.0",
- "postcss": "^7",
- "postcss-functions": "^3",
- "postcss-js": "^2",
- "postcss-load-config": "^3.1.0",
- "postcss-nested": "^4",
- "postcss-selector-parser": "^6.0.6",
- "postcss-value-parser": "^4.1.0",
- "pretty-hrtime": "^1.0.3",
- "purgecss": "^4.0.3",
- "quick-lru": "^5.1.1",
- "reduce-css-calc": "^2.1.8",
- "resolve": "^1.20.0",
- "tmp": "^0.2.1"
- },
- "bin": {
- "tailwind": "lib/cli.js",
- "tailwindcss": "lib/cli.js"
- },
- "engines": {
- "node": ">=12.13.0"
+ "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1"
}
},
"node_modules/@turf/area": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/@turf/area/-/area-6.5.0.tgz",
- "integrity": "sha512-xCZdiuojokLbQ+29qR6qoMD89hv+JAgWjLrwSEWL+3JV8IXKeNFl6XkEJz9HGkVpnXvQKJoRz4/liT+8ZZ5Jyg==",
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/@turf/area/-/area-7.3.5.tgz",
+ "integrity": "sha512-sSn80wPT7XfBIDN3vurCPxhk9W4U8ozS/XImSqeLN8qveTICOxzZkhsGDMp0CuncaN+plWut4a2TdNM7mzZB6Q==",
+ "license": "MIT",
"dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
+ "@turf/helpers": "7.3.5",
+ "@turf/meta": "7.3.5",
+ "@types/geojson": "^7946.0.10",
+ "tslib": "^2.8.1"
},
"funding": {
"url": "https://opencollective.com/turf"
}
},
"node_modules/@turf/bbox": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-6.5.0.tgz",
- "integrity": "sha512-RBbLaao5hXTYyyg577iuMtDB8ehxMlUqHEJiMs8jT1GHkFhr6sYre3lmLsPeYEi/ZKj5TP5tt7fkzNdJ4GIVyw==",
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/@turf/bbox/-/bbox-7.3.5.tgz",
+ "integrity": "sha512-oG1ya/HtBjAIg4TimbWx+nOYPbY0bCvt82Bq8tm6sBw3qqtbOyRSfDz79Sq90TnH7DXJprJ1qnVGKNtZ6jemfw==",
+ "license": "MIT",
"dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
+ "@turf/helpers": "7.3.5",
+ "@turf/meta": "7.3.5",
+ "@types/geojson": "^7946.0.10",
+ "tslib": "^2.8.1"
},
"funding": {
"url": "https://opencollective.com/turf"
}
},
"node_modules/@turf/centroid": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-6.5.0.tgz",
- "integrity": "sha512-MwE1oq5E3isewPprEClbfU5pXljIK/GUOMbn22UM3IFPDJX0KeoyLNwghszkdmFp/qMGL/M13MMWvU+GNLXP/A==",
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/@turf/centroid/-/centroid-7.3.5.tgz",
+ "integrity": "sha512-hkWaqwGFdOn6Tf0EWfn2yn1XZ1FWE1h2C5ZWstDMu/FxYO5DB+YjlmOFPl4K6SmSOEgdV07eK2vDCyPeTHqKGA==",
+ "license": "MIT",
"dependencies": {
- "@turf/helpers": "^6.5.0",
- "@turf/meta": "^6.5.0"
+ "@turf/helpers": "7.3.5",
+ "@turf/meta": "7.3.5",
+ "@types/geojson": "^7946.0.10",
+ "tslib": "^2.8.1"
},
"funding": {
"url": "https://opencollective.com/turf"
}
},
"node_modules/@turf/helpers": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-6.5.0.tgz",
- "integrity": "sha512-VbI1dV5bLFzohYYdgqwikdMVpe7pJ9X3E+dlr425wa2/sMJqYDhTO++ec38/pcPvPE6oD9WEEeU3Xu3gza+VPw==",
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/@turf/helpers/-/helpers-7.3.5.tgz",
+ "integrity": "sha512-E/NMGV5MwbjjP7AJXBtsanC3yY8N2MQ87IGdIgkB2ji5AtBpwnH4L3gEqpYN4RlCJJWbLbzO91BbKv2waUd0eg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/geojson": "^7946.0.10",
+ "tslib": "^2.8.1"
+ },
"funding": {
"url": "https://opencollective.com/turf"
}
},
"node_modules/@turf/meta": {
- "version": "6.5.0",
- "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-6.5.0.tgz",
- "integrity": "sha512-RrArvtsV0vdsCBegoBtOalgdSOfkBrTJ07VkpiCnq/491W67hnMWmDu7e6Ztw0C3WldRYTXkg3SumfdzZxLBHA==",
+ "version": "7.3.5",
+ "resolved": "https://registry.npmjs.org/@turf/meta/-/meta-7.3.5.tgz",
+ "integrity": "sha512-r+ohqxoyqeigFB0oFrQx/YEHIkOKqcKpCjvZkvZs7Tkv+IFco5MezAd2zd4rzK+0DfFgDP3KpJc7HqrYjvEjhg==",
+ "license": "MIT",
"dependencies": {
- "@turf/helpers": "^6.5.0"
+ "@turf/helpers": "7.3.5",
+ "@types/geojson": "^7946.0.10",
+ "tslib": "^2.8.1"
},
"funding": {
"url": "https://opencollective.com/turf"
}
},
"node_modules/@types/body-parser": {
- "version": "1.19.2",
- "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.2.tgz",
- "integrity": "sha512-ALYone6pm6QmwZoAgeyNksccT9Q4AWZQ6PvfwR37GT6r6FWUPguq6sUmNGSMV2Wr761oQoBxwGGa6DR5o1DC9g==",
+ "version": "1.19.6",
+ "resolved": "https://registry.npmjs.org/@types/body-parser/-/body-parser-1.19.6.tgz",
+ "integrity": "sha512-HLFeCYgz89uk22N5Qg3dvGvsv46B8GLvKKo1zKG4NybA8U2DiEO3w9lqGg29t/tfLRJpJ6iQxnVw4OnB7MoM9g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/connect": "*",
"@types/node": "*"
}
},
+ "node_modules/@types/bonjour": {
+ "version": "3.5.13",
+ "resolved": "https://registry.npmjs.org/@types/bonjour/-/bonjour-3.5.13.tgz",
+ "integrity": "sha512-z9fJ5Im06zvUL548KvYNecEVlA7cVDkGUi6kZusb04mpyEFKCIZJvloCcmpmLaIahDpOQGHaHmG6imtPMmPXGQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
+ },
"node_modules/@types/connect": {
- "version": "3.4.35",
- "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.35.tgz",
- "integrity": "sha512-cdeYyv4KWoEgpBISTxWvqYsVy444DOqehiF3fM3ne10AmJ62RSyNkUnxMJXHQWRQQX2eR94m5y1IZyDwBjV9FQ==",
+ "version": "3.4.38",
+ "resolved": "https://registry.npmjs.org/@types/connect/-/connect-3.4.38.tgz",
+ "integrity": "sha512-K6uROf1LD88uDQqJCktA4yzL1YYAK6NgfsI0v/mTgyPKWsX1CnJ0XPSDhViejru1GcRkLWb8RlzFYJRqGUbaug==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
"node_modules/@types/connect-history-api-fallback": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.3.5.tgz",
- "integrity": "sha512-h8QJa8xSb1WD4fpKBDcATDNGXghFj6/3GRWG6dhmRcu0RX1Ubasur2Uvx5aeEwlf0MwblEC2bMzzMQntxnw/Cw==",
+ "version": "1.5.4",
+ "resolved": "https://registry.npmjs.org/@types/connect-history-api-fallback/-/connect-history-api-fallback-1.5.4.tgz",
+ "integrity": "sha512-n6Cr2xS1h4uAulPRdlw6Jl6s1oG8KrVilPN2yUITEs+K48EzMJJ3W1xy8K5eWuFvjp3R74AOIGSmp2UfBJ8HFw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/express-serve-static-core": "*",
"@types/node": "*"
}
},
+ "node_modules/@types/eslint": {
+ "version": "8.56.12",
+ "resolved": "https://registry.npmjs.org/@types/eslint/-/eslint-8.56.12.tgz",
+ "integrity": "sha512-03ruubjWyOHlmljCVoxSuNDdmfZDzsrrz0P2LeJsOXr+ZwFQ+0yQIwNCwt/GYhV7Z31fgtXJTAEs+FYlEL851g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/estree": "*",
+ "@types/json-schema": "*"
+ }
+ },
+ "node_modules/@types/eslint-scope": {
+ "version": "3.7.7",
+ "resolved": "https://registry.npmjs.org/@types/eslint-scope/-/eslint-scope-3.7.7.tgz",
+ "integrity": "sha512-MzMFlSLBqNF2gcHWO0G1vP/YQyfvrxZ0bF+u7mzUdZ1/xK4A4sru+nraZz5i3iEIk1l1uyicaDVTB4QbbEkAYg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/eslint": "*",
+ "@types/estree": "*"
+ }
+ },
+ "node_modules/@types/esrecurse": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/@types/esrecurse/-/esrecurse-4.3.1.tgz",
+ "integrity": "sha512-xJBAbDifo5hpffDBuHl0Y8ywswbiAp/Wi7Y/GtAgSlZyIABppyurxVueOPE8LUQOxdlgi6Zqce7uoEpqNTeiUw==",
+ "dev": true,
+ "license": "MIT",
+ "peer": true
+ },
+ "node_modules/@types/estree": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz",
+ "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==",
+ "license": "MIT"
+ },
"node_modules/@types/express": {
- "version": "4.17.13",
- "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.13.tgz",
- "integrity": "sha512-6bSZTPaTIACxn48l50SR+axgrqm6qXFIxrdAKaG6PaJk3+zuUr35hBlgT7vOmJcum+OEaIBLtHV/qloEAFITeA==",
+ "version": "4.17.25",
+ "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.25.tgz",
+ "integrity": "sha512-dVd04UKsfpINUnK0yBoYHDF3xu7xVH4BuDotC/xGuycx4CgbP48X/KF/586bcObxT0HENHXEU8Nqtu6NR+eKhw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/body-parser": "*",
- "@types/express-serve-static-core": "^4.17.18",
+ "@types/express-serve-static-core": "^4.17.33",
"@types/qs": "*",
- "@types/serve-static": "*"
+ "@types/serve-static": "^1"
}
},
"node_modules/@types/express-serve-static-core": {
- "version": "4.17.26",
- "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.26.tgz",
- "integrity": "sha512-zeu3tpouA043RHxW0gzRxwCHchMgftE8GArRsvYT0ByDMbn19olQHx5jLue0LxWY6iYtXb7rXmuVtSkhy9YZvQ==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-5.1.1.tgz",
+ "integrity": "sha512-v4zIMr/cX7/d2BpAEX3KNKL/JrT1s43s96lLvvdTmza1oEvDudCqK9aF/djc/SWgy8Yh0h30TZx5VpzqFCxk5A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/node": "*",
"@types/qs": "*",
- "@types/range-parser": "*"
+ "@types/range-parser": "*",
+ "@types/send": "*"
}
},
- "node_modules/@types/glob": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/@types/glob/-/glob-7.2.0.tgz",
- "integrity": "sha512-ZUxbzKl0IfJILTS6t7ip5fQQM/J3TJYubDm3nMbgubNNYS62eXeUpoLUC8/7fJNiFYHTrGPQn7hspDUzIHX3UA==",
+ "node_modules/@types/express/node_modules/@types/express-serve-static-core": {
+ "version": "4.19.8",
+ "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.19.8.tgz",
+ "integrity": "sha512-02S5fmqeoKzVZCHPZid4b8JH2eM5HzQLZWN2FohQEy/0eXTq8VXZfSN6Pcr3F6N9R/vNrj7cpgbhjie6m/1tCA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@types/minimatch": "*",
- "@types/node": "*"
+ "@types/node": "*",
+ "@types/qs": "*",
+ "@types/range-parser": "*",
+ "@types/send": "*"
+ }
+ },
+ "node_modules/@types/geojson": {
+ "version": "7946.0.16",
+ "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.16.tgz",
+ "integrity": "sha512-6C8nqWur3j98U6+lXDfTUWIfgvZU+EumvpHKcYjujKH7woYyLj2sUmff0tRhrqM7BohUw7Pz3ZB1jj2gW9Fvmg==",
+ "license": "MIT"
+ },
+ "node_modules/@types/geojson-vt": {
+ "version": "3.2.5",
+ "resolved": "https://registry.npmjs.org/@types/geojson-vt/-/geojson-vt-3.2.5.tgz",
+ "integrity": "sha512-qDO7wqtprzlpe8FfQ//ClPV9xiuoh2nkIgiouIptON9w5jvD/fA4szvP9GBlDVdJ5dldAl0kX/sy3URbWwLx0g==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/geojson": "*"
}
},
+ "node_modules/@types/html-minifier-terser": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
+ "integrity": "sha512-oh/6byDPnL1zeNXFrDXFLyZjkr1MsBG667IM792caf1L2UPOOMf65NFzjUH/ltyfwjAGfs1rsX1eftK0jC/KIg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/http-errors": {
+ "version": "2.0.5",
+ "resolved": "https://registry.npmjs.org/@types/http-errors/-/http-errors-2.0.5.tgz",
+ "integrity": "sha512-r8Tayk8HJnX0FztbZN7oVqGccWgw98T/0neJphO91KkmOzug1KkofZURD4UaD5uH8AqcFLfdPErnBod0u71/qg==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@types/http-proxy": {
- "version": "1.17.7",
- "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.7.tgz",
- "integrity": "sha512-9hdj6iXH64tHSLTY+Vt2eYOGzSogC+JQ2H7bdPWkuh7KXP5qLllWx++t+K9Wk556c3dkDdPws/SpMRi0sdCT1w==",
+ "version": "1.17.17",
+ "resolved": "https://registry.npmjs.org/@types/http-proxy/-/http-proxy-1.17.17.tgz",
+ "integrity": "sha512-ED6LB+Z1AVylNTu7hdzuBqOgMnvG/ld6wGCG8wFnAzKX5uyW2K3WD52v0gnLCTK/VLpXtKckgWuyScYK6cSPaw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/node": "*"
}
},
+ "node_modules/@types/istanbul-lib-coverage": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.6.tgz",
+ "integrity": "sha512-2QF/t/auWm0lsy8XtKVPG19v3sSOQlJe/YHZgfjb/KBBHOGSV+J2q/S671rcq9uTBrLAXmZpqJiaQbMT+zNU1w==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/istanbul-lib-report": {
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.3.tgz",
+ "integrity": "sha512-NQn7AHQnk/RSLOxrBbGyJM/aVQ+pjj5HCgasFxc0K/KhoATfQ/47AyUl15I2yBUpihjmas+a+VJBOqecrFH+uA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-coverage": "*"
+ }
+ },
+ "node_modules/@types/istanbul-reports": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.4.tgz",
+ "integrity": "sha512-pk2B1NWalF9toCRu6gjBzR69syFjP4Od8WRAX+0mmf9lAjCRicLOWc+ZrxZHx/0XRjotgkF9t6iaMJ+aXcOdZQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/istanbul-lib-report": "*"
+ }
+ },
"node_modules/@types/json-schema": {
- "version": "7.0.9",
- "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.9.tgz",
- "integrity": "sha512-qcUXuemtEu+E5wZSJHNxUXeCZhAfXKQ41D+duX+VYPde7xyEVZci+/oXKJL13tnRs9lR2pr4fod59GT6/X1/yQ==",
- "dev": true
+ "version": "7.0.15",
+ "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
+ "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==",
+ "license": "MIT"
},
"node_modules/@types/lodash": {
- "version": "4.14.178",
- "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.14.178.tgz",
- "integrity": "sha512-0d5Wd09ItQWH1qFbEyQ7oTQ3GZrMfth5JkbN3EvTKLXcHLRDSXeLnlvlOn0wvxVIwK5o2M8JzP/OWz7T3NRsbw=="
+ "version": "4.17.24",
+ "resolved": "https://registry.npmjs.org/@types/lodash/-/lodash-4.17.24.tgz",
+ "integrity": "sha512-gIW7lQLZbue7lRSWEFql49QJJWThrTFFeIMJdp3eH4tKoxm1OvEPg02rm4wCCSHS0cL3/Fizimb35b7k8atwsQ==",
+ "license": "MIT"
},
- "node_modules/@types/mime": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.2.tgz",
- "integrity": "sha512-YATxVxgRqNH6nHEIsvg6k2Boc1JHI9ZbH5iWFFv/MTkchz3b1ieGDa5T0a9RznNdI0KhVbdbWSN+KWWrQZRxTw==",
- "dev": true
+ "node_modules/@types/mapbox__point-geometry": {
+ "version": "0.1.4",
+ "resolved": "https://registry.npmjs.org/@types/mapbox__point-geometry/-/mapbox__point-geometry-0.1.4.tgz",
+ "integrity": "sha512-mUWlSxAmYLfwnRBmgYV86tgYmMIICX4kza8YnE/eIlywGe2XoOxlpVnXWwir92xRLjwyarqwpu2EJKD2pk0IUA==",
+ "license": "MIT"
},
- "node_modules/@types/minimatch": {
- "version": "3.0.5",
- "resolved": "https://registry.npmjs.org/@types/minimatch/-/minimatch-3.0.5.tgz",
- "integrity": "sha512-Klz949h02Gz2uZCMGwDUSDS1YBlTdDDgbWHi+81l29tQALUtvz4rAYi5uoVhE5Lagoq6DeqAUlbrHvW/mXDgdQ==",
- "dev": true
+ "node_modules/@types/mapbox__vector-tile": {
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/@types/mapbox__vector-tile/-/mapbox__vector-tile-1.3.4.tgz",
+ "integrity": "sha512-bpd8dRn9pr6xKvuEBQup8pwQfD4VUyqO/2deGjfpe6AwC8YRlyEipvefyRJUSiCJTZuCb8Pl1ciVV5ekqJ96Bg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/geojson": "*",
+ "@types/mapbox__point-geometry": "*",
+ "@types/pbf": "*"
+ }
+ },
+ "node_modules/@types/mime": {
+ "version": "1.3.5",
+ "resolved": "https://registry.npmjs.org/@types/mime/-/mime-1.3.5.tgz",
+ "integrity": "sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/minimist": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.2.tgz",
- "integrity": "sha512-jhuKLIRrhvCPLqwPcx6INqmKeiA5EWrsCOPhrlFSrbrmU4ZMPjj5Ul/oLCMDO98XRUIwVm78xICz4EPCektzeQ==",
- "dev": true
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/@types/minimist/-/minimist-1.2.5.tgz",
+ "integrity": "sha512-hov8bUuiLiyFPGyFPE1lwWhmzYbirOXQNNo40+y3zow8aFVTeyn3VWL0VFFfdNddA8S4Vf0Tc062rzyNr7Paag==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/node": {
- "version": "16.11.12",
- "resolved": "https://registry.npmjs.org/@types/node/-/node-16.11.12.tgz",
- "integrity": "sha512-+2Iggwg7PxoO5Kyhvsq9VarmPbIelXP070HMImEpbtGCoyWNINQj4wzjbQCXzdHTRXnqufutJb5KAURZANNBAw==",
- "dev": true
+ "version": "25.6.0",
+ "resolved": "https://registry.npmjs.org/@types/node/-/node-25.6.0.tgz",
+ "integrity": "sha512-+qIYRKdNYJwY3vRCZMdJbPLJAtGjQBudzZzdzwQYkEPQd+PJGixUL5QfvCLDaULoLv+RhT3LDkwEfKaAkgSmNQ==",
+ "license": "MIT",
+ "dependencies": {
+ "undici-types": "~7.19.0"
+ }
+ },
+ "node_modules/@types/node-forge": {
+ "version": "1.3.14",
+ "resolved": "https://registry.npmjs.org/@types/node-forge/-/node-forge-1.3.14.tgz",
+ "integrity": "sha512-mhVF2BnD4BO+jtOp7z1CdzaK4mbuK0LLQYAvdOLqHTavxFNq4zA1EmYkpnFjP8HOUzedfQkRnp0E2ulSAYSzAw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
+ }
},
"node_modules/@types/normalize-package-data": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.1.tgz",
- "integrity": "sha512-Gj7cI7z+98M282Tqmp2K5EIsoouUEzbBJhQQzDE3jSIRk6r9gsz0oUokqIUR4u1R3dMHo0pDHM7sNOHyhulypw==",
- "dev": true
+ "version": "2.4.4",
+ "resolved": "https://registry.npmjs.org/@types/normalize-package-data/-/normalize-package-data-2.4.4.tgz",
+ "integrity": "sha512-37i+OaWTh9qeK4LSHPsyRC7NahnGotNuZvjLSgcPzblpHB3rrCJxAOgI5gCdKm7coonsaX1Of0ILiTcnZjbfxA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha512-//oorEZjL6sbPcKUaCdIGlIUeH26mgzimjBB77G6XRgnDl/L5wOnpyBGRe/Mmf5CVW3PwEBE1NjiMZ/ssFh4wA==",
- "dev": true
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/@types/parse-json/-/parse-json-4.0.2.tgz",
+ "integrity": "sha512-dISoDXWWQwUquiKsyZ4Ng+HX2KsPL7LyHKHQwgGFEA3IaKac4Obd+h2a/a6waisAoepJlBcx9paWqjA8/HVjCw==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/@types/q": {
- "version": "1.5.5",
- "resolved": "https://registry.npmjs.org/@types/q/-/q-1.5.5.tgz",
- "integrity": "sha512-L28j2FcJfSZOnL1WBjDYp2vUHCeIFlyYI/53EwD/rKUBQ7MtUUfbQWiyKJGpcnv4/WgrhWsFKrcPstcAt/J0tQ==",
- "dev": true
+ "node_modules/@types/pbf": {
+ "version": "3.0.5",
+ "resolved": "https://registry.npmjs.org/@types/pbf/-/pbf-3.0.5.tgz",
+ "integrity": "sha512-j3pOPiEcWZ34R6a6mN07mUkM4o4Lwf6hPNt8eilOeZhTFbxFXmKhvXl9Y28jotFPaI1bpPDJsbCprUoNke6OrA==",
+ "license": "MIT"
},
"node_modules/@types/qs": {
- "version": "6.9.7",
- "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.7.tgz",
- "integrity": "sha512-FGa1F62FT09qcrueBA6qYTrJPVDzah9a+493+o2PCXsesWHIn27G98TsSMs3WPNbZIEj4+VJf6saSFpvD+3Zsw==",
- "dev": true
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.15.0.tgz",
+ "integrity": "sha512-JawvT8iBVWpzTrz3EGw9BTQFg3BQNmwERdKE22vlTxawwtbyUSlMppvZYKLZzB5zgACXdXxbD3m1bXaMqP/9ow==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@types/range-parser": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.4.tgz",
- "integrity": "sha512-EEhsLsD6UsDM1yFhAvy0Cjr6VwmpMWqFBCb9w07wVugF7w9nfajxLuVmngTIpgS6svCnm6Vaw+MZhoDCKnOfsw==",
- "dev": true
+ "version": "1.2.7",
+ "resolved": "https://registry.npmjs.org/@types/range-parser/-/range-parser-1.2.7.tgz",
+ "integrity": "sha512-hKormJbkJqzQGhziax5PItDUTMAM9uE2XXQmM37dyd4hVM+5aVl7oVxMVUiVQn2oCQFN/LKCZdvSM0pFRqbSmQ==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/@types/serve-static": {
- "version": "1.13.10",
- "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.10.tgz",
- "integrity": "sha512-nCkHGI4w7ZgAdNkrEu0bv+4xNV/XDqW+DydknebMOQwkpDGx8G+HTlj7R7ABI8i8nKxVw0wtKPi1D+lPOkh4YQ==",
+ "node_modules/@types/retry": {
+ "version": "0.12.0",
+ "resolved": "https://registry.npmjs.org/@types/retry/-/retry-0.12.0.tgz",
+ "integrity": "sha512-wWKOClTTiizcZhXnPY4wikVAwmdYHp8q6DmC+EJUzAMsycb7HB32Kh9RN4+0gExjmPmZSAQjgURXIGATPegAvA==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/@types/send": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-1.2.1.tgz",
+ "integrity": "sha512-arsCikDvlU99zl1g69TcAB3mzZPpxgw0UQnaHeC1Nwb015xp8bknZv5rIfri9xTOcMuaVgvabfIRA7PSZVuZIQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@types/mime": "^1",
"@types/node": "*"
}
},
- "node_modules/@types/source-list-map": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/@types/source-list-map/-/source-list-map-0.1.2.tgz",
- "integrity": "sha512-K5K+yml8LTo9bWJI/rECfIPrGgxdpeNbj+d53lwN4QjW1MCwlkhUms+gtdzigTeUyBr09+u8BwOIY3MXvHdcsA==",
- "dev": true
- },
- "node_modules/@types/tapable": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/@types/tapable/-/tapable-1.0.8.tgz",
- "integrity": "sha512-ipixuVrh2OdNmauvtT51o3d8z12p6LtFW9in7U79der/kwejjdNchQC5UMn5u/KxNoM7VHHOs/l8KS8uHxhODQ==",
- "dev": true
- },
- "node_modules/@types/uglify-js": {
- "version": "3.13.1",
- "resolved": "https://registry.npmjs.org/@types/uglify-js/-/uglify-js-3.13.1.tgz",
- "integrity": "sha512-O3MmRAk6ZuAKa9CHgg0Pr0+lUOqoMLpc9AS4R8ano2auvsg7IE8syF3Xh/NPr26TWklxYcqoEEFdzLLs1fV9PQ==",
+ "node_modules/@types/serve-index": {
+ "version": "1.9.4",
+ "resolved": "https://registry.npmjs.org/@types/serve-index/-/serve-index-1.9.4.tgz",
+ "integrity": "sha512-qLpGZ/c2fhSs5gnYsQxtDEq3Oy8SXPClIXkW5ghvAvsNuVSA8k+gCONcUCS/UjLEYvYps+e8uBtfgXgvhwfNug==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "source-map": "^0.6.1"
+ "@types/express": "*"
}
},
- "node_modules/@types/uglify-js/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==",
+ "node_modules/@types/serve-static": {
+ "version": "1.15.10",
+ "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.15.10.tgz",
+ "integrity": "sha512-tRs1dB+g8Itk72rlSI2ZrW6vZg0YrLI81iQSTkMmOqnqCaNr/8Ek4VwWcN5vZgCYWbg/JJSGBlUaYGAOP73qBw==",
"dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "license": "MIT",
+ "dependencies": {
+ "@types/http-errors": "*",
+ "@types/node": "*",
+ "@types/send": "<1"
}
},
- "node_modules/@types/webpack": {
- "version": "4.41.32",
- "resolved": "https://registry.npmjs.org/@types/webpack/-/webpack-4.41.32.tgz",
- "integrity": "sha512-cb+0ioil/7oz5//7tZUSwbrSAN/NWHrQylz5cW8G0dWTcF/g+/dSdMlKVZspBYuMAN1+WnwHrkxiRrLcwd0Heg==",
+ "node_modules/@types/serve-static/node_modules/@types/send": {
+ "version": "0.17.6",
+ "resolved": "https://registry.npmjs.org/@types/send/-/send-0.17.6.tgz",
+ "integrity": "sha512-Uqt8rPBE8SY0RK8JB1EzVOIZ32uqy8HwdxCnoCOsYrvnswqmFZ/k+9Ikidlk/ImhsdvBsloHbAlewb2IEBV/Og==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@types/node": "*",
- "@types/tapable": "^1",
- "@types/uglify-js": "*",
- "@types/webpack-sources": "*",
- "anymatch": "^3.0.0",
- "source-map": "^0.6.0"
+ "@types/mime": "^1",
+ "@types/node": "*"
}
},
- "node_modules/@types/webpack-dev-server": {
- "version": "3.11.6",
- "resolved": "https://registry.npmjs.org/@types/webpack-dev-server/-/webpack-dev-server-3.11.6.tgz",
- "integrity": "sha512-XCph0RiiqFGetukCTC3KVnY1jwLcZ84illFRMbyFzCcWl90B/76ew0tSqF46oBhnLC4obNDG7dMO0JfTN0MgMQ==",
+ "node_modules/@types/sockjs": {
+ "version": "0.3.36",
+ "resolved": "https://registry.npmjs.org/@types/sockjs/-/sockjs-0.3.36.tgz",
+ "integrity": "sha512-MK9V6NzAS1+Ud7JV9lJLFqW85VbC9dq3LmwZCuBe4wBDgKC0Kj/jd8Xl+nSviU+Qc3+m7umHHyHg//2KSa0a0Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@types/connect-history-api-fallback": "*",
- "@types/express": "*",
- "@types/serve-static": "*",
- "@types/webpack": "^4",
- "http-proxy-middleware": "^1.0.0"
+ "@types/node": "*"
}
},
- "node_modules/@types/webpack-sources": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/@types/webpack-sources/-/webpack-sources-3.2.0.tgz",
- "integrity": "sha512-Ft7YH3lEVRQ6ls8k4Ff1oB4jN6oy/XmU6tQISKdhfh+1mR+viZFphS6WL0IrtDOzvefmJg5a0s7ZQoRXwqTEFg==",
- "dev": true,
+ "node_modules/@types/supercluster": {
+ "version": "7.1.3",
+ "resolved": "https://registry.npmjs.org/@types/supercluster/-/supercluster-7.1.3.tgz",
+ "integrity": "sha512-Z0pOY34GDFl3Q6hUFYf3HkTwKEE02e7QgtJppBt+beEAxnyOpJua+voGFvxINBHa06GwLFFym7gRPY2SiKIfIA==",
+ "license": "MIT",
"dependencies": {
- "@types/node": "*",
- "@types/source-list-map": "*",
- "source-map": "^0.7.3"
+ "@types/geojson": "*"
}
},
- "node_modules/@types/webpack-sources/node_modules/source-map": {
- "version": "0.7.3",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.7.3.tgz",
- "integrity": "sha512-CkCj6giN3S+n9qrYiBTX5gystlENnRW5jZeNLHpe6aue+SrHcG5VYwujhW9s4dY31mEGsxBDrHR6oI69fTXsaQ==",
+ "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==",
+ "license": "MIT",
+ "optional": true,
+ "peer": true
+ },
+ "node_modules/@types/ws": {
+ "version": "8.18.1",
+ "resolved": "https://registry.npmjs.org/@types/ws/-/ws-8.18.1.tgz",
+ "integrity": "sha512-ThVF6DCVhA8kUGy+aazFQ4kXQ7E1Ty7A3ypFOe0IcJV8O/M511G99AW24irKrW56Wt44yG9+ij8FaqoBGkuBXg==",
"dev": true,
- "engines": {
- "node": ">= 8"
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*"
}
},
- "node_modules/@types/webpack/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==",
+ "node_modules/@types/yargs": {
+ "version": "17.0.35",
+ "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.35.tgz",
+ "integrity": "sha512-qUHkeCyQFxMXg79wQfTtfndEC+N9ZZg76HJftDJp+qH2tV7Gj4OJi7l+PiWwJ+pWtW8GwSmqsDj/oymhrTWXjg==",
"dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "license": "MIT",
+ "dependencies": {
+ "@types/yargs-parser": "*"
}
},
+ "node_modules/@types/yargs-parser": {
+ "version": "21.0.3",
+ "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.3.tgz",
+ "integrity": "sha512-I4q9QU9MQv4oEOz4tAHJtNz1cwuLxn2F3xcc2iV5WdqLPpUnj30aUuxt1mAxYTG+oe8CZMV/+6rU4S4gRDzqtQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@vue-hero-icons/outline": {
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@vue-hero-icons/outline/-/outline-1.7.2.tgz",
"integrity": "sha512-mgMpncarjZHXY1K2tyjbYHf53yQG9amroDR9t2iH/umpsN8+f8RNcTy1m131EZ8WBCm8MpF97XpXPV129rvtVg==",
+ "license": "MIT",
"dependencies": {
"babel-helper-vue-jsx-merge-props": "^2.0.3"
}
@@ -2449,92 +2969,117 @@
"version": "1.7.2",
"resolved": "https://registry.npmjs.org/@vue-hero-icons/solid/-/solid-1.7.2.tgz",
"integrity": "sha512-ngjgdYgdjXp8BuHmx998Kl2tAmbatJXdYO8Cut+DXo9OVGZMuVmIzIjnar4H5Wf9wFVdCuag+HazLEu9F7T3cw==",
+ "license": "MIT",
"dependencies": {
"babel-helper-vue-jsx-merge-props": "^2.0.3"
}
},
"node_modules/@vue/babel-helper-vue-jsx-merge-props": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.2.1.tgz",
- "integrity": "sha512-QOi5OW45e2R20VygMSNhyQHvpdUwQZqGPc748JLGCYEy+yp8fNFNdbNIGAgZmi9e+2JHPd6i6idRuqivyicIkA==",
- "dev": true
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-1.4.0.tgz",
+ "integrity": "sha512-JkqXfCkUDp4PIlFdDQ0TdXoIejMtTHP67/pvxlgeY+u5k3LEdKuWZ3LK6xkxo52uDoABIVyRwqVkfLQJhk7VBA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@vue/babel-helper-vue-transform-on": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.0.2.tgz",
- "integrity": "sha512-hz4R8tS5jMn8lDq6iD+yWL6XNB699pGIVLk7WSJnn1dbpjaazsjZQkieJoRX6gW5zpYSCFqQ7jUquPNY65tQYA==",
- "dev": true
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-helper-vue-transform-on/-/babel-helper-vue-transform-on-1.5.0.tgz",
+ "integrity": "sha512-0dAYkerNhhHutHZ34JtTl2czVQHUNWv6xEbkdF5W+Yrv5pCWsqjeORdOgbtW2I9gWlt+wBmVn+ttqN9ZxR5tzA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@vue/babel-plugin-jsx": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.1.1.tgz",
- "integrity": "sha512-j2uVfZjnB5+zkcbc/zsOc0fSNGCMMjaEXP52wdwdIfn0qjFfEYpYZBFKFg+HHnQeJCVrjOeO0YxgaL7DMrym9w==",
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-plugin-jsx/-/babel-plugin-jsx-1.5.0.tgz",
+ "integrity": "sha512-mneBhw1oOqCd2247O0Yw/mRwC9jIGACAJUlawkmMBiNmL4dGA2eMzuNZVNqOUfYTa6vqmND4CtOPzmEEEqLKFw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.0.0",
- "@babel/plugin-syntax-jsx": "^7.0.0",
- "@babel/template": "^7.0.0",
- "@babel/traverse": "^7.0.0",
- "@babel/types": "^7.0.0",
- "@vue/babel-helper-vue-transform-on": "^1.0.2",
- "camelcase": "^6.0.0",
- "html-tags": "^3.1.0",
- "svg-tags": "^1.0.0"
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/plugin-syntax-jsx": "^7.27.1",
+ "@babel/template": "^7.27.2",
+ "@babel/traverse": "^7.28.0",
+ "@babel/types": "^7.28.2",
+ "@vue/babel-helper-vue-transform-on": "1.5.0",
+ "@vue/babel-plugin-resolve-type": "1.5.0",
+ "@vue/shared": "^3.5.18"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@babel/core": {
+ "optional": true
+ }
}
},
- "node_modules/@vue/babel-plugin-transform-vue-jsx": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.2.1.tgz",
- "integrity": "sha512-HJuqwACYehQwh1fNT8f4kyzqlNMpBuUK4rSiSES5D4QsYncv5fxFsLyrxFPG2ksO7t5WP+Vgix6tt6yKClwPzA==",
+ "node_modules/@vue/babel-plugin-resolve-type": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-plugin-resolve-type/-/babel-plugin-resolve-type-1.5.0.tgz",
+ "integrity": "sha512-Wm/60o+53JwJODm4Knz47dxJnLDJ9FnKnGZJbUUf8nQRAtt6P+undLUAVU3Ha33LxOJe6IPoifRQ6F/0RrU31w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-module-imports": "^7.0.0",
- "@babel/plugin-syntax-jsx": "^7.2.0",
- "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1",
- "html-tags": "^2.0.0",
- "lodash.kebabcase": "^4.1.1",
- "svg-tags": "^1.0.0"
+ "@babel/code-frame": "^7.27.1",
+ "@babel/helper-module-imports": "^7.27.1",
+ "@babel/helper-plugin-utils": "^7.27.1",
+ "@babel/parser": "^7.28.0",
+ "@vue/compiler-sfc": "^3.5.18"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sxzz"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@vue/babel-plugin-transform-vue-jsx/node_modules/html-tags": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz",
- "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos= sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==",
+ "node_modules/@vue/babel-plugin-transform-vue-jsx": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-plugin-transform-vue-jsx/-/babel-plugin-transform-vue-jsx-1.4.0.tgz",
+ "integrity": "sha512-Fmastxw4MMx0vlgLS4XBX0XiBbUFzoMGeVXuMV08wyOfXdikAFqBTuYPR0tlk+XskL19EzHc39SgjrPGY23JnA==",
"dev": true,
- "engines": {
- "node": ">=4"
+ "license": "MIT",
+ "dependencies": {
+ "@babel/helper-module-imports": "^7.0.0",
+ "@babel/plugin-syntax-jsx": "^7.2.0",
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0",
+ "html-tags": "^2.0.0",
+ "lodash.kebabcase": "^4.1.1",
+ "svg-tags": "^1.0.0"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0-0"
}
},
"node_modules/@vue/babel-preset-app": {
- "version": "4.5.15",
- "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-4.5.15.tgz",
- "integrity": "sha512-J+YttzvwRfV1BPczf8r3qCevznYk+jh531agVF+5EYlHF4Sgh/cGXTz9qkkiux3LQgvhEGXgmCteg1n38WuuKg==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/@vue/babel-preset-app/-/babel-preset-app-5.0.9.tgz",
+ "integrity": "sha512-0rKOF4s/AhaRMJLybxOCgXfwtYhO3pwDSL/q/W8wRs1LzmHAc77FyTXWlun6VyKiSKwSdtH7CvOiWqq+DfofdA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/core": "^7.11.0",
- "@babel/helper-compilation-targets": "^7.9.6",
- "@babel/helper-module-imports": "^7.8.3",
- "@babel/plugin-proposal-class-properties": "^7.8.3",
- "@babel/plugin-proposal-decorators": "^7.8.3",
+ "@babel/core": "^7.12.16",
+ "@babel/helper-compilation-targets": "^7.12.16",
+ "@babel/helper-module-imports": "^7.12.13",
+ "@babel/plugin-proposal-class-properties": "^7.12.13",
+ "@babel/plugin-proposal-decorators": "^7.12.13",
"@babel/plugin-syntax-dynamic-import": "^7.8.3",
- "@babel/plugin-syntax-jsx": "^7.8.3",
- "@babel/plugin-transform-runtime": "^7.11.0",
- "@babel/preset-env": "^7.11.0",
- "@babel/runtime": "^7.11.0",
+ "@babel/plugin-syntax-jsx": "^7.12.13",
+ "@babel/plugin-transform-runtime": "^7.12.15",
+ "@babel/preset-env": "^7.12.16",
+ "@babel/runtime": "^7.12.13",
"@vue/babel-plugin-jsx": "^1.0.3",
- "@vue/babel-preset-jsx": "^1.2.4",
+ "@vue/babel-preset-jsx": "^1.1.2",
"babel-plugin-dynamic-import-node": "^2.3.3",
- "core-js": "^3.6.5",
- "core-js-compat": "^3.6.5",
- "semver": "^6.1.0"
+ "core-js": "^3.8.3",
+ "core-js-compat": "^3.8.3",
+ "semver": "^7.3.4"
},
"peerDependencies": {
"@babel/core": "*",
"core-js": "^3",
- "vue": "^2 || ^3.0.0-0"
+ "vue": "^2 || ^3.2.13"
},
"peerDependenciesMeta": {
"core-js": {
@@ -2546,29 +3091,37 @@
}
},
"node_modules/@vue/babel-preset-jsx": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.2.4.tgz",
- "integrity": "sha512-oRVnmN2a77bYDJzeGSt92AuHXbkIxbf/XXSE3klINnh9AXBmVS1DGa1f0d+dDYpLfsAKElMnqKTQfKn7obcL4w==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-preset-jsx/-/babel-preset-jsx-1.4.0.tgz",
+ "integrity": "sha512-QmfRpssBOPZWL5xw7fOuHNifCQcNQC1PrOo/4fu6xlhlKJJKSA3HqX92Nvgyx8fqHZTUGMPHmFA+IDqwXlqkSA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1",
- "@vue/babel-plugin-transform-vue-jsx": "^1.2.1",
- "@vue/babel-sugar-composition-api-inject-h": "^1.2.1",
- "@vue/babel-sugar-composition-api-render-instance": "^1.2.4",
- "@vue/babel-sugar-functional-vue": "^1.2.2",
- "@vue/babel-sugar-inject-h": "^1.2.2",
- "@vue/babel-sugar-v-model": "^1.2.3",
- "@vue/babel-sugar-v-on": "^1.2.3"
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.4.0",
+ "@vue/babel-sugar-composition-api-inject-h": "^1.4.0",
+ "@vue/babel-sugar-composition-api-render-instance": "^1.4.0",
+ "@vue/babel-sugar-functional-vue": "^1.4.0",
+ "@vue/babel-sugar-inject-h": "^1.4.0",
+ "@vue/babel-sugar-v-model": "^1.4.0",
+ "@vue/babel-sugar-v-on": "^1.4.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.0.0-0",
+ "vue": "*"
+ },
+ "peerDependenciesMeta": {
+ "vue": {
+ "optional": true
+ }
}
},
"node_modules/@vue/babel-sugar-composition-api-inject-h": {
- "version": "1.2.1",
- "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.2.1.tgz",
- "integrity": "sha512-4B3L5Z2G+7s+9Bwbf+zPIifkFNcKth7fQwekVbnOA3cr3Pq71q71goWr97sk4/yyzH8phfe5ODVzEjX7HU7ItQ==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-inject-h/-/babel-sugar-composition-api-inject-h-1.4.0.tgz",
+ "integrity": "sha512-VQq6zEddJHctnG4w3TfmlVp5FzDavUSut/DwR0xVoe/mJKXyMcsIibL42wPntozITEoY90aBV0/1d2KjxHU52g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/plugin-syntax-jsx": "^7.2.0"
},
@@ -2577,10 +3130,11 @@
}
},
"node_modules/@vue/babel-sugar-composition-api-render-instance": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.2.4.tgz",
- "integrity": "sha512-joha4PZznQMsxQYXtR3MnTgCASC9u3zt9KfBxIeuI5g2gscpTsSKRDzWQt4aqNIpx6cv8On7/m6zmmovlNsG7Q==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-composition-api-render-instance/-/babel-sugar-composition-api-render-instance-1.4.0.tgz",
+ "integrity": "sha512-6ZDAzcxvy7VcnCjNdHJ59mwK02ZFuP5CnucloidqlZwVQv5CQLijc3lGpR7MD3TWFi78J7+a8J56YxbCtHgT9Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/plugin-syntax-jsx": "^7.2.0"
},
@@ -2589,10 +3143,11 @@
}
},
"node_modules/@vue/babel-sugar-functional-vue": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.2.2.tgz",
- "integrity": "sha512-JvbgGn1bjCLByIAU1VOoepHQ1vFsroSA/QkzdiSs657V79q6OwEWLCQtQnEXD/rLTA8rRit4rMOhFpbjRFm82w==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-functional-vue/-/babel-sugar-functional-vue-1.4.0.tgz",
+ "integrity": "sha512-lTEB4WUFNzYt2In6JsoF9sAYVTo84wC4e+PoZWSgM6FUtqRJz7wMylaEhSRgG71YF+wfLD6cc9nqVeXN2rwBvw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/plugin-syntax-jsx": "^7.2.0"
},
@@ -2601,10 +3156,11 @@
}
},
"node_modules/@vue/babel-sugar-inject-h": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.2.2.tgz",
- "integrity": "sha512-y8vTo00oRkzQTgufeotjCLPAvlhnpSkcHFEp60+LJUwygGcd5Chrpn5480AQp/thrxVm8m2ifAk0LyFel9oCnw==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-inject-h/-/babel-sugar-inject-h-1.4.0.tgz",
+ "integrity": "sha512-muwWrPKli77uO2fFM7eA3G1lAGnERuSz2NgAxuOLzrsTlQl8W4G+wwbM4nB6iewlKbwKRae3nL03UaF5ffAPMA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/plugin-syntax-jsx": "^7.2.0"
},
@@ -2613,14 +3169,15 @@
}
},
"node_modules/@vue/babel-sugar-v-model": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.2.3.tgz",
- "integrity": "sha512-A2jxx87mySr/ulAsSSyYE8un6SIH0NWHiLaCWpodPCVOlQVODCaSpiR4+IMsmBr73haG+oeCuSvMOM+ttWUqRQ==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-model/-/babel-sugar-v-model-1.4.0.tgz",
+ "integrity": "sha512-0t4HGgXb7WHYLBciZzN5s0Hzqan4Ue+p/3FdQdcaHAb7s5D9WZFGoSxEZHrR1TFVZlAPu1bejTKGeAzaaG3NCQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/plugin-syntax-jsx": "^7.2.0",
- "@vue/babel-helper-vue-jsx-merge-props": "^1.2.1",
- "@vue/babel-plugin-transform-vue-jsx": "^1.2.1",
+ "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.4.0",
"camelcase": "^5.0.0",
"html-tags": "^2.0.0",
"svg-tags": "^1.0.0"
@@ -2629,187 +3186,162 @@
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@vue/babel-sugar-v-model/node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/@vue/babel-sugar-v-model/node_modules/html-tags": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz",
- "integrity": "sha1-ELMKOGCF9Dzt41PMj6fLDe7qZos= sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
"node_modules/@vue/babel-sugar-v-on": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.2.3.tgz",
- "integrity": "sha512-kt12VJdz/37D3N3eglBywV8GStKNUhNrsxChXIV+o0MwVXORYuhDTHJRKPgLJRb/EY3vM2aRFQdxJBp9CLikjw==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/@vue/babel-sugar-v-on/-/babel-sugar-v-on-1.4.0.tgz",
+ "integrity": "sha512-m+zud4wKLzSKgQrWwhqRObWzmTuyzl6vOP7024lrpeJM4x2UhQtRDLgYjXAw9xBXjCwS0pP9kXjg91F9ZNo9JA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/plugin-syntax-jsx": "^7.2.0",
- "@vue/babel-plugin-transform-vue-jsx": "^1.2.1",
+ "@vue/babel-plugin-transform-vue-jsx": "^1.4.0",
"camelcase": "^5.0.0"
},
"peerDependencies": {
"@babel/core": "^7.0.0-0"
}
},
- "node_modules/@vue/babel-sugar-v-on/node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/@vue/cli-overlay": {
- "version": "4.5.15",
- "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-4.5.15.tgz",
- "integrity": "sha512-0zI0kANAVmjFO2LWGUIzdGPMeE3+9k+KeRDXsUqB30YfRF7abjfiiRPq5BU9pOzlJbVdpRkisschBrvdJqDuDg==",
- "dev": true
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/@vue/cli-overlay/-/cli-overlay-5.0.9.tgz",
+ "integrity": "sha512-aBdZWrYKxLuFz1FDsk/muFD7GycrsW73Gi11yRc7R2W7Bm8mDRc9HKAI790gdg4NV+chkDFmfkegjg5iMDEpAA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@vue/cli-plugin-babel": {
- "version": "4.5.15",
- "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-4.5.15.tgz",
- "integrity": "sha512-hBLrwYfFkHldEe34op/YNgPhpOWI5n5DB2Qt9I/1Epeif4M4iFaayrgjvOR9AVM6WbD3Yx7WCFszYpWrQZpBzQ==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/@vue/cli-plugin-babel/-/cli-plugin-babel-5.0.9.tgz",
+ "integrity": "sha512-oDZt1Kfe4KGNtig3/3zFo2pIeDJij2uS0M6S+tAqQno4Zpla2D8Hk/AR5PrstUd/HmhHZYJoGyF78MOfj3SbWg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/core": "^7.11.0",
- "@vue/babel-preset-app": "^4.5.15",
- "@vue/cli-shared-utils": "^4.5.15",
- "babel-loader": "^8.1.0",
- "cache-loader": "^4.1.0",
- "thread-loader": "^2.1.3",
- "webpack": "^4.0.0"
+ "@babel/core": "^7.12.16",
+ "@vue/babel-preset-app": "^5.0.9",
+ "@vue/cli-shared-utils": "^5.0.9",
+ "babel-loader": "^8.2.2",
+ "thread-loader": "^3.0.0",
+ "webpack": "^5.54.0"
},
"peerDependencies": {
- "@vue/cli-service": "^3.0.0 || ^4.0.0-0"
+ "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
}
},
"node_modules/@vue/cli-plugin-eslint": {
- "version": "4.5.15",
- "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-4.5.15.tgz",
- "integrity": "sha512-/2Fl6wY/5bz3HD035oSnFRMsKNxDxU396KqBdpCQdwdvqk4mm6JAbXqihpcBRTNPeTO6w+LwGe6FE56PVbJdbg==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/@vue/cli-plugin-eslint/-/cli-plugin-eslint-5.0.9.tgz",
+ "integrity": "sha512-OfAa85qhP0dKSprI8+9qjbXW8BzOlOvEtXwdrTrAKlD6aN8oa/u6k4vbfJGdYbpsbpkj8FXYdCRkTgNG8KZbxg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@vue/cli-shared-utils": "^4.5.15",
- "eslint-loader": "^2.2.1",
- "globby": "^9.2.0",
- "inquirer": "^7.1.0",
- "webpack": "^4.0.0",
+ "@vue/cli-shared-utils": "^5.0.9",
+ "eslint-webpack-plugin": "^3.1.0",
+ "globby": "^11.0.2",
+ "webpack": "^5.54.0",
"yorkie": "^2.0.0"
},
"peerDependencies": {
- "@vue/cli-service": "^3.0.0 || ^4.0.0-0",
- "eslint": ">= 1.6.0 < 7.0.0"
+ "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0",
+ "eslint": ">=7.5.0"
}
},
"node_modules/@vue/cli-plugin-router": {
- "version": "4.5.15",
- "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-4.5.15.tgz",
- "integrity": "sha512-q7Y6kP9b3k55Ca2j59xJ7XPA6x+iSRB+N4ac0ZbcL1TbInVQ4j5wCzyE+uqid40hLy4fUdlpl4X9fHJEwuVxPA==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/@vue/cli-plugin-router/-/cli-plugin-router-5.0.9.tgz",
+ "integrity": "sha512-kopbO/8kIl5CAffwgptXEwV509i+M0FfwW4sSkgQ2RzpxOYBjQZvp+096mjZfFcWKSmryNP/ri/Mnu78vmhlhw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@vue/cli-shared-utils": "^4.5.15"
+ "@vue/cli-shared-utils": "^5.0.9"
},
"peerDependencies": {
- "@vue/cli-service": "^3.0.0 || ^4.0.0-0"
+ "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
}
},
"node_modules/@vue/cli-plugin-vuex": {
- "version": "4.5.15",
- "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-4.5.15.tgz",
- "integrity": "sha512-fqap+4HN+w+InDxlA3hZTOGE0tzBTgXhKLoDydhywqgmhQ1D9JA6Feh94ze6tG8DsWX58/ujYUqA8jAz17FJtg==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/@vue/cli-plugin-vuex/-/cli-plugin-vuex-5.0.9.tgz",
+ "integrity": "sha512-AQhgGNFVd4Pu2crvS0a+hRckgrJv07gzOASdbLd3I72wkT43dd01MLRp8IBRRsu92t3MXenW86AZUCbQBz3//A==",
"dev": true,
+ "license": "MIT",
"peerDependencies": {
- "@vue/cli-service": "^3.0.0 || ^4.0.0-0"
+ "@vue/cli-service": "^3.0.0 || ^4.0.0 || ^5.0.0-0"
}
},
"node_modules/@vue/cli-service": {
- "version": "4.5.15",
- "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-4.5.15.tgz",
- "integrity": "sha512-sFWnLYVCn4zRfu45IcsIE9eXM0YpDV3S11vlM2/DVbIPAGoYo5ySpSof6aHcIvkeGsIsrHFpPHzNvDZ/efs7jA==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/@vue/cli-service/-/cli-service-5.0.9.tgz",
+ "integrity": "sha512-yTX7GVyM19tEbd+y5/gA6MkVKA6K61nVYHYAivD61Hx6odVFmQsaC3/R3cWAHM1P5oVKCevBbumPljbT+tFG2w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@intervolga/optimize-cssnano-plugin": "^1.0.5",
- "@soda/friendly-errors-webpack-plugin": "^1.7.1",
- "@soda/get-current-script": "^1.0.0",
+ "@babel/helper-compilation-targets": "^7.12.16",
+ "@soda/friendly-errors-webpack-plugin": "^1.8.0",
+ "@soda/get-current-script": "^1.0.2",
"@types/minimist": "^1.2.0",
- "@types/webpack": "^4.0.0",
- "@types/webpack-dev-server": "^3.11.0",
- "@vue/cli-overlay": "^4.5.15",
- "@vue/cli-plugin-router": "^4.5.15",
- "@vue/cli-plugin-vuex": "^4.5.15",
- "@vue/cli-shared-utils": "^4.5.15",
- "@vue/component-compiler-utils": "^3.1.2",
- "@vue/preload-webpack-plugin": "^1.1.0",
- "@vue/web-component-wrapper": "^1.2.0",
- "acorn": "^7.4.0",
- "acorn-walk": "^7.1.1",
+ "@vue/cli-overlay": "^5.0.9",
+ "@vue/cli-plugin-router": "^5.0.9",
+ "@vue/cli-plugin-vuex": "^5.0.9",
+ "@vue/cli-shared-utils": "^5.0.9",
+ "@vue/component-compiler-utils": "^3.3.0",
+ "@vue/vue-loader-v15": "npm:vue-loader@^15.9.7",
+ "@vue/web-component-wrapper": "^1.3.0",
+ "acorn": "^8.0.5",
+ "acorn-walk": "^8.0.2",
"address": "^1.1.2",
- "autoprefixer": "^9.8.6",
- "browserslist": "^4.12.0",
- "cache-loader": "^4.1.0",
+ "autoprefixer": "^10.2.4",
+ "browserslist": "^4.16.3",
"case-sensitive-paths-webpack-plugin": "^2.3.0",
- "cli-highlight": "^2.1.4",
+ "cli-highlight": "^2.1.10",
"clipboardy": "^2.3.0",
- "cliui": "^6.0.0",
- "copy-webpack-plugin": "^5.1.1",
- "css-loader": "^3.5.3",
- "cssnano": "^4.1.10",
+ "cliui": "^7.0.4",
+ "copy-webpack-plugin": "^9.0.1",
+ "css-loader": "^6.5.0",
+ "css-minimizer-webpack-plugin": "^3.0.2",
+ "cssnano": "^5.0.0",
"debug": "^4.1.1",
- "default-gateway": "^5.0.5",
- "dotenv": "^8.2.0",
+ "default-gateway": "^6.0.3",
+ "dotenv": "^10.0.0",
"dotenv-expand": "^5.1.0",
- "file-loader": "^4.2.0",
- "fs-extra": "^7.0.1",
- "globby": "^9.2.0",
+ "fs-extra": "^9.1.0",
+ "globby": "^11.0.2",
"hash-sum": "^2.0.0",
- "html-webpack-plugin": "^3.2.0",
+ "html-webpack-plugin": "^5.1.0",
+ "is-file-esm": "^1.0.0",
"launch-editor-middleware": "^2.2.1",
"lodash.defaultsdeep": "^4.6.1",
"lodash.mapvalues": "^4.6.0",
- "lodash.transform": "^4.6.0",
- "mini-css-extract-plugin": "^0.9.0",
+ "mini-css-extract-plugin": "^2.5.3",
"minimist": "^1.2.5",
- "pnp-webpack-plugin": "^1.6.4",
+ "module-alias": "^2.2.2",
"portfinder": "^1.0.26",
- "postcss-loader": "^3.0.0",
+ "postcss": "^8.2.6",
+ "postcss-loader": "^6.1.1",
+ "progress-webpack-plugin": "^1.0.12",
"ssri": "^8.0.1",
- "terser-webpack-plugin": "^1.4.4",
- "thread-loader": "^2.1.3",
- "url-loader": "^2.2.0",
- "vue-loader": "^15.9.2",
- "vue-style-loader": "^4.1.2",
- "webpack": "^4.0.0",
- "webpack-bundle-analyzer": "^3.8.0",
- "webpack-chain": "^6.4.0",
- "webpack-dev-server": "^3.11.0",
- "webpack-merge": "^4.2.2"
+ "terser-webpack-plugin": "^5.1.1",
+ "thread-loader": "^3.0.0",
+ "vue-loader": "^17.0.0",
+ "vue-style-loader": "^4.1.3",
+ "webpack": "^5.54.0",
+ "webpack-bundle-analyzer": "^4.4.0",
+ "webpack-chain": "^6.5.1",
+ "webpack-dev-server": "^4.7.3",
+ "webpack-merge": "^5.7.3",
+ "webpack-virtual-modules": "^0.4.2",
+ "whatwg-fetch": "^3.6.2"
},
"bin": {
"vue-cli-service": "bin/vue-cli-service.js"
},
"engines": {
- "node": ">=8"
- },
- "optionalDependencies": {
- "vue-loader-v16": "npm:vue-loader@^16.1.0"
+ "node": "^12.0.0 || >= 14.0.0"
},
"peerDependencies": {
- "@vue/compiler-sfc": "^3.0.0-beta.14",
- "vue-template-compiler": "^2.0.0"
+ "vue-template-compiler": "^2.0.0",
+ "webpack-sources": "*"
},
"peerDependenciesMeta": {
- "@vue/compiler-sfc": {
+ "cache-loader": {
"optional": true
},
"less-loader": {
@@ -2829,121 +3361,122 @@
},
"vue-template-compiler": {
"optional": true
+ },
+ "webpack-sources": {
+ "optional": true
}
}
},
- "node_modules/@vue/cli-service/node_modules/fs-extra": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-7.0.1.tgz",
- "integrity": "sha512-YJDaCJZEnBmcbw13fvdAM9AwNOJwOzrE4pqMqBq5nFiEqXUqHwlK4B+3pUw6JNvfSPtX05xFHtYy/1ni01eGCw==",
- "dev": true,
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "jsonfile": "^4.0.0",
- "universalify": "^0.1.0"
- },
- "engines": {
- "node": ">=6 <7 || >=8"
- }
- },
- "node_modules/@vue/cli-service/node_modules/jsonfile": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz",
- "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss= sha512-m6F1R3z8jjlf2imQHS2Qez5sjKWQzbuuhuJ/FKYFRZvPE3PuHcSMVZzfsLhGVOkfd20obL5SWEBew5ShlquNxg==",
- "dev": true,
- "optionalDependencies": {
- "graceful-fs": "^4.1.6"
- }
- },
- "node_modules/@vue/cli-service/node_modules/universalify": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz",
- "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==",
- "dev": true,
- "engines": {
- "node": ">= 4.0.0"
- }
- },
"node_modules/@vue/cli-shared-utils": {
- "version": "4.5.15",
- "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-4.5.15.tgz",
- "integrity": "sha512-SKaej9hHzzjKSOw1NlFmc6BSE0vcqUQMQiv1cxQ2DhVyy4QxZXBmzmiLBUBe+hYZZs1neXW7n//udeN9bCAY+Q==",
+ "version": "5.0.9",
+ "resolved": "https://registry.npmjs.org/@vue/cli-shared-utils/-/cli-shared-utils-5.0.9.tgz",
+ "integrity": "sha512-lf4KykiG8j9KwvNVi7fKtASmHuLsxCcCsflVU2b2CHMRuR4weOIV3zuuCrjWKjk0APn/MHJhgCjJGzHMbTtd5w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@hapi/joi": "^15.0.1",
- "chalk": "^2.4.2",
+ "@achrinza/node-ipc": "^9.2.5",
+ "chalk": "^4.1.2",
"execa": "^1.0.0",
+ "joi": "^17.4.0",
"launch-editor": "^2.2.1",
- "lru-cache": "^5.1.1",
- "node-ipc": "^9.1.1",
- "open": "^6.3.0",
- "ora": "^3.4.0",
+ "lru-cache": "^6.0.0",
+ "node-fetch": "^2.6.7",
+ "open": "^8.0.2",
+ "ora": "^5.3.0",
"read-pkg": "^5.1.1",
- "request": "^2.88.2",
- "semver": "^6.1.0",
+ "semver": "^7.3.4",
"strip-ansi": "^6.0.0"
}
},
- "node_modules/@vue/cli-shared-utils/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "node_modules/@vue/cli-shared-utils/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "color-convert": "^1.9.0"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/@vue/cli-shared-utils/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "node_modules/@vue/cli-shared-utils/node_modules/lru-cache": {
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
+ "integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
+ "yallist": "^4.0.0"
},
"engines": {
- "node": ">=4"
+ "node": ">=10"
}
},
- "node_modules/@vue/cli-shared-utils/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "node_modules/@vue/cli-shared-utils/node_modules/yallist": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
+ "integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@vue/compiler-core": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-core/-/compiler-core-3.5.34.tgz",
+ "integrity": "sha512-s9cLyK5mLcvZ4Agva5QgRsQyLKvts9WbU9DB6NqiZkkGEdwmcEiylj5Jbwkp680drF/NNCV8OlAJSe+yMLxaJw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "color-name": "1.1.3"
+ "@babel/parser": "^7.29.3",
+ "@vue/shared": "3.5.34",
+ "entities": "^7.0.1",
+ "estree-walker": "^2.0.2",
+ "source-map-js": "^1.2.1"
}
},
- "node_modules/@vue/cli-shared-utils/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
+ "node_modules/@vue/compiler-dom": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-dom/-/compiler-dom-3.5.34.tgz",
+ "integrity": "sha512-EbF/T++k0e2MMZlJsBhzK8Sgwt0HcIPOhzn1CTB/lv6sQcyk+OWf8YeiLxZp3ro7MbbLcAfAJ6sEvjFWuNgUCw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@vue/compiler-core": "3.5.34",
+ "@vue/shared": "3.5.34"
+ }
},
- "node_modules/@vue/cli-shared-utils/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "node_modules/@vue/compiler-sfc": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-3.5.34.tgz",
+ "integrity": "sha512-D/ihr6uZeIt6r+pVZf46RWT1fAsLFMbUP7k8G1VkiiWexriED9GrX3echHd4Abbt17zjlfiFJ8z7a3BxZOPNjg==",
"dev": true,
- "engines": {
- "node": ">=4"
+ "license": "MIT",
+ "dependencies": {
+ "@babel/parser": "^7.29.3",
+ "@vue/compiler-core": "3.5.34",
+ "@vue/compiler-dom": "3.5.34",
+ "@vue/compiler-ssr": "3.5.34",
+ "@vue/shared": "3.5.34",
+ "estree-walker": "^2.0.2",
+ "magic-string": "^0.30.21",
+ "postcss": "^8.5.14",
+ "source-map-js": "^1.2.1"
}
},
- "node_modules/@vue/cli-shared-utils/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "node_modules/@vue/compiler-ssr": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-ssr/-/compiler-ssr-3.5.34.tgz",
+ "integrity": "sha512-cDtTHKibkThKGHH1SP+WdccquNRYQDFH6rRjQCqT9G2ltFAfoR5pUftpab/z+aM5mW9HLLVQW7hfKKQe/1GBeQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
+ "@vue/compiler-dom": "3.5.34",
+ "@vue/shared": "3.5.34"
}
},
"node_modules/@vue/component-compiler-utils": {
@@ -2951,6 +3484,7 @@
"resolved": "https://registry.npmjs.org/@vue/component-compiler-utils/-/component-compiler-utils-3.3.0.tgz",
"integrity": "sha512-97sfH2mYNU+2PzGrmK2haqffDpVASuib9/w2/noxiFi31Z54hW+q3izKQXXQZSNhtiUpAI36uSuYepeBe4wpHQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"consolidate": "^0.15.1",
"hash-sum": "^1.0.2",
@@ -2968,233 +3502,247 @@
"node_modules/@vue/component-compiler-utils/node_modules/hash-sum": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
- "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ= sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
- "dev": true
+ "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@vue/component-compiler-utils/node_modules/lru-cache": {
"version": "4.1.5",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
"integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"pseudomap": "^1.0.2",
"yallist": "^2.1.2"
}
},
- "node_modules/@vue/component-compiler-utils/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==",
+ "node_modules/@vue/component-compiler-utils/node_modules/picocolors": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
+ "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
+ "dev": true,
+ "license": "ISC"
+ },
+ "node_modules/@vue/component-compiler-utils/node_modules/postcss": {
+ "version": "7.0.39",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
+ "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "picocolors": "^0.2.1",
+ "source-map": "^0.6.1"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">=6.0.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
}
},
"node_modules/@vue/component-compiler-utils/node_modules/yallist": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
- "dev": true
+ "integrity": "sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
+ "dev": true,
+ "license": "ISC"
},
- "node_modules/@vue/composition-api": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/@vue/composition-api/-/composition-api-1.7.2.tgz",
- "integrity": "sha512-M8jm9J/laYrYT02665HkZ5l2fWTK4dcVg3BsDHm/pfz+MjDYwX+9FUaZyGwEyXEDonQYRCo0H7aLgdklcIELjw==",
- "peerDependencies": {
- "vue": ">= 2.5 < 2.7"
- }
+ "node_modules/@vue/shared": {
+ "version": "3.5.34",
+ "resolved": "https://registry.npmjs.org/@vue/shared/-/shared-3.5.34.tgz",
+ "integrity": "sha512-24uqU4OIiX29ryC3MeWid/Xf2fa2EFRUVLb77nRhk+UrTVrh/XiGtFAFmJBAtBRbjwNdsPRP+jj/OL27Eg1NDA==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/@vue/preload-webpack-plugin": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@vue/preload-webpack-plugin/-/preload-webpack-plugin-1.1.2.tgz",
- "integrity": "sha512-LIZMuJk38pk9U9Ur4YzHjlIyMuxPlACdBIHH9/nGYVTsaGKOSnSuELiE8vS9wa+dJpIYspYUOqk+L1Q4pgHQHQ==",
+ "node_modules/@vue/vue-loader-v15": {
+ "name": "vue-loader",
+ "version": "15.11.1",
+ "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.11.1.tgz",
+ "integrity": "sha512-0iw4VchYLePqJfJu9s62ACWUXeSqM30SQqlIftbYWM3C+jpPcEHKSPUZBLjSF9au4HTHQ/naF6OGnO3Q/qGR3Q==",
"dev": true,
- "engines": {
- "node": ">=6.0.0"
+ "license": "MIT",
+ "dependencies": {
+ "@vue/component-compiler-utils": "^3.1.0",
+ "hash-sum": "^1.0.2",
+ "loader-utils": "^1.1.0",
+ "vue-hot-reload-api": "^2.3.0",
+ "vue-style-loader": "^4.1.0"
},
"peerDependencies": {
- "html-webpack-plugin": ">=2.26.0",
- "webpack": ">=4.0.0"
+ "css-loader": "*",
+ "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "cache-loader": {
+ "optional": true
+ },
+ "prettier": {
+ "optional": true
+ },
+ "vue-template-compiler": {
+ "optional": true
+ }
}
},
+ "node_modules/@vue/vue-loader-v15/node_modules/hash-sum": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
+ "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/@vue/web-component-wrapper": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/@vue/web-component-wrapper/-/web-component-wrapper-1.3.0.tgz",
"integrity": "sha512-Iu8Tbg3f+emIIMmI2ycSI8QcEuAUgPTgHwesDU1eKMLE4YC/c/sFbGc70QgMq31ijRftV0R7vCm9co6rldCeOA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/@webassemblyjs/ast": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.9.0.tgz",
- "integrity": "sha512-C6wW5L+b7ogSDVqymbkkvuW9kruN//YisMED04xzeBBqjHa2FYnmvOlS6Xj68xWQRgWvI9cIglsjFowH/RJyEA==",
- "dev": true,
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
+ "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/helper-module-context": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/wast-parser": "1.9.0"
+ "@webassemblyjs/helper-numbers": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2"
}
},
"node_modules/@webassemblyjs/floating-point-hex-parser": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.9.0.tgz",
- "integrity": "sha512-TG5qcFsS8QB4g4MhrxK5TqfdNe7Ey/7YL/xN+36rRjl/BlGE/NcBvJcqsRgCP6Z92mRE+7N50pRIi8SmKUbcQA==",
- "dev": true
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
+ "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==",
+ "license": "MIT"
},
"node_modules/@webassemblyjs/helper-api-error": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.9.0.tgz",
- "integrity": "sha512-NcMLjoFMXpsASZFxJ5h2HZRcEhDkvnNFOAKneP5RbKRzaWJN36NC4jqQHKwStIhGXu5mUWlUUk7ygdtrO8lbmw==",
- "dev": true
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
+ "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==",
+ "license": "MIT"
},
"node_modules/@webassemblyjs/helper-buffer": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.9.0.tgz",
- "integrity": "sha512-qZol43oqhq6yBPx7YM3m9Bv7WMV9Eevj6kMi6InKOuZxhw+q9hOkvq5e/PpKSiLfyetpaBnogSbNCfBwyB00CA==",
- "dev": true
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
+ "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==",
+ "license": "MIT"
},
- "node_modules/@webassemblyjs/helper-code-frame": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-code-frame/-/helper-code-frame-1.9.0.tgz",
- "integrity": "sha512-ERCYdJBkD9Vu4vtjUYe8LZruWuNIToYq/ME22igL+2vj2dQ2OOujIZr3MEFvfEaqKoVqpsFKAGsRdBSBjrIvZA==",
- "dev": true,
+ "node_modules/@webassemblyjs/helper-numbers": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
+ "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/wast-printer": "1.9.0"
+ "@webassemblyjs/floating-point-hex-parser": "1.13.2",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@xtuc/long": "4.2.2"
}
},
- "node_modules/@webassemblyjs/helper-fsm": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-fsm/-/helper-fsm-1.9.0.tgz",
- "integrity": "sha512-OPRowhGbshCb5PxJ8LocpdX9Kl0uB4XsAjl6jH/dWKlk/mzsANvhwbiULsaiqT5GZGT9qinTICdj6PLuM5gslw==",
- "dev": true
+ "node_modules/@webassemblyjs/helper-wasm-bytecode": {
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
+ "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==",
+ "license": "MIT"
},
- "node_modules/@webassemblyjs/helper-module-context": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-module-context/-/helper-module-context-1.9.0.tgz",
- "integrity": "sha512-MJCW8iGC08tMk2enck1aPW+BE5Cw8/7ph/VGZxwyvGbJwjktKkDK7vy7gAmMDx88D7mhDTCNKAW5tED+gZ0W8g==",
- "dev": true,
+ "node_modules/@webassemblyjs/helper-wasm-section": {
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
+ "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.9.0"
- }
- },
- "node_modules/@webassemblyjs/helper-wasm-bytecode": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.9.0.tgz",
- "integrity": "sha512-R7FStIzyNcd7xKxCZH5lE0Bqy+hGTwS3LJjuv1ZVxd9O7eHCedSdrId/hMOd20I+v8wDXEn+bjfKDLzTepoaUw==",
- "dev": true
- },
- "node_modules/@webassemblyjs/helper-wasm-section": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.9.0.tgz",
- "integrity": "sha512-XnMB8l3ek4tvrKUUku+IVaXNHz2YsJyOOmz+MMkZvh8h1uSJpSen6vYnw3IoQ7WwEuAhL8Efjms1ZWjqh2agvw==",
- "dev": true,
- "dependencies": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-buffer": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/wasm-gen": "1.9.0"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/wasm-gen": "1.14.1"
}
},
"node_modules/@webassemblyjs/ieee754": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.9.0.tgz",
- "integrity": "sha512-dcX8JuYU/gvymzIHc9DgxTzUUTLexWwt8uCTWP3otys596io0L5aW02Gb1RjYpx2+0Jus1h4ZFqjla7umFniTg==",
- "dev": true,
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
+ "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
+ "license": "MIT",
"dependencies": {
"@xtuc/ieee754": "^1.2.0"
}
},
"node_modules/@webassemblyjs/leb128": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.9.0.tgz",
- "integrity": "sha512-ENVzM5VwV1ojs9jam6vPys97B/S65YQtv/aanqnU7D8aSoHFX8GyhGg0CMfyKNIHBuAVjy3tlzd5QMMINa7wpw==",
- "dev": true,
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
+ "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
+ "license": "Apache-2.0",
"dependencies": {
"@xtuc/long": "4.2.2"
}
},
"node_modules/@webassemblyjs/utf8": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.9.0.tgz",
- "integrity": "sha512-GZbQlWtopBTP0u7cHrEx+73yZKrQoBMpwkGEIqlacljhXCkVM1kMQge/Mf+csMJAjEdSwhOyLAS0AoR3AG5P8w==",
- "dev": true
+ "version": "1.13.2",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
+ "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==",
+ "license": "MIT"
},
"node_modules/@webassemblyjs/wasm-edit": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.9.0.tgz",
- "integrity": "sha512-FgHzBm80uwz5M8WKnMTn6j/sVbqilPdQXTWraSjBwFXSYGirpkSWE2R9Qvz9tNiTKQvoKILpCuTjBKzOIm0nxw==",
- "dev": true,
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
+ "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-buffer": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/helper-wasm-section": "1.9.0",
- "@webassemblyjs/wasm-gen": "1.9.0",
- "@webassemblyjs/wasm-opt": "1.9.0",
- "@webassemblyjs/wasm-parser": "1.9.0",
- "@webassemblyjs/wast-printer": "1.9.0"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/helper-wasm-section": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-opt": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1",
+ "@webassemblyjs/wast-printer": "1.14.1"
}
},
"node_modules/@webassemblyjs/wasm-gen": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.9.0.tgz",
- "integrity": "sha512-cPE3o44YzOOHvlsb4+E9qSqjc9Qf9Na1OO/BHFy4OI91XDE14MjFN4lTMezzaIWdPqHnsTodGGNP+iRSYfGkjA==",
- "dev": true,
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
+ "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/ieee754": "1.9.0",
- "@webassemblyjs/leb128": "1.9.0",
- "@webassemblyjs/utf8": "1.9.0"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
}
},
"node_modules/@webassemblyjs/wasm-opt": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.9.0.tgz",
- "integrity": "sha512-Qkjgm6Anhm+OMbIL0iokO7meajkzQD71ioelnfPEj6r4eOFuqm4YC3VBPqXjFyyNwowzbMD+hizmprP/Fwkl2A==",
- "dev": true,
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
+ "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-buffer": "1.9.0",
- "@webassemblyjs/wasm-gen": "1.9.0",
- "@webassemblyjs/wasm-parser": "1.9.0"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-buffer": "1.14.1",
+ "@webassemblyjs/wasm-gen": "1.14.1",
+ "@webassemblyjs/wasm-parser": "1.14.1"
}
},
"node_modules/@webassemblyjs/wasm-parser": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.9.0.tgz",
- "integrity": "sha512-9+wkMowR2AmdSWQzsPEjFU7njh8HTO5MqO8vjwEHuM+AMHioNqSBONRdr0NQQ3dVQrzp0s8lTcYqzUdb7YgELA==",
- "dev": true,
- "dependencies": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-api-error": "1.9.0",
- "@webassemblyjs/helper-wasm-bytecode": "1.9.0",
- "@webassemblyjs/ieee754": "1.9.0",
- "@webassemblyjs/leb128": "1.9.0",
- "@webassemblyjs/utf8": "1.9.0"
- }
- },
- "node_modules/@webassemblyjs/wast-parser": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-parser/-/wast-parser-1.9.0.tgz",
- "integrity": "sha512-qsqSAP3QQ3LyZjNC/0jBJ/ToSxfYJ8kYyuiGvtn/8MK89VrNEfwj7BPQzJVHi0jGTRK2dGdJ5PRqhtjzoww+bw==",
- "dev": true,
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
+ "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/floating-point-hex-parser": "1.9.0",
- "@webassemblyjs/helper-api-error": "1.9.0",
- "@webassemblyjs/helper-code-frame": "1.9.0",
- "@webassemblyjs/helper-fsm": "1.9.0",
- "@xtuc/long": "4.2.2"
+ "@webassemblyjs/ast": "1.14.1",
+ "@webassemblyjs/helper-api-error": "1.13.2",
+ "@webassemblyjs/helper-wasm-bytecode": "1.13.2",
+ "@webassemblyjs/ieee754": "1.13.2",
+ "@webassemblyjs/leb128": "1.13.2",
+ "@webassemblyjs/utf8": "1.13.2"
}
},
"node_modules/@webassemblyjs/wast-printer": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.9.0.tgz",
- "integrity": "sha512-2J0nE95rHXHyQ24cWjMKJ1tqB/ds8z/cyeOZxJhcb+rW+SQASVjuznUSmdz5GpVJTzU8JkhYut0D3siFDD6wsA==",
- "dev": true,
+ "version": "1.14.1",
+ "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
+ "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
+ "license": "MIT",
"dependencies": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/wast-parser": "1.9.0",
+ "@webassemblyjs/ast": "1.14.1",
"@xtuc/long": "4.2.2"
}
},
@@ -3202,36 +3750,49 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==",
- "dev": true
+ "license": "BSD-3-Clause"
},
"node_modules/@xtuc/long": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==",
- "dev": true
+ "license": "Apache-2.0"
},
"node_modules/abs-svg-path": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/abs-svg-path/-/abs-svg-path-0.1.1.tgz",
- "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA=="
+ "integrity": "sha512-d8XPSGjfyzlXC3Xx891DJRyZfqk5JU0BJrDQcsWomFIV1/BIzPW5HDH5iDdWpqWaav0YVIEzT1RHTwWr0FFshA==",
+ "license": "MIT"
},
"node_modules/accepts": {
- "version": "1.3.7",
- "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.7.tgz",
- "integrity": "sha512-Il80Qs2WjYlJIBNzNkK6KYqlVMTbZLXgHx2oT0pU/fjRHyEp+PEfEPY0R3WCwAGVOtauxh1hOxNgIf5bv7dQpA==",
+ "version": "1.3.8",
+ "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.8.tgz",
+ "integrity": "sha512-PYAthTa2m2VKxuvSD3DPC/Gy+U+sOA1LAuT8mkmRuvw+NACSaeXEQ+NHcVF7rONl6qcaxV3Uuemwawk+7+SJLw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "mime-types": "~2.1.24",
- "negotiator": "0.6.2"
+ "mime-types": "~2.1.34",
+ "negotiator": "0.6.3"
},
"engines": {
"node": ">= 0.6"
}
},
+ "node_modules/accepts/node_modules/negotiator": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.3.tgz",
+ "integrity": "sha512-+EUsqGPLsM+j/zdChZjsnX51g4XrHFOIXwfnCVPGlQk/k5giakcKsuxCObBRu6DSm9opw/O6slWbJdghQM4bBg==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/acorn": {
- "version": "7.4.1",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
- "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "version": "8.16.0",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.16.0.tgz",
+ "integrity": "sha512-UVJyE9MttOsBQIDKw1skb9nAwQuR5wuGD3+82K6JgJlm/Y+KI92oNsMNGZCYdDsVtRHSak0pcV5Dno5+4jh9sw==",
+ "license": "MIT",
"bin": {
"acorn": "bin/acorn"
},
@@ -3239,49 +3800,57 @@
"node": ">=0.4.0"
}
},
+ "node_modules/acorn-import-phases": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz",
+ "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=10.13.0"
+ },
+ "peerDependencies": {
+ "acorn": "^8.14.0"
+ }
+ },
"node_modules/acorn-jsx": {
"version": "5.3.2",
"resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-5.3.2.tgz",
"integrity": "sha512-rq9s+JNhf0IChjtDXxllJ7g41oZk5SlXtp0LHwyA5cejwn7vKmKp4pPri6YEePv2PU65sAsegbXtIinmDFDXgQ==",
"dev": true,
+ "license": "MIT",
"peerDependencies": {
"acorn": "^6.0.0 || ^7.0.0 || ^8.0.0"
}
},
- "node_modules/acorn-node": {
- "version": "1.8.2",
- "resolved": "https://registry.npmjs.org/acorn-node/-/acorn-node-1.8.2.tgz",
- "integrity": "sha512-8mt+fslDufLYntIoPAaIMUe/lrbrehIiwmR3t2k9LljIzoigEPF27eLk2hy8zSGzmR/ogr7zbRKINMo1u0yh5A==",
- "dev": true,
- "dependencies": {
- "acorn": "^7.0.0",
- "acorn-walk": "^7.0.0",
- "xtend": "^4.0.2"
- }
- },
"node_modules/acorn-walk": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-7.2.0.tgz",
- "integrity": "sha512-OPdCF6GsMIP+Az+aWfAAOEt2/+iVDKE7oy6lJ098aoe59oAmK76qV6Gw60SbZ8jHuG2wH058GF4pLFbYamYrVA==",
+ "version": "8.3.5",
+ "resolved": "https://registry.npmjs.org/acorn-walk/-/acorn-walk-8.3.5.tgz",
+ "integrity": "sha512-HEHNfbars9v4pgpW6SO1KSPkfoS0xVOM/9UzkJltjlsHZmJasxg8aXkuZa7SMf8vKGIBhpUsPluQSqhJFCqebw==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "acorn": "^8.11.0"
+ },
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/address": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/address/-/address-1.1.2.tgz",
- "integrity": "sha512-aT6camzM4xEA54YVJYSqxz1kv4IHnQZRtThJJHhUMRExaU5spC7jX5ugSwTaTgJliIgs4VhZOk7htClvQ/LmRA==",
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/address/-/address-1.2.2.tgz",
+ "integrity": "sha512-4B/qKCfeE/ODUaAUpSwfzazo5x29WD4r3vXiWsB7I2mSDAihwEqKO+g8GELZUQSSAo5e1XTYh3ZVfLyxBc12nA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 0.12.0"
+ "node": ">= 10.0.0"
}
},
"node_modules/ajv": {
- "version": "6.12.6",
- "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.12.6.tgz",
- "integrity": "sha512-j3fVLgvTo527anyYyJOGTYJbG+vnnQYvE0m5mmkc1TK+nxAppkCLMIL0aZ4dblVCNoGShhm+kzE4ZUykBoMg4g==",
+ "version": "6.15.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.15.0.tgz",
+ "integrity": "sha512-fgFx7Hfoq60ytK2c7DhnF8jIvzYgOMxfugjLOSMHjLIPgenqa7S7oaagATUq99mV6IYvN2tRmC0wnTYX6iPbMw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"fast-deep-equal": "^3.1.1",
"fast-json-stable-stringify": "^2.0.0",
@@ -3293,20 +3862,51 @@
"url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/ajv-errors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/ajv-errors/-/ajv-errors-1.0.1.tgz",
- "integrity": "sha512-DCRfO/4nQ+89p/RK43i8Ezd41EqdGIU4ld7nGF8OQ14oc/we5rEntLCUa7+jrn3nn83BosfwZA0wb4pon2o8iQ==",
- "dev": true,
+ "node_modules/ajv-formats": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/ajv-formats/-/ajv-formats-2.1.1.tgz",
+ "integrity": "sha512-Wx0Kx52hxE7C18hkMEggYlEifqWZtYaRgouJor+WMdPnQyEK13vgEWyVNup7SoeeoLMsr4kf5h6dOW11I15MUA==",
+ "license": "MIT",
+ "dependencies": {
+ "ajv": "^8.0.0"
+ },
"peerDependencies": {
- "ajv": ">=5.0.0"
+ "ajv": "^8.0.0"
+ },
+ "peerDependenciesMeta": {
+ "ajv": {
+ "optional": true
+ }
}
},
+ "node_modules/ajv-formats/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/ajv-formats/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==",
+ "license": "MIT"
+ },
"node_modules/ajv-keywords": {
"version": "3.5.2",
"resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.5.2.tgz",
"integrity": "sha512-5p6WTN0DdTGVQk6VjcEju19IgaHudalcfabD7yhDGeA6bcQnmL+CpveLJq/3hvfwd1aof6L386Ougkx6RfyMIQ==",
"dev": true,
+ "license": "MIT",
"peerDependencies": {
"ajv": "^6.9.1"
}
@@ -3314,36 +3914,17 @@
"node_modules/almost-equal": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/almost-equal/-/almost-equal-1.1.0.tgz",
- "integrity": "sha512-0V/PkoculFl5+0Lp47JoxUcO0xSxhIBvm+BxHdD/OgXNmdRpRHCFnKVuUoWyS9EzQP+otSGv0m9Lb4yVkQBn2A=="
- },
- "node_modules/alphanum-sort": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/alphanum-sort/-/alphanum-sort-1.0.2.tgz",
- "integrity": "sha1-l6ERlkmyEa0zaR2fn0hqjsn74KM= sha512-0FcBfdcmaumGPQ0qPn7Q5qTgz/ooXgIyp1rf8ik5bGX8mpE2YHjC0P/eyQvxu1GURYQgq9ozf2mteQ5ZD9YiyQ==",
- "dev": true
- },
- "node_modules/ansi-colors": {
- "version": "3.2.4",
- "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-3.2.4.tgz",
- "integrity": "sha512-hHUXGagefjN2iRrID63xckIvotOXOojhQKWIPUZ4mNUZ9nLZW+7FMNoE1lOkEhNWYsx/7ysGIuJYCiMAA9FnrA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
+ "integrity": "sha512-0V/PkoculFl5+0Lp47JoxUcO0xSxhIBvm+BxHdD/OgXNmdRpRHCFnKVuUoWyS9EzQP+otSGv0m9Lb4yVkQBn2A==",
+ "license": "MIT"
},
"node_modules/ansi-escapes": {
- "version": "4.3.2",
- "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-4.3.2.tgz",
- "integrity": "sha512-gKXj5ALrKWQLsYG9jlTRmR/xKluxHV+Z9QEwNIgCfM1/uwPMCuzVVnh5mwTd+OuBZcwSIMbqssNWRm1lE51QaQ==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.2.0.tgz",
+ "integrity": "sha512-cBhpre4ma+U0T1oM5fXg7Dy1Jw7zzwv7lt/GoCpr+hDQJoYnKVPLL4dCvSEFMmQurOQvSrwT7SL/DAlhBI97RQ==",
"dev": true,
- "dependencies": {
- "type-fest": "^0.21.3"
- },
+ "license": "MIT",
"engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=4"
}
},
"node_modules/ansi-html-community": {
@@ -3354,6 +3935,7 @@
"engines": [
"node >= 0.8.0"
],
+ "license": "Apache-2.0",
"bin": {
"ansi-html": "bin/ansi-html"
}
@@ -3363,6 +3945,7 @@
"resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-5.0.1.tgz",
"integrity": "sha512-quJQXlTSUGL2LH9SUXo8VwsY4soanhgo6LNSm84E1LBcE8s3O0wpdiRzyR9z/ZZJMlMWv37qOOb9pdJlMUEKFQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -3372,6 +3955,7 @@
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-convert": "^2.0.1"
},
@@ -3385,14 +3969,14 @@
"node_modules/any-promise": {
"version": "1.3.0",
"resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz",
- "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8= sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
- "dev": true
+ "integrity": "sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==",
+ "license": "MIT"
},
"node_modules/anymatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.2.tgz",
- "integrity": "sha512-P43ePfOAIupkguHUycrc4qJ9kz8ZiuOUijaETwX7THt0Y/GNK7v0aa8rY816xWjZ7rJdA5XdMcpVFTKMq+RvWg==",
- "dev": true,
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
+ "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "license": "ISC",
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -3401,12 +3985,6 @@
"node": ">= 8"
}
},
- "node_modules/aproba": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz",
- "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==",
- "dev": true
- },
"node_modules/arch": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/arch/-/arch-2.2.0.tgz",
@@ -3425,59 +4003,33 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
+ ],
+ "license": "MIT"
},
"node_modules/arg": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.1.tgz",
- "integrity": "sha512-e0hDa9H2Z9AwFkk2qDlwhoMYE4eToKarchkQHovNdLTCYMHZHeRjI71crOh+dio4K6u1IcwubQqo79Ga4CyAQA==",
- "dev": true
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/arg/-/arg-5.0.2.tgz",
+ "integrity": "sha512-PYjyFOLKQ9y57JvQ6QLo8dAgNqswh8M1RMJYdQduT6xbWSgK36P/Z/v+p888pM69jMMfS8Xd8F6I1kQ/I9HUGg==",
+ "license": "MIT"
},
"node_modules/argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dev": true,
- "dependencies": {
- "sprintf-js": "~1.0.2"
- }
- },
- "node_modules/arr-diff": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/arr-diff/-/arr-diff-4.0.0.tgz",
- "integrity": "sha1-1kYQdP6/7HHn4VI1dhoyml3HxSA= sha512-YVIQ82gZPGBebQV/a8dar4AitzCQs0jjXwMPZllpXMaGjXPYVUawSxQrRsjhjupyVxEvbHgUmIhKVlND+j02kA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/arr-flatten": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/arr-flatten/-/arr-flatten-1.1.0.tgz",
- "integrity": "sha512-L3hKV5R/p5o81R7O02IGnwpDmkp6E982XhtbuwSe3O4qOtMMMtodicASA1Cny2U+aCXcNpml+m4dPsvsJ3jatg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/arr-union": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/arr-union/-/arr-union-3.1.0.tgz",
- "integrity": "sha1-45sJrqne+Gao8gbiiK9jkZuuOcQ= sha512-sKpyeERZ02v1FeCZT8lrfJq5u6goHCtpTAzPwJYe7c8SPFOboNjNg1vz2L4VTn9T4PQxEx13TbXLmYUcS6Ug7Q==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/argparse/-/argparse-2.0.1.tgz",
+ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==",
"dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
+ "license": "Python-2.0"
},
"node_modules/array-bounds": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/array-bounds/-/array-bounds-1.0.1.tgz",
- "integrity": "sha512-8wdW3ZGk6UjMPJx/glyEt0sLzzwAE1bhToPsO1W2pbpR2gULyxe3BjSiuJFheP50T/GgODVPz2fuMUmIywt8cQ=="
+ "integrity": "sha512-8wdW3ZGk6UjMPJx/glyEt0sLzzwAE1bhToPsO1W2pbpR2gULyxe3BjSiuJFheP50T/GgODVPz2fuMUmIywt8cQ==",
+ "license": "MIT"
},
"node_modules/array-find-index": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/array-find-index/-/array-find-index-1.0.2.tgz",
"integrity": "sha512-M1HQyIXcBGtVywBt8WVdim+lrNaK7VHp99Qt5pSNziXznKHViIBbXWtfRTpEFpF/c4FdfxNAsCCwPp5phBYJtw==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -3485,13 +4037,15 @@
"node_modules/array-flatten": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz",
- "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI= sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
- "dev": true
+ "integrity": "sha512-PCVAQswWemu6UdxsDFFX/+gVeYqKAod3D3UVm91jHwynguOwAvYPhx8nNlM++NqRcK6CxxpUafjmhIdKiHibqg==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/array-normalize": {
"version": "1.1.4",
"resolved": "https://registry.npmjs.org/array-normalize/-/array-normalize-1.1.4.tgz",
"integrity": "sha512-fCp0wKFLjvSPmCn4F5Tiw4M3lpMZoHlCjfcs7nNzuj3vqQQ1/a8cgB9DXcpDSn18c+coLnaW7rqfcYCvKbyJXg==",
+ "license": "MIT",
"dependencies": {
"array-bounds": "^1.0.0"
}
@@ -3499,355 +4053,197 @@
"node_modules/array-range": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/array-range/-/array-range-1.0.1.tgz",
- "integrity": "sha512-shdaI1zT3CVNL2hnx9c0JMc0ZogGaxDs5e85akgHWKYa0yVbIyp06Ind3dVkTj/uuFrzaHBOyqFzo+VV6aXgtA=="
- },
- "node_modules/array-rearrange": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/array-rearrange/-/array-rearrange-2.2.2.tgz",
- "integrity": "sha512-UfobP5N12Qm4Qu4fwLDIi2v6+wZsSf6snYSxAMeKhrh37YGnNWZPRmVEKc/2wfms53TLQnzfpG8wCx2Y/6NG1w=="
+ "integrity": "sha512-shdaI1zT3CVNL2hnx9c0JMc0ZogGaxDs5e85akgHWKYa0yVbIyp06Ind3dVkTj/uuFrzaHBOyqFzo+VV6aXgtA==",
+ "license": "MIT"
},
"node_modules/array-union": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz",
- "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk= sha512-Dxr6QJj/RdU/hCaBjOfxW+q6lyuVE6JFWIrAUpuOOhoJJoQ99cUn3igRaHVB5P9WrgFVN0FfArM3x0cueOU8ng==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/array-union/-/array-union-2.1.0.tgz",
+ "integrity": "sha512-HGyxoOTYUyCM6stUe6EJgnd4EoewAI7zMdfqO+kGjnlZmBDz/cR5pf8r/cR4Wq60sL/p0IkcjUEEPwS3GFrIyw==",
"dev": true,
- "dependencies": {
- "array-uniq": "^1.0.1"
- },
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
}
},
- "node_modules/array-uniq": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz",
- "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY= sha512-MNha4BWQ6JbwhFhj03YK552f7cb3AzoE8SzeljgChvL1dl3IcvggXVz1DilzySZkCja+CXuZbdW7yATchWn8/Q==",
+ "node_modules/async": {
+ "version": "3.2.6",
+ "resolved": "https://registry.npmjs.org/async/-/async-3.2.6.tgz",
+ "integrity": "sha512-htCUDlxyyCLMgaM3xXg0C0LW2xqfuQ6p05pCEIsXuyQ+a1koYKTuBMzRNwmybfLgvJDMd0r1LTn4+E0Ti6C2AA==",
"dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
+ "license": "MIT"
+ },
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q==",
+ "license": "MIT"
},
- "node_modules/array-unique": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/array-unique/-/array-unique-0.3.2.tgz",
- "integrity": "sha1-qJS3XUvE9s1nnvMkSp/Y9Gri1Cg= sha512-SleRWjh9JUud2wH1hPs9rZBZ33H6T9HOiL0uwGnGx9FpE6wKGyfWugmbkEOIs6qWrZhg0LWeLziLrEwQJhs5mQ==",
+ "node_modules/at-least-node": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/at-least-node/-/at-least-node-1.0.0.tgz",
+ "integrity": "sha512-+q/t7Ekv1EDY2l6Gda6LLiX14rU9TV20Wa3ofeQmwPFZbOMo9DXrLbOjFaaclkXKWidIaopwAObQDqwWtGUjqg==",
"dev": true,
+ "license": "ISC",
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 4.0.0"
}
},
- "node_modules/asn1": {
- "version": "0.2.6",
- "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.6.tgz",
- "integrity": "sha512-ix/FxPn0MDjeyJ7i/yoHGFt/EX6LyNbxSEhPPXODPL+KB0VPk86UYfL0lMdy+KCnv+fmvIzySwaK5COwqVbWTQ==",
+ "node_modules/autoprefixer": {
+ "version": "10.5.0",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.5.0.tgz",
+ "integrity": "sha512-FMhOoZV4+qR6aTUALKX2rEqGG+oyATvwBt9IIzVR5rMa2HRWPkxf+P+PAJLD1I/H5/II+HuZcBJYEFBpq39ong==",
"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"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "safer-buffer": "~2.1.0"
+ "browserslist": "^4.28.2",
+ "caniuse-lite": "^1.0.30001787",
+ "fraction.js": "^5.3.4",
+ "picocolors": "^1.1.1",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
}
},
- "node_modules/asn1.js": {
- "version": "4.10.1",
- "resolved": "https://registry.npmjs.org/asn1.js/-/asn1.js-4.10.1.tgz",
- "integrity": "sha512-p32cOF5q0Zqs9uBiONKYLm6BClCoBCM5O9JfeUSlnQLBTxYdTK+pW+nXflm8UkKd2UYlEbYz5qEi0JuZR9ckSw==",
- "dev": true,
+ "node_modules/axios": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.16.0.tgz",
+ "integrity": "sha512-6hp5CwvTPlN2A31g5dxnwAX0orzM7pmCRDLnZSX772mv8WDqICwFjowHuPs04Mc8deIld1+ejhtaMn5vp6b+1w==",
+ "license": "MIT",
"dependencies": {
- "bn.js": "^4.0.0",
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0"
+ "follow-redirects": "^1.16.0",
+ "form-data": "^4.0.5",
+ "proxy-from-env": "^2.1.0"
}
},
- "node_modules/asn1.js/node_modules/bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
- "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
- "dev": true
+ "node_modules/babel-helper-vue-jsx-merge-props": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
+ "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg==",
+ "license": "MIT"
},
- "node_modules/assert": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/assert/-/assert-1.5.0.tgz",
- "integrity": "sha512-EDsgawzwoun2CZkCgtxJbv392v4nbk9XDD06zI+kQYoBM/3RBWLlEyJARDOmhAAosBjWACEkKL6S+lIZtcAubA==",
+ "node_modules/babel-loader": {
+ "version": "8.4.1",
+ "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.4.1.tgz",
+ "integrity": "sha512-nXzRChX+Z1GoE6yWavBQg6jDslyFF3SDjl2paADuoQtQW10JqShJt62R6eJQ5m/pjJFDT8xgKIWSP85OY8eXeA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "object-assign": "^4.1.1",
- "util": "0.10.3"
+ "find-cache-dir": "^3.3.1",
+ "loader-utils": "^2.0.4",
+ "make-dir": "^3.1.0",
+ "schema-utils": "^2.6.5"
+ },
+ "engines": {
+ "node": ">= 8.9"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.0.0",
+ "webpack": ">=2"
}
},
- "node_modules/assert-plus": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz",
- "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU= sha512-NfJ4UzBCcQGLDlQq7nHxH+tv3kyZ0hHQqF5BO6J7tNJeP5do1llPr8dZ8zHonfhAu0PHAdMkSo+8o0wxg9lZWw==",
+ "node_modules/babel-loader/node_modules/loader-utils": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ },
"engines": {
- "node": ">=0.8"
+ "node": ">=8.9.0"
}
},
- "node_modules/assert/node_modules/inherits": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.1.tgz",
- "integrity": "sha1-sX0I0ya0Qj5Wjv9xn5GwscvfafE= sha512-8nWq2nLTAwd02jTqJExUYFSD/fKq6VH9Y/oG2accc/kdI0V98Bag8d5a4gi3XHz73rDWa2PvTtvcWYquKqSENA==",
- "dev": true
- },
- "node_modules/assert/node_modules/util": {
- "version": "0.10.3",
- "resolved": "https://registry.npmjs.org/util/-/util-0.10.3.tgz",
- "integrity": "sha1-evsa/lCAUkZInj23/g7TeTNqwPk= sha512-5KiHfsmkqacuKjkRkdV7SsfDJ2EGiPsK92s2MhNSY0craxjTdKTtqKsJaCWp4LW33ZZ0OPUv1WO/TFvNQRiQxQ==",
+ "node_modules/babel-plugin-dynamic-import-node": {
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
+ "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "inherits": "2.0.1"
+ "object.assign": "^4.1.0"
}
},
- "node_modules/assign-symbols": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/assign-symbols/-/assign-symbols-1.0.0.tgz",
- "integrity": "sha1-WWZ/QfrdTyDMvCu5a41Pf3jsA2c= sha512-Q+JC7Whu8HhmTdBph/Tq59IoRtoy6KAm5zzPv00WdujX82lbAL8K7WVjne7vdCsAmbF4AYaDOPyO3k0kl8qIrw==",
+ "node_modules/babel-plugin-polyfill-corejs2": {
+ "version": "0.4.17",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.4.17.tgz",
+ "integrity": "sha512-aTyf30K/rqAsNwN76zYrdtx8obu0E4KoUME29B1xj+B3WxgvWkp943vYQ+z8Mv3lw9xHXMHpvSPOBxzAkIa94w==",
"dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "license": "MIT",
+ "dependencies": {
+ "@babel/compat-data": "^7.28.6",
+ "@babel/helper-define-polyfill-provider": "^0.6.8",
+ "semver": "^6.3.1"
+ },
+ "peerDependencies": {
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
- "node_modules/astral-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/astral-regex/-/astral-regex-1.0.0.tgz",
- "integrity": "sha512-+Ryf6g3BKoRc7jfp7ad8tM4TtMiaWvbF/1/sQcZPkkS7ag3D5nMBCe2UfOTONtAkaG0tO0ij3C5Lwmf1EiyjHg==",
+ "node_modules/babel-plugin-polyfill-corejs3": {
+ "version": "0.13.0",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.13.0.tgz",
+ "integrity": "sha512-U+GNwMdSFgzVmfhNm8GJUX88AadB3uo9KpJqS3FaqNIPKgySuvMb+bHPsOmmuWyIcuqZj/pzt1RUIUZns4y2+A==",
"dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/async": {
- "version": "2.6.4",
- "resolved": "https://registry.npmjs.org/async/-/async-2.6.4.tgz",
- "integrity": "sha512-mzo5dfJYwAn29PeiJ0zvwTo04zj8HDJj0Mn8TD7sno7q12prdbnasKJHhkm2c1LgrhlJ0teaea8860oxi51mGA==",
- "dev": true,
- "dependencies": {
- "lodash": "^4.17.14"
- }
- },
- "node_modules/async-each": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/async-each/-/async-each-1.0.3.tgz",
- "integrity": "sha512-z/WhQ5FPySLdvREByI2vZiTWwCnF0moMJ1hK9YQwDTHKh6I7/uSckMetoRGb5UBZPC1z0jlw+n/XCgjeH7y1AQ==",
- "dev": true
- },
- "node_modules/async-limiter": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/async-limiter/-/async-limiter-1.0.1.tgz",
- "integrity": "sha512-csOlWGAcRFJaI6m+F2WKdnMKr4HhdhFVBk0H/QbJFMCr+uO2kwohwXQPxw/9OCxp05r5ghVBFSyioixx3gfkNQ==",
- "dev": true
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k= sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
- },
- "node_modules/atob": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/atob/-/atob-2.1.2.tgz",
- "integrity": "sha512-Wm6ukoaOGJi/73p/cl2GvLjTI5JM1k/O14isD73YML8StrH/7/lRFgmg8nICZgD3bZZvjwCGxtMOD3wWNAu8cg==",
- "dev": true,
- "bin": {
- "atob": "bin/atob.js"
- },
- "engines": {
- "node": ">= 4.5.0"
- }
- },
- "node_modules/autoprefixer": {
- "version": "9.8.8",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-9.8.8.tgz",
- "integrity": "sha512-eM9d/swFopRt5gdJ7jrpCwgvEMIayITpojhkkSMRsFHYuH5bkSQ4p/9qTEHtmNudUZh22Tehu7I6CxAW0IXTKA==",
- "dev": true,
- "dependencies": {
- "browserslist": "^4.12.0",
- "caniuse-lite": "^1.0.30001109",
- "normalize-range": "^0.1.2",
- "num2fraction": "^1.2.2",
- "picocolors": "^0.2.1",
- "postcss": "^7.0.32",
- "postcss-value-parser": "^4.1.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "funding": {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
- }
- },
- "node_modules/autoprefixer/node_modules/picocolors": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
- "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
- "dev": true
- },
- "node_modules/aws-sign2": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz",
- "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg= sha512-08kcGqnYf/YmjoRhfxyu+CLxBjUtHLXLXX/vUfx9l2LYzG3c1m61nrpyFUZI6zeS+Li/wWMMidD9KgrqtGq3mA==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/aws4": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.11.0.tgz",
- "integrity": "sha512-xh1Rl34h6Fi1DC2WWKfxUTVqRsNnr6LsKz2+hfwDxQJWmrx8+c7ylaqBMcHfl1U1r2dsifOvKX3LQuLNZ+XSvA==",
- "dev": true
- },
- "node_modules/axios": {
- "version": "1.8.3",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.8.3.tgz",
- "integrity": "sha512-iP4DebzoNlP/YN2dpwCgb8zoCmhtkajzS48JvwmkSkXvPI3DHc7m+XYL5tGnSlJtR6nImXZmdCuN5aP8dh1d8A==",
- "license": "MIT",
- "dependencies": {
- "follow-redirects": "^1.15.6",
- "form-data": "^4.0.0",
- "proxy-from-env": "^1.1.0"
- }
- },
- "node_modules/axios/node_modules/form-data": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.2.tgz",
- "integrity": "sha512-hGfm/slu0ZabnNt4oaRZ6uREyfCj6P4fT/n6A1rGV+Z0VdGXjfOhVUpkn6qVQONHGIFwmveGXyDs75+nr6FM8w==",
"license": "MIT",
"dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.8",
- "es-set-tostringtag": "^2.1.0",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/babel-eslint": {
- "version": "10.1.0",
- "resolved": "https://registry.npmjs.org/babel-eslint/-/babel-eslint-10.1.0.tgz",
- "integrity": "sha512-ifWaTHQ0ce+448CYop8AdrQiBsGrnC+bMgfyKFdi6EsPLTAWG+QfyDeM6OH+FmWnKvEq5NnBMLvlBUPKQZoDSg==",
- "deprecated": "babel-eslint is now @babel/eslint-parser. This package will no longer receive updates.",
- "dev": true,
- "dependencies": {
- "@babel/code-frame": "^7.0.0",
- "@babel/parser": "^7.7.0",
- "@babel/traverse": "^7.7.0",
- "@babel/types": "^7.7.0",
- "eslint-visitor-keys": "^1.0.0",
- "resolve": "^1.12.0"
- },
- "engines": {
- "node": ">=6"
- },
- "peerDependencies": {
- "eslint": ">= 4.12.1"
- }
- },
- "node_modules/babel-helper-vue-jsx-merge-props": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/babel-helper-vue-jsx-merge-props/-/babel-helper-vue-jsx-merge-props-2.0.3.tgz",
- "integrity": "sha512-gsLiKK7Qrb7zYJNgiXKpXblxbV5ffSwR0f5whkPAaBAR4fhi6bwRZxX9wBlIc5M/v8CCkXUbXZL4N/nSE97cqg=="
- },
- "node_modules/babel-loader": {
- "version": "8.2.3",
- "resolved": "https://registry.npmjs.org/babel-loader/-/babel-loader-8.2.3.tgz",
- "integrity": "sha512-n4Zeta8NC3QAsuyiizu0GkmRcQ6clkV9WFUnUf1iXP//IeSKbWjofW3UHyZVwlOB4y039YQKefawyTn64Zwbuw==",
- "dev": true,
- "dependencies": {
- "find-cache-dir": "^3.3.1",
- "loader-utils": "^1.4.0",
- "make-dir": "^3.1.0",
- "schema-utils": "^2.6.5"
- },
- "engines": {
- "node": ">= 8.9"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0",
- "webpack": ">=2"
- }
- },
- "node_modules/babel-plugin-dynamic-import-node": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/babel-plugin-dynamic-import-node/-/babel-plugin-dynamic-import-node-2.3.3.tgz",
- "integrity": "sha512-jZVI+s9Zg3IqA/kdi0i6UDCybUI3aSBLnglhYbSSjKlV7yF1F/5LWv8MakQmvYpnbJDS6fcBL2KzHSxNCMtWSQ==",
- "dev": true,
- "dependencies": {
- "object.assign": "^4.1.0"
- }
- },
- "node_modules/babel-plugin-polyfill-corejs2": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs2/-/babel-plugin-polyfill-corejs2-0.3.0.tgz",
- "integrity": "sha512-wMDoBJ6uG4u4PNFh72Ty6t3EgfA91puCuAwKIazbQlci+ENb/UU9A3xG5lutjUIiXCIn1CY5L15r9LimiJyrSA==",
- "dev": true,
- "dependencies": {
- "@babel/compat-data": "^7.13.11",
- "@babel/helper-define-polyfill-provider": "^0.3.0",
- "semver": "^6.1.1"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/babel-plugin-polyfill-corejs3": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-corejs3/-/babel-plugin-polyfill-corejs3-0.4.0.tgz",
- "integrity": "sha512-YxFreYwUfglYKdLUGvIF2nJEsGwj+RhWSX/ije3D2vQPOXuyMLMtg/cCGMDpOA7Nd+MwlNdnGODbd2EwUZPlsw==",
- "dev": true,
- "dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.3.0",
- "core-js-compat": "^3.18.0"
+ "@babel/helper-define-polyfill-provider": "^0.6.5",
+ "core-js-compat": "^3.43.0"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.0"
}
},
"node_modules/babel-plugin-polyfill-regenerator": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.3.0.tgz",
- "integrity": "sha512-dhAPTDLGoMW5/84wkgwiLRwMnio2i1fUe53EuvtKMv0pn2p3S8OCoV1xAzfJPl0KOX7IB89s2ib85vbYiea3jg==",
+ "version": "0.6.8",
+ "resolved": "https://registry.npmjs.org/babel-plugin-polyfill-regenerator/-/babel-plugin-polyfill-regenerator-0.6.8.tgz",
+ "integrity": "sha512-M762rNHfSF1EV3SLtnCJXFoQbbIIz0OyRwnCmV0KPC7qosSfCO0QLTSuJX3ayAebubhE6oYBAYPrBA5ljowaZg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/helper-define-polyfill-provider": "^0.3.0"
+ "@babel/helper-define-polyfill-provider": "^0.6.8"
},
"peerDependencies": {
- "@babel/core": "^7.0.0-0"
+ "@babel/core": "^7.4.0 || ^8.0.0-0 <8.0.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/base": {
- "version": "0.11.2",
- "resolved": "https://registry.npmjs.org/base/-/base-0.11.2.tgz",
- "integrity": "sha512-5T6P4xPgpp0YDFvSWwEZ4NoE3aM4QBQXDzmVbraCkFj8zHM+mba8SyqB5DbZWyR7mYHo6Y7BdQo3MoA4m0TeQg==",
"dev": true,
- "dependencies": {
- "cache-base": "^1.0.1",
- "class-utils": "^0.3.5",
- "component-emitter": "^1.2.1",
- "define-property": "^1.0.0",
- "isobject": "^3.0.1",
- "mixin-deep": "^1.2.0",
- "pascalcase": "^0.1.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
+ "license": "MIT"
},
- "node_modules/base/node_modules/define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY= sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
- "dev": true,
- "dependencies": {
- "is-descriptor": "^1.0.0"
- },
+ "node_modules/base64-arraybuffer": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/base64-arraybuffer/-/base64-arraybuffer-1.0.2.tgz",
+ "integrity": "sha512-I3yl4r9QB5ZRY3XuJVEPfc2XhZO6YweFPI+UovAzn+8/hb3oJ6lnysaFcjVpkCPfVWFUDvoZ8kmVDP7WyRtYtQ==",
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 0.6.0"
}
},
"node_modules/base64-js": {
@@ -3868,130 +4264,110 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
+ ],
+ "license": "MIT"
+ },
+ "node_modules/baseline-browser-mapping": {
+ "version": "2.10.27",
+ "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.10.27.tgz",
+ "integrity": "sha512-zEs/ufmZoUd7WftKpKyXaT6RFxpQ5Qm9xytKRHvJfxFV9DFJkZph9RvJ1LcOUi0Z1ZVijMte65JbILeV+8QQEA==",
+ "license": "Apache-2.0",
+ "bin": {
+ "baseline-browser-mapping": "dist/cli.cjs"
+ },
+ "engines": {
+ "node": ">=6.0.0"
+ }
},
"node_modules/batch": {
"version": "0.6.1",
"resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz",
- "integrity": "sha1-3DQxT05nkxgJP8dgJyUl+UvyXBY= sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
- "dev": true
- },
- "node_modules/bcrypt-pbkdf": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz",
- "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4= sha512-qeFIXtP4MSoi6NLqO12WfqARWWuCKi2Rn/9hJLEmtB5yTNr9DqFWkJRCf2qShWzPeAMRnOgCrq0sg/KLv5ES9w==",
- "dev": true,
- "dependencies": {
- "tweetnacl": "^0.14.3"
- }
- },
- "node_modules/bfj": {
- "version": "6.1.2",
- "resolved": "https://registry.npmjs.org/bfj/-/bfj-6.1.2.tgz",
- "integrity": "sha512-BmBJa4Lip6BPRINSZ0BPEIfB1wUY/9rwbwvIHQA1KjX9om29B6id0wnWXq7m3bn5JrUVjeOTnVuhPT1FiHwPGw==",
+ "integrity": "sha512-x+VAiMRL6UPkx+kudNvxTl6hB2XNNCG2r+7wixVfIYwu/2HKRXimwQyaumLjMveWvT2Hkd/cAJw+QBMfJ/EKVw==",
"dev": true,
- "dependencies": {
- "bluebird": "^3.5.5",
- "check-types": "^8.0.3",
- "hoopy": "^0.1.4",
- "tryer": "^1.0.1"
- },
- "engines": {
- "node": ">= 6.0.0"
- }
+ "license": "MIT"
},
"node_modules/big.js": {
"version": "5.2.2",
"resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz",
"integrity": "sha512-vyL2OymJxmarO8gxMr0mhChsO9QGwhynfuu4+MHTAW6czfq9humCB7rKpUjDd9YUiDPU4mzpyupFSvOClAwbmQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": "*"
}
},
"node_modules/binary-extensions": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.2.0.tgz",
- "integrity": "sha512-jDctJ/IVQbZoJykoeHbhXpOlNBqGNcwXJKJog42E5HDPUwQTSdjCHdihjj0DlnheQ7blbT6dHOafNAiS8ooQKA==",
- "dev": true,
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz",
+ "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==",
+ "license": "MIT",
"engines": {
"node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/binary-search-bounds": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/binary-search-bounds/-/binary-search-bounds-2.0.5.tgz",
- "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA=="
- },
- "node_modules/bindings": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/bindings/-/bindings-1.5.0.tgz",
- "integrity": "sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "file-uri-to-path": "1.0.0"
- }
+ "integrity": "sha512-H0ea4Fd3lS1+sTEB2TgcLoK21lLhwEJzlQv3IN47pJS976Gx4zoWe0ak3q+uYh60ppQxg9F16Ri4tS1sfD4+jA==",
+ "license": "MIT"
},
"node_modules/bit-twiddle": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/bit-twiddle/-/bit-twiddle-1.0.2.tgz",
- "integrity": "sha512-B9UhK0DKFZhoTFcfvAzhqsjStvGJp9vYWf3+6SNTtdSQnvIgfkHbgHrg/e4+TH71N2GDu8tpmCVoyfrL1d7ntA=="
+ "integrity": "sha512-B9UhK0DKFZhoTFcfvAzhqsjStvGJp9vYWf3+6SNTtdSQnvIgfkHbgHrg/e4+TH71N2GDu8tpmCVoyfrL1d7ntA==",
+ "license": "MIT"
},
"node_modules/bitmap-sdf": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/bitmap-sdf/-/bitmap-sdf-1.0.4.tgz",
- "integrity": "sha512-1G3U4n5JE6RAiALMxu0p1XmeZkTeCwGKykzsLTCqVzfSDaN6S7fKnkIkfejogz+iwqBWc0UYAIKnKHNN7pSfDg=="
+ "integrity": "sha512-1G3U4n5JE6RAiALMxu0p1XmeZkTeCwGKykzsLTCqVzfSDaN6S7fKnkIkfejogz+iwqBWc0UYAIKnKHNN7pSfDg==",
+ "license": "MIT"
},
"node_modules/bl": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
- "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-4.1.0.tgz",
+ "integrity": "sha512-1W07cM9gS6DcLperZfFSj+bWLtaPGSOHWhPiGzXmvVJbRLdG82sH/Kn8EtW1VqWVA54AKf2h5k5BbnIbwF3h6w==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "readable-stream": "^2.3.5",
- "safe-buffer": "^5.1.1"
+ "buffer": "^5.5.0",
+ "inherits": "^2.0.4",
+ "readable-stream": "^3.4.0"
}
},
"node_modules/bluebird": {
"version": "3.7.2",
"resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.7.2.tgz",
"integrity": "sha512-XpNj6GDQzdfW+r2Wnn7xiSAd7TM3jzkxGXBGTtWKuSXv1xUV+azxAm8jdWZN06QTQk+2N2XB9jRDkvbmQmcRtg==",
- "dev": true
- },
- "node_modules/bn.js": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-5.2.1.tgz",
- "integrity": "sha512-eXRvHzWyYPBuB4NBy0cmYQjGitUrtqwbvlzP3G6VFnNRbsZQIxQ10PbKKHt8gZ/HW/D/747aDl+QkDqg3KQLMQ==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/body-parser": {
- "version": "1.19.0",
- "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.19.0.tgz",
- "integrity": "sha512-dhEPs72UPbDnAQJ9ZKMNTP6ptJaionhP5cBb541nXPlW60Jepo9RV/a4fX4XWW9CuFNK22krhrj1+rgzifNCsw==",
+ "version": "1.20.5",
+ "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.20.5.tgz",
+ "integrity": "sha512-3grm+/2tUOvu2cjJkvsIxrv/wVpfXQW4PsQHYm7yk4vfpu7Ekl6nEsYBoJUL6qDwZUx8wUhQ8tR2qz+ad9c9OA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "bytes": "3.1.0",
- "content-type": "~1.0.4",
+ "bytes": "~3.1.2",
+ "content-type": "~1.0.5",
"debug": "2.6.9",
- "depd": "~1.1.2",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "on-finished": "~2.3.0",
- "qs": "6.7.0",
- "raw-body": "2.4.0",
- "type-is": "~1.6.17"
+ "depd": "2.0.0",
+ "destroy": "~1.2.0",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "on-finished": "~2.4.1",
+ "qs": "~6.15.1",
+ "raw-body": "~2.5.3",
+ "type-is": "~1.6.18",
+ "unpipe": "~1.0.0"
},
"engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/body-parser/node_modules/bytes": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
- "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
- "dev": true,
- "engines": {
- "node": ">= 0.8"
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
}
},
"node_modules/body-parser/node_modules/debug": {
@@ -3999,6 +4375,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@@ -4006,171 +4383,87 @@
"node_modules/body-parser/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "node_modules/body-parser/node_modules/qs": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
- "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true,
- "engines": {
- "node": ">=0.6"
- }
+ "license": "MIT"
},
- "node_modules/bonjour": {
- "version": "3.5.0",
- "resolved": "https://registry.npmjs.org/bonjour/-/bonjour-3.5.0.tgz",
- "integrity": "sha1-jokKGD2O6aI5OzhExpGkK897yfU= sha512-RaVTblr+OnEli0r/ud8InrU7D+G0y6aJhlxaLa6Pwty4+xoxboF1BsUI45tujvRpbj9dQVoglChqonGAsjEBYg==",
+ "node_modules/bonjour-service": {
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/bonjour-service/-/bonjour-service-1.3.0.tgz",
+ "integrity": "sha512-3YuAUiSkWykd+2Azjgyxei8OWf8thdn8AITIog2M4UICzoqfjlqr64WIjEXZllf/W6vK1goqleSR6brGomxQqA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "array-flatten": "^2.1.0",
- "deep-equal": "^1.0.1",
- "dns-equal": "^1.0.0",
- "dns-txt": "^2.0.2",
- "multicast-dns": "^6.0.1",
- "multicast-dns-service-types": "^1.1.0"
+ "fast-deep-equal": "^3.1.3",
+ "multicast-dns": "^7.2.5"
}
},
- "node_modules/bonjour/node_modules/array-flatten": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-2.1.2.tgz",
- "integrity": "sha512-hNfzcOV8W4NdualtqBFPyVO+54DSJuZGY9qT4pRroB6S9e3iiido2ISIC5h9R2sPJ8H3FHCIiEnsv1lPXO3KtQ==",
- "dev": true
- },
"node_modules/boolbase": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz",
- "integrity": "sha1-aN/1++YMUes3cl6p4+0xDcwed24= sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
- "dev": true
+ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==",
+ "dev": true,
+ "license": "ISC"
},
"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==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.1.0.tgz",
+ "integrity": "sha512-TN1kCZAgdgweJhWWpgKYrQaMNHcDULHkWwQIspdtjV4Y5aurRdZpjAqn6yX3FPqTA9ngHCc4hJxMAMgGfve85w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "balanced-match": "^1.0.0",
- "concat-map": "0.0.1"
+ "balanced-match": "^1.0.0"
}
},
"node_modules/braces": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
- "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
- "dev": true,
+ "version": "3.0.3",
+ "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz",
+ "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==",
+ "license": "MIT",
"dependencies": {
- "fill-range": "^7.0.1"
+ "fill-range": "^7.1.1"
},
"engines": {
"node": ">=8"
}
},
- "node_modules/brorand": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/brorand/-/brorand-1.1.0.tgz",
- "integrity": "sha1-EsJe/kCkXjwyPrhnWgoM5XsiNx8= sha512-cKV8tMCEpQs4hK/ik71d6LrPOnpkpGBR0wzxqr68g2m/LB2GxVYQroAjMJZRVM1Y4BCjCKc3vAamxSzOY2RP+w==",
- "dev": true
- },
- "node_modules/browserify-aes": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/browserify-aes/-/browserify-aes-1.2.0.tgz",
- "integrity": "sha512-+7CHXqGuspUn/Sl5aO7Ea0xWGAtETPXNSAjHo48JfLdPWcMng33Xe4znFvQweqc/uzk5zSOI3H52CYnjCfb5hA==",
- "dev": true,
+ "node_modules/browserslist": {
+ "version": "4.28.2",
+ "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.2.tgz",
+ "integrity": "sha512-48xSriZYYg+8qXna9kwqjIVzuQxi+KYWp2+5nCYnYKPTr0LvD89Jqk2Or5ogxz0NUMfIjhh2lIUX/LyX9B4oIg==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "buffer-xor": "^1.0.3",
- "cipher-base": "^1.0.0",
- "create-hash": "^1.1.0",
- "evp_bytestokey": "^1.0.3",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
+ "baseline-browser-mapping": "^2.10.12",
+ "caniuse-lite": "^1.0.30001782",
+ "electron-to-chromium": "^1.5.328",
+ "node-releases": "^2.0.36",
+ "update-browserslist-db": "^1.2.3"
+ },
+ "bin": {
+ "browserslist": "cli.js"
+ },
+ "engines": {
+ "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
- "node_modules/browserify-cipher": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/browserify-cipher/-/browserify-cipher-1.0.1.tgz",
- "integrity": "sha512-sPhkz0ARKbf4rRQt2hTpAHqn47X3llLkUGn+xEJzLjwY8LRs2p0v7ljvI5EyoRO/mexrNunNECisZs+gw2zz1w==",
- "dev": true,
- "dependencies": {
- "browserify-aes": "^1.0.4",
- "browserify-des": "^1.0.0",
- "evp_bytestokey": "^1.0.0"
- }
- },
- "node_modules/browserify-des": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/browserify-des/-/browserify-des-1.0.2.tgz",
- "integrity": "sha512-BioO1xf3hFwz4kc6iBhI3ieDFompMhrMlnDFC4/0/vd5MokpuAc3R+LYbwTA9A5Yc9pq9UYPqffKpW2ObuwX5A==",
- "dev": true,
- "dependencies": {
- "cipher-base": "^1.0.1",
- "des.js": "^1.0.0",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.1.2"
- }
- },
- "node_modules/browserify-rsa": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/browserify-rsa/-/browserify-rsa-4.1.0.tgz",
- "integrity": "sha512-AdEER0Hkspgno2aR97SAf6vi0y0k8NuOpGnVH3O99rcA5Q6sh8QxcngtHuJ6uXwnfAXNM4Gn1Gb7/MV1+Ymbog==",
- "dev": true,
- "dependencies": {
- "bn.js": "^5.0.0",
- "randombytes": "^2.0.1"
- }
- },
- "node_modules/browserify-sign": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/browserify-sign/-/browserify-sign-4.2.3.tgz",
- "integrity": "sha512-JWCZW6SKhfhjJxO8Tyiiy+XYB7cqd2S5/+WeYHsKdNKFlCBhKbblba1A/HN/90YwtxKc8tCErjffZl++UNmGiw==",
- "dev": true,
- "dependencies": {
- "bn.js": "^5.2.1",
- "browserify-rsa": "^4.1.0",
- "create-hash": "^1.2.0",
- "create-hmac": "^1.1.7",
- "elliptic": "^6.5.5",
- "hash-base": "~3.0",
- "inherits": "^2.0.4",
- "parse-asn1": "^5.1.7",
- "readable-stream": "^2.3.8",
- "safe-buffer": "^5.2.1"
- },
- "engines": {
- "node": ">= 0.12"
- }
- },
- "node_modules/browserify-sign/node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "dev": true
- },
- "node_modules/browserify-sign/node_modules/readable-stream": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
- "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
- "dev": true,
- "dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
- }
- },
- "node_modules/browserify-sign/node_modules/readable-stream/node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
- "dev": true
- },
- "node_modules/browserify-sign/node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
+ "node_modules/buffer": {
+ "version": "5.7.1",
+ "resolved": "https://registry.npmjs.org/buffer/-/buffer-5.7.1.tgz",
+ "integrity": "sha512-EHcyIPBQ4BSGlvjB16k5KgAJ27CIsHY/2JBmCRReo48y9rQ3MaUzWX3KVlBa4U7MyX02HdVj0K7C3WaB3ju7FQ==",
"dev": true,
"funding": [
{
@@ -4185,175 +4478,43 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
- },
- "node_modules/browserify-zlib": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/browserify-zlib/-/browserify-zlib-0.2.0.tgz",
- "integrity": "sha512-Z942RysHXmJrhqk88FmKBVq/v5tqmSkDz7p54G/MGyjMnCFFnC79XWNbg+Vta8W6Wb2qtSZTSxIGkJrRpCFEiA==",
- "dev": true,
- "dependencies": {
- "pako": "~1.0.5"
- }
- },
- "node_modules/browserslist": {
- "version": "4.18.1",
- "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.18.1.tgz",
- "integrity": "sha512-8ScCzdpPwR2wQh8IT82CA2VgDwjHyqMovPBZSNH54+tm4Jk2pCuv90gmAdH6J84OCRWi0b4gMe6O6XPXuJnjgQ==",
- "dev": true,
- "dependencies": {
- "caniuse-lite": "^1.0.30001280",
- "electron-to-chromium": "^1.3.896",
- "escalade": "^3.1.1",
- "node-releases": "^2.0.1",
- "picocolors": "^1.0.0"
- },
- "bin": {
- "browserslist": "cli.js"
- },
- "engines": {
- "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/browserslist"
- }
- },
- "node_modules/buffer": {
- "version": "4.9.2",
- "resolved": "https://registry.npmjs.org/buffer/-/buffer-4.9.2.tgz",
- "integrity": "sha512-xq+q3SRMOxGivLhBNaUdC64hDTQwejJ+H0T/NB1XMtTVEwNTrfFF3gAxiyW0Bu/xWEGhjVKgUcMhCrUy2+uCWg==",
- "dev": true,
+ ],
+ "license": "MIT",
"dependencies": {
- "base64-js": "^1.0.2",
- "ieee754": "^1.1.4",
- "isarray": "^1.0.0"
+ "base64-js": "^1.3.1",
+ "ieee754": "^1.1.13"
}
},
"node_modules/buffer-from": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz",
- "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ=="
- },
- "node_modules/buffer-indexof": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/buffer-indexof/-/buffer-indexof-1.1.1.tgz",
- "integrity": "sha512-4/rOEg86jivtPTeOUUT61jJO1Ya1TrR/OkqCSZDyq84WJh3LuuiphBYJN+fm5xufIk4XAFcEwte/8WzC8If/1g==",
- "dev": true
- },
- "node_modules/buffer-json": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/buffer-json/-/buffer-json-2.0.0.tgz",
- "integrity": "sha512-+jjPFVqyfF1esi9fvfUs3NqM0pH1ziZ36VP4hmA/y/Ssfo/5w5xHKfTw9BwQjoJ1w/oVtpLomqwUHKdefGyuHw==",
- "dev": true
- },
- "node_modules/buffer-xor": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/buffer-xor/-/buffer-xor-1.0.3.tgz",
- "integrity": "sha1-JuYe0UIvtw3ULm42cp7VHYVf6Nk= sha512-571s0T7nZWK6vB67HI5dyUF7wXiNcfaPPPTl6zYCNApANjIvYJTg7hlud/+cJpdAhS7dVzqMLmfhfHR3rAcOjQ==",
- "dev": true
- },
- "node_modules/buffer/node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "dev": true
- },
- "node_modules/builtin-status-codes": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/builtin-status-codes/-/builtin-status-codes-3.0.0.tgz",
- "integrity": "sha1-hZgoeOIbmOHGZCXgPQF0eI9Wnug= sha512-HpGFw18DgFWlncDfjTa2rcQ4W88O1mC8e8yZ2AvQY5KDaktSTwo+KRf6nHK6FRI5FyRyb/5T6+TSxfP7QyGsmQ==",
- "dev": true
+ "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==",
+ "license": "MIT"
},
"node_modules/bytes": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.1.tgz",
- "integrity": "sha512-dWe4nWO/ruEOY7HkUJ5gFt1DCFV9zPRoJr8pV0/ASQermOZjtq8jMjOprC0Kd10GLN+l7xaUPvxzJFWtxGu8Fg==",
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz",
+ "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
- "node_modules/cacache": {
- "version": "12.0.4",
- "resolved": "https://registry.npmjs.org/cacache/-/cacache-12.0.4.tgz",
- "integrity": "sha512-a0tMB40oefvuInr4Cwb3GerbL9xTj1D5yg0T5xrjGCGyfvbxseIXX7BAO/u/hIXdafzOI5JC3wDwHyf24buOAQ==",
- "dev": true,
- "dependencies": {
- "bluebird": "^3.5.5",
- "chownr": "^1.1.1",
- "figgy-pudding": "^3.5.1",
- "glob": "^7.1.4",
- "graceful-fs": "^4.1.15",
- "infer-owner": "^1.0.3",
- "lru-cache": "^5.1.1",
- "mississippi": "^3.0.0",
- "mkdirp": "^0.5.1",
- "move-concurrently": "^1.0.1",
- "promise-inflight": "^1.0.1",
- "rimraf": "^2.6.3",
- "ssri": "^6.0.1",
- "unique-filename": "^1.1.1",
- "y18n": "^4.0.0"
- }
- },
- "node_modules/cacache/node_modules/ssri": {
- "version": "6.0.2",
- "resolved": "https://registry.npmjs.org/ssri/-/ssri-6.0.2.tgz",
- "integrity": "sha512-cepbSq/neFK7xB6A50KHN0xHDotYzq58wWCa5LeWqnPrHG8GzfEjO/4O8kpmcGW+oaxkvhEJCWgbgNk4/ZV93Q==",
- "dev": true,
- "dependencies": {
- "figgy-pudding": "^3.5.1"
- }
- },
- "node_modules/cache-base": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/cache-base/-/cache-base-1.0.1.tgz",
- "integrity": "sha512-AKcdTnFSWATd5/GCPRxr2ChwIJ85CeyrEyjRHlKxQ56d4XJMGym0uAiKn0xbLOGOl3+yRpOTi484dVCEc5AUzQ==",
- "dev": true,
- "dependencies": {
- "collection-visit": "^1.0.0",
- "component-emitter": "^1.2.1",
- "get-value": "^2.0.6",
- "has-value": "^1.0.0",
- "isobject": "^3.0.1",
- "set-value": "^2.0.0",
- "to-object-path": "^0.3.0",
- "union-value": "^1.0.0",
- "unset-value": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/cache-loader": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/cache-loader/-/cache-loader-4.1.0.tgz",
- "integrity": "sha512-ftOayxve0PwKzBF/GLsZNC9fJBXl8lkZE3TOsjkboHfVHVkL39iUEs1FO07A33mizmci5Dudt38UZrrYXDtbhw==",
+ "node_modules/call-bind": {
+ "version": "1.0.9",
+ "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.9.tgz",
+ "integrity": "sha512-a/hy+pNsFUTR+Iz8TCJvXudKVLAnz/DyeSUo10I5yvFDQJBFU2s9uqQpoSrJlroHUKoKqzg+epxyP9lqFdzfBQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "buffer-json": "^2.0.0",
- "find-cache-dir": "^3.0.0",
- "loader-utils": "^1.2.3",
- "mkdirp": "^0.5.1",
- "neo-async": "^2.6.1",
- "schema-utils": "^2.0.0"
+ "call-bind-apply-helpers": "^1.0.2",
+ "es-define-property": "^1.0.1",
+ "get-intrinsic": "^1.3.0",
+ "set-function-length": "^1.2.2"
},
"engines": {
- "node": ">= 8.9.0"
- },
- "peerDependencies": {
- "webpack": "^4.0.0"
- }
- },
- "node_modules/call-bind": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/call-bind/-/call-bind-1.0.2.tgz",
- "integrity": "sha512-7O+FbCihrB5WGbFYesctwmTKae6rOiIzmz1icreWJ+0aA7LJfuqhEso2T9ncpcFtzMQtzXf2QGGueWJGTYsqrA==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.0.2"
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
@@ -4372,43 +4533,21 @@
"node": ">= 0.4"
}
},
- "node_modules/call-me-maybe": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/call-me-maybe/-/call-me-maybe-1.0.1.tgz",
- "integrity": "sha1-JtII6onje1y95gJQoV8DHBak1ms= sha512-wCyFsDQkKPwwF8BDwOiWNx/9K45L/hvggQiDbve+viMNMQnWhrlYIuBk09offfwCRtCO9P6XwUttufzU11WCVw==",
- "dev": true
- },
- "node_modules/caller-callsite": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/caller-callsite/-/caller-callsite-2.0.0.tgz",
- "integrity": "sha1-hH4PzgoiN1CpoCfFSzNzGtMVQTQ= sha512-JuG3qI4QOftFsZyOn1qq87fq5grLIyk1JYd5lJmdA+fG7aQ9pA/i3JIJGcO3q0MrRcHlOt1U+ZeHW8Dq9axALQ==",
+ "node_modules/call-bound": {
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz",
+ "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "callsites": "^2.0.0"
+ "call-bind-apply-helpers": "^1.0.2",
+ "get-intrinsic": "^1.3.0"
},
"engines": {
- "node": ">=4"
- }
- },
- "node_modules/caller-callsite/node_modules/callsites": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/callsites/-/callsites-2.0.0.tgz",
- "integrity": "sha1-BuuE8A7qQT2oav/vrL/7Ngk7PFA= sha512-ksWePWBloaWPxJYQ8TL0JHvtci6G5QTKwQ95RcWAa/lzoAKuAOflGdAK92hpHXjkwb8zLxoLNUoNYZgVsaJzvQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/caller-path": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-2.0.0.tgz",
- "integrity": "sha1-Ro+DBE42mrIBD6xfBs7uFbsssfQ= sha512-MCL3sf6nCSXOwCTzvPKhN18TU7AHTvdtam8DAogxcrJ8Rjfbbg7Lgng64H9Iy+vUV6VGFClN/TyxBkAebLRR4A==",
- "dev": true,
- "dependencies": {
- "caller-callsite": "^2.0.0"
+ "node": ">= 0.4"
},
- "engines": {
- "node": ">=4"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/callsites": {
@@ -4416,37 +4555,37 @@
"resolved": "https://registry.npmjs.org/callsites/-/callsites-3.1.0.tgz",
"integrity": "sha512-P8BjAsXvZS+VIDUI11hHCQEv74YT67YUi5JJFNWIqL235sBmjX4+qx9Muvls5ivyNENctx46xQLQ3aTuE7ssaQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/camel-case": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-3.0.0.tgz",
- "integrity": "sha1-yjw2iKTpzzpM2nd9xNy8cTJJz3M= sha512-+MbKztAYHXPr1jNTSKQF52VpcFjwY5RkR7fxksV8Doo4KAYc5Fl4UJRgthBbTmEx8C54DqahhbLJkDwjI3PI/w==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/camel-case/-/camel-case-4.1.2.tgz",
+ "integrity": "sha512-gxGWBrTT1JuMx6R+o5PTXMmUnhnVzLQ9SNutD4YqKtI6ap897t3tKECYla6gCWEkplXnlNybEkZg9GEGxKFCgw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "no-case": "^2.2.0",
- "upper-case": "^1.1.1"
+ "pascal-case": "^3.1.2",
+ "tslib": "^2.0.3"
}
},
"node_modules/camelcase": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.2.1.tgz",
- "integrity": "sha512-tVI4q5jjFV5CavAU8DXfza/TJcZutVKo/5Foskmsqcm0MsL91moHvwiGNnqaa2o6PF/7yT5ikDRcVcl8Rj6LCA==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
+ "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=6"
}
},
"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,
+ "license": "MIT",
"engines": {
"node": ">= 6"
}
@@ -4456,6 +4595,7 @@
"resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz",
"integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"browserslist": "^4.0.0",
"caniuse-lite": "^1.0.0",
@@ -4464,10 +4604,9 @@
}
},
"node_modules/caniuse-lite": {
- "version": "1.0.30001482",
- "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001482.tgz",
- "integrity": "sha512-F1ZInsg53cegyjroxLNW9DmrEQ1SuGRTO1QlpA0o2/6OpQ0gFeDRoq1yFmnr8Sakn9qwwt9DmbxHB6w167OSuQ==",
- "dev": true,
+ "version": "1.0.30001792",
+ "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001792.tgz",
+ "integrity": "sha512-hVLMUZFgR4JJ6ACt1uEESvQN1/dBVqPAKY0hgrV70eN3391K6juAfTjKZLKvOMsx8PxA7gsY1/tLMMTcfFLLpw==",
"funding": [
{
"type": "opencollective",
@@ -4481,12 +4620,14 @@
"type": "github",
"url": "https://github.com/sponsors/ai"
}
- ]
+ ],
+ "license": "CC-BY-4.0"
},
"node_modules/canvas-fit": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/canvas-fit/-/canvas-fit-1.5.0.tgz",
"integrity": "sha512-onIcjRpz69/Hx5bB5HGbYKUF2uC6QT6Gp+pfpGm3A7mPfcluSLV5v4Zu+oflDUwLdUw0rLIBhUbi0v8hM4FJQQ==",
+ "license": "MIT",
"dependencies": {
"element-size": "^1.1.1"
}
@@ -4496,47 +4637,36 @@
"resolved": "https://registry.npmjs.org/case-sensitive-paths-webpack-plugin/-/case-sensitive-paths-webpack-plugin-2.4.0.tgz",
"integrity": "sha512-roIFONhcxog0JSSWbvVAh3OocukmSgpqOH6YpMkCvav/ySIV3JKg4Dc8vYtQjYi/UxpNE36r/9v+VqTQqgkYmw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
},
- "node_modules/caseless": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz",
- "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw= sha512-4tYFyifaFfGacoiObjJegolkwSU4xQNGbVgUiNYVUxbQ2x2lUsFvY4hVgVzGiIe6WLOPqycWXA40l+PWsxthUw==",
- "dev": true
- },
"node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-3.0.0.tgz",
+ "integrity": "sha512-4D3B6Wf41KOYRFdszmDqMCGq5VV/uMAB273JILmO+3jAlh8X4qDtdtgCR3fxtbLEMzSx22QdhnDcJvu2u1fVwg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.1.0",
"supports-color": "^7.1.0"
},
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/chalk?sponsor=1"
+ "node": ">=8"
}
},
- "node_modules/chardet": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz",
- "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==",
- "dev": true
- },
"node_modules/chart.js": {
- "version": "3.7.1",
- "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.7.1.tgz",
- "integrity": "sha512-8knRegQLFnPQAheZV8MjxIXc5gQEfDFD897BJgv/klO/vtIyFFmgMXrNfgrXpbTr/XbTturxRgxIXx/Y+ASJBA=="
+ "version": "3.9.1",
+ "resolved": "https://registry.npmjs.org/chart.js/-/chart.js-3.9.1.tgz",
+ "integrity": "sha512-Ro2JbLmvg83gXF5F4sniaQ+lTbSv18E+TIf2cOeiH1Iqd2PGFOtem+DUufMZsCJwFE7ywPOpfXFBwRTGq7dh6w==",
+ "license": "MIT"
},
"node_modules/chartjs-plugin-zoom": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/chartjs-plugin-zoom/-/chartjs-plugin-zoom-1.2.0.tgz",
- "integrity": "sha512-cLYKUHHx4bevuZQDpEKdjpvZ6HGu6NF8laTThgA0I9af+PV1N4qVTRZmyDNh0SAzsHZPtDOhuO3I7B4CF1lstw==",
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/chartjs-plugin-zoom/-/chartjs-plugin-zoom-1.2.1.tgz",
+ "integrity": "sha512-2zbWvw2pljrtMLMXkKw1uxYzAne5PtjJiOZftcut4Lo3Ee8qUt95RpMKDWrZ+pBZxZKQKOD/etdU4pN2jxZUmg==",
+ "license": "MIT",
"dependencies": {
"hammerjs": "^2.0.8"
},
@@ -4544,17 +4674,11 @@
"chart.js": "^3.2.0"
}
},
- "node_modules/check-types": {
- "version": "8.0.3",
- "resolved": "https://registry.npmjs.org/check-types/-/check-types-8.0.3.tgz",
- "integrity": "sha512-YpeKZngUmG65rLudJ4taU7VLkOCTMhNl/u4ctNC56LQS/zJTyNH0Lrtwm1tfTsbLlwvlfsA2d1c8vCf/Kh2KwQ==",
- "dev": true
- },
"node_modules/chokidar": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.5.2.tgz",
- "integrity": "sha512-ekGhOnNVPgT77r4K/U3GDhu+FQ2S8TnK/s2KbIGXi0SZWuwkZ2QNyfWdZW+TVfn84DpEP7rLeCt2UI6bJ8GwbQ==",
- "dev": true,
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz",
+ "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==",
+ "license": "MIT",
"dependencies": {
"anymatch": "~3.1.2",
"braces": "~3.0.2",
@@ -4567,6 +4691,9 @@
"engines": {
"node": ">= 8.10.0"
},
+ "funding": {
+ "url": "https://paulmillr.com/funding/"
+ },
"optionalDependencies": {
"fsevents": "~2.3.2"
}
@@ -4575,7 +4702,7 @@
"version": "5.1.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
- "dev": true,
+ "license": "ISC",
"dependencies": {
"is-glob": "^4.0.1"
},
@@ -4583,17 +4710,11 @@
"node": ">= 6"
}
},
- "node_modules/chownr": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.4.tgz",
- "integrity": "sha512-jJ0bqzaylmJtVnNgzTeSOs8DPavpbYgEr/b0YL8/2GO3xJEhInFmhKMUnEJQjZumK7KXGFhUy89PrsJWlakBVg==",
- "dev": true
- },
"node_modules/chrome-trace-event": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.3.tgz",
- "integrity": "sha512-p3KULyQg4S7NIHixdwbGX+nFHkoBiA4YQmyWtjb8XngSKV124nJmRysgAeujbUVb15vh+RvFUfCPqU7rXk+hZg==",
- "dev": true,
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/chrome-trace-event/-/chrome-trace-event-1.0.4.tgz",
+ "integrity": "sha512-rNjApaLzuwaOTjCiT8lSDdGN1APCiqkChLMJxJPWLunPAt5fy8xgU9/jNOchV84wfIxrA0lRQB7oCT8jrn/wrQ==",
+ "license": "MIT",
"engines": {
"node": ">=6.0"
}
@@ -4602,182 +4723,86 @@
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/ci-info/-/ci-info-1.6.0.tgz",
"integrity": "sha512-vsGdkwSCDpWmP80ncATX7iea5DWQemg1UgCW5J8tqjU3lYw4FBYuj89J0CTVomA7BEfvSZd84GmHko+MxFQU2A==",
- "dev": true
- },
- "node_modules/cipher-base": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/cipher-base/-/cipher-base-1.0.4.tgz",
- "integrity": "sha512-Kkht5ye6ZGmwv40uUDZztayT2ThLQGfnj/T71N/XzeZeo3nf8foyW7zGTsPYkEya3m5f3cAypH+qe7YOrM1U2Q==",
"dev": true,
- "dependencies": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
- }
+ "license": "MIT"
},
"node_modules/clamp": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz",
- "integrity": "sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA=="
+ "integrity": "sha512-kgMuFyE78OC6Dyu3Dy7vcx4uy97EIbVxJB/B0eJ3bUNAkwdNcxYzgKltnyADiYwsR7SEqkkUPsEUT//OVS6XMA==",
+ "license": "MIT"
},
- "node_modules/class-utils": {
- "version": "0.3.6",
- "resolved": "https://registry.npmjs.org/class-utils/-/class-utils-0.3.6.tgz",
- "integrity": "sha512-qOhPa/Fj7s6TY8H8esGu5QNpMMQxz79h+urzrNYN6mn+9BnxlDGf5QZ+XeCDsxSjPqsSR56XOZOJmpeurnLMeg==",
+ "node_modules/clean-css": {
+ "version": "5.3.3",
+ "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-5.3.3.tgz",
+ "integrity": "sha512-D5J+kHaVb/wKSFcyyV75uCn8fiY4sV38XJoe4CUyGQ+mOU/fMVYUdH1hJC+CJQ5uY3EnW27SbJYS4X8BiLrAFg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "arr-union": "^3.1.0",
- "define-property": "^0.2.5",
- "isobject": "^3.0.0",
- "static-extend": "^0.1.1"
+ "source-map": "~0.6.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 10.0"
}
},
- "node_modules/class-utils/node_modules/define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+ "node_modules/cli-cursor": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
+ "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-descriptor": "^0.1.0"
+ "restore-cursor": "^3.1.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
}
},
- "node_modules/class-utils/node_modules/is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==",
- "deprecated": "Please upgrade to v0.1.7",
+ "node_modules/cli-highlight": {
+ "version": "2.1.11",
+ "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz",
+ "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==",
"dev": true,
+ "license": "ISC",
"dependencies": {
- "kind-of": "^3.0.2"
+ "chalk": "^4.0.0",
+ "highlight.js": "^10.7.1",
+ "mz": "^2.4.0",
+ "parse5": "^5.1.1",
+ "parse5-htmlparser2-tree-adapter": "^6.0.0",
+ "yargs": "^16.0.0"
+ },
+ "bin": {
+ "highlight": "bin/highlight"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8.0.0",
+ "npm": ">=5.0.0"
}
},
- "node_modules/class-utils/node_modules/is-accessor-descriptor/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+ "node_modules/cli-highlight/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-buffer": "^1.1.5"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/class-utils/node_modules/is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==",
- "deprecated": "Please upgrade to v0.1.5",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/class-utils/node_modules/is-data-descriptor/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/class-utils/node_modules/is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "dev": true,
- "dependencies": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/class-utils/node_modules/kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/clean-css": {
- "version": "4.2.4",
- "resolved": "https://registry.npmjs.org/clean-css/-/clean-css-4.2.4.tgz",
- "integrity": "sha512-EJUDT7nDVFDvaQgAo2G/PJvxmp1o/c6iXLbswsBbUFXi1Nr+AjA2cKmfbKDMjMvzEe75g3P6JkaDDAKk96A85A==",
- "dev": true,
- "dependencies": {
- "source-map": "~0.6.0"
- },
- "engines": {
- "node": ">= 4.0"
- }
- },
- "node_modules/clean-css/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/cli-cursor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-3.1.0.tgz",
- "integrity": "sha512-I/zHAwsKf9FqGoXM4WWRACob9+SNukZTd94DWF57E4toouRulbCxcUh6RKUEOQlYTHJnzkPMySvPNaaSLNfLZw==",
- "dev": true,
- "dependencies": {
- "restore-cursor": "^3.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/cli-highlight": {
- "version": "2.1.11",
- "resolved": "https://registry.npmjs.org/cli-highlight/-/cli-highlight-2.1.11.tgz",
- "integrity": "sha512-9KDcoEVwyUXrjcJNvHD0NFc/hiwe/WPVYIleQh2O1N2Zro5gWJZ/K+3DGn8w8P/F6FxOgzyC5bxDyHIgCSPhGg==",
- "dev": true,
- "dependencies": {
- "chalk": "^4.0.0",
- "highlight.js": "^10.7.1",
- "mz": "^2.4.0",
- "parse5": "^5.1.1",
- "parse5-htmlparser2-tree-adapter": "^6.0.0",
- "yargs": "^16.0.0"
- },
- "bin": {
- "highlight": "bin/highlight"
- },
- "engines": {
- "node": ">=8.0.0",
- "npm": ">=5.0.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/cli-spinners": {
- "version": "2.6.1",
- "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.6.1.tgz",
- "integrity": "sha512-x/5fWmGMnbKQAaNwN+UZlV79qBLM9JFnJuJ03gIi5whrob0xV0ofNVHy9DhwGdsMJQc2OKv0oGmLzvaqvAVv+g==",
+ "version": "2.9.2",
+ "resolved": "https://registry.npmjs.org/cli-spinners/-/cli-spinners-2.9.2.tgz",
+ "integrity": "sha512-ywqV+5MmyL4E7ybXgKys4DugZbX0FC6LnwrhjuykIjnK9k8OQacQ7axGKnjDXWNhns0xot3bZI5h55H8yo9cJg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
},
@@ -4785,20 +4810,12 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/cli-width": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-3.0.0.tgz",
- "integrity": "sha512-FxqpkPPwu1HjuN93Omfm4h8uIanXofW0RxVEW3k5RKx+mJJYSthzNhp32Kzxxy3YAEZ/Dc/EWN1vZRY0+kOhbw==",
- "dev": true,
- "engines": {
- "node": ">= 10"
- }
- },
"node_modules/clipboardy": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/clipboardy/-/clipboardy-2.3.0.tgz",
"integrity": "sha512-mKhiIL2DrQIsuXMgBgnfEHOZOryC7kY7YO//TN6c63wlEm3NG5tz+YgY5rVi29KCmq/QQjKYvM7a19+MDOTHOQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"arch": "^2.1.1",
"execa": "^1.0.0",
@@ -4809,137 +4826,66 @@
}
},
"node_modules/cliui": {
- "version": "6.0.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
- "integrity": "sha512-t6wbgtoCXvAzst7QgXxJYqPt0usEfbgQdftEPbLL/cvv6HPE5VgvqCuAIDR0NgU52ds6rFwqrgakNLrHEjCbrQ==",
+ "version": "7.0.4",
+ "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
+ "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"string-width": "^4.2.0",
"strip-ansi": "^6.0.0",
- "wrap-ansi": "^6.2.0"
+ "wrap-ansi": "^7.0.0"
}
},
"node_modules/clone": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/clone/-/clone-1.0.4.tgz",
- "integrity": "sha1-2jCcwmPfFZlMaIypAheco8fNfH4= sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
+ "integrity": "sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.8"
}
},
- "node_modules/coa": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/coa/-/coa-2.0.2.tgz",
- "integrity": "sha512-q5/jG+YQnSy4nRTV4F7lPepBJZ8qBNJJDBuJdoejDyLXgmL7IEo+Le2JDZudFTFt7mrCqIRaSjws4ygRCTCAXA==",
- "dev": true,
- "dependencies": {
- "@types/q": "^1.5.1",
- "chalk": "^2.4.1",
- "q": "^1.1.2"
- },
- "engines": {
- "node": ">= 4.0"
- }
- },
- "node_modules/coa/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/coa/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/coa/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/coa/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/coa/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/coa/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/collection-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/collection-visit/-/collection-visit-1.0.0.tgz",
- "integrity": "sha1-S8A3PBZLwykbTTaMgpzxqApZ3KA= sha512-lNkKvzEeMBBjUGHZ+q6z9pSJla0KWAQPvtzhEV9+iGyQYG+pBpl7xKDhxoNSOZH2hhv0v5k0y2yAM4o4SjoSkw==",
+ "node_modules/clone-deep": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/clone-deep/-/clone-deep-4.0.1.tgz",
+ "integrity": "sha512-neHB9xuzh/wk0dIHweyAXv2aPGZIVk3pLMe+/RNzINf17fe0OG96QroktYAUm7SM1PBnzTabaLboqqxDyMU+SQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "map-visit": "^1.0.0",
- "object-visit": "^1.0.0"
+ "is-plain-object": "^2.0.4",
+ "kind-of": "^6.0.2",
+ "shallow-clone": "^3.0.0"
},
"engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/color": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/color/-/color-4.1.0.tgz",
- "integrity": "sha512-o2rkkxyLGgYoeUy1OodXpbPAQNmlNBrirQ8ODO8QutzDiDMNdezSOZLNnusQ6pUpCQJUsaJIo9DZJKqa2HgH7A==",
- "dev": true,
- "dependencies": {
- "color-convert": "^2.0.1",
- "color-string": "^1.9.0"
+ "node": ">=6"
}
},
"node_modules/color-alpha": {
"version": "1.0.4",
"resolved": "https://registry.npmjs.org/color-alpha/-/color-alpha-1.0.4.tgz",
"integrity": "sha512-lr8/t5NPozTSqli+duAN+x+no/2WaKTeWvxhHGN+aXT6AJ8vPlzLa7UriyjWak0pSC2jHol9JgjBYnnHsGha9A==",
+ "license": "MIT",
"dependencies": {
"color-parse": "^1.3.8"
}
},
+ "node_modules/color-alpha/node_modules/color-parse": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.3.tgz",
+ "integrity": "sha512-BADfVl/FHkQkyo8sRBwMYBqemqsgnu7JZAwUgvBvuwwuNUZAhSvLTbsEErS5bQXzOjDR0dWzJ4vXN2Q+QoPx0A==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "^1.0.0"
+ }
+ },
"node_modules/color-convert": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"color-name": "~1.1.4"
},
@@ -4951,6 +4897,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/color-id/-/color-id-1.1.0.tgz",
"integrity": "sha512-2iRtAn6dC/6/G7bBIo0uupVrIne1NsQJvJxZOBCzQOfk7jRq97feaDZ3RdzuHakRXXnHGNwglto3pqtRx1sX0g==",
+ "license": "MIT",
"dependencies": {
"clamp": "^1.0.1"
}
@@ -4958,12 +4905,14 @@
"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=="
+ "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
+ "license": "MIT"
},
"node_modules/color-normalize": {
"version": "1.5.0",
"resolved": "https://registry.npmjs.org/color-normalize/-/color-normalize-1.5.0.tgz",
"integrity": "sha512-rUT/HDXMr6RFffrR53oX3HGWkDOP9goSAQGBkUaAYKjOE2JxozccdGyufageWDlInRAjm/jYPrf/Y38oa+7obw==",
+ "license": "MIT",
"dependencies": {
"clamp": "^1.0.1",
"color-rgba": "^2.1.1",
@@ -4971,56 +4920,63 @@
}
},
"node_modules/color-parse": {
- "version": "1.3.8",
- "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.3.8.tgz",
- "integrity": "sha512-1Y79qFv0n1xair3lNMTNeoFvmc3nirMVBij24zbs1f13+7fPpQClMg5b4AuKXLt3szj7BRlHMCXHplkce6XlmA==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-2.0.0.tgz",
+ "integrity": "sha512-g2Z+QnWsdHLppAbrpcFWo629kLOnOPtpxYV69GCqm92gqSgyXbzlfyN3MXs0412fPBkFmiuS+rXposgBgBa6Kg==",
+ "license": "MIT",
"dependencies": {
- "color-name": "^1.0.0",
- "defined": "^1.0.0",
- "is-plain-obj": "^1.1.0"
- }
- },
- "node_modules/color-parse/node_modules/is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
- "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4= sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
- "engines": {
- "node": ">=0.10.0"
+ "color-name": "^1.0.0"
}
},
"node_modules/color-rgba": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/color-rgba/-/color-rgba-2.1.1.tgz",
"integrity": "sha512-VaX97wsqrMwLSOR6H7rU1Doa2zyVdmShabKrPEIFywLlHoibgD3QW9Dw6fSqM4+H/LfjprDNAUUW31qEQcGzNw==",
+ "license": "MIT",
"dependencies": {
"clamp": "^1.0.1",
"color-parse": "^1.3.8",
"color-space": "^1.14.6"
}
},
+ "node_modules/color-rgba/node_modules/color-parse": {
+ "version": "1.4.3",
+ "resolved": "https://registry.npmjs.org/color-parse/-/color-parse-1.4.3.tgz",
+ "integrity": "sha512-BADfVl/FHkQkyo8sRBwMYBqemqsgnu7JZAwUgvBvuwwuNUZAhSvLTbsEErS5bQXzOjDR0dWzJ4vXN2Q+QoPx0A==",
+ "license": "MIT",
+ "dependencies": {
+ "color-name": "^1.0.0"
+ }
+ },
"node_modules/color-space": {
"version": "1.16.0",
"resolved": "https://registry.npmjs.org/color-space/-/color-space-1.16.0.tgz",
"integrity": "sha512-A6WMiFzunQ8KEPFmj02OnnoUnqhmSaHaZ/0LVFcPTdlvm8+3aMJ5x1HRHy3bDHPkovkf4sS0f4wsVvwk71fKkg==",
+ "license": "MIT",
"dependencies": {
"hsluv": "^0.0.3",
"mumath": "^3.3.4"
}
},
- "node_modules/color-string": {
- "version": "1.9.0",
- "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.9.0.tgz",
- "integrity": "sha512-9Mrz2AQLefkH1UvASKj6v6hj/7eWgjnT/cVsR8CumieLoT+g900exWeNogqtweI8dxloXN9BDQTYro1oWu/5CQ==",
+ "node_modules/colord": {
+ "version": "2.9.3",
+ "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz",
+ "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==",
"dev": true,
- "dependencies": {
- "color-name": "^1.0.0",
- "simple-swizzle": "^0.2.2"
- }
+ "license": "MIT"
+ },
+ "node_modules/colorette": {
+ "version": "2.0.20",
+ "resolved": "https://registry.npmjs.org/colorette/-/colorette-2.0.20.tgz",
+ "integrity": "sha512-IfEDxwoWIjkeXL1eXcDiow4UbKjhLdq6/EuSVR9GMN7KVH3r9gQ83e73hsz1Nd1T3ijd5xv1wcWRYO+D6kCI2w==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
"integrity": "sha512-FQN4MRfuJeHf7cBbBMJFXhKSDq+2kAArBlmRBvcvFE5BB1HZKXtSFASDhdlz9zOYwxh8lDdnvmMOe/+5cdoEdg==",
+ "license": "MIT",
"dependencies": {
"delayed-stream": "~1.0.0"
},
@@ -5029,39 +4985,41 @@
}
},
"node_modules/commander": {
- "version": "2.17.1",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.17.1.tgz",
- "integrity": "sha512-wPMUt6FnH2yzG95SA6mzjQOEKUU3aLaDEmzs1ti+1E9h+CsrZghRlqEM/EJ4KscsQVG8uNN4uVreUeT8+drlgg=="
+ "version": "8.3.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
+ "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 12"
+ }
},
"node_modules/commondir": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz",
- "integrity": "sha1-3dgA2gxmEnOTzKWVDqloo6rxJTs= sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
- "dev": true
+ "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/complex.js": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.1.1.tgz",
- "integrity": "sha512-8njCHOTtFFLtegk6zQo0kkVX1rngygb/KQI6z1qZxlFI3scluC+LVTCFbrkWjBv4vvLlbQ9t88IPMC6k95VTTg==",
+ "version": "2.4.3",
+ "resolved": "https://registry.npmjs.org/complex.js/-/complex.js-2.4.3.tgz",
+ "integrity": "sha512-UrQVSUur14tNX6tiP4y8T4w4FeJAX3bi2cIv0pu/DTLFNxoq7z2Yh83Vfzztj6Px3X/lubqQ9IrPp7Bpn6p4MQ==",
+ "license": "MIT",
"engines": {
"node": "*"
},
"funding": {
- "type": "patreon",
- "url": "https://www.patreon.com/infusion"
+ "type": "github",
+ "url": "https://github.com/sponsors/rawify"
}
},
- "node_modules/component-emitter": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/component-emitter/-/component-emitter-1.3.0.tgz",
- "integrity": "sha512-Rd3se6QB+sO1TwqZjscQrurpEPIfO0/yYnSin6Q/rD3mOutHvUrCAhJub3r90uNb+SESBuE0QYoB90YdfatsRg==",
- "dev": true
- },
"node_modules/compressible": {
"version": "2.0.18",
"resolved": "https://registry.npmjs.org/compressible/-/compressible-2.0.18.tgz",
"integrity": "sha512-AF3r7P5dWxL8MxyITRMlORQNaOA2IkAFaTr4k7BUumjPtRpGDTZpl0Pb1XCO6JeDCBdp126Cgs9sMxqSjgYyRg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"mime-db": ">= 1.43.0 < 2"
},
@@ -5070,37 +5028,30 @@
}
},
"node_modules/compression": {
- "version": "1.7.4",
- "resolved": "https://registry.npmjs.org/compression/-/compression-1.7.4.tgz",
- "integrity": "sha512-jaSIDzP9pZVS4ZfQ+TzvtiWhdpFhE2RDHz8QJkpX9SIpLq88VueF5jJw6t+6CUQcAoA6t+x89MLrWAqpfDE8iQ==",
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/compression/-/compression-1.8.1.tgz",
+ "integrity": "sha512-9mAqGPHLakhCLeNyxPkK4xVo746zQ/czLH1Ky+vkitMnWfWZps8r0qXuwhwizagCRttsL4lfG4pIOvaWLpAP0w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "accepts": "~1.3.5",
- "bytes": "3.0.0",
- "compressible": "~2.0.16",
+ "bytes": "3.1.2",
+ "compressible": "~2.0.18",
"debug": "2.6.9",
- "on-headers": "~1.0.2",
- "safe-buffer": "5.1.2",
+ "negotiator": "~0.6.4",
+ "on-headers": "~1.1.0",
+ "safe-buffer": "5.2.1",
"vary": "~1.1.2"
},
"engines": {
"node": ">= 0.8.0"
}
},
- "node_modules/compression/node_modules/bytes": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz",
- "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg= sha512-pMhOfFDPiv9t5jjIXkHosWmkSyQbvsgEVNkz0ERHbuLh2T/7j4Mqqpz523Fe8MVY89KC6Sh/QfS2sM+SjgFDcw==",
- "dev": true,
- "engines": {
- "node": ">= 0.8"
- }
- },
"node_modules/compression/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@@ -5108,14 +5059,9 @@
"node_modules/compression/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "node_modules/concat-map": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s= sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
- "dev": true
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/concat-stream": {
"version": "1.6.2",
@@ -5124,6 +5070,7 @@
"engines": [
"node >= 0.8"
],
+ "license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"inherits": "^2.0.3",
@@ -5131,354 +5078,194 @@
"typedarray": "^0.0.6"
}
},
- "node_modules/connect-history-api-fallback": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-1.6.0.tgz",
- "integrity": "sha512-e54B99q/OUoH64zYYRf3HBP5z24G38h5D3qXu23JGRoigpX5Ss4r9ZnDk3g0Z8uQC2x2lPaJ+UlWBc1ZWBWdLg==",
- "dev": true,
- "engines": {
- "node": ">=0.8"
- }
- },
- "node_modules/console-browserify": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/console-browserify/-/console-browserify-1.2.0.tgz",
- "integrity": "sha512-ZMkYO/LkF17QvCPqM0gxw8yUzigAOZOSWSHg91FH6orS7vcEj5dVZTidN2fQ14yBSdg97RqhSNwLUXInd52OTA==",
- "dev": true
+ "node_modules/concat-stream/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "license": "MIT"
},
- "node_modules/consolidate": {
- "version": "0.15.1",
- "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz",
- "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==",
- "deprecated": "Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog",
- "dev": true,
+ "node_modules/concat-stream/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
"dependencies": {
- "bluebird": "^3.1.1"
- },
- "engines": {
- "node": ">= 0.10.0"
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
}
},
- "node_modules/constants-browserify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/constants-browserify/-/constants-browserify-1.0.0.tgz",
- "integrity": "sha1-wguW2MYXdIqvHBYCF2DNJ/y4y3U= sha512-xFxOwqIzR/e1k1gLiWEophSCMqXcwVHIH7akf7b/vxcUeGunlj3hvZaaqxwHsTgn+IndtkQJgSztIDWeumWJDQ==",
- "dev": true
+ "node_modules/concat-stream/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/concat-stream/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/connect-history-api-fallback": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/connect-history-api-fallback/-/connect-history-api-fallback-2.0.0.tgz",
+ "integrity": "sha512-U73+6lQFmfiNPrYbXqr6kZ1i1wiRqXnp2nhMsINseWXO8lDau0LGEffJ8kQi4EjLZympVgRdvqjAgiZ1tgzDDA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.8"
+ }
+ },
+ "node_modules/consolidate": {
+ "version": "0.15.1",
+ "resolved": "https://registry.npmjs.org/consolidate/-/consolidate-0.15.1.tgz",
+ "integrity": "sha512-DW46nrsMJgy9kqAbPt5rKaCr7uFtpo4mSUvLHIUbJEjm0vo+aY5QLwBUq3FK4tRnJr/X0Psc0C4jf/h+HtXSMw==",
+ "deprecated": "Please upgrade to consolidate v1.0.0+ as it has been modernized with several long-awaited fixes implemented. Maintenance is supported by Forward Email at https://forwardemail.net ; follow/watch https://github.com/ladjs/consolidate for updates and release changelog",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "bluebird": "^3.1.1"
+ },
+ "engines": {
+ "node": ">= 0.10.0"
+ }
},
"node_modules/content-disposition": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.3.tgz",
- "integrity": "sha512-ExO0774ikEObIAEV9kDo50o+79VCUdEB6n6lzKgGwupcVeRlhrj3qGAfwq8G6uBJjkqLrhT0qEYFcWng8z1z0g==",
+ "version": "0.5.4",
+ "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.4.tgz",
+ "integrity": "sha512-FveZTNuGw04cxlAiWbzi6zTAL/lhehaWbTtgluJh4/E95DqMwTmha3KZN1aAWA8cFIhHzMZUvLevkw5Rqk+tSQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "safe-buffer": "5.1.2"
+ "safe-buffer": "5.2.1"
},
"engines": {
"node": ">= 0.6"
}
},
"node_modules/content-type": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz",
- "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==",
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz",
+ "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/convert-source-map": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-1.8.0.tgz",
- "integrity": "sha512-+OQdjP49zViI/6i7nIJpA8rAl4sV/JdPfU9nZs3VqOwGIgizICvuN2ru6fMd+4llL0tar18UYJXfZ/TWtmhUjA==",
+ "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,
- "dependencies": {
- "safe-buffer": "~5.1.1"
- }
+ "license": "MIT"
},
"node_modules/cookie": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.4.0.tgz",
- "integrity": "sha512-+Hp8fLp57wnUSt0tY0tHEXh4voZRDnoIrZPqlo3DPiI4y9lwg/jqx+1Om94/W6ZaPDOUbnjOt/99w66zk+l1Xg==",
+ "version": "0.7.2",
+ "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz",
+ "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/cookie-signature": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz",
- "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw= sha512-QADzlaHc8icV8I7vbaJXJwod9HWYp8uCqf1xa4OfNu1T7JVxQIrUgOWtHdNDtPiywmFbiS12VjotIXLrKM3orQ==",
- "dev": true
- },
- "node_modules/copy-concurrently": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/copy-concurrently/-/copy-concurrently-1.0.5.tgz",
- "integrity": "sha512-f2domd9fsVDFtaFcbaRZuYXwtdmnzqbADSwhSWYxYB/Q8zsdUUFMXVRwXGDMWmbEzAn1kdRrtI1T/KTFOL4X2A==",
- "deprecated": "This package is no longer supported.",
- "dev": true,
- "dependencies": {
- "aproba": "^1.1.1",
- "fs-write-stream-atomic": "^1.0.8",
- "iferr": "^0.1.5",
- "mkdirp": "^0.5.1",
- "rimraf": "^2.5.4",
- "run-queue": "^1.0.0"
- }
- },
- "node_modules/copy-descriptor": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/copy-descriptor/-/copy-descriptor-0.1.1.tgz",
- "integrity": "sha1-Z29us8OZl8LuGsOpJP1hJHSPV40= sha512-XgZ0pFcakEUlbwQEVNg3+QAis1FyTL3Qel9FYy8pSkQqoG3PNoT0bOCQtOXcOkur21r2Eq2kI+IE+gsmAEVlYw==",
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.7.tgz",
+ "integrity": "sha512-NXdYc3dLr47pBkpUCHtKSwIOQXLVn8dZEuywboCOJY/osA0wFSLlSawr3KN8qXJEyX66FcONTH8EIlVuK0yyFA==",
"dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
+ "license": "MIT"
},
"node_modules/copy-webpack-plugin": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-5.1.2.tgz",
- "integrity": "sha512-Uh7crJAco3AjBvgAy9Z75CjK8IG+gxaErro71THQ+vv/bl4HaQcpkexAY8KVW/T6D2W2IRr+couF/knIRkZMIQ==",
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/copy-webpack-plugin/-/copy-webpack-plugin-9.1.0.tgz",
+ "integrity": "sha512-rxnR7PaGigJzhqETHGmAcxKnLZSR5u1Y3/bcIv/1FnqXedcL/E2ewK7ZCNrArJKCiSv8yVXhTqetJh8inDvfsA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cacache": "^12.0.3",
- "find-cache-dir": "^2.1.0",
- "glob-parent": "^3.1.0",
- "globby": "^7.1.1",
- "is-glob": "^4.0.1",
- "loader-utils": "^1.2.3",
- "minimatch": "^3.0.4",
+ "fast-glob": "^3.2.7",
+ "glob-parent": "^6.0.1",
+ "globby": "^11.0.3",
"normalize-path": "^3.0.0",
- "p-limit": "^2.2.1",
- "schema-utils": "^1.0.0",
- "serialize-javascript": "^4.0.0",
- "webpack-log": "^2.0.0"
+ "schema-utils": "^3.1.1",
+ "serialize-javascript": "^6.0.0"
},
"engines": {
- "node": ">= 6.9.0"
+ "node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
- "webpack": "^4.0.0 || ^5.0.0"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/find-cache-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
- "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
- "dev": true,
- "dependencies": {
- "commondir": "^1.0.1",
- "make-dir": "^2.0.0",
- "pkg-dir": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "dependencies": {
- "locate-path": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
- "dev": true,
- "dependencies": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/glob-parent/node_modules/is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/globby": {
- "version": "7.1.1",
- "resolved": "https://registry.npmjs.org/globby/-/globby-7.1.1.tgz",
- "integrity": "sha1-+yzP+UAfhgCUXfral0QMypcrhoA= sha512-yANWAN2DUcBtuus5Cpd+SKROzXHs2iVXFZt/Ykrfz6SAXqacLX25NZpltE+39ceMexYF4TtEadjuSTw8+3wX4g==",
- "dev": true,
- "dependencies": {
- "array-union": "^1.0.1",
- "dir-glob": "^2.0.0",
- "glob": "^7.1.2",
- "ignore": "^3.3.5",
- "pify": "^3.0.0",
- "slash": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/globby/node_modules/pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/ignore": {
- "version": "3.3.10",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-3.3.10.tgz",
- "integrity": "sha512-Pgs951kaMm5GXP7MOvxERINe3gsaVjUWFm+UZPSq9xYriQAksyhg0csnS0KXSNRD5NmNdapXEpjxG49+AKh/ug==",
- "dev": true
- },
- "node_modules/copy-webpack-plugin/node_modules/locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "dependencies": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/make-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
- "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
- "dev": true,
- "dependencies": {
- "pify": "^4.0.1",
- "semver": "^5.6.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "dependencies": {
- "p-limit": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/pkg-dir": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
- "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
- "dev": true,
- "dependencies": {
- "find-up": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
+ "webpack": "^5.1.0"
}
},
"node_modules/copy-webpack-plugin/node_modules/schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
- "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
},
"engines": {
- "node": ">= 4"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true,
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/copy-webpack-plugin/node_modules/slash": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-1.0.0.tgz",
- "integrity": "sha1-xB8vbDn8FtHNF61LXYlhFK5HDVU= sha512-3TYDR7xWt4dIqV2JauJr+EJeW356RXijHeUlO+8djJ+uBXPn8/2dpzBc8yQhh583sVvc9CvFAeQVgijsH+PNNg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/core-js": {
- "version": "3.19.3",
- "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.19.3.tgz",
- "integrity": "sha512-LeLBMgEGSsG7giquSzvgBrTS7V5UL6ks3eQlUSbN8dJStlLFiRzUm5iqsRyzUB8carhfKjkJ2vzKqE6z1Vga9g==",
- "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.",
+ "version": "3.49.0",
+ "resolved": "https://registry.npmjs.org/core-js/-/core-js-3.49.0.tgz",
+ "integrity": "sha512-es1U2+YTtzpwkxVLwAFdSpaIMyQaq0PBgm3YD1W3Qpsn1NAmO3KSgZfu+oGSWVu6NvLHoHCV/aYcsE5wiB7ALg==",
"hasInstallScript": true,
+ "license": "MIT",
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
"node_modules/core-js-compat": {
- "version": "3.19.3",
- "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.19.3.tgz",
- "integrity": "sha512-59tYzuWgEEVU9r+SRgceIGXSSUn47JknoiXW6Oq7RW8QHjXWz3/vp8pa7dbtuVu40sewz3OP3JmQEcDdztrLhA==",
+ "version": "3.49.0",
+ "resolved": "https://registry.npmjs.org/core-js-compat/-/core-js-compat-3.49.0.tgz",
+ "integrity": "sha512-VQXt1jr9cBz03b331DFDCCP90b3fanciLkgiOoy8SBHy06gNf+vQ1A3WFLqG7I8TipYIKeYK9wxd0tUrvHcOZA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "browserslist": "^4.18.1",
- "semver": "7.0.0"
+ "browserslist": "^4.28.1"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/core-js"
}
},
- "node_modules/core-js-compat/node_modules/semver": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-7.0.0.tgz",
- "integrity": "sha512-+GB6zVA9LWh6zovYQLALHwv5rb2PHGlJi3lfiqIHxR0uuwCgefcOJc59v9fv1w8GbStwxuuqqAjI9NMAOOgq1A==",
- "dev": true,
- "bin": {
- "semver": "bin/semver.js"
- }
- },
"node_modules/core-util-is": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.3.tgz",
- "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ=="
+ "integrity": "sha512-ZQBvi1DcpJ4GDqanjucZ2Hj3wEO5pZDS89BWbkcrvdxksJorwUDDZamX9ldFkp9aw2lmBDLgkObEA4DWNJ9FYQ==",
+ "license": "MIT"
},
"node_modules/cosmiconfig": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.0.1.tgz",
- "integrity": "sha512-a1YWNUV2HwGimB7dU2s1wUMurNKjpx60HxBB6xUM8Re+2s1g1IIfJvFR0/iCF+XHdE0GMTKTuLR32UQff4TEyQ==",
+ "version": "7.1.0",
+ "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-7.1.0.tgz",
+ "integrity": "sha512-AdmX6xUzdNASswsFtmwSt7Vj8po9IuqXm0UXz7QKPuEUmPB4XyjGfaAr2PSuELMwkRMVH1EpIkX5bTZGRB3eCA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/parse-json": "^4.0.0",
"import-fresh": "^3.2.1",
@@ -5493,124 +5280,42 @@
"node_modules/country-regex": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/country-regex/-/country-regex-1.1.0.tgz",
- "integrity": "sha512-iSPlClZP8vX7MC3/u6s3lrDuoQyhQukh5LyABJ3hvfzbQ3Yyayd4fp04zjLnfi267B/B2FkumcWWgrbban7sSA=="
- },
- "node_modules/create-ecdh": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/create-ecdh/-/create-ecdh-4.0.4.tgz",
- "integrity": "sha512-mf+TCx8wWc9VpuxfP2ht0iSISLZnt0JgWlrOKZiNqyUZWnjIaCIVNQArMHnCZKfEYRg6IM7A+NeJoN8gf/Ws0A==",
- "dev": true,
- "dependencies": {
- "bn.js": "^4.1.0",
- "elliptic": "^6.5.3"
- }
- },
- "node_modules/create-ecdh/node_modules/bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
- "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
- "dev": true
- },
- "node_modules/create-hash": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/create-hash/-/create-hash-1.2.0.tgz",
- "integrity": "sha512-z00bCGNHDG8mHAkP7CtT1qVu+bFQUPjYq/4Iv3C3kWjTFV10zIjfSoeqXo9Asws8gwSHDGj/hl2u4OGIjapeCg==",
- "dev": true,
- "dependencies": {
- "cipher-base": "^1.0.1",
- "inherits": "^2.0.1",
- "md5.js": "^1.3.4",
- "ripemd160": "^2.0.1",
- "sha.js": "^2.4.0"
- }
- },
- "node_modules/create-hmac": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/create-hmac/-/create-hmac-1.1.7.tgz",
- "integrity": "sha512-MJG9liiZ+ogc4TzUwuvbER1JRdgvUFSB5+VR/g5h82fGaIRWMWddtKBHi7/sVhfjQZ6SehlyhvQYrcYkaUIpLg==",
- "dev": true,
- "dependencies": {
- "cipher-base": "^1.0.3",
- "create-hash": "^1.1.0",
- "inherits": "^2.0.1",
- "ripemd160": "^2.0.0",
- "safe-buffer": "^5.0.1",
- "sha.js": "^2.4.8"
- }
+ "integrity": "sha512-iSPlClZP8vX7MC3/u6s3lrDuoQyhQukh5LyABJ3hvfzbQ3Yyayd4fp04zjLnfi267B/B2FkumcWWgrbban7sSA==",
+ "license": "MIT"
},
"node_modules/cross-spawn": {
- "version": "6.0.5",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz",
- "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==",
- "dev": true,
- "dependencies": {
- "nice-try": "^1.0.4",
- "path-key": "^2.0.1",
- "semver": "^5.5.0",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- },
- "engines": {
- "node": ">=4.8"
- }
- },
- "node_modules/cross-spawn/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true,
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/crypto-browserify": {
- "version": "3.12.0",
- "resolved": "https://registry.npmjs.org/crypto-browserify/-/crypto-browserify-3.12.0.tgz",
- "integrity": "sha512-fz4spIh+znjO2VjL+IdhEpRJ3YN6sMzITSBijk6FK2UvTqruSQW+/cCZTSNsMiZNvUeq0CqurF+dAbyiGOY6Wg==",
+ "version": "7.0.6",
+ "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.6.tgz",
+ "integrity": "sha512-uV2QOWP2nWzsy2aMp8aRibhi9dlzF5Hgh5SHaB9OiTGEyDTiJJyx0uy51QXdyWbtAHNua4XJzUKca3OzKUd3vA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "browserify-cipher": "^1.0.0",
- "browserify-sign": "^4.0.0",
- "create-ecdh": "^4.0.0",
- "create-hash": "^1.1.0",
- "create-hmac": "^1.1.0",
- "diffie-hellman": "^5.0.0",
- "inherits": "^2.0.1",
- "pbkdf2": "^3.0.3",
- "public-encrypt": "^4.0.0",
- "randombytes": "^2.0.0",
- "randomfill": "^1.0.3"
+ "path-key": "^3.1.0",
+ "shebang-command": "^2.0.0",
+ "which": "^2.0.1"
},
"engines": {
- "node": "*"
- }
- },
- "node_modules/css-color-names": {
- "version": "0.0.4",
- "resolved": "https://registry.npmjs.org/css-color-names/-/css-color-names-0.0.4.tgz",
- "integrity": "sha1-gIrcLnnPhHOAabZGyyDsJ762KeA= sha512-zj5D7X1U2h2zsXOAM8EyUREBnnts6H+Jm+d1M2DbiQQcUtnqgQsMrdo8JW9R80YFUmIdBZeMu5wvYM7hcgWP/Q==",
- "dev": true,
- "engines": {
- "node": "*"
+ "node": ">= 8"
}
},
"node_modules/css-declaration-sorter": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-4.0.1.tgz",
- "integrity": "sha512-BcxQSKTSEEQUftYpBVnsH4SF05NTuBokb19/sBt6asXGKZ/6VP7PLG1CBCkFDYOnhXhPh0jMhO6xZ71oYHXHBA==",
+ "version": "6.4.1",
+ "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz",
+ "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==",
"dev": true,
- "dependencies": {
- "postcss": "^7.0.1",
- "timsort": "^0.3.0"
- },
+ "license": "ISC",
"engines": {
- "node": ">4"
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.0.9"
}
},
"node_modules/css-font": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/css-font/-/css-font-1.2.0.tgz",
"integrity": "sha512-V4U4Wps4dPDACJ4WpgofJ2RT5Yqwe1lEH6wlOOaIxMi0gTjdIijsc5FmxQlZ7ZZyKQkkutqqvULOp07l9c7ssA==",
+ "license": "MIT",
"dependencies": {
"css-font-size-keywords": "^1.0.0",
"css-font-stretch-keywords": "^1.0.1",
@@ -5626,128 +5331,208 @@
"node_modules/css-font-size-keywords": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-font-size-keywords/-/css-font-size-keywords-1.0.0.tgz",
- "integrity": "sha512-Q+svMDbMlelgCfH/RVDKtTDaf5021O486ZThQPIpahnIjUkMUslC+WuOQSWTgGSrNCH08Y7tYNEmmy0hkfMI8Q=="
+ "integrity": "sha512-Q+svMDbMlelgCfH/RVDKtTDaf5021O486ZThQPIpahnIjUkMUslC+WuOQSWTgGSrNCH08Y7tYNEmmy0hkfMI8Q==",
+ "license": "MIT"
},
"node_modules/css-font-stretch-keywords": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/css-font-stretch-keywords/-/css-font-stretch-keywords-1.0.1.tgz",
- "integrity": "sha512-KmugPO2BNqoyp9zmBIUGwt58UQSfyk1X5DbOlkb2pckDXFSAfjsD5wenb88fNrD6fvS+vu90a/tsPpb9vb0SLg=="
+ "integrity": "sha512-KmugPO2BNqoyp9zmBIUGwt58UQSfyk1X5DbOlkb2pckDXFSAfjsD5wenb88fNrD6fvS+vu90a/tsPpb9vb0SLg==",
+ "license": "MIT"
},
"node_modules/css-font-style-keywords": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/css-font-style-keywords/-/css-font-style-keywords-1.0.1.tgz",
- "integrity": "sha512-0Fn0aTpcDktnR1RzaBYorIxQily85M2KXRpzmxQPgh8pxUN9Fcn00I8u9I3grNr1QXVgCl9T5Imx0ZwKU973Vg=="
+ "integrity": "sha512-0Fn0aTpcDktnR1RzaBYorIxQily85M2KXRpzmxQPgh8pxUN9Fcn00I8u9I3grNr1QXVgCl9T5Imx0ZwKU973Vg==",
+ "license": "MIT"
},
"node_modules/css-font-weight-keywords": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-font-weight-keywords/-/css-font-weight-keywords-1.0.0.tgz",
- "integrity": "sha512-5So8/NH+oDD+EzsnF4iaG4ZFHQ3vaViePkL1ZbZ5iC/KrsCY+WHq/lvOgrtmuOQ9pBBZ1ADGpaf+A4lj1Z9eYA=="
+ "integrity": "sha512-5So8/NH+oDD+EzsnF4iaG4ZFHQ3vaViePkL1ZbZ5iC/KrsCY+WHq/lvOgrtmuOQ9pBBZ1ADGpaf+A4lj1Z9eYA==",
+ "license": "MIT"
},
"node_modules/css-global-keywords": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/css-global-keywords/-/css-global-keywords-1.0.1.tgz",
- "integrity": "sha512-X1xgQhkZ9n94WDwntqst5D/FKkmiU0GlJSFZSV3kLvyJ1WC5VeyoXDOuleUD+SIuH9C7W05is++0Woh0CGfKjQ=="
+ "integrity": "sha512-X1xgQhkZ9n94WDwntqst5D/FKkmiU0GlJSFZSV3kLvyJ1WC5VeyoXDOuleUD+SIuH9C7W05is++0Woh0CGfKjQ==",
+ "license": "MIT"
},
"node_modules/css-loader": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz",
- "integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==",
+ "version": "6.11.0",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-6.11.0.tgz",
+ "integrity": "sha512-CTJ+AEQJjq5NzLga5pE39qdiSV56F8ywCIsqNIRF0r7BDgWsN25aazToqAFg7ZrtA/U016xudB3ffgweORxX7g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "camelcase": "^5.3.1",
- "cssesc": "^3.0.0",
- "icss-utils": "^4.1.1",
- "loader-utils": "^1.2.3",
- "normalize-path": "^3.0.0",
- "postcss": "^7.0.32",
- "postcss-modules-extract-imports": "^2.0.0",
- "postcss-modules-local-by-default": "^3.0.2",
- "postcss-modules-scope": "^2.2.0",
- "postcss-modules-values": "^3.0.0",
- "postcss-value-parser": "^4.1.0",
- "schema-utils": "^2.7.0",
- "semver": "^6.3.0"
+ "icss-utils": "^5.1.0",
+ "postcss": "^8.4.33",
+ "postcss-modules-extract-imports": "^3.1.0",
+ "postcss-modules-local-by-default": "^4.0.5",
+ "postcss-modules-scope": "^3.2.0",
+ "postcss-modules-values": "^4.0.0",
+ "postcss-value-parser": "^4.2.0",
+ "semver": "^7.5.4"
},
"engines": {
- "node": ">= 8.9.0"
+ "node": ">= 12.13.0"
},
"funding": {
"type": "opencollective",
"url": "https://opencollective.com/webpack"
},
"peerDependencies": {
- "webpack": "^4.0.0 || ^5.0.0"
+ "@rspack/core": "0.x || 1.x",
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/core": {
+ "optional": true
+ },
+ "webpack": {
+ "optional": true
+ }
}
},
- "node_modules/css-loader/node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "node_modules/css-minimizer-webpack-plugin": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/css-minimizer-webpack-plugin/-/css-minimizer-webpack-plugin-3.4.1.tgz",
+ "integrity": "sha512-1u6D71zeIfgngN2XNRJefc/hY7Ybsxd74Jm4qngIXyUEk7fss3VUzuHxLAq/R8NAba4QU9OUSaMZlbpRc7bM4Q==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "cssnano": "^5.0.6",
+ "jest-worker": "^27.0.2",
+ "postcss": "^8.3.5",
+ "schema-utils": "^4.0.0",
+ "serialize-javascript": "^6.0.0",
+ "source-map": "^0.6.1"
+ },
"engines": {
- "node": ">=6"
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "@parcel/css": {
+ "optional": true
+ },
+ "clean-css": {
+ "optional": true
+ },
+ "csso": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/css-minimizer-webpack-plugin/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/css-minimizer-webpack-plugin/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/css-minimizer-webpack-plugin/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,
+ "license": "MIT"
+ },
+ "node_modules/css-minimizer-webpack-plugin/node_modules/schema-utils": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/css-select": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.1.3.tgz",
- "integrity": "sha512-gT3wBNd9Nj49rAbmtFHj1cljIAOLYSX1nZ8CB7TBO3INYckygm5B7LISU/szY//YmdiSLbJvDLOx9VnMVpMBxA==",
+ "version": "4.3.0",
+ "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz",
+ "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0",
- "css-what": "^5.0.0",
- "domhandler": "^4.2.0",
- "domutils": "^2.6.0",
- "nth-check": "^2.0.0"
+ "css-what": "^6.0.1",
+ "domhandler": "^4.3.1",
+ "domutils": "^2.8.0",
+ "nth-check": "^2.0.1"
},
"funding": {
"url": "https://github.com/sponsors/fb55"
}
},
- "node_modules/css-select-base-adapter": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/css-select-base-adapter/-/css-select-base-adapter-0.1.1.tgz",
- "integrity": "sha512-jQVeeRG70QI08vSTwf1jHxp74JoZsr2XSgETae8/xC8ovSnL2WF87GTLO86Sbwdt2lK4Umg4HnnwMO4YF3Ce7w==",
- "dev": true
- },
"node_modules/css-system-font-keywords": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/css-system-font-keywords/-/css-system-font-keywords-1.0.0.tgz",
- "integrity": "sha512-1umTtVd/fXS25ftfjB71eASCrYhilmEsvDEI6wG/QplnmlfmVM5HkZ/ZX46DT5K3eblFPgLUHt5BRCb0YXkSFA=="
+ "integrity": "sha512-1umTtVd/fXS25ftfjB71eASCrYhilmEsvDEI6wG/QplnmlfmVM5HkZ/ZX46DT5K3eblFPgLUHt5BRCb0YXkSFA==",
+ "license": "MIT"
},
"node_modules/css-tree": {
- "version": "1.0.0-alpha.37",
- "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.0.0-alpha.37.tgz",
- "integrity": "sha512-DMxWJg0rnz7UgxKT0Q1HU/L9BeJI0M6ksor0OgqOnF+aRCDWg/N2641HmVyU9KVIu0OVVWOb2IpC9A+BJRnejg==",
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
+ "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "mdn-data": "2.0.4",
+ "mdn-data": "2.0.14",
"source-map": "^0.6.1"
},
"engines": {
"node": ">=8.0.0"
}
},
- "node_modules/css-tree/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/css-unit-converter": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/css-unit-converter/-/css-unit-converter-1.1.2.tgz",
- "integrity": "sha512-IiJwMC8rdZE0+xiEZHeru6YoONC4rfPMqGm2W85jMIbkFvv5nFTwJVFHam2eFrN6txmoUYFAFXiv8ICVeTO0MA==",
- "dev": true
- },
"node_modules/css-what": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-5.1.0.tgz",
- "integrity": "sha512-arSMRWIIFY0hV8pIxZMEfmMI47Wj3R/aWpZDDxWYCPEiOMv6tfOrnpDtgxBYPEQD4V0Y/958+1TdC3iWTFcUPw==",
+ "version": "6.2.2",
+ "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz",
+ "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==",
"dev": true,
+ "license": "BSD-2-Clause",
"engines": {
"node": ">= 6"
},
@@ -5758,13 +5543,14 @@
"node_modules/csscolorparser": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/csscolorparser/-/csscolorparser-1.0.3.tgz",
- "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w=="
+ "integrity": "sha512-umPSgYwZkdFoUrH5hIq5kf0wPSXiro51nPw0j2K/c83KflkPSTBGMz6NJvMB+07VlL0y7VPo6QJcDjcgKTTm3w==",
+ "license": "MIT"
},
"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,
+ "license": "MIT",
"bin": {
"cssesc": "bin/cssesc"
},
@@ -5773,148 +5559,82 @@
}
},
"node_modules/cssnano": {
- "version": "4.1.11",
- "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-4.1.11.tgz",
- "integrity": "sha512-6gZm2htn7xIPJOHY824ERgj8cNPgPxyCSnkXc4v7YvNW+TdVfzgngHcEhy/8D11kUWRUMbke+tC+AUcUsnMz2g==",
+ "version": "5.1.15",
+ "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz",
+ "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cosmiconfig": "^5.0.0",
- "cssnano-preset-default": "^4.0.8",
- "is-resolvable": "^1.0.0",
- "postcss": "^7.0.0"
+ "cssnano-preset-default": "^5.2.14",
+ "lilconfig": "^2.0.3",
+ "yaml": "^1.10.2"
},
"engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/cssnano-preset-default": {
- "version": "4.0.8",
- "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-4.0.8.tgz",
- "integrity": "sha512-LdAyHuq+VRyeVREFmuxUZR1TXjQm8QQU/ktoo/x7bz+SdOge1YKc5eMN6pRW7YWBmyq59CqYba1dJ5cUukEjLQ==",
- "dev": true,
- "dependencies": {
- "css-declaration-sorter": "^4.0.1",
- "cssnano-util-raw-cache": "^4.0.1",
- "postcss": "^7.0.0",
- "postcss-calc": "^7.0.1",
- "postcss-colormin": "^4.0.3",
- "postcss-convert-values": "^4.0.1",
- "postcss-discard-comments": "^4.0.2",
- "postcss-discard-duplicates": "^4.0.2",
- "postcss-discard-empty": "^4.0.1",
- "postcss-discard-overridden": "^4.0.1",
- "postcss-merge-longhand": "^4.0.11",
- "postcss-merge-rules": "^4.0.3",
- "postcss-minify-font-values": "^4.0.2",
- "postcss-minify-gradients": "^4.0.2",
- "postcss-minify-params": "^4.0.2",
- "postcss-minify-selectors": "^4.0.2",
- "postcss-normalize-charset": "^4.0.1",
- "postcss-normalize-display-values": "^4.0.2",
- "postcss-normalize-positions": "^4.0.2",
- "postcss-normalize-repeat-style": "^4.0.2",
- "postcss-normalize-string": "^4.0.2",
- "postcss-normalize-timing-functions": "^4.0.2",
- "postcss-normalize-unicode": "^4.0.1",
- "postcss-normalize-url": "^4.0.1",
- "postcss-normalize-whitespace": "^4.0.2",
- "postcss-ordered-values": "^4.1.2",
- "postcss-reduce-initial": "^4.0.3",
- "postcss-reduce-transforms": "^4.0.2",
- "postcss-svgo": "^4.0.3",
- "postcss-unique-selectors": "^4.0.1"
+ "node": "^10 || ^12 || >=14.0"
},
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/cssnano-util-get-arguments": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/cssnano-util-get-arguments/-/cssnano-util-get-arguments-4.0.0.tgz",
- "integrity": "sha1-7ToIKZ8h11dBsg87gfGU7UnMFQ8= sha512-6RIcwmV3/cBMG8Aj5gucQRsJb4vv4I4rn6YjPbVWd5+Pn/fuG+YseGvXGk00XLkoZkaj31QOD7vMUpNPC4FIuw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/cssnano-util-get-match": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/cssnano-util-get-match/-/cssnano-util-get-match-4.0.0.tgz",
- "integrity": "sha1-wOTKB/U4a7F+xeUiULT1lhNlFW0= sha512-JPMZ1TSMRUPVIqEalIBNoBtAYbi8okvcFns4O0YIhcdGebeYZK7dMyHJiQ6GqNBA9kE0Hym4Aqym5rPdsV/4Cw==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/cssnano-util-raw-cache": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/cssnano-util-raw-cache/-/cssnano-util-raw-cache-4.0.1.tgz",
- "integrity": "sha512-qLuYtWK2b2Dy55I8ZX3ky1Z16WYsx544Q0UWViebptpwn/xDBmog2TLg4f+DBMg1rJ6JDWtn96WHbOKDWt1WQA==",
- "dev": true,
- "dependencies": {
- "postcss": "^7.0.0"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/cssnano"
},
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/cssnano-util-same-parent": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/cssnano-util-same-parent/-/cssnano-util-same-parent-4.0.1.tgz",
- "integrity": "sha512-WcKx5OY+KoSIAxBW6UBBRay1U6vkYheCdjyVNDm85zt5K9mHoGOfsOsqIszfAqrQQFIIKgjh2+FDgIj/zsl21Q==",
- "dev": true,
- "engines": {
- "node": ">=6.9.0"
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/cssnano/node_modules/cosmiconfig": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
- "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
+ "node_modules/cssnano-preset-default": {
+ "version": "5.2.14",
+ "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz",
+ "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "import-fresh": "^2.0.0",
- "is-directory": "^0.3.1",
- "js-yaml": "^3.13.1",
- "parse-json": "^4.0.0"
+ "css-declaration-sorter": "^6.3.1",
+ "cssnano-utils": "^3.1.0",
+ "postcss-calc": "^8.2.3",
+ "postcss-colormin": "^5.3.1",
+ "postcss-convert-values": "^5.1.3",
+ "postcss-discard-comments": "^5.1.2",
+ "postcss-discard-duplicates": "^5.1.0",
+ "postcss-discard-empty": "^5.1.1",
+ "postcss-discard-overridden": "^5.1.0",
+ "postcss-merge-longhand": "^5.1.7",
+ "postcss-merge-rules": "^5.1.4",
+ "postcss-minify-font-values": "^5.1.0",
+ "postcss-minify-gradients": "^5.1.1",
+ "postcss-minify-params": "^5.1.4",
+ "postcss-minify-selectors": "^5.2.1",
+ "postcss-normalize-charset": "^5.1.0",
+ "postcss-normalize-display-values": "^5.1.0",
+ "postcss-normalize-positions": "^5.1.1",
+ "postcss-normalize-repeat-style": "^5.1.1",
+ "postcss-normalize-string": "^5.1.0",
+ "postcss-normalize-timing-functions": "^5.1.0",
+ "postcss-normalize-unicode": "^5.1.1",
+ "postcss-normalize-url": "^5.1.0",
+ "postcss-normalize-whitespace": "^5.1.1",
+ "postcss-ordered-values": "^5.1.3",
+ "postcss-reduce-initial": "^5.1.2",
+ "postcss-reduce-transforms": "^5.1.0",
+ "postcss-svgo": "^5.1.0",
+ "postcss-unique-selectors": "^5.1.1"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
},
- "engines": {
- "node": ">=4"
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/cssnano/node_modules/import-fresh": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
- "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY= sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
+ "node_modules/cssnano-utils": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz",
+ "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==",
"dev": true,
- "dependencies": {
- "caller-path": "^2.0.0",
- "resolve-from": "^3.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=4"
- }
- },
- "node_modules/cssnano/node_modules/parse-json": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
- "dev": true,
- "dependencies": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
+ "node": "^10 || ^12 || >=14.0"
},
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/cssnano/node_modules/resolve-from": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
- "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g= sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==",
- "dev": true,
- "engines": {
- "node": ">=4"
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
"node_modules/csso": {
@@ -5922,6 +5642,7 @@
"resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz",
"integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"css-tree": "^1.1.2"
},
@@ -5929,69 +5650,42 @@
"node": ">=8.0.0"
}
},
- "node_modules/csso/node_modules/css-tree": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz",
- "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==",
- "dev": true,
- "dependencies": {
- "mdn-data": "2.0.14",
- "source-map": "^0.6.1"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/csso/node_modules/mdn-data": {
- "version": "2.0.14",
- "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
- "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==",
- "dev": true
- },
- "node_modules/csso/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/csstype": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.1.3.tgz",
- "integrity": "sha512-M1uQkMl8rQK/szD0LNhtqxIPLpimGm8sOBwU7lLnCpSbTyY3yeU1Vc7l4KT5zT4s/yOxHH5O7tIuuLOCnLADRw==",
+ "version": "3.2.3",
+ "resolved": "https://registry.npmjs.org/csstype/-/csstype-3.2.3.tgz",
+ "integrity": "sha512-z1HGKcYy2xA8AGQfwrn0PAy+PB7X/GSj3UVJW9qKyn43xWa+gl5nXmU4qqLMRzWVLFC8KusUX8T/0kCiOYpAIQ==",
"license": "MIT"
},
- "node_modules/cyclist": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/cyclist/-/cyclist-1.0.1.tgz",
- "integrity": "sha1-WW6WmP0MgOEgOMK4LW6xs1tiJNk= sha512-NJGVKPS81XejHcLhaLJS7plab0fK3slPh11mESeeDq2W4ZI5kUKK/LRRdVDvjJseojbPB7ZwjnyOybg3Igea/A==",
- "dev": true
- },
"node_modules/d": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/d/-/d-1.0.1.tgz",
- "integrity": "sha512-m62ShEObQ39CfralilEQRjH6oAMtNCV1xJyEx5LpRYUVN+EviphDgUc/F3hnYbADmkiNs67Y+3ylmlG7Lnu+FA==",
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/d/-/d-1.0.2.tgz",
+ "integrity": "sha512-MOqHvMWF9/9MX6nza0KgvFH4HpMU0EF5uUDXqX/BtxtU8NfB0QzRtJ8Oe/6SuS4kbhyzVJwjd97EA4PKrzJ8bw==",
+ "license": "ISC",
"dependencies": {
- "es5-ext": "^0.10.50",
- "type": "^1.0.1"
+ "es5-ext": "^0.10.64",
+ "type": "^2.7.2"
+ },
+ "engines": {
+ "node": ">=0.12"
}
},
"node_modules/d3-array": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
- "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw=="
+ "integrity": "sha512-KHW6M86R+FUPYGb3R5XiYjXPq7VzwxZ22buHhAEVG5ztoEcZZMLov530mmccaqA1GghZArjQV46fuc8kUqhhHw==",
+ "license": "BSD-3-Clause"
},
"node_modules/d3-collection": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-collection/-/d3-collection-1.0.7.tgz",
- "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A=="
+ "integrity": "sha512-ii0/r5f4sjKNTfh84Di+DpztYwqKhEyUlKoPrzUFfeSkWxjW49xU2QzO9qrPrNkpdI0XJkfzvmTu8V2Zylln6A==",
+ "license": "BSD-3-Clause"
},
"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==",
+ "license": "ISC",
"engines": {
"node": ">=12"
}
@@ -5999,12 +5693,14 @@
"node_modules/d3-dispatch": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/d3-dispatch/-/d3-dispatch-1.0.6.tgz",
- "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA=="
+ "integrity": "sha512-fVjoElzjhCEy+Hbn8KygnmMS7Or0a9sI2UzGwoB7cCtvI1XpVN9GpoYlnb3xt2YV66oXYb1fLJ8GMvP4hdU1RA==",
+ "license": "BSD-3-Clause"
},
"node_modules/d3-force": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/d3-force/-/d3-force-1.2.1.tgz",
"integrity": "sha512-HHvehyaiUlVo5CxBJ0yF/xny4xoaxFxDnBXNvNcfW9adORGZfyNF1dj6DGLKyk4Yh3brP/1h3rnDzdIAwL08zg==",
+ "license": "BSD-3-Clause",
"dependencies": {
"d3-collection": "1",
"d3-dispatch": "1",
@@ -6015,12 +5711,14 @@
"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=="
+ "integrity": "sha512-J0piedu6Z8iB6TbIGfZgDzfXxUFN3qQRMofy2oPdXzQibYGqPB/9iMcxr/TGalU+2RsyDO+U4f33id8tbnSRMQ==",
+ "license": "BSD-3-Clause"
},
"node_modules/d3-geo": {
"version": "1.12.1",
"resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-1.12.1.tgz",
"integrity": "sha512-XG4d1c/UJSEX9NfU02KwBL6BYPj8YKHxgBEw5om2ZnTRSbIcego6dhHwcxuSR3clxh0EpE38os1DVPOmnYtTPg==",
+ "license": "BSD-3-Clause",
"dependencies": {
"d3-array": "1"
}
@@ -6029,6 +5727,7 @@
"version": "2.9.0",
"resolved": "https://registry.npmjs.org/d3-geo-projection/-/d3-geo-projection-2.9.0.tgz",
"integrity": "sha512-ZULvK/zBn87of5rWAfFMc9mJOipeSo57O+BBitsKIXmU4rTVAnX1kSsJkE0R+TxY8pGNoM1nbyRRE7GYHhdOEQ==",
+ "license": "BSD-3-Clause",
"dependencies": {
"commander": "2",
"d3-array": "1",
@@ -6043,15 +5742,23 @@
"geostitch": "bin/geostitch"
}
},
+ "node_modules/d3-geo-projection/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "license": "MIT"
+ },
"node_modules/d3-hierarchy": {
"version": "1.1.9",
"resolved": "https://registry.npmjs.org/d3-hierarchy/-/d3-hierarchy-1.1.9.tgz",
- "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ=="
+ "integrity": "sha512-j8tPxlqh1srJHAtxfvOUwKNYJkQuBFdM1+JAUfq6xqH5eAqf93L7oG1NVqDa4CpFZNvnNKtCYEUC8KY9yEn9lQ==",
+ "license": "BSD-3-Clause"
},
"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==",
+ "license": "ISC",
"dependencies": {
"d3-color": "1 - 3"
},
@@ -6062,17 +5769,20 @@
"node_modules/d3-path": {
"version": "1.0.9",
"resolved": "https://registry.npmjs.org/d3-path/-/d3-path-1.0.9.tgz",
- "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg=="
+ "integrity": "sha512-VLaYcn81dtHVTjEHd8B+pbe9yHWpXKZUC87PzoFmsFrJqgFwDe/qxfp5MlfsfM1V5E/iVt0MmEbWQ7FVIXh/bg==",
+ "license": "BSD-3-Clause"
},
"node_modules/d3-quadtree": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/d3-quadtree/-/d3-quadtree-1.0.7.tgz",
- "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA=="
+ "integrity": "sha512-RKPAeXnkC59IDGD0Wu5mANy0Q2V28L+fNe65pOCXVdVuTJS3WPKaJlFHer32Rbh9gIo9qMuJXio8ra4+YmIymA==",
+ "license": "BSD-3-Clause"
},
"node_modules/d3-shape": {
"version": "1.3.7",
"resolved": "https://registry.npmjs.org/d3-shape/-/d3-shape-1.3.7.tgz",
"integrity": "sha512-EUkvKjqPFUAZyOlhY5gzCxCeI0Aep04LwIRpsZ/mLFelJiUfnK56jo5JMDSE7yyP2kLSb6LtF+S5chMk7uqPqw==",
+ "license": "BSD-3-Clause",
"dependencies": {
"d3-path": "1"
}
@@ -6080,12 +5790,14 @@
"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=="
+ "integrity": "sha512-Xh0isrZ5rPYYdqhAVk8VLnMEidhz5aP7htAADH6MfzgmmicPkTo8LhkLxci61/lCB7n7UmE3bN0leRt+qvkLxA==",
+ "license": "BSD-3-Clause"
},
"node_modules/d3-time-format": {
"version": "2.3.0",
"resolved": "https://registry.npmjs.org/d3-time-format/-/d3-time-format-2.3.0.tgz",
"integrity": "sha512-guv6b2H37s2Uq/GefleCDtbe0XZAuy7Wa49VGkPVPMfLL9qObgBST3lEHJBMUp8S7NdLQAGIvr2KXk8Hc98iKQ==",
+ "license": "BSD-3-Clause",
"dependencies": {
"d3-time": "1"
}
@@ -6093,19 +5805,8 @@
"node_modules/d3-timer": {
"version": "1.0.10",
"resolved": "https://registry.npmjs.org/d3-timer/-/d3-timer-1.0.10.tgz",
- "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw=="
- },
- "node_modules/dashdash": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz",
- "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA= sha512-jRFi8UDGo6j+odZiEpjazZaWqEal3w/basFjQHQEwVtZJGDpxbH1MeYluwCS8Xq5wmLJooDlMgvVarmWfGM44g==",
- "dev": true,
- "dependencies": {
- "assert-plus": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10"
- }
+ "integrity": "sha512-B1JDm0XDaQC+uvo4DT79H0XmBskgS3l6Ve+1SBCfxgmtIb1AVrPIoqd+nPSv+loMX8szQ0sVUhGngL7D5QPiXw==",
+ "license": "BSD-3-Clause"
},
"node_modules/de-indent": {
"version": "1.0.2",
@@ -6113,13 +5814,21 @@
"integrity": "sha512-e/1zu3xH5MQryN2zdVaF0OrdNLUbvWxzMbi+iNA6Bky7l1RoP8a2fIbRocyHclXt/arDrrR6lL3TqFD9pMQTsg==",
"license": "MIT"
},
+ "node_modules/debounce": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/debounce/-/debounce-1.2.1.tgz",
+ "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/debug": {
- "version": "4.3.3",
- "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.3.tgz",
- "integrity": "sha512-/zxw5+vh1Tfv+4Qn7a5nsbcJKPaSvCDhojn6FEl9vupwK2VCSDtEiEtqr8DFtzYFOdz63LBkxec7DYuc2jon6Q==",
+ "version": "4.4.3",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz",
+ "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ms": "2.1.2"
+ "ms": "^2.1.3"
},
"engines": {
"node": ">=6.0"
@@ -6130,117 +5839,74 @@
}
}
},
- "node_modules/decamelize": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz",
- "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA= sha512-z2S+W9X73hAUUki+N+9Za2lBlun89zigOyGrsax+KUQ6wKW4ZoWpEYBkGhQjwAjjDCkWxhY0VKEhk8wzY7F5cA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/decimal.js": {
- "version": "10.4.3",
- "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
- "integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
- },
- "node_modules/decode-uri-component": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/decode-uri-component/-/decode-uri-component-0.2.2.tgz",
- "integrity": "sha512-FqUYQ+8o158GyGTrMFJms9qh3CqTKvAqgqsTnkLI8sKu0028orqBhxNMFkFen0zGyg6epACD32pjVk58ngIErQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/deep-equal": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.1.1.tgz",
- "integrity": "sha512-yd9c5AdiqVcR+JjcwUQb9DkhJc8ngNr0MahEBGvDiJw8puWab2yZlh+nkasOnZP+EGTAP6rRp2JzJhJZzvNF8g==",
- "dev": true,
- "dependencies": {
- "is-arguments": "^1.0.4",
- "is-date-object": "^1.0.1",
- "is-regex": "^1.0.4",
- "object-is": "^1.0.1",
- "object-keys": "^1.1.1",
- "regexp.prototype.flags": "^1.2.0"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
+ "version": "10.6.0",
+ "resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.6.0.tgz",
+ "integrity": "sha512-YpgQiITW3JXGntzdUmyUR1V812Hn8T1YVXhCu+wO3OpS4eU9l4YdD3qjyiKdV6mvV29zapkMeD390UVEf2lkUg==",
+ "license": "MIT"
},
"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=="
+ "integrity": "sha512-oIPzksmTg4/MriiaYGO+okXDT7ztn/w3Eptv/+gSIdMdKsJo0u4CfYNFJPy+4SKMuCqGw2wxnA+URMg3t8a/bQ==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/deepmerge": {
"version": "1.5.2",
"resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-1.5.2.tgz",
"integrity": "sha512-95k0GDqvBjZavkuvzx/YqVLv/6YYa17fz6ILMSf7neqQITCPbnfEnQvEgMPNjH4kgobe7+WIL0yJEHku+H3qtQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/default-gateway": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-5.0.5.tgz",
- "integrity": "sha512-z2RnruVmj8hVMmAnEJMTIJNijhKCDiGjbLP+BHJFOT7ld3Bo5qcIBpVYDniqhbMIIf+jZDlkP2MkPXiQy/DBLA==",
- "dev": true,
- "dependencies": {
- "execa": "^3.3.0"
- },
- "engines": {
- "node": "^8.12.0 || >=9.7.0"
- }
- },
- "node_modules/default-gateway/node_modules/cross-spawn": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-7.0.3.tgz",
- "integrity": "sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==",
+ "version": "6.0.3",
+ "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-6.0.3.tgz",
+ "integrity": "sha512-fwSOJsbbNzZ/CUFpqFBqYfYNLj1NbMPm8MMCIzHjC83iSJRBEGmDUxU+WP661BaBQImeC2yHwXtz+P/O9o+XEg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "path-key": "^3.1.0",
- "shebang-command": "^2.0.0",
- "which": "^2.0.1"
+ "execa": "^5.0.0"
},
"engines": {
- "node": ">= 8"
+ "node": ">= 10"
}
},
"node_modules/default-gateway/node_modules/execa": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/execa/-/execa-3.4.0.tgz",
- "integrity": "sha512-r9vdGQk4bmCuK1yKQu1KTwcT2zwfWdbdaXfCtAh+5nU/4fSX+JAb7vZGvI5naJrQlvONrEB20jeruESI69530g==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/execa/-/execa-5.1.1.tgz",
+ "integrity": "sha512-8uSpZZocAZRBAPIEINJj3Lo9HyGitllczc27Eh5YYojjMFMn8yHMDMaUHE2Jqfq05D/wucwI4JGURyXt1vchyg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cross-spawn": "^7.0.0",
- "get-stream": "^5.0.0",
- "human-signals": "^1.1.1",
+ "cross-spawn": "^7.0.3",
+ "get-stream": "^6.0.0",
+ "human-signals": "^2.1.0",
"is-stream": "^2.0.0",
"merge-stream": "^2.0.0",
- "npm-run-path": "^4.0.0",
- "onetime": "^5.1.0",
- "p-finally": "^2.0.0",
- "signal-exit": "^3.0.2",
+ "npm-run-path": "^4.0.1",
+ "onetime": "^5.1.2",
+ "signal-exit": "^3.0.3",
"strip-final-newline": "^2.0.0"
},
"engines": {
- "node": "^8.12.0 || >=9.7.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sindresorhus/execa?sponsor=1"
}
},
"node_modules/default-gateway/node_modules/get-stream": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-5.2.0.tgz",
- "integrity": "sha512-nBF+F1rAZVCu/p7rjzgA+Yb4lfYXrpl7a6VmJrU8wF9I1CKvP/QwPNZHnOlwbTkY6dvtFIzFMSyQXbLoTQPRpA==",
- "dev": true,
- "dependencies": {
- "pump": "^3.0.0"
- },
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
+ "integrity": "sha512-ts6Wi+2j3jQjqi70w5AlN8DFnkSwC+MqmxEzdEALB2qXZYV3X/b1CTfgPLGJNMeAWxdPfU8FO1ms3NUfaHCPYg==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
@@ -6251,6 +5917,7 @@
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-2.0.1.tgz",
"integrity": "sha512-hFoiJiTl63nn+kstHGBtewWSKnQLpyb155KHheA1l39uvtO9nWIop1p3udqPcUd/xbF1VLMO4n7OI6p7RbngDg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
},
@@ -6263,6 +5930,7 @@
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-4.0.1.tgz",
"integrity": "sha512-S48WzZW777zhNIrn7gxOlISNAqi9ZC/uQFnRdbeIHhZhCA6UqpkOT8T1G7BvfdgP4Er8gF4sUbaS0i7QvIfCWw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"path-key": "^3.0.0"
},
@@ -6270,300 +5938,153 @@
"node": ">=8"
}
},
- "node_modules/default-gateway/node_modules/p-finally": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-2.0.1.tgz",
- "integrity": "sha512-vpm09aKwq6H9phqRQzecoDpD8TmVyGw70qmWlyq5onxY7tqyTTFVvxMykxQSQKILBSFlbXpypIw2T1Ml7+DDtw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/default-gateway/node_modules/path-key": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
- "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/default-gateway/node_modules/shebang-command": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
- "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
- "dev": true,
- "dependencies": {
- "shebang-regex": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/default-gateway/node_modules/shebang-regex": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
- "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/default-gateway/node_modules/which": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
- "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
- "dev": true,
- "dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "node-which": "bin/node-which"
- },
- "engines": {
- "node": ">= 8"
- }
- },
"node_modules/defaults": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.3.tgz",
- "integrity": "sha1-xlYFHpgX2f8I7YgUd/P+QBnz730= sha512-s82itHOnYrN0Ib8r+z7laQz3sdE+4FP3d9Q7VLO7U+KRT+CR0GsWuyHxzdAY82I7cXv0G/twrqomTJLOssO5HA==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/defaults/-/defaults-1.0.4.tgz",
+ "integrity": "sha512-eFuaLoy/Rxalv2kr+lqMlUnrDWV+3j4pljOIJgLIhI058IQfWJ7vXhyEIHu+HtC738klGALYxOKDO0bQP3tg8A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"clone": "^1.0.2"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/define-properties": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.1.3.tgz",
- "integrity": "sha512-3MqfYKj2lLzdMSf8ZIZE/V+Zuy+BgD6f164e8K2w7dgnpKArBDerGYpM46IYYcjnkdPNMjPk9A6VFB8+3SKlXQ==",
+ "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,
+ "license": "MIT",
"dependencies": {
- "object-keys": "^1.0.12"
+ "es-define-property": "^1.0.0",
+ "es-errors": "^1.3.0",
+ "gopd": "^1.0.1"
},
"engines": {
"node": ">= 0.4"
- }
- },
- "node_modules/define-property": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-2.0.2.tgz",
- "integrity": "sha512-jwK2UV4cnPpbcG7+VRARKTZPUWowwXA8bzH5NP6ud0oeAxyYPuGZUAC7hMugpCdz4BeSZl2Dl9k66CHJ/46ZYQ==",
- "dev": true,
- "dependencies": {
- "is-descriptor": "^1.0.2",
- "isobject": "^3.0.1"
},
- "engines": {
- "node": ">=0.10.0"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/defined": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.0.tgz",
- "integrity": "sha1-yY2bzvdWdBiOEQlpFRGZ45sfppM= sha512-Y2caI5+ZwS5c3RiNDJ6u53VhQHv+hHKwhkI1iHvceKUHw9Df6EK2zRLfjejRgMuCuxK7PfSWIMwWecceVvThjQ=="
- },
- "node_modules/del": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/del/-/del-4.1.1.tgz",
- "integrity": "sha512-QwGuEUouP2kVwQenAsOof5Fv8K9t3D8Ca8NxcXKrIpEHjTXK5J2nXLdP+ALI1cgv8wj7KuwBhTwBkOZSJKM5XQ==",
+ "node_modules/define-lazy-prop": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-2.0.0.tgz",
+ "integrity": "sha512-Ds09qNh8yw3khSjiJjiUInaGX9xlqZDY7JVryGxdxV7NPeuqQfplOpQ66yJFZut3jLa5zOwkXw1g9EI2uKh4Og==",
"dev": true,
- "dependencies": {
- "@types/glob": "^7.1.1",
- "globby": "^6.1.0",
- "is-path-cwd": "^2.0.0",
- "is-path-in-cwd": "^2.0.0",
- "p-map": "^2.0.0",
- "pify": "^4.0.1",
- "rimraf": "^2.6.3"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">=8"
}
},
- "node_modules/del/node_modules/globby": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-6.1.0.tgz",
- "integrity": "sha1-9abXDoOV4hyFj7BInWTfAkJNUGw= sha512-KVbFv2TQtbzCoxAnfD6JcHZTYCzyliEaaeM/gH8qQdkKr5s0OP9scEgvdcngyk7AVdY6YVW/TJHd+lQ/Df3Daw==",
+ "node_modules/define-properties": {
+ "version": "1.2.1",
+ "resolved": "https://registry.npmjs.org/define-properties/-/define-properties-1.2.1.tgz",
+ "integrity": "sha512-8QmQKqEASLd5nx0U1B1okLElbUuuttJ/AnYmRXbbbGDWh6uS208EjD4Xqq/I9wK7u0v6O08XhTWnt5XtEbR6Dg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "array-union": "^1.0.1",
- "glob": "^7.0.3",
- "object-assign": "^4.0.1",
- "pify": "^2.0.0",
- "pinkie-promise": "^2.0.0"
+ "define-data-property": "^1.0.1",
+ "has-property-descriptors": "^1.0.0",
+ "object-keys": "^1.1.1"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/del/node_modules/globby/node_modules/pify": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
- "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw= sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node_modules/defined": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/defined/-/defined-1.0.1.tgz",
+ "integrity": "sha512-hsBd2qSVCRE+5PmNdHt1uzyrFu5d3RwmFDKzyNZMFq/EwDNJF7Ee5+D5oEKF0hU6LhtoUF1macFvOe4AskQC1Q==",
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/delayed-stream": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz",
- "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk= sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "integrity": "sha512-ZySD7Nf91aLB0RxL4KGrKHBXl7Eds1DAmEdcoVawXnLD7SDhpNgtuII2aAkg7a7QS41jxPSZ17p4VdGnMHk3MQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.4.0"
}
},
"node_modules/depd": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
- "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak= sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz",
+ "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">= 0.6"
+ "node": ">= 0.8"
}
},
- "node_modules/des.js": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/des.js/-/des.js-1.0.1.tgz",
- "integrity": "sha512-Q0I4pfFrv2VPd34/vfLrFOoRmlYj3OV50i7fskps1jZWK1kApMWWT9G6RRUeYedLcBDIhnSDaUvJMb3AhUlaEA==",
+ "node_modules/destroy": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.2.0.tgz",
+ "integrity": "sha512-2sJGJTaXIIaR1w4iJSNoN0hnMY7Gpc/n8D4qSCJw8QqFWXf7cuAgnEHxBpweaVcPevC2l3KpjYCx3NypQQgaJg==",
"dev": true,
- "dependencies": {
- "inherits": "^2.0.1",
- "minimalistic-assert": "^1.0.0"
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.8",
+ "npm": "1.2.8000 || >= 1.4.16"
}
},
- "node_modules/destroy": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz",
- "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA= sha512-3NdhDuEXnfun/z7x9GOElY49LoqVHoGScmOKwmxhsS8N5Y+Z8KyPPDnaSzqWgYt/ji4mqwfTS34Htrk0zPIXVg==",
- "dev": true
- },
"node_modules/detect-kerning": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/detect-kerning/-/detect-kerning-2.1.2.tgz",
- "integrity": "sha512-I3JIbrnKPAntNLl1I6TpSQQdQ4AutYzv/sKMFKbepawV/hlH0GmYKhUoOEMd4xqaUHT+Bm0f4127lh5qs1m1tw=="
+ "integrity": "sha512-I3JIbrnKPAntNLl1I6TpSQQdQ4AutYzv/sKMFKbepawV/hlH0GmYKhUoOEMd4xqaUHT+Bm0f4127lh5qs1m1tw==",
+ "license": "MIT"
},
"node_modules/detect-node": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/detect-node/-/detect-node-2.1.0.tgz",
"integrity": "sha512-T0NIuQpnTvFDATNuHN5roPwSBG83rFsuO+MXXH9/3N1eFbn4wcPjttvjMLEPWJ0RGUYgQE7cGgS3tNxbqCGM7g==",
- "dev": true
- },
- "node_modules/detective": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/detective/-/detective-5.2.0.tgz",
- "integrity": "sha512-6SsIx+nUUbuK0EthKjv0zrdnajCCXVYGmbYYiYjFVpzcjwEs/JMDZ8tPRG29J/HhN56t3GJp2cGSWDRjjot8Pg==",
"dev": true,
- "dependencies": {
- "acorn-node": "^1.6.1",
- "defined": "^1.0.0",
- "minimist": "^1.1.1"
- },
- "bin": {
- "detective": "bin/detective.js"
- },
- "engines": {
- "node": ">=0.8.0"
- }
+ "license": "MIT"
},
"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/diffie-hellman": {
- "version": "5.0.3",
- "resolved": "https://registry.npmjs.org/diffie-hellman/-/diffie-hellman-5.0.3.tgz",
- "integrity": "sha512-kqag/Nl+f3GwyK25fhUMYj81BUOrZ9IuJsjIcDE5icNM9FJHAVm3VcUDxdLPoQtTuUylWm6ZIknYJwwaPxsUzg==",
- "dev": true,
- "dependencies": {
- "bn.js": "^4.1.0",
- "miller-rabin": "^4.0.0",
- "randombytes": "^2.0.0"
- }
- },
- "node_modules/diffie-hellman/node_modules/bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
- "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
- "dev": true
+ "license": "Apache-2.0"
},
"node_modules/dir-glob": {
- "version": "2.2.2",
- "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-2.2.2.tgz",
- "integrity": "sha512-f9LBi5QWzIW3I6e//uxZoLBlUt9kcp66qo0sSCxL6YZKc75R1c4MFCoe/LaZiBGmgujvQdxc5Bn3QhfyvK5Hsw==",
- "dev": true,
- "dependencies": {
- "path-type": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/dir-glob/node_modules/path-type": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-type/-/path-type-3.0.0.tgz",
- "integrity": "sha512-T2ZUsdZFHgA3u4e5PfPbjd7HDDpxPnQb5jN0SrDsjNSuVXHJqtwTnWqG0B1jZrgmJ/7lj1EmVIByWt1gxGkWvg==",
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/dir-glob/-/dir-glob-3.0.1.tgz",
+ "integrity": "sha512-WkrWp9GR4KXfKGYzOLmTuGVi1UWFfws377n9cc55/tb6DuqyF6pcQ5AbiHEshaDpY9v6oaSr2XCDidGmMwdzIA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "pify": "^3.0.0"
+ "path-type": "^4.0.0"
},
"engines": {
- "node": ">=4"
- }
- },
- "node_modules/dir-glob/node_modules/pify": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pify/-/pify-3.0.0.tgz",
- "integrity": "sha1-5aSs0sEB/fPZpNB/DbxNtJ3SgXY= sha512-C3FsVNH1udSEX48gGX1xfvwTWfsYWj5U+8/uK15BGzIGrKoUpghX8hWZwa/OFnakBiiVNmBvemTJR5mcy7iPcg==",
- "dev": true,
- "engines": {
- "node": ">=4"
+ "node": ">=8"
}
},
"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/dns-equal": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/dns-equal/-/dns-equal-1.0.0.tgz",
- "integrity": "sha1-s55/HabrCnW6nBcySzR1PEfgZU0= sha512-z+paD6YUQsk+AbGCEM4PrOXSss5gd66QfcVBFTKR/HpFL9jCqikS94HYwKww6fQyO7IxrIIyUu+g0Ka9tUS2Cg==",
- "dev": true
+ "license": "MIT"
},
"node_modules/dns-packet": {
- "version": "1.3.4",
- "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
- "integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
- "dev": true,
- "dependencies": {
- "ip": "^1.1.0",
- "safe-buffer": "^5.0.1"
- }
- },
- "node_modules/dns-txt": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/dns-txt/-/dns-txt-2.0.2.tgz",
- "integrity": "sha1-uR2Ab10nGI5Ks+fRB9iBocxGQrY= sha512-Ix5PrWjphuSoUXV/Zv5gaFHjnaJtb02F2+Si3Ht9dyJ87+Z/lMmy+dpNHtTGraNK958ndXq2i+GLkWsWHcKaBQ==",
- "dev": true,
- "dependencies": {
- "buffer-indexof": "^1.0.0"
- }
- },
- "node_modules/doctrine": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-3.0.0.tgz",
- "integrity": "sha512-yS+Q5i3hBf7GBkd4KG8a7eBNNWNGLTaEwwYWUijIYM7zrlYDM0BFXHjjPWlWZ1Rg7UaddZeIDmi9jF3HmqiQ2w==",
+ "version": "5.6.1",
+ "resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-5.6.1.tgz",
+ "integrity": "sha512-l4gcSouhcgIKRvyy99RNVOgxXiicE+2jZoNmaNmZ6JXiGajBOJAesk1OBlJuM5k2c+eudGdLxDqXuPCKIj6kpw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "esutils": "^2.0.2"
+ "@leichtgewicht/ip-codec": "^2.0.1"
},
"engines": {
- "node": ">=6.0.0"
+ "node": ">=6"
}
},
"node_modules/dom-converter": {
@@ -6571,15 +6092,17 @@
"resolved": "https://registry.npmjs.org/dom-converter/-/dom-converter-0.2.0.tgz",
"integrity": "sha512-gd3ypIPfOMr9h5jIKq8E3sHOTCjeirnl0WK5ZdS1AW0Odt0b1PaWaHdJ4Qk4klv+YB9aJBS7mESXjFoDQPu6DA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"utila": "~0.4"
}
},
"node_modules/dom-serializer": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.3.2.tgz",
- "integrity": "sha512-5c54Bk5Dw4qAxNOI1pFEizPSjVsx5+bpJKmL2kPn8JhBUq2q09tTCa3mjijun2NfK78NMouDYNMBkOrPZiS+ig==",
+ "version": "1.4.1",
+ "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz",
+ "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^4.2.0",
@@ -6589,33 +6112,35 @@
"url": "https://github.com/cheeriojs/dom-serializer?sponsor=1"
}
},
- "node_modules/domain-browser": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/domain-browser/-/domain-browser-1.2.0.tgz",
- "integrity": "sha512-jnjyiM6eRyZl2H+W8Q/zLMA481hzi0eszAaBUzIVnmYVDBbnLxVNnfu1HgEBvCbL+71FrxMl3E6lpKH7Ge3OXA==",
+ "node_modules/dom-serializer/node_modules/entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
"dev": true,
- "engines": {
- "node": ">=0.4",
- "npm": ">=1.2"
+ "license": "BSD-2-Clause",
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
}
},
"node_modules/domelementtype": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.2.0.tgz",
- "integrity": "sha512-DtBMo82pv1dFtUmHyr48beiuq792Sxohr+8Hm9zoxklYPfa6n0Z3Byjj2IV7bmr2IyqClnqEQhfgHJJ5QF0R5A==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz",
+ "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==",
"dev": true,
"funding": [
{
"type": "github",
"url": "https://github.com/sponsors/fb55"
}
- ]
+ ],
+ "license": "BSD-2-Clause"
},
"node_modules/domhandler": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.0.tgz",
- "integrity": "sha512-fC0aXNQXqKSFTr2wDNZDhsEYjCiYsDWl3D01kwt25hm1YIPyDGHvvi3rw+PLqHAl/m71MaiF7d5zvBr0p5UB2g==",
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz",
+ "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"domelementtype": "^2.2.0"
},
@@ -6626,11 +6151,22 @@
"url": "https://github.com/fb55/domhandler?sponsor=1"
}
},
+ "node_modules/dompurify": {
+ "version": "3.2.7",
+ "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz",
+ "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==",
+ "license": "(MPL-2.0 OR Apache-2.0)",
+ "peer": true,
+ "optionalDependencies": {
+ "@types/trusted-types": "^2.0.7"
+ }
+ },
"node_modules/domutils": {
"version": "2.8.0",
"resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz",
"integrity": "sha512-w96Cjofp72M5IIhpjgobBimYEfoPjx1Vx0BSX9P30WBdZW2WIKU0T1Bd0kz2eNZ9ikjKgHbEyKx8BB6H1L3h3A==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"dom-serializer": "^1.0.1",
"domelementtype": "^2.2.0",
@@ -6640,32 +6176,23 @@
"url": "https://github.com/fb55/domutils?sponsor=1"
}
},
- "node_modules/dot-prop": {
- "version": "5.3.0",
- "resolved": "https://registry.npmjs.org/dot-prop/-/dot-prop-5.3.0.tgz",
- "integrity": "sha512-QM8q3zDe58hqUqjraQOmzZ1LIH9SWQJTlEKCH4kJ2oQvLZk7RbQXvtDM2XEq3fwkV9CCvvH4LA0AV+ogFsBM2Q==",
+ "node_modules/dot-case": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/dot-case/-/dot-case-3.0.4.tgz",
+ "integrity": "sha512-Kv5nKlh6yRrdrGvxeJ2e5y2eRUpkUosIW4A2AS38zwSz27zu7ufDwQPi5Jhs3XAlGNetl3bmnGhQsMtkKJnj3w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-obj": "^2.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/dot-prop/node_modules/is-obj": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-obj/-/is-obj-2.0.0.tgz",
- "integrity": "sha512-drqDG3cbczxxEJRoOXcOjtdp1J/lyp1mNn0xaznRs8+muBhgQcrnbspox5X5fOw0HnMnbfDzvnEMEtqDEJEo8w==",
- "dev": true,
- "engines": {
- "node": ">=8"
+ "no-case": "^3.0.4",
+ "tslib": "^2.0.3"
}
},
"node_modules/dotenv": {
- "version": "8.6.0",
- "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-8.6.0.tgz",
- "integrity": "sha512-IrPdXQsk2BbzvCBGBOTmmSH5SodmqZNt4ERAZDmW4CT+tL8VtvinqywuANaFu4bOMWki16nqf0e4oC0QIaDr/g==",
+ "version": "10.0.0",
+ "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-10.0.0.tgz",
+ "integrity": "sha512-rlBi9d8jpv9Sf1klPjNfFAuWDjKLwTIJJ/VxtoTwIR6hnZxcEOQCZg2oIL3MWBYw5GpUDKOEnND7LXTbIpQ03Q==",
"dev": true,
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=10"
}
@@ -6674,12 +6201,14 @@
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/dotenv-expand/-/dotenv-expand-5.1.0.tgz",
"integrity": "sha512-YXQl1DSa4/PQyRfgrv6aoNjhasp/p4qs9FjJ4q4cQk+8m4r6k4ZSiEyytKG8f8W9gi8WsQtIObNmKd+tMzNTmA==",
- "dev": true
+ "dev": true,
+ "license": "BSD-2-Clause"
},
"node_modules/draw-svg-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/draw-svg-path/-/draw-svg-path-1.0.0.tgz",
"integrity": "sha512-P8j3IHxcgRMcY6sDzr0QvJDLzBnJJqpTG33UZ2Pvp8rw0apCHhJCWqYprqrXjrgHnJ6tuhP1iTJSAodPDHxwkg==",
+ "license": "MIT",
"dependencies": {
"abs-svg-path": "~0.1.1",
"normalize-svg-path": "~0.1.0"
@@ -6689,6 +6218,7 @@
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/dtype/-/dtype-2.0.0.tgz",
"integrity": "sha512-s2YVcLKdFGS0hpFqJaTwscsyt0E8nNFdmo73Ocd81xNPj4URI4rj6D60A+vFMIw7BXWlb4yRkEwfBqcZzPGiZg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.8.0"
}
@@ -6710,18 +6240,21 @@
"node_modules/dup": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/dup/-/dup-1.0.0.tgz",
- "integrity": "sha512-Bz5jxMMC0wgp23Zm15ip1x8IhYRqJvF3nFC0UInJUDkN1z4uNPk9jTnfCUJXbOGiQ1JbXLQsiV41Fb+HXcj5BA=="
+ "integrity": "sha512-Bz5jxMMC0wgp23Zm15ip1x8IhYRqJvF3nFC0UInJUDkN1z4uNPk9jTnfCUJXbOGiQ1JbXLQsiV41Fb+HXcj5BA==",
+ "license": "MIT"
},
"node_modules/duplexer": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/duplexer/-/duplexer-0.1.2.tgz",
"integrity": "sha512-jtD6YG370ZCIi/9GTaJKQxWTZD045+4R4hTk/x1UyoqadyJ9x9CgSi1RlVDQF8U2sxLLSnFkCaMihqljHIWgMg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/duplexify": {
"version": "3.7.1",
"resolved": "https://registry.npmjs.org/duplexify/-/duplexify-3.7.1.tgz",
"integrity": "sha512-07z8uv2wMyS51kKhD1KsdXJg5WQ6t93RneqRxUHnskXVtlYYkLqM0gqStQZ3pj073g687jPCHrqNfCzawLYh5g==",
+ "license": "MIT",
"dependencies": {
"end-of-stream": "^1.0.0",
"inherits": "^2.0.1",
@@ -6729,216 +6262,166 @@
"stream-shift": "^1.0.0"
}
},
- "node_modules/earcut": {
- "version": "2.2.3",
- "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.3.tgz",
- "integrity": "sha512-iRDI1QeCQIhMCZk48DRDMVgQSSBDmbzzNhnxIo+pwx3swkfjMh6vh0nWLq1NdvGHLKH6wIrAM3vQWeTj6qeoug=="
- },
- "node_modules/easy-stack": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz",
- "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==",
- "dev": true,
- "engines": {
- "node": ">=6.0.0"
- }
+ "node_modules/duplexify/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "license": "MIT"
},
- "node_modules/ecc-jsbn": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz",
- "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk= sha512-eh9O+hwRHNbG4BLTjEl3nw044CkGm5X6LoaCf7LPp7UU8Qrt47JYNi6nPX8xjW97TKGKm1ouctg0QSpZe9qrnw==",
- "dev": true,
+ "node_modules/duplexify/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
"dependencies": {
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.1.0"
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
}
},
- "node_modules/ee-first": {
+ "node_modules/duplexify/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/duplexify/node_modules/string_decoder": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
- "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0= sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
- "dev": true
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/earcut": {
+ "version": "2.2.4",
+ "resolved": "https://registry.npmjs.org/earcut/-/earcut-2.2.4.tgz",
+ "integrity": "sha512-/pjZsA1b4RPHbeWZQn66SWS8nZZWLQQ23oE3Eam7aroEFGEvwKAsJfZ9ytiEMycfzXWpca4FA9QIOehf7PocBQ==",
+ "license": "ISC"
},
- "node_modules/ejs": {
- "version": "2.7.4",
- "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.7.4.tgz",
- "integrity": "sha512-7vmuyh5+kuUyJKePhQfRQBhXV5Ce+RnaeeQArKu1EAMpL3WbgMt5WG6uQZpEVvYSSsxMXRKOewtDk9RaTKXRlA==",
+ "node_modules/easy-stack": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/easy-stack/-/easy-stack-1.0.1.tgz",
+ "integrity": "sha512-wK2sCs4feiiJeFXn3zvY0p41mdU5VUgbgs1rNsc/y5ngFUijdWd+iIN8eoyuZHKB8xN6BL4PdWmzqFmxNg6V2w==",
"dev": true,
- "hasInstallScript": true,
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=6.0.0"
}
},
+ "node_modules/ee-first": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz",
+ "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/electron-to-chromium": {
- "version": "1.4.12",
- "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.12.tgz",
- "integrity": "sha512-zjfhG9Us/hIy8AlQ5OzfbR/C4aBv1Dg/ak4GX35CELYlJ4tDAtoEcQivXvyBdqdNQ+R6PhlgQqV8UNPJmhkJog==",
- "dev": true
+ "version": "1.5.351",
+ "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.351.tgz",
+ "integrity": "sha512-9D7Iqx8RImSvCnOsj86rCH6eQjZFQoM04Jn6HnZVM0Nu/G58/gmKYQ1d12MZTbjQbQSTGI8nwEy07ErsA2slLA==",
+ "license": "ISC"
},
"node_modules/element-size": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/element-size/-/element-size-1.1.1.tgz",
- "integrity": "sha512-eaN+GMOq/Q+BIWy0ybsgpcYImjGIdNLyjLFJU4XsLHXYQao5jCNb36GyN6C2qwmDDYSfIBmKpPpr4VnBdLCsPQ=="
+ "integrity": "sha512-eaN+GMOq/Q+BIWy0ybsgpcYImjGIdNLyjLFJU4XsLHXYQao5jCNb36GyN6C2qwmDDYSfIBmKpPpr4VnBdLCsPQ==",
+ "license": "MIT"
},
"node_modules/elementary-circuits-directed-graph": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/elementary-circuits-directed-graph/-/elementary-circuits-directed-graph-1.3.1.tgz",
"integrity": "sha512-ZEiB5qkn2adYmpXGnJKkxT8uJHlW/mxmBpmeqawEHzPxh9HkLD4/1mFYX5l0On+f6rcPIt8/EWlRU2Vo3fX6dQ==",
+ "license": "MIT",
"dependencies": {
"strongly-connected-components": "^1.0.1"
}
},
- "node_modules/elliptic": {
- "version": "6.5.6",
- "resolved": "https://registry.npmjs.org/elliptic/-/elliptic-6.5.6.tgz",
- "integrity": "sha512-mpzdtpeCLuS3BmE3pO3Cpp5bbjlOPY2Q0PgoF+Od1XZrHLYI28Xe3ossCmYCQt11FQKEYd9+PF8jymTvtWJSHQ==",
- "dev": true,
- "dependencies": {
- "bn.js": "^4.11.9",
- "brorand": "^1.1.0",
- "hash.js": "^1.0.0",
- "hmac-drbg": "^1.0.1",
- "inherits": "^2.0.4",
- "minimalistic-assert": "^1.0.1",
- "minimalistic-crypto-utils": "^1.0.1"
- }
- },
- "node_modules/elliptic/node_modules/bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
- "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
- "dev": true
- },
"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
+ "dev": true,
+ "license": "MIT"
},
"node_modules/emojis-list": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-3.0.0.tgz",
"integrity": "sha512-/kyM18EfinwXZbno9FyUGeFh87KC8HRQBQGildHZbEuRyWFOmv1U10o9BBp8XVZDVNNuQKyIGIu5ZYAAXJ0V2Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 4"
}
},
"node_modules/encodeurl": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz",
- "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k= sha512-TPJXq8JqFaVYm2CWmPvnP2Iyo4ZSM7/QKcSmuMLDObfpH5fi7RUGmd/rTDf+rut/saiDiQEeVTNgAmJEdAOx0w==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz",
+ "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
"node_modules/end-of-stream": {
- "version": "1.4.4",
- "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz",
- "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==",
+ "version": "1.4.5",
+ "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.5.tgz",
+ "integrity": "sha512-ooEGc6HP26xXq/N+GCGOT0JKCLDGrq2bQUZrQ7gyrJiZANJ/8YDTxTpQBXGMn+WbIQXNVpyWymm7KYVICQnyOg==",
+ "license": "MIT",
"dependencies": {
"once": "^1.4.0"
}
},
"node_modules/enhanced-resolve": {
- "version": "4.5.0",
- "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-4.5.0.tgz",
- "integrity": "sha512-Nv9m36S/vxpsI+Hc4/ZGRs0n9mXqSWGGq49zxb/cJfPAQMbUtttJAlNPS4AQzaBdw/pKskw5bMbekT/Y7W/Wlg==",
- "dev": true,
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "memory-fs": "^0.5.0",
- "tapable": "^1.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/enhanced-resolve/node_modules/memory-fs": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.5.0.tgz",
- "integrity": "sha512-jA0rdU5KoQMC0e6ppoNRtpp6vjFq6+NY7r8hywnC7V+1Xj/MtHwGIbB1QaK/dunyjWteJzmkpd7ooeWg10T7GA==",
- "dev": true,
+ "version": "5.21.0",
+ "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.21.0.tgz",
+ "integrity": "sha512-otxSQPw4lkOZWkHpB3zaEQs6gWYEsmX4xQF68ElXC/TWvGxGMSGOvoNbaLXm6/cS/fSfHtsEdw90y20PCd+sCA==",
+ "license": "MIT",
"dependencies": {
- "errno": "^0.1.3",
- "readable-stream": "^2.0.1"
+ "graceful-fs": "^4.2.4",
+ "tapable": "^2.3.3"
},
"engines": {
- "node": ">=4.3.0 <5.0.0 || >=5.10"
+ "node": ">=10.13.0"
}
},
"node_modules/entities": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
- "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-7.0.1.tgz",
+ "integrity": "sha512-TWrgLOFUQTH994YUyl1yT4uyavY5nNB5muff+RtWaqNVCAK408b5ZnnbNAUEWLTCpum9w6arT70i1XdQ4UeOPA==",
"dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=0.12"
+ },
"funding": {
"url": "https://github.com/fb55/entities?sponsor=1"
}
},
- "node_modules/errno": {
- "version": "0.1.8",
- "resolved": "https://registry.npmjs.org/errno/-/errno-0.1.8.tgz",
- "integrity": "sha512-dJ6oBr5SQ1VSd9qkk7ByRgb/1SH4JZjCHSW/mr63/QcXO9zLVxvJ6Oy13nio03rxpSnVDDjFor75SjVeZWPW/A==",
- "dev": true,
- "dependencies": {
- "prr": "~1.0.1"
- },
- "bin": {
- "errno": "cli.js"
- }
- },
"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==",
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.4.tgz",
+ "integrity": "sha512-sqQamAnR14VgCr1A618A3sGrygcpK+HEbenA/HiEAkkUwcZIIB/tgWqHFxWgOyDh4nB4JCRimh79dR5Ywc9MDQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-arrayish": "^0.2.1"
}
},
"node_modules/error-stack-parser": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.0.6.tgz",
- "integrity": "sha512-d51brTeqC+BHlwF0BhPtcYgF5nlzf9ZZ0ZIUQNZpc9ZB9qw5IJ2diTrBY9jlCJkTLITYPjmiX6OWCwH+fuyNgQ==",
- "dev": true,
- "dependencies": {
- "stackframe": "^1.1.1"
- }
- },
- "node_modules/es-abstract": {
- "version": "1.19.1",
- "resolved": "https://registry.npmjs.org/es-abstract/-/es-abstract-1.19.1.tgz",
- "integrity": "sha512-2vJ6tjA/UfqLm2MPs7jxVybLoB8i1t1Jd9R3kISld20sIxPcTbLuggQOUxeWeAvIUkduv/CfMjuh4WmiXr2v9w==",
+ "version": "2.1.4",
+ "resolved": "https://registry.npmjs.org/error-stack-parser/-/error-stack-parser-2.1.4.tgz",
+ "integrity": "sha512-Sk5V6wVazPhq5MhpO+AUxJn5x7XSXGl1R93Vn7i+zS15KDVxQijejNCrz8340/2bgLBjR9GtEG8ZVKONDjcqGQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "es-to-primitive": "^1.2.1",
- "function-bind": "^1.1.1",
- "get-intrinsic": "^1.1.1",
- "get-symbol-description": "^1.0.0",
- "has": "^1.0.3",
- "has-symbols": "^1.0.2",
- "internal-slot": "^1.0.3",
- "is-callable": "^1.2.4",
- "is-negative-zero": "^2.0.1",
- "is-regex": "^1.1.4",
- "is-shared-array-buffer": "^1.0.1",
- "is-string": "^1.0.7",
- "is-weakref": "^1.0.1",
- "object-inspect": "^1.11.0",
- "object-keys": "^1.1.1",
- "object.assign": "^4.1.2",
- "string.prototype.trimend": "^1.0.4",
- "string.prototype.trimstart": "^1.0.4",
- "unbox-primitive": "^1.0.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "stackframe": "^1.3.4"
}
},
"node_modules/es-define-property": {
@@ -6959,6 +6442,12 @@
"node": ">= 0.4"
}
},
+ "node_modules/es-module-lexer": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.1.0.tgz",
+ "integrity": "sha512-n27zTYMjYu1aj4MjCWzSP7G9r75utsaoc8m61weK+W8JMBGGQybd43GstCXZ3WNmSFtGT9wi59qQTW6mhTR5LQ==",
+ "license": "MIT"
+ },
"node_modules/es-object-atoms": {
"version": "1.1.1",
"resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz",
@@ -6986,31 +6475,16 @@
"node": ">= 0.4"
}
},
- "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/es5-ext": {
- "version": "0.10.61",
- "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.61.tgz",
- "integrity": "sha512-yFhIqQAzu2Ca2I4SE2Au3rxVfmohU9Y7wqGR+s7+H7krk26NXhIRAZDgqd6xqjCEFUomDEA3/Bo/7fKmIkW1kA==",
+ "version": "0.10.64",
+ "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.64.tgz",
+ "integrity": "sha512-p2snDhiLaXe6dahss1LddxqEm+SkuDvV8dnIQG0MWjyHpcMNfXKPE+/Cc0y+PhxJX3A4xGNeFCj5oc0BUh6deg==",
"hasInstallScript": true,
+ "license": "ISC",
"dependencies": {
"es6-iterator": "^2.0.3",
"es6-symbol": "^3.1.3",
+ "esniff": "^2.0.1",
"next-tick": "^1.1.0"
},
"engines": {
@@ -7021,6 +6495,7 @@
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz",
"integrity": "sha512-zw4SRzoUkd+cl+ZoE15A9o1oQd920Bb0iOJMQkQhl3jNc03YqVjAhG7scf9C5KWRU/R13Orf588uCC6525o02g==",
+ "license": "MIT",
"dependencies": {
"d": "1",
"es5-ext": "^0.10.35",
@@ -7028,18 +6503,23 @@
}
},
"node_modules/es6-symbol": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.3.tgz",
- "integrity": "sha512-NJ6Yn3FuDinBaBRWl/q5X/s4koRHBrgKAu+yGI6JCBeiu3qrcbJhwT2GeR/EXVfylRk8dpQVJoLEFhK+Mu31NA==",
+ "version": "3.1.4",
+ "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.4.tgz",
+ "integrity": "sha512-U9bFFjX8tFiATgtkJ1zg25+KviIXpgRvRHS8sau3GfhVzThRQrOeksPeT0BWW2MNZs1OEWJ1DPXOQMn0KKRkvg==",
+ "license": "ISC",
"dependencies": {
- "d": "^1.0.1",
- "ext": "^1.1.2"
+ "d": "^1.0.2",
+ "ext": "^1.7.0"
+ },
+ "engines": {
+ "node": ">=0.12"
}
},
"node_modules/es6-weak-map": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.3.tgz",
"integrity": "sha512-p5um32HOTO1kP+w7PRnB+5lQ43Z6muuMuIMffvDN8ZB4GcnjLBV6zGStpbASIMk4DCAvEaamhe2zhyCb/QXXsA==",
+ "license": "ISC",
"dependencies": {
"d": "1",
"es5-ext": "^0.10.46",
@@ -7048,10 +6528,10 @@
}
},
"node_modules/escalade": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
- "integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
- "dev": true,
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz",
+ "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==",
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -7059,166 +6539,170 @@
"node_modules/escape-html": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz",
- "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg= sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
- "dev": true
+ "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/escape-latex": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/escape-latex/-/escape-latex-1.2.0.tgz",
- "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw=="
+ "integrity": "sha512-nV5aVWW1K0wEiUIEdZ4erkGGH8mDxGyxSeqPzRNtWP7ataw+/olFObw7hujFWlVjNsaDFw5VZ5NzVSIqRgfTiw==",
+ "license": "MIT"
},
"node_modules/escape-string-regexp": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
- "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ= sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-4.0.0.tgz",
+ "integrity": "sha512-TtpcNJ3XAzx3Gq8sWRzJaVajRs0uVxA2YAkdb1jm2YkPz4G6egUFAyA3n5vtEIZefPk5Wa4UXbKuS5fKkJWdgA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=0.8.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/escodegen": {
- "version": "1.14.3",
- "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-1.14.3.tgz",
- "integrity": "sha512-qFcX0XJkdg+PB3xjZZG/wKSuT1PnQWx57+TVSjIMmILd2yC/6ByYElPwJnslDsuWuSAp4AwJGumarAAmJch5Kw==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/escodegen/-/escodegen-2.1.0.tgz",
+ "integrity": "sha512-2NlIDTwUWJN0mRPQOdtQBzbUHvdGY2P1VXSyU83Q3xKxM7WHX2Ql8dKq782Q9TgQUNOLEzEYu9bzLNj1q88I5w==",
+ "license": "BSD-2-Clause",
"dependencies": {
"esprima": "^4.0.1",
- "estraverse": "^4.2.0",
- "esutils": "^2.0.2",
- "optionator": "^0.8.1"
+ "estraverse": "^5.2.0",
+ "esutils": "^2.0.2"
},
"bin": {
"escodegen": "bin/escodegen.js",
"esgenerate": "bin/esgenerate.js"
},
"engines": {
- "node": ">=4.0"
+ "node": ">=6.0"
},
"optionalDependencies": {
"source-map": "~0.6.1"
}
},
- "node_modules/escodegen/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==",
- "optional": true,
+ "node_modules/escodegen/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "license": "BSD-2-Clause",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=4.0"
}
},
"node_modules/eslint": {
- "version": "6.8.0",
- "resolved": "https://registry.npmjs.org/eslint/-/eslint-6.8.0.tgz",
- "integrity": "sha512-K+Iayyo2LtyYhDSYwz5D5QdWw0hCacNzyq1Y821Xna2xSJj7cijoLLYmLxTQgcgZ9mC61nryMy9S7GRbYpI5Ig==",
- "deprecated": "This version is no longer supported. Please see https://eslint.org/version-support for other options.",
+ "version": "9.39.4",
+ "resolved": "https://registry.npmjs.org/eslint/-/eslint-9.39.4.tgz",
+ "integrity": "sha512-XoMjdBOwe/esVgEvLmNsD3IRHkm7fbKIUGvrleloJXUZgDHig2IPWNniv+GwjyJXzuNqVjlr5+4yVUZjycJwfQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@babel/code-frame": "^7.0.0",
- "ajv": "^6.10.0",
- "chalk": "^2.1.0",
- "cross-spawn": "^6.0.5",
- "debug": "^4.0.1",
- "doctrine": "^3.0.0",
- "eslint-scope": "^5.0.0",
- "eslint-utils": "^1.4.3",
- "eslint-visitor-keys": "^1.1.0",
- "espree": "^6.1.2",
- "esquery": "^1.0.1",
+ "@eslint-community/eslint-utils": "^4.8.0",
+ "@eslint-community/regexpp": "^4.12.1",
+ "@eslint/config-array": "^0.21.2",
+ "@eslint/config-helpers": "^0.4.2",
+ "@eslint/core": "^0.17.0",
+ "@eslint/eslintrc": "^3.3.5",
+ "@eslint/js": "9.39.4",
+ "@eslint/plugin-kit": "^0.4.1",
+ "@humanfs/node": "^0.16.6",
+ "@humanwhocodes/module-importer": "^1.0.1",
+ "@humanwhocodes/retry": "^0.4.2",
+ "@types/estree": "^1.0.6",
+ "ajv": "^6.14.0",
+ "chalk": "^4.0.0",
+ "cross-spawn": "^7.0.6",
+ "debug": "^4.3.2",
+ "escape-string-regexp": "^4.0.0",
+ "eslint-scope": "^8.4.0",
+ "eslint-visitor-keys": "^4.2.1",
+ "espree": "^10.4.0",
+ "esquery": "^1.5.0",
"esutils": "^2.0.2",
- "file-entry-cache": "^5.0.1",
- "functional-red-black-tree": "^1.0.1",
- "glob-parent": "^5.0.0",
- "globals": "^12.1.0",
- "ignore": "^4.0.6",
- "import-fresh": "^3.0.0",
+ "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",
- "inquirer": "^7.0.0",
"is-glob": "^4.0.0",
- "js-yaml": "^3.13.1",
"json-stable-stringify-without-jsonify": "^1.0.1",
- "levn": "^0.3.0",
- "lodash": "^4.17.14",
- "minimatch": "^3.0.4",
- "mkdirp": "^0.5.1",
+ "lodash.merge": "^4.6.2",
+ "minimatch": "^3.1.5",
"natural-compare": "^1.4.0",
- "optionator": "^0.8.3",
- "progress": "^2.0.0",
- "regexpp": "^2.0.1",
- "semver": "^6.1.2",
- "strip-ansi": "^5.2.0",
- "strip-json-comments": "^3.0.1",
- "table": "^5.2.3",
- "text-table": "^0.2.0",
- "v8-compile-cache": "^2.0.3"
+ "optionator": "^0.9.3"
},
"bin": {
"eslint": "bin/eslint.js"
},
"engines": {
- "node": "^8.10.0 || ^10.13.0 || >=11.10.1"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"funding": {
- "url": "https://opencollective.com/eslint"
- }
- },
- "node_modules/eslint-loader": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/eslint-loader/-/eslint-loader-2.2.1.tgz",
- "integrity": "sha512-RLgV9hoCVsMLvOxCuNjdqOrUqIj9oJg8hF44vzJaYqsAHuY9G2YAeN3joQ9nxP0p5Th9iFSIpKo+SD8KISxXRg==",
- "deprecated": "This loader has been deprecated. Please use eslint-webpack-plugin",
- "dev": true,
- "dependencies": {
- "loader-fs-cache": "^1.0.0",
- "loader-utils": "^1.0.2",
- "object-assign": "^4.0.1",
- "object-hash": "^1.1.4",
- "rimraf": "^2.6.1"
+ "url": "https://eslint.org/donate"
},
"peerDependencies": {
- "eslint": ">=1.6.0 <7.0.0",
- "webpack": ">=2.0.0 <5.0.0"
- }
- },
- "node_modules/eslint-loader/node_modules/object-hash": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-1.3.1.tgz",
- "integrity": "sha512-OSuu/pU4ENM9kmREg0BdNrUDIl1heYa4mBZacJc+vVWz4GtAwu7jO8s4AIt2aGRUTqxykpWzI3Oqnsm13tTMDA==",
- "dev": true,
- "engines": {
- "node": ">= 0.10.0"
+ "jiti": "*"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ }
}
},
"node_modules/eslint-plugin-vue": {
- "version": "6.2.2",
- "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-6.2.2.tgz",
- "integrity": "sha512-Nhc+oVAHm0uz/PkJAWscwIT4ijTrK5fqNqz9QB1D35SbbuMG1uB6Yr5AJpvPSWg+WOw7nYNswerYh0kOk64gqQ==",
+ "version": "10.9.1",
+ "resolved": "https://registry.npmjs.org/eslint-plugin-vue/-/eslint-plugin-vue-10.9.1.tgz",
+ "integrity": "sha512-cHB0Tf4Duvzwecwd/AqWzZvF/QszE13BhjVUpVXWCy9AeMR5GjkAjP3i85vqgLgOuTmkHR1OJ5oMeqLHtuw8zg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
+ "@eslint-community/eslint-utils": "^4.4.0",
"natural-compare": "^1.4.0",
- "semver": "^5.6.0",
- "vue-eslint-parser": "^7.0.0"
+ "nth-check": "^2.1.1",
+ "postcss-selector-parser": "^7.1.0",
+ "semver": "^7.6.3",
+ "xml-name-validator": "^4.0.0"
},
"engines": {
- "node": ">=8.10"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
},
"peerDependencies": {
- "eslint": "^5.0.0 || ^6.0.0"
+ "@stylistic/eslint-plugin": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0",
+ "@typescript-eslint/parser": "^7.0.0 || ^8.0.0",
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0",
+ "vue-eslint-parser": "^10.3.0"
+ },
+ "peerDependenciesMeta": {
+ "@stylistic/eslint-plugin": {
+ "optional": true
+ },
+ "@typescript-eslint/parser": {
+ "optional": true
+ }
}
},
- "node_modules/eslint-plugin-vue/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
+ "node_modules/eslint-plugin-vue/node_modules/postcss-selector-parser": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
+ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
"dev": true,
- "bin": {
- "semver": "bin/semver"
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
+ "engines": {
+ "node": ">=4"
}
},
"node_modules/eslint-scope": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz",
"integrity": "sha512-2NxwbF/hZ0KpepYN0cNbo+FN6XoK7GaHlQhgx/hIZl6Va0bF45RQOOwhLIy8lQDbuCiadSLCBnH2CFYquit5bw==",
- "dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"esrecurse": "^4.3.0",
"estraverse": "^4.1.1"
@@ -7227,164 +6711,238 @@
"node": ">=8.0.0"
}
},
- "node_modules/eslint-utils": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.4.3.tgz",
- "integrity": "sha512-fbBN5W2xdY45KulGXmLHZ3c3FHfVYmKg0IrAKGOkT/464PQsx2UeIzfz1RmEci+KLm1bBaAzZAh8+/E+XAeZ8Q==",
- "dev": true,
- "dependencies": {
- "eslint-visitor-keys": "^1.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/eslint-visitor-keys": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.3.0.tgz",
- "integrity": "sha512-6J72N8UNa462wa/KFODt/PJ3IU60SDpC3QXC1Hjc1BXXpfL2C9R5+AU7jhe0F6GREqVMh4Juu+NY7xn+6dipUQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/eslint/node_modules/ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-2.1.0.tgz",
+ "integrity": "sha512-0rSmRBzXgDzIsD6mGdJgevzgezI534Cer5L/vyMX0kHzT/jiB43jRhd9YUlMGYLQy2zprNmoT8qasCGtY+QaKw==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=6"
+ "node": ">=10"
}
},
- "node_modules/eslint/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "node_modules/eslint-webpack-plugin": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/eslint-webpack-plugin/-/eslint-webpack-plugin-4.2.0.tgz",
+ "integrity": "sha512-rsfpFQ01AWQbqtjgPRr2usVRxhWDuG0YDYcG8DJOteD3EFnpeuYuOwk0PQiN7PRBTqS6ElNdtPZPggj8If9WnA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "color-convert": "^1.9.0"
+ "@types/eslint": "^8.56.10",
+ "jest-worker": "^29.7.0",
+ "micromatch": "^4.0.5",
+ "normalize-path": "^3.0.0",
+ "schema-utils": "^4.2.0"
},
"engines": {
- "node": ">=4"
+ "node": ">= 14.15.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "eslint": "^8.0.0 || ^9.0.0",
+ "webpack": "^5.0.0"
}
},
- "node_modules/eslint/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "node_modules/eslint-webpack-plugin/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
},
- "engines": {
- "node": ">=4"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/eslint/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "node_modules/eslint-webpack-plugin/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "color-name": "1.1.3"
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
}
},
- "node_modules/eslint/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/eslint/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==",
+ "node_modules/eslint-webpack-plugin/node_modules/jest-worker": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.7.0.tgz",
+ "integrity": "sha512-eIz2msL/EzL9UFTFFx7jBTkeZfku0yUAyZZZmJ93H2TYEiroIx2PQjEXcwYtYl8zXCxb+PAmA2hLIt/6ZEkPHw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-glob": "^4.0.1"
+ "@types/node": "*",
+ "jest-util": "^29.7.0",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
},
"engines": {
- "node": ">= 6"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/eslint/node_modules/globals": {
- "version": "12.4.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-12.4.0.tgz",
- "integrity": "sha512-BWICuzzDvDoH54NHKCseDanAhE3CeDorgDL5MT6LMXXj2WCnd9UC2szdk4AWLfjdgNBCXLUanXYcpBBKOSWGwg==",
+ "node_modules/eslint-webpack-plugin/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,
+ "license": "MIT"
+ },
+ "node_modules/eslint-webpack-plugin/node_modules/schema-utils": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "type-fest": "^0.8.1"
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
},
"engines": {
- "node": ">=8"
+ "node": ">= 10.13.0"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
- "node_modules/eslint/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "node_modules/eslint-webpack-plugin/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
}
},
- "node_modules/eslint/node_modules/strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "node_modules/eslint/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-regex": "^4.1.0"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=6"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/eslint/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "node_modules/eslint/node_modules/eslint-scope": {
+ "version": "8.4.0",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-8.4.0.tgz",
+ "integrity": "sha512-sNXOfKCn74rt8RICKMvJS7XKV/Xk9kA7DyJr8mJik3S7Cwgy3qlkkmyS2uQB3jiJg6VNdZd/pDBJu0nvG2NlTg==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "has-flag": "^3.0.0"
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
},
"engines": {
- "node": ">=4"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/eslint/node_modules/type-fest": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
- "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
+ "node_modules/eslint/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=8"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/eslint/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "engines": {
+ "node": ">=4.0"
+ }
+ },
+ "node_modules/esniff": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/esniff/-/esniff-2.0.1.tgz",
+ "integrity": "sha512-kTUIGKQ/mDPFoJ0oVfcmyJn4iBDRptjNVIzwIFR7tqWXdVI9xfA2RMwY/gbSpJG3lkdWNEjLap/NqVHZiJsdfg==",
+ "license": "ISC",
+ "dependencies": {
+ "d": "^1.0.1",
+ "es5-ext": "^0.10.62",
+ "event-emitter": "^0.3.5",
+ "type": "^2.7.2"
+ },
+ "engines": {
+ "node": ">=0.10"
}
},
"node_modules/espree": {
- "version": "6.2.1",
- "resolved": "https://registry.npmjs.org/espree/-/espree-6.2.1.tgz",
- "integrity": "sha512-ysCxRQY3WaXJz9tdbWOwuWr5Y/XrPTGX9Kiz3yoUXwW0VZ4w30HTkQLaGx/+ttFjF8i+ACbArnB4ce68a9m5hw==",
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/espree/-/espree-10.4.0.tgz",
+ "integrity": "sha512-j6PAQ2uUr79PZhBjP5C5fhl8e39FmRnOjsD5lGnWrFU8i2G776tBK7+nP8KuQUTTyAZUwfQqXAgrVH5MbH9CYQ==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "acorn": "^7.1.1",
- "acorn-jsx": "^5.2.0",
- "eslint-visitor-keys": "^1.1.0"
+ "acorn": "^8.15.0",
+ "acorn-jsx": "^5.3.2",
+ "eslint-visitor-keys": "^4.2.1"
},
"engines": {
- "node": ">=6.0.0"
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
+ }
+ },
+ "node_modules/espree/node_modules/eslint-visitor-keys": {
+ "version": "4.2.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-4.2.1.tgz",
+ "integrity": "sha512-Uhdk5sfqcee/9H/rCOJikYz67o0a2Tw2hGRPOG2Y1R2dg7brRe1uG0yaNQDHu+TO/uQPF/5eCapvYSmHUjt7JQ==",
+ "dev": true,
+ "license": "Apache-2.0",
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
"node_modules/esprima": {
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "license": "BSD-2-Clause",
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
@@ -7394,10 +6952,11 @@
}
},
"node_modules/esquery": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.4.0.tgz",
- "integrity": "sha512-cCDispWt5vHHtwMY2YrAQ4ibFkAL8RbH5YGBnZBc90MolvvfkkQcJro/aZiAQUlQ3qgrYS6D6v8Gc5G5CQsc9w==",
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.7.0.tgz",
+ "integrity": "sha512-Ap6G0WQwcU/LHsvLwON1fAQX9Zp0A2Y6Y/cJBl9r/JbW90Zyg4/zbG6zzKa2OTALELarYHmKu0GhpM5EO+7T0g==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"estraverse": "^5.1.0"
},
@@ -7410,6 +6969,7 @@
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=4.0"
}
@@ -7418,7 +6978,7 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.3.0.tgz",
"integrity": "sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==",
- "dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"estraverse": "^5.2.0"
},
@@ -7430,7 +6990,7 @@
"version": "5.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
"integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
- "dev": true,
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=4.0"
}
@@ -7439,14 +6999,23 @@
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.3.0.tgz",
"integrity": "sha512-39nnKffWz8xN1BU/2c79n9nB9HDzo0niYUqx6xyqUnyoAnQyyWpOTdZEeiCch8BBu515t4wp9ZmgVfVhn9EBpw==",
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=4.0"
}
},
+ "node_modules/estree-walker": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-2.0.2.tgz",
+ "integrity": "sha512-Rfkk/Mp/DL7JVje3u18FxFujQlTNR2q6QfMSMB7AvCBx91NGj/ba3kCfza0f6dVDbw7YlRf/nDrn7pQrCCyQ/w==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/esutils": {
"version": "2.0.3",
"resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.3.tgz",
"integrity": "sha512-kVscqXk4OCp68SZ0dkgEKVi6/8ij300KBWTJq32P/dYeWTSwK41WyTxalN1eRmA5Z9UU/LX9D7FWSmV9SAYx6g==",
+ "license": "BSD-2-Clause",
"engines": {
"node": ">=0.10.0"
}
@@ -7454,17 +7023,29 @@
"node_modules/etag": {
"version": "1.8.1",
"resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz",
- "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc= sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
+ "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
+ "node_modules/event-emitter": {
+ "version": "0.3.5",
+ "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz",
+ "integrity": "sha512-D9rRn9y7kLPnJ+hMq7S/nhvoKwwvVJahBi2BPmx3bvbsEdK3W9ii8cBSGjP+72/LnM4n6fo3+dkCX5FeTQruXA==",
+ "license": "MIT",
+ "dependencies": {
+ "d": "1",
+ "es5-ext": "~0.10.14"
+ }
+ },
"node_modules/event-pubsub": {
"version": "4.3.0",
"resolved": "https://registry.npmjs.org/event-pubsub/-/event-pubsub-4.3.0.tgz",
"integrity": "sha512-z7IyloorXvKbFx9Bpie2+vMJKKx1fH1EN5yiTfp8CiLOTptSYy1g8H4yDpGlEdshL1PBiFtBHepF2cNsqeEeFQ==",
"dev": true,
+ "license": "Unlicense",
"engines": {
"node": ">=4.0.0"
}
@@ -7473,40 +7054,24 @@
"version": "4.0.7",
"resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz",
"integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/events": {
"version": "3.3.0",
"resolved": "https://registry.npmjs.org/events/-/events-3.3.0.tgz",
"integrity": "sha512-mQw+2fkQbALzQ7V0MY0IqdnXNOeTtP4r0lN9z7AAawCXgqea7bDii20AYrIBrFd/Hx0M2Ocz6S111CaFkUcb0Q==",
+ "license": "MIT",
"engines": {
"node": ">=0.8.x"
}
},
- "node_modules/eventsource": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/eventsource/-/eventsource-1.1.2.tgz",
- "integrity": "sha512-xAH3zWhgO2/3KIniEKYPr8plNSzlGINOUqYj0m0u7AB81iRw8b/3E73W6AuU+6klLbaSFmZnaETQ2lXPfAydrA==",
- "dev": true,
- "engines": {
- "node": ">=0.12.0"
- }
- },
- "node_modules/evp_bytestokey": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/evp_bytestokey/-/evp_bytestokey-1.0.3.tgz",
- "integrity": "sha512-/f2Go4TognH/KvCISP7OUsHn85hT9nUkxxA9BEWxFn+Oj9o8ZNLm/40hdlgSLyuOimsrTKLUMEorQexp/aPQeA==",
- "dev": true,
- "dependencies": {
- "md5.js": "^1.3.4",
- "safe-buffer": "^5.1.1"
- }
- },
"node_modules/execa": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz",
"integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"cross-spawn": "^6.0.0",
"get-stream": "^4.0.0",
@@ -7520,764 +7085,528 @@
"node": ">=6"
}
},
- "node_modules/expand-brackets": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/expand-brackets/-/expand-brackets-2.1.4.tgz",
- "integrity": "sha1-t3c14xXOMPa27/D4OwQVGiJEliI= sha512-w/ozOKR9Obk3qoWeY/WDi6MFta9AoMR+zud60mdnbniMcBxRuFJyDt2LdX/14A1UABeqk+Uk+LDfUpvoGKppZA==",
+ "node_modules/express": {
+ "version": "4.22.1",
+ "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz",
+ "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "debug": "^2.3.3",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "posix-character-classes": "^0.1.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
+ "accepts": "~1.3.8",
+ "array-flatten": "1.1.1",
+ "body-parser": "~1.20.3",
+ "content-disposition": "~0.5.4",
+ "content-type": "~1.0.4",
+ "cookie": "~0.7.1",
+ "cookie-signature": "~1.0.6",
+ "debug": "2.6.9",
+ "depd": "2.0.0",
+ "encodeurl": "~2.0.0",
+ "escape-html": "~1.0.3",
+ "etag": "~1.8.1",
+ "finalhandler": "~1.3.1",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.0",
+ "merge-descriptors": "1.0.3",
+ "methods": "~1.1.2",
+ "on-finished": "~2.4.1",
+ "parseurl": "~1.3.3",
+ "path-to-regexp": "~0.1.12",
+ "proxy-addr": "~2.0.7",
+ "qs": "~6.14.0",
+ "range-parser": "~1.2.1",
+ "safe-buffer": "5.2.1",
+ "send": "~0.19.0",
+ "serve-static": "~1.16.2",
+ "setprototypeof": "1.2.0",
+ "statuses": "~2.0.1",
+ "type-is": "~1.6.18",
+ "utils-merge": "1.0.1",
+ "vary": "~1.1.2"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 0.10.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
- "node_modules/expand-brackets/node_modules/debug": {
+ "node_modules/express/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
- "node_modules/expand-brackets/node_modules/define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
+ "node_modules/express/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/ext": {
+ "version": "1.7.0",
+ "resolved": "https://registry.npmjs.org/ext/-/ext-1.7.0.tgz",
+ "integrity": "sha512-6hxeJYaL110a9b5TEJSj0gojyHQAmA2ch5Os+ySCiA1QGdS697XWY1pzsrSjqA9LDEEgdB/KypIlR59RcLuHYw==",
+ "license": "ISC",
+ "dependencies": {
+ "type": "^2.7.2"
+ }
+ },
+ "node_modules/falafel": {
+ "version": "2.2.5",
+ "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.2.5.tgz",
+ "integrity": "sha512-HuC1qF9iTnHDnML9YZAdCDQwT0yKl/U55K4XSUXqGAA2GLoafFgWRqdAbhWJxXaYD4pyoVxAJ8wH670jMpI9DQ==",
+ "license": "MIT",
"dependencies": {
- "is-descriptor": "^0.1.0"
+ "acorn": "^7.1.1",
+ "isarray": "^2.0.1"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=0.4.0"
}
},
- "node_modules/expand-brackets/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
- "dev": true,
- "dependencies": {
- "is-extendable": "^0.1.0"
+ "node_modules/falafel/node_modules/acorn": {
+ "version": "7.4.1",
+ "resolved": "https://registry.npmjs.org/acorn/-/acorn-7.4.1.tgz",
+ "integrity": "sha512-nQyp0o1/mNdbTO1PO6kHkwSrmgZ0MT/jCCpNiwbUjGoRN4dlBhqJtoQuCnEOKzgTVwg0ZWiCoQy6SxMebQVh8A==",
+ "license": "MIT",
+ "bin": {
+ "acorn": "bin/acorn"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=0.4.0"
}
},
- "node_modules/expand-brackets/node_modules/is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==",
- "deprecated": "Please upgrade to v0.1.7",
- "dev": true,
+ "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==",
+ "license": "MIT"
+ },
+ "node_modules/fast-glob": {
+ "version": "3.3.3",
+ "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.3.3.tgz",
+ "integrity": "sha512-7MptL8U0cqcFdzIzwOTHoilX9x5BrNqye7Z/LuC7kCMRio1EMSyqRK3BEAUD7sXRq4iT4AzTVuZdhgQ2TCvYLg==",
+ "license": "MIT",
"dependencies": {
- "kind-of": "^3.0.2"
+ "@nodelib/fs.stat": "^2.0.2",
+ "@nodelib/fs.walk": "^1.2.3",
+ "glob-parent": "^5.1.2",
+ "merge2": "^1.3.0",
+ "micromatch": "^4.0.8"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8.6.0"
}
},
- "node_modules/expand-brackets/node_modules/is-accessor-descriptor/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
+ "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==",
+ "license": "ISC",
"dependencies": {
- "is-buffer": "^1.1.5"
+ "is-glob": "^4.0.1"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 6"
}
},
- "node_modules/expand-brackets/node_modules/is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==",
- "deprecated": "Please upgrade to v0.1.5",
+ "node_modules/fast-isnumeric": {
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/fast-isnumeric/-/fast-isnumeric-1.1.4.tgz",
+ "integrity": "sha512-1mM8qOr2LYz8zGaUdmiqRDiuue00Dxjgcb1NQR7TnhLVh6sQyngP9xvLo7Sl7LZpP/sk5eb+bcyWXw530NTBZw==",
+ "license": "MIT",
+ "dependencies": {
+ "is-string-blank": "^1.0.1"
+ }
+ },
+ "node_modules/fast-json-stable-stringify": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-levenshtein": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz",
+ "integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/fast-uri": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.2.tgz",
+ "integrity": "sha512-rVjf7ArG3LTk+FS6Yw81V1DLuZl1bRbNrev6Tmd/9RaroeeRRJhAt7jg/6YFxbvAQXUCavSoZhPPj6oOx+5KjQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/fastify"
+ },
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/fastify"
+ }
+ ],
+ "license": "BSD-3-Clause"
+ },
+ "node_modules/fastq": {
+ "version": "1.20.1",
+ "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.20.1.tgz",
+ "integrity": "sha512-GGToxJ/w1x32s/D2EKND7kTil4n8OVk/9mycTc4VDza13lOvpUZTGX3mFSCtV9ksdGBVzvsyAVLM6mHFThxXxw==",
+ "license": "ISC",
"dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
+ "reusify": "^1.0.4"
}
},
- "node_modules/expand-brackets/node_modules/is-data-descriptor/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+ "node_modules/faye-websocket": {
+ "version": "0.11.4",
+ "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
+ "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "is-buffer": "^1.1.5"
+ "websocket-driver": ">=0.5.1"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=0.8.0"
}
},
- "node_modules/expand-brackets/node_modules/is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
+ "node_modules/figures": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz",
+ "integrity": "sha512-Oa2M9atig69ZkfwiApY8F2Yy+tzMbazyvqv21R0NsSC8floSOC09BbT1ITWAdoMGQvJ/aZnR1KMwdx9tvHnTNA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
+ "escape-string-regexp": "^1.0.5"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=4"
}
},
- "node_modules/expand-brackets/node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
+ "node_modules/figures/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=0.8.0"
}
},
- "node_modules/expand-brackets/node_modules/kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
+ "node_modules/file-entry-cache": {
+ "version": "8.0.0",
+ "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-8.0.0.tgz",
+ "integrity": "sha512-XXTUwCvisa5oacNGRP9SfNtYBNAMi+RPwBFmblZEF7N7swHYQS6/Zfk7SRwx4D5j3CH211YNRco1DEMNVfZCnQ==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "flat-cache": "^4.0.0"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">=16.0.0"
}
},
- "node_modules/expand-brackets/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "node_modules/express": {
- "version": "4.17.1",
- "resolved": "https://registry.npmjs.org/express/-/express-4.17.1.tgz",
- "integrity": "sha512-mHJ9O79RqluphRrcw2X/GTh3k9tVv8YcoyY4Kkh4WDMUYKRZUq0h1o0w2rrrxBqM7VoeUVqgb27xlEMXTnYt4g==",
- "dev": true,
+ "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==",
+ "license": "MIT",
"dependencies": {
- "accepts": "~1.3.7",
- "array-flatten": "1.1.1",
- "body-parser": "1.19.0",
- "content-disposition": "0.5.3",
- "content-type": "~1.0.4",
- "cookie": "0.4.0",
- "cookie-signature": "1.0.6",
- "debug": "2.6.9",
- "depd": "~1.1.2",
- "encodeurl": "~1.0.2",
+ "to-regex-range": "^5.0.1"
+ },
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/finalhandler": {
+ "version": "1.3.2",
+ "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.3.2.tgz",
+ "integrity": "sha512-aA4RyPcd3badbdABGDuTXCMTtOneUCAYH/gxoYRTZlIJdF0YPWuGqiAsIrhNnnqdXGswYk6dGujem4w80UJFhg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "debug": "2.6.9",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
- "etag": "~1.8.1",
- "finalhandler": "~1.1.2",
- "fresh": "0.5.2",
- "merge-descriptors": "1.0.1",
- "methods": "~1.1.2",
- "on-finished": "~2.3.0",
+ "on-finished": "~2.4.1",
"parseurl": "~1.3.3",
- "path-to-regexp": "0.1.7",
- "proxy-addr": "~2.0.5",
- "qs": "6.7.0",
- "range-parser": "~1.2.1",
- "safe-buffer": "5.1.2",
- "send": "0.17.1",
- "serve-static": "1.14.1",
- "setprototypeof": "1.1.1",
- "statuses": "~1.5.0",
- "type-is": "~1.6.18",
- "utils-merge": "1.0.1",
- "vary": "~1.1.2"
+ "statuses": "~2.0.2",
+ "unpipe": "~1.0.0"
},
"engines": {
- "node": ">= 0.10.0"
+ "node": ">= 0.8"
}
},
- "node_modules/express/node_modules/debug": {
+ "node_modules/finalhandler/node_modules/debug": {
"version": "2.6.9",
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
- "node_modules/express/node_modules/ms": {
+ "node_modules/finalhandler/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "node_modules/express/node_modules/qs": {
- "version": "6.7.0",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.7.0.tgz",
- "integrity": "sha512-VCdBRNFTX1fyE7Nb6FYoURo/SPe62QCaAyzJvUjwRaIsc+NePBEniHlvxFmmX56+HZphIGtV0XeCirBtpDrTyQ==",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true,
- "engines": {
- "node": ">=0.6"
- }
- },
- "node_modules/ext": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/ext/-/ext-1.6.0.tgz",
- "integrity": "sha512-sdBImtzkq2HpkdRLtlLWDa6w4DX22ijZLKx8BMPUuKe1c5lbN6xwQDQCxSfxBQnHZ13ls/FH0MQZx/q/gr6FQg==",
- "dependencies": {
- "type": "^2.5.0"
- }
- },
- "node_modules/ext/node_modules/type": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/type/-/type-2.6.0.tgz",
- "integrity": "sha512-eiDBDOmkih5pMbo9OqsqPRGMljLodLcwd5XD5JbtNB0o89xZAwynY9EdCDsJU7LtcVCClu9DvM7/0Ep1hYX3EQ=="
- },
- "node_modules/extend": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz",
- "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==",
- "dev": true
+ "license": "MIT"
},
- "node_modules/extend-shallow": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-3.0.2.tgz",
- "integrity": "sha1-Jqcarwc7OfshJxcnRhMcJwQCjbg= sha512-BwY5b5Ql4+qZoefgMj2NUmx+tehVTH/Kf4k1ZEtOHNFcm2wSxMRo992l6X3TIgni2eZVTZ85xMOjF31fwZAj6Q==",
+ "node_modules/find-cache-dir": {
+ "version": "3.3.2",
+ "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
+ "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "assign-symbols": "^1.0.0",
- "is-extendable": "^1.0.1"
+ "commondir": "^1.0.1",
+ "make-dir": "^3.0.2",
+ "pkg-dir": "^4.1.0"
},
"engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/external-editor": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.1.0.tgz",
- "integrity": "sha512-hMQ4CX1p1izmuLYyZqLMO/qGNw10wSv9QDCPfzXfyFrOaCSSoRfqE1Kf1s5an66J5JZC62NewG+mK49jOCtQew==",
- "dev": true,
- "dependencies": {
- "chardet": "^0.7.0",
- "iconv-lite": "^0.4.24",
- "tmp": "^0.0.33"
+ "node": ">=8"
},
- "engines": {
- "node": ">=4"
+ "funding": {
+ "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
}
},
- "node_modules/external-editor/node_modules/tmp": {
- "version": "0.0.33",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz",
- "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==",
+ "node_modules/find-up": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-5.0.0.tgz",
+ "integrity": "sha512-78/PXT1wlLLDgTzDs7sjq9hzz0vXD+zn+7wypEe4fXQxCmdmqfGsEPQxmiCSQI3ajFV91bVSsvNtrJRiW6nGng==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "os-tmpdir": "~1.0.2"
+ "locate-path": "^6.0.0",
+ "path-exists": "^4.0.0"
},
"engines": {
- "node": ">=0.6.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/extglob": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/extglob/-/extglob-2.0.4.tgz",
- "integrity": "sha512-Nmb6QXkELsuBr24CJSkilo6UHHgbekK5UiZgfE6UHD3Eb27YC6oD+bhcT+tJ6cl8dmsgdQxnWlcry8ksBIBLpw==",
+ "node_modules/flat": {
+ "version": "5.0.2",
+ "resolved": "https://registry.npmjs.org/flat/-/flat-5.0.2.tgz",
+ "integrity": "sha512-b6suED+5/3rTpUBdG1gupIl8MPFCAMA0QXwmljLhvCUKcUvdE4gWky9zpuGCcXHOsz4J9wPGNWq6OKpmIzz3hQ==",
"dev": true,
- "dependencies": {
- "array-unique": "^0.3.2",
- "define-property": "^1.0.0",
- "expand-brackets": "^2.1.4",
- "extend-shallow": "^2.0.1",
- "fragment-cache": "^0.2.1",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
+ "license": "BSD-3-Clause",
+ "bin": {
+ "flat": "cli.js"
}
},
- "node_modules/extglob/node_modules/define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY= sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
+ "node_modules/flat-cache": {
+ "version": "4.0.1",
+ "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-4.0.1.tgz",
+ "integrity": "sha512-f7ccFPK3SXFHpx15UIGyRJ/FJQctuKZ0zVuN3frBo4HnK3cay9VEW0R6yPYFHC0AgqhukPzKjq22t5DmAyqGyw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-descriptor": "^1.0.0"
+ "flatted": "^3.2.9",
+ "keyv": "^4.5.4"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=16"
}
},
- "node_modules/extglob/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "node_modules/flatted": {
+ "version": "3.4.2",
+ "resolved": "https://registry.npmjs.org/flatted/-/flatted-3.4.2.tgz",
+ "integrity": "sha512-PjDse7RzhcPkIJwy5t7KPWQSZ9cAbzQXcafsetQoD7sOJRQlGikNbx7yZp2OotDnJyrDcbyRq3Ttb18iYOqkxA==",
"dev": true,
+ "license": "ISC"
+ },
+ "node_modules/flatten-vertex-data": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/flatten-vertex-data/-/flatten-vertex-data-1.0.2.tgz",
+ "integrity": "sha512-BvCBFK2NZqerFTdMDgqfHBwxYWnxeCkwONsw6PvBMcUXqo8U/KDWwmXhqx1x2kLIg7DqIsJfOaJFOmlua3Lxuw==",
+ "license": "MIT",
"dependencies": {
- "is-extendable": "^0.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
+ "dtype": "^2.0.0"
}
},
- "node_modules/extglob/node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
- "dev": true,
+ "node_modules/follow-redirects": {
+ "version": "1.16.0",
+ "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.16.0.tgz",
+ "integrity": "sha512-y5rN/uOsadFT/JfYwhxRS5R7Qce+g3zG97+JrtFZlC9klX/W5hD7iiLzScI4nZqUS7DNUdhPgw4xI8W2LuXlUw==",
+ "funding": [
+ {
+ "type": "individual",
+ "url": "https://github.com/sponsors/RubenVerborgh"
+ }
+ ],
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=4.0"
+ },
+ "peerDependenciesMeta": {
+ "debug": {
+ "optional": true
+ }
}
},
- "node_modules/extsprintf": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz",
- "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU= sha512-11Ndz7Nv+mvAC1j0ktTa7fAb0vLyGGX+rMHNBYQviQDGU0Hw7lhctJANqbPhu9nV9/izT/IntTgZ7Im/9LJs9g==",
- "dev": true,
- "engines": [
- "node >=0.6.0"
- ]
- },
- "node_modules/falafel": {
- "version": "2.2.5",
- "resolved": "https://registry.npmjs.org/falafel/-/falafel-2.2.5.tgz",
- "integrity": "sha512-HuC1qF9iTnHDnML9YZAdCDQwT0yKl/U55K4XSUXqGAA2GLoafFgWRqdAbhWJxXaYD4pyoVxAJ8wH670jMpI9DQ==",
+ "node_modules/font-atlas": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/font-atlas/-/font-atlas-2.1.0.tgz",
+ "integrity": "sha512-kP3AmvX+HJpW4w3d+PiPR2X6E1yvsBXt2yhuCw+yReO9F1WYhvZwx3c95DGZGwg9xYzDGrgJYa885xmVA+28Cg==",
+ "license": "MIT",
"dependencies": {
- "acorn": "^7.1.1",
- "isarray": "^2.0.1"
- },
- "engines": {
- "node": ">=0.4.0"
+ "css-font": "^1.0.0"
}
},
- "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-glob": {
- "version": "3.2.7",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-3.2.7.tgz",
- "integrity": "sha512-rYGMRwip6lUMvYD3BTScMwT1HtAs2d71SMv66Vrxs0IekGZEjhM0pcMfjQPnknBt2zeCwQMEupiN02ZP4DiT1Q==",
- "dev": true,
+ "node_modules/font-measure": {
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/font-measure/-/font-measure-1.2.2.tgz",
+ "integrity": "sha512-mRLEpdrWzKe9hbfaF3Qpr06TAjquuBVP5cHy4b3hyeNdjc9i0PO6HniGsX5vjL5OWv7+Bd++NiooNpT/s8BvIA==",
+ "license": "MIT",
"dependencies": {
- "@nodelib/fs.stat": "^2.0.2",
- "@nodelib/fs.walk": "^1.2.3",
- "glob-parent": "^5.1.2",
- "merge2": "^1.3.0",
- "micromatch": "^4.0.4"
- },
- "engines": {
- "node": ">=8"
+ "css-font": "^1.2.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,
+ "node_modules/form-data": {
+ "version": "4.0.5",
+ "resolved": "https://registry.npmjs.org/form-data/-/form-data-4.0.5.tgz",
+ "integrity": "sha512-8RipRLol37bNs2bhoV67fiTEvdTrbMUYcFTiy3+wuuOnUog2QBHCZWXDRijWQfAkhBj2Uf5UnVaiWwA5vdd82w==",
+ "license": "MIT",
"dependencies": {
- "is-glob": "^4.0.1"
+ "asynckit": "^0.4.0",
+ "combined-stream": "^1.0.8",
+ "es-set-tostringtag": "^2.1.0",
+ "hasown": "^2.0.2",
+ "mime-types": "^2.1.12"
},
"engines": {
"node": ">= 6"
}
},
- "node_modules/fast-isnumeric": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/fast-isnumeric/-/fast-isnumeric-1.1.4.tgz",
- "integrity": "sha512-1mM8qOr2LYz8zGaUdmiqRDiuue00Dxjgcb1NQR7TnhLVh6sQyngP9xvLo7Sl7LZpP/sk5eb+bcyWXw530NTBZw==",
- "dependencies": {
- "is-string-blank": "^1.0.1"
- }
- },
- "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": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc= sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
- },
- "node_modules/fastq": {
- "version": "1.13.0",
- "resolved": "https://registry.npmjs.org/fastq/-/fastq-1.13.0.tgz",
- "integrity": "sha512-YpkpUnK8od0o1hmeSc7UUs/eB/vIPWJYjKck2QKIzAf71Vm1AAQ3EbuZB3g2JIy+pg+ERD0vqI79KyZiB2e2Nw==",
- "dev": true,
- "dependencies": {
- "reusify": "^1.0.4"
- }
- },
- "node_modules/faye-websocket": {
- "version": "0.11.4",
- "resolved": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.11.4.tgz",
- "integrity": "sha512-CzbClwlXAuiRQAlUyfqPgvPoNKTckTPGfwZV4ZdAhVcP2lh9KUxJg2b5GkE7XbjKQ3YJnQ9z6D9ntLAlB+tP8g==",
+ "node_modules/forwarded": {
+ "version": "0.2.0",
+ "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
+ "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
"dev": true,
- "dependencies": {
- "websocket-driver": ">=0.5.1"
- },
+ "license": "MIT",
"engines": {
- "node": ">=0.8.0"
+ "node": ">= 0.6"
}
},
- "node_modules/figgy-pudding": {
- "version": "3.5.2",
- "resolved": "https://registry.npmjs.org/figgy-pudding/-/figgy-pudding-3.5.2.tgz",
- "integrity": "sha512-0btnI/H8f2pavGMN8w40mlSKOfTK2SVJmBfBeVIj3kNw0swwgzyRq0d5TJVOwodFmtvpPeWPN/MCcfuWF0Ezbw==",
- "deprecated": "This module is no longer supported.",
- "dev": true
- },
- "node_modules/figures": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/figures/-/figures-3.2.0.tgz",
- "integrity": "sha512-yaduQFRKLXYOGgEn6AZau90j3ggSOyiqXU0F9JZfeXYhNa+Jk4X+s45A2zg5jns87GAFa34BBm2kXw4XpNcbdg==",
+ "node_modules/fraction.js": {
+ "version": "5.3.4",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-5.3.4.tgz",
+ "integrity": "sha512-1X1NTtiJphryn/uLQz3whtY6jK3fTqoE3ohKs0tT+Ujr1W59oopxmoEh7Lu5p6vBaPbgoM0bzveAW4Qi5RyWDQ==",
"dev": true,
- "dependencies": {
- "escape-string-regexp": "^1.0.5"
- },
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": "*"
},
"funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "type": "github",
+ "url": "https://github.com/sponsors/rawify"
}
},
- "node_modules/file-entry-cache": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-5.0.1.tgz",
- "integrity": "sha512-bCg29ictuBaKUwwArK4ouCaqDgLZcysCFLmM/Yn/FDoqndh/9vNuQfXRDvTuXKLxfD/JtZQGKFT8MGcJBK644g==",
+ "node_modules/fresh": {
+ "version": "0.5.2",
+ "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
+ "integrity": "sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
"dev": true,
- "dependencies": {
- "flat-cache": "^2.0.1"
- },
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">= 0.6"
}
},
- "node_modules/file-loader": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/file-loader/-/file-loader-4.3.0.tgz",
- "integrity": "sha512-aKrYPYjF1yG3oX0kWRrqrSMfgftm7oJW5M+m4owoldH5C51C0RkIwB++JbRvEW3IU6/ZG5n8UvEcdgwOt2UOWA==",
- "dev": true,
+ "node_modules/from2": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
+ "integrity": "sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==",
+ "license": "MIT",
"dependencies": {
- "loader-utils": "^1.2.3",
- "schema-utils": "^2.5.0"
- },
- "engines": {
- "node": ">= 8.9.0"
- },
- "peerDependencies": {
- "webpack": "^4.0.0"
+ "inherits": "^2.0.1",
+ "readable-stream": "^2.0.0"
}
},
- "node_modules/file-uri-to-path": {
+ "node_modules/from2/node_modules/isarray": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/file-uri-to-path/-/file-uri-to-path-1.0.0.tgz",
- "integrity": "sha512-0Zt+s3L7Vf1biwWZ29aARiVYLx7iMGnEUl9x33fbB/j3jR81u/O2LbqK+Bm1CDSNDKVtJ/YjwY7TUd5SkeLQLw==",
- "dev": true,
- "optional": true
- },
- "node_modules/filesize": {
- "version": "3.6.1",
- "resolved": "https://registry.npmjs.org/filesize/-/filesize-3.6.1.tgz",
- "integrity": "sha512-7KjR1vv6qnicaPMi1iiTcI85CyYwRO/PSFCu6SvqL8jN2Wjt/NIYQTFtFs7fSDCYOstUkEWIQGFUg5YZQfjlcg==",
- "dev": true,
- "engines": {
- "node": ">= 0.4.0"
- }
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "license": "MIT"
},
- "node_modules/fill-range": {
- "version": "7.0.1",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
- "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
- "dev": true,
- "dependencies": {
- "to-regex-range": "^5.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/finalhandler": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-1.1.2.tgz",
- "integrity": "sha512-aAWcW57uxVNrQZqFXjITpW3sIUQmHGG3qSb9mUah9MgMC4NeWhNOlNjXEYq3HjRAvL6arUviZGGJsBg6z0zsWA==",
- "dev": true,
- "dependencies": {
- "debug": "2.6.9",
- "encodeurl": "~1.0.2",
- "escape-html": "~1.0.3",
- "on-finished": "~2.3.0",
- "parseurl": "~1.3.3",
- "statuses": "~1.5.0",
- "unpipe": "~1.0.0"
- },
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/finalhandler/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/finalhandler/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "node_modules/find-cache-dir": {
- "version": "3.3.2",
- "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-3.3.2.tgz",
- "integrity": "sha512-wXZV5emFEjrridIgED11OoUKLxiYjAcqot/NJdAkOhlJ+vGzwhOAfcG5OX1jP+S0PcjEn8bdMJv+g2jwQ3Onig==",
- "dev": true,
- "dependencies": {
- "commondir": "^1.0.1",
- "make-dir": "^3.0.2",
- "pkg-dir": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- },
- "funding": {
- "url": "https://github.com/avajs/find-cache-dir?sponsor=1"
- }
- },
- "node_modules/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dev": true,
- "dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/flat-cache": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-2.0.1.tgz",
- "integrity": "sha512-LoQe6yDuUMDzQAEH8sgmh4Md6oZnc/7PjtwjNFSzveXqSHt6ka9fPBuso7IGf9Rz4uqnSnWiFH2B/zj24a5ReA==",
- "dev": true,
- "dependencies": {
- "flatted": "^2.0.0",
- "rimraf": "2.6.3",
- "write": "1.0.3"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/flat-cache/node_modules/rimraf": {
- "version": "2.6.3",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.3.tgz",
- "integrity": "sha512-mwqeW5XsA2qAejG46gYdENaxXjx9onRNCfn7L0duuP4hCuTIi/QO7PDK07KJfp1d+izWPrzEJDcSqBa0OZQriA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "dev": true,
+ "node_modules/from2/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
"dependencies": {
- "glob": "^7.1.3"
- },
- "bin": {
- "rimraf": "bin.js"
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
}
},
- "node_modules/flatted": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/flatted/-/flatted-2.0.2.tgz",
- "integrity": "sha512-r5wGx7YeOwNWNlCA0wQ86zKyDLMQr+/RB8xy74M4hTphfmjlijTSSXGuH8rnvKZnfT9i+75zmd8jcKdMR4O6jA==",
- "dev": true
- },
- "node_modules/flatten-vertex-data": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/flatten-vertex-data/-/flatten-vertex-data-1.0.2.tgz",
- "integrity": "sha512-BvCBFK2NZqerFTdMDgqfHBwxYWnxeCkwONsw6PvBMcUXqo8U/KDWwmXhqx1x2kLIg7DqIsJfOaJFOmlua3Lxuw==",
- "dependencies": {
- "dtype": "^2.0.0"
- }
+ "node_modules/from2/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
},
- "node_modules/flush-write-stream": {
+ "node_modules/from2/node_modules/string_decoder": {
"version": "1.1.1",
- "resolved": "https://registry.npmjs.org/flush-write-stream/-/flush-write-stream-1.1.1.tgz",
- "integrity": "sha512-3Z4XhFZ3992uIq0XOqb9AreonueSYphE6oYbpt5+3u06JWklbsPkNv3ZKkP9Bz/r+1MWCaMoSQ28P85+1Yc77w==",
- "dev": true,
- "dependencies": {
- "inherits": "^2.0.3",
- "readable-stream": "^2.3.6"
- }
- },
- "node_modules/follow-redirects": {
- "version": "1.15.6",
- "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.6.tgz",
- "integrity": "sha512-wWN62YITEaOpSK584EZXJafH1AGpO8RVgElfkuXbTOrPX4fIfOyEpW/CsiNd8JdYrAoOvafRTOEnvsO++qCqFA==",
- "funding": [
- {
- "type": "individual",
- "url": "https://github.com/sponsors/RubenVerborgh"
- }
- ],
- "engines": {
- "node": ">=4.0"
- },
- "peerDependenciesMeta": {
- "debug": {
- "optional": true
- }
- }
- },
- "node_modules/font-atlas": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/font-atlas/-/font-atlas-2.1.0.tgz",
- "integrity": "sha512-kP3AmvX+HJpW4w3d+PiPR2X6E1yvsBXt2yhuCw+yReO9F1WYhvZwx3c95DGZGwg9xYzDGrgJYa885xmVA+28Cg==",
- "dependencies": {
- "css-font": "^1.0.0"
- }
- },
- "node_modules/font-measure": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/font-measure/-/font-measure-1.2.2.tgz",
- "integrity": "sha512-mRLEpdrWzKe9hbfaF3Qpr06TAjquuBVP5cHy4b3hyeNdjc9i0PO6HniGsX5vjL5OWv7+Bd++NiooNpT/s8BvIA==",
- "dependencies": {
- "css-font": "^1.2.0"
- }
- },
- "node_modules/for-in": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/for-in/-/for-in-1.0.2.tgz",
- "integrity": "sha1-gQaNKVqBQuwKxybG4iAMMPttXoA= sha512-7EwmXrOjyL+ChxMhmG5lnW9MPt1aIeZEwKhQzoBUdTV0N3zuwWDZYVJatDvZ2OyzPUvdIAZDsCetk3coyMfcnQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/forever-agent": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz",
- "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE= sha512-j0KLYPhm6zeac4lz3oJ3o65qvgQCcPubiyotZrXqEaG4hNagNYO8qdlUrX5vwqv9ohqeT/Z3j6+yW067yWWdUw==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/form-data": {
- "version": "2.3.3",
- "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz",
- "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==",
- "dev": true,
- "dependencies": {
- "asynckit": "^0.4.0",
- "combined-stream": "^1.0.6",
- "mime-types": "^2.1.12"
- },
- "engines": {
- "node": ">= 0.12"
- }
- },
- "node_modules/forwarded": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.2.0.tgz",
- "integrity": "sha512-buRG0fpBtRHSTCOASe6hD258tEubFoRLb4ZNA6NxMVHNw2gOcwHo9wyablzMzOA5z9xA9L1KNjk/Nt6MT9aYow==",
- "dev": true,
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/fraction.js": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
- "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
- "engines": {
- "node": "*"
- },
- "funding": {
- "type": "patreon",
- "url": "https://www.patreon.com/infusion"
- }
- },
- "node_modules/fragment-cache": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/fragment-cache/-/fragment-cache-0.2.1.tgz",
- "integrity": "sha1-QpD60n8T6Jvn8zeZxrxaCr//DRk= sha512-GMBAbW9antB8iZRHLoGw0b3HANt57diZYFO/HL1JGIC1MjKrdmhxvrJbupnVvpys0zsz7yBApXdQyfepKly2kA==",
- "dev": true,
- "dependencies": {
- "map-cache": "^0.2.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/fresh": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz",
- "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac= sha512-zJ2mQYM18rEFOudeV4GShTGIQ7RbzA7ozbU9I/XBpm7kqgMywgmylMwXHxZJmkVoYkna9d2pVXVXPdYTP9ej8Q==",
- "dev": true,
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/from2": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/from2/-/from2-2.3.0.tgz",
- "integrity": "sha1-i/tVAr3kpNNs/e6gB/zKIdfjgq8= sha512-OMcX/4IC/uqEPVgGeyfN22LJk6AZrMkRZHxcHBMBvHScDGgwTm2GT2Wkgtocyd3JfZffjj2kYUDXXII0Fk9W0g==",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
"dependencies": {
- "inherits": "^2.0.1",
- "readable-stream": "^2.0.0"
+ "safe-buffer": "~5.1.0"
}
},
"node_modules/fs-extra": {
- "version": "10.0.0",
- "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-10.0.0.tgz",
- "integrity": "sha512-C5owb14u9eJwizKGdchcDUQeFtlSHHthBk8pbX9Vc1PFZrLombudjDnNns88aYslCyF6IY5SUw3Roz6xShcEIQ==",
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-9.1.0.tgz",
+ "integrity": "sha512-hcg3ZmepS30/7BSFqRvoo3DOMQu7IjqxO5nCDt+zM9XWjb33Wg7ziNT+Qvqbuc3+gWpzO02JubVyk2G4Zvo1OQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
+ "at-least-node": "^1.0.0",
"graceful-fs": "^4.2.0",
"jsonfile": "^6.0.1",
"universalify": "^2.0.0"
},
"engines": {
- "node": ">=12"
+ "node": ">=10"
}
},
- "node_modules/fs-write-stream-atomic": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/fs-write-stream-atomic/-/fs-write-stream-atomic-1.0.10.tgz",
- "integrity": "sha1-tH31NJPvkR33VzHnCp3tAYnbQMk= sha512-gehEzmPn2nAwr39eay+x3X34Ra+M2QlVUTLhkXPjWdeO8RF9kszk116avgBJM3ZyNHgHXBNx+VmPaFC36k0PzA==",
- "deprecated": "This package is no longer supported.",
+ "node_modules/fs-monkey": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/fs-monkey/-/fs-monkey-1.1.0.tgz",
+ "integrity": "sha512-QMUezzXWII9EV5aTFXW1UBVUO77wYPpjqIF8/AviUCThNeSYZykpoTixUeaNNBwmCev0AMDWMAni+f8Hxb1IFw==",
"dev": true,
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "iferr": "^0.1.5",
- "imurmurhash": "^0.1.4",
- "readable-stream": "1 || 2"
- }
+ "license": "Unlicense"
},
"node_modules/fs.realpath": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz",
- "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8= sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
- "dev": true
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true,
+ "license": "ISC"
},
"node_modules/fsevents": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
- "integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
- "dev": true,
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz",
+ "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==",
"hasInstallScript": true,
+ "license": "MIT",
"optional": true,
"os": [
"darwin"
@@ -8295,17 +7624,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/functional-red-black-tree": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz",
- "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc= sha512-dsKNQNdj6xA3T+QlADDA7mOSlX0qiMINjn0cgr+eGHGsbSHzTabcIogz2+p/iqP1Xs6EP/sS2SbqH+brGTbq0g==",
- "dev": true
- },
"node_modules/gensync": {
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6.9.0"
}
@@ -8313,13 +7637,15 @@
"node_modules/geojson-vt": {
"version": "3.2.1",
"resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-3.2.1.tgz",
- "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg=="
+ "integrity": "sha512-EvGQQi/zPrDA6zr6BnJD/YhwAkBP8nnJ9emh3EnHQKVMfg/MRVtPbMYdgVy/IaEmn4UfagD2a6fafPDL5hbtwg==",
+ "license": "ISC"
},
"node_modules/get-caller-file": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-2.0.5.tgz",
"integrity": "sha512-DyFP3BM/3YHTQOCUL/w0OZHR0lpKeGrxotcHWcqNEdnltqFwXVfhEBQ94eIo34AfQpo0rGki4cyIiftY06h2Fg==",
"dev": true,
+ "license": "ISC",
"engines": {
"node": "6.* || 8.* || >= 10.*"
}
@@ -8327,7 +7653,8 @@
"node_modules/get-canvas-context": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/get-canvas-context/-/get-canvas-context-1.0.2.tgz",
- "integrity": "sha512-LnpfLf/TNzr9zVOGiIY6aKCz8EKuXmlYNV7CM2pUjBa/B+c2I15tS7KLySep75+FuerJdmArvJLcsAXWEy2H0A=="
+ "integrity": "sha512-LnpfLf/TNzr9zVOGiIY6aKCz8EKuXmlYNV7CM2pUjBa/B+c2I15tS7KLySep75+FuerJdmArvJLcsAXWEy2H0A==",
+ "license": "MIT"
},
"node_modules/get-intrinsic": {
"version": "1.3.0",
@@ -8371,6 +7698,7 @@
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz",
"integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"pump": "^3.0.0"
},
@@ -8378,54 +7706,23 @@
"node": ">=6"
}
},
- "node_modules/get-symbol-description": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/get-symbol-description/-/get-symbol-description-1.0.0.tgz",
- "integrity": "sha512-2EmdH1YvIQiZpltCNgkuiUnyukzxM/R6NDJX31Ke3BG1Nq5b0S2PhX59UKi9vZpPDQVdqn+1IcaAwnzTT5vCjw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "get-intrinsic": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/get-value": {
- "version": "2.0.6",
- "resolved": "https://registry.npmjs.org/get-value/-/get-value-2.0.6.tgz",
- "integrity": "sha1-3BXKHGcjh8p2vTesCjlbogQqLCg= sha512-Ln0UQDlxH1BapMu3GPtf7CuYNwRZf2gwCuPqbyG6pB8WfmFpzqcy4xtAaAMUhnNqjMKTiCPZG2oMT3YSx8U2NA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/getpass": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz",
- "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo= sha512-0fzj9JxOLfJ+XGLhR8ze3unN0KZCgZwiSSDz168VERjK8Wl8kVSdcu2kspd4s4wtAa1y/qrVRiAA0WclVsu0ng==",
- "dev": true,
- "dependencies": {
- "assert-plus": "^1.0.0"
- }
- },
"node_modules/gl-mat4": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gl-mat4/-/gl-mat4-1.2.0.tgz",
- "integrity": "sha512-sT5C0pwB1/e9G9AvAoLsoaJtbMGjfd/jfxo8jMCKqYYEnjZuFvqV5rehqar0538EmssjdDeiEWnKyBSTw7quoA=="
+ "integrity": "sha512-sT5C0pwB1/e9G9AvAoLsoaJtbMGjfd/jfxo8jMCKqYYEnjZuFvqV5rehqar0538EmssjdDeiEWnKyBSTw7quoA==",
+ "license": "Zlib"
},
"node_modules/gl-matrix": {
- "version": "3.4.3",
- "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.3.tgz",
- "integrity": "sha512-wcCp8vu8FT22BnvKVPjXa/ICBWRq/zjFfdofZy1WSpQZpphblv12/bOQLBC1rMM7SGOFS9ltVmKOHil5+Ml7gA=="
+ "version": "3.4.4",
+ "resolved": "https://registry.npmjs.org/gl-matrix/-/gl-matrix-3.4.4.tgz",
+ "integrity": "sha512-latSnyDNt/8zYUB6VIJ6PCh2jBjJX6gnDsoCZ7LyW7GkqrD51EWwa9qCoGixj8YqBtETQK/xY7OmpTF8xz1DdQ==",
+ "license": "MIT"
},
"node_modules/gl-text": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/gl-text/-/gl-text-1.3.1.tgz",
- "integrity": "sha512-/f5gcEMiZd+UTBJLTl3D+CkCB/0UFGTx3nflH8ZmyWcLkZhsZ1+Xx5YYkw2rgWAzgPeE35xCqBuHSoMKQVsR+w==",
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/gl-text/-/gl-text-1.4.0.tgz",
+ "integrity": "sha512-o47+XBqLCj1efmuNyCHt7/UEJmB9l66ql7pnobD6p+sgmBUdzfMZXIF0zD2+KRfpd99DJN+QXdvTFAGCKCVSmQ==",
+ "license": "MIT",
"dependencies": {
"bit-twiddle": "^1.0.2",
"color-normalize": "^1.5.0",
@@ -8446,18 +7743,11 @@
"typedarray-pool": "^1.1.0"
}
},
- "node_modules/gl-text/node_modules/is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
- "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4= sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/gl-util": {
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/gl-util/-/gl-util-3.1.3.tgz",
"integrity": "sha512-dvRTggw5MSkJnCbh74jZzSoTOGnVYK+Bt+Ckqm39CVcl6+zSsxqWk4lr5NKhkqXHL6qvZAU9h17ZF8mIskY9mA==",
+ "license": "MIT",
"dependencies": {
"is-browser": "^2.0.1",
"is-firefox": "^1.0.3",
@@ -8468,25 +7758,18 @@
"weak-map": "^1.0.5"
}
},
- "node_modules/gl-util/node_modules/is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
- "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4= sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/glob": {
- "version": "7.2.0",
- "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.0.tgz",
- "integrity": "sha512-lmLf6gtyrPq8tTjSmrO94wBeQbFR3HbLHbuyD69wuyQkImp2hWqMGB47OX65FBkPffO641IP9jWa1z4ivqG26Q==",
- "deprecated": "Glob versions prior to v9 are no longer supported",
+ "version": "7.2.3",
+ "resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
+ "integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "deprecated": "Old versions of glob are not supported, and contain widely publicized security vulnerabilities, which have been fixed in the current version. Please update. Support for old versions may be purchased (at exorbitant rates) by contacting i@izs.me",
"dev": true,
+ "license": "ISC",
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
"inherits": "2",
- "minimatch": "^3.0.4",
+ "minimatch": "^3.1.1",
"once": "^1.3.0",
"path-is-absolute": "^1.0.0"
},
@@ -8501,7 +7784,7 @@
"version": "6.0.2",
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-6.0.2.tgz",
"integrity": "sha512-XxwI8EOhVQgWp6iDL+3b0r86f4d6AX6zSU55HfB4ydCEuXLXc5FcYeOu+nnGftS4TEju/11rt4KJPTMgbfmv4A==",
- "dev": true,
+ "license": "ISC",
"dependencies": {
"is-glob": "^4.0.3"
},
@@ -8510,221 +7793,88 @@
}
},
"node_modules/glob-to-regexp": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.3.0.tgz",
- "integrity": "sha1-jFoUlNIGbFcMw7/kSWF1rMTVAqs= sha512-Iozmtbqv0noj0uDDqoL0zNq0VBEfK2YFoMAZoxJe4cwphvLR+JskfF30QhXHOR4m3KrE6NLRYw+U9MRXvifyig==",
- "dev": true
- },
- "node_modules/globals": {
- "version": "11.12.0",
- "resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
- "integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/globby": {
- "version": "9.2.0",
- "resolved": "https://registry.npmjs.org/globby/-/globby-9.2.0.tgz",
- "integrity": "sha512-ollPHROa5mcxDEkwg6bPt3QbEf4pDQSNtd6JPL1YvOvAo/7/0VAm9TccUeoTmarjPw4pfUthSCqcyfNB1I3ZSg==",
- "dev": true,
- "dependencies": {
- "@types/glob": "^7.1.1",
- "array-union": "^1.0.2",
- "dir-glob": "^2.2.2",
- "fast-glob": "^2.2.6",
- "glob": "^7.1.3",
- "ignore": "^4.0.3",
- "pify": "^4.0.1",
- "slash": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/globby/node_modules/@nodelib/fs.stat": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/@nodelib/fs.stat/-/fs.stat-1.1.3.tgz",
- "integrity": "sha512-shAmDyaQC4H92APFoIaVDHCx5bStIocgvbwQyxPRrbUY20V1EYTbSDchWbuwlMG3V17cprZhA6+78JfB+3DTPw==",
- "dev": true,
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/globby/node_modules/braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
- "dev": true,
- "dependencies": {
- "arr-flatten": "^1.1.0",
- "array-unique": "^0.3.2",
- "extend-shallow": "^2.0.1",
- "fill-range": "^4.0.0",
- "isobject": "^3.0.1",
- "repeat-element": "^1.1.2",
- "snapdragon": "^0.8.1",
- "snapdragon-node": "^2.0.1",
- "split-string": "^3.0.2",
- "to-regex": "^3.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
+ "version": "0.4.1",
+ "resolved": "https://registry.npmjs.org/glob-to-regexp/-/glob-to-regexp-0.4.1.tgz",
+ "integrity": "sha512-lkX1HJXwyMcprw/5YUZc2s7DrpAiHB21/V+E1rHUrVNokkvB6bqMzT0VfV6/86ZNabt1k14YOIaT7nDvOX3Iiw==",
+ "license": "BSD-2-Clause"
},
- "node_modules/globby/node_modules/braces/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
- "dev": true,
+ "node_modules/global-prefix": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/global-prefix/-/global-prefix-4.0.0.tgz",
+ "integrity": "sha512-w0Uf9Y9/nyHinEk5vMJKRie+wa4kR5hmDbEhGGds/kG1PwGLLHKRoNMeJOyCQjjBkANlnScqgzcFwGHgmgLkVA==",
+ "license": "MIT",
"dependencies": {
- "is-extendable": "^0.1.0"
+ "ini": "^4.1.3",
+ "kind-of": "^6.0.3",
+ "which": "^4.0.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=16"
}
},
- "node_modules/globby/node_modules/fast-glob": {
- "version": "2.2.7",
- "resolved": "https://registry.npmjs.org/fast-glob/-/fast-glob-2.2.7.tgz",
- "integrity": "sha512-g1KuQwHOZAmOZMuBtHdxDtju+T2RT8jgCC9aANsbpdiDDTSnjgfuVsIBNKbUeJI3oKMRExcfNDtJl4OhbffMsw==",
- "dev": true,
- "dependencies": {
- "@mrmlnc/readdir-enhanced": "^2.2.1",
- "@nodelib/fs.stat": "^1.1.2",
- "glob-parent": "^3.1.0",
- "is-glob": "^4.0.0",
- "merge2": "^1.2.3",
- "micromatch": "^3.1.10"
- },
+ "node_modules/global-prefix/node_modules/isexe": {
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/isexe/-/isexe-3.1.5.tgz",
+ "integrity": "sha512-6B3tLtFqtQS4ekarvLVMZ+X+VlvQekbe4taUkf/rhVO3d/h0M2rfARm/pXLcPEsjjMsFgrFgSrhQIxcSVrBz8w==",
+ "license": "BlueOak-1.0.0",
"engines": {
- "node": ">=4.0.0"
+ "node": ">=18"
}
},
- "node_modules/globby/node_modules/fill-range": {
+ "node_modules/global-prefix/node_modules/which": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
- "dev": true,
- "dependencies": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/globby/node_modules/fill-range/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/which/-/which-4.0.0.tgz",
+ "integrity": "sha512-GlaYyEb07DPxYCKhKzplCWBJtvxZcZMrL+4UkrTSJHHPyZU4mYYTv3qaOe77H7EODLSSopAUFAc6W8U4yqvscg==",
+ "license": "ISC",
"dependencies": {
- "is-extendable": "^0.1.0"
+ "isexe": "^3.1.1"
},
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/globby/node_modules/glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
- "dev": true,
- "dependencies": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- }
- },
- "node_modules/globby/node_modules/glob-parent/node_modules/is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
- "dev": true,
- "dependencies": {
- "is-extglob": "^2.1.0"
+ "bin": {
+ "node-which": "bin/which.js"
},
"engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/globby/node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node": "^16.13.0 || >=18.0.0"
}
},
- "node_modules/globby/node_modules/is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
+ "node_modules/globals": {
+ "version": "16.5.0",
+ "resolved": "https://registry.npmjs.org/globals/-/globals-16.5.0.tgz",
+ "integrity": "sha512-c/c15i26VrJ4IRt5Z89DnIzCGDn9EcebibhAOjw5ibqEHsE1wLUgkPn9RDmNcUKyU87GeaL633nyJ+pplFR2ZQ==",
"dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/globby/node_modules/is-number/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
+ "node": ">=18"
},
- "engines": {
- "node": ">=0.10.0"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/globby/node_modules/micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "node_modules/globby": {
+ "version": "11.1.0",
+ "resolved": "https://registry.npmjs.org/globby/-/globby-11.1.0.tgz",
+ "integrity": "sha512-jhIXaOzy1sb8IyocaruWSn1TjmnBVs8Ayhcy83rmxNJ8q2uWKCAj3CnJY+KpGSXCueAPc0i05kVvVKtP1t9S3g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "braces": "^2.3.1",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "extglob": "^2.0.4",
- "fragment-cache": "^0.2.1",
- "kind-of": "^6.0.2",
- "nanomatch": "^1.2.9",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.2"
+ "array-union": "^2.1.0",
+ "dir-glob": "^3.0.1",
+ "fast-glob": "^3.2.9",
+ "ignore": "^5.2.0",
+ "merge2": "^1.4.1",
+ "slash": "^3.0.0"
},
"engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/globby/node_modules/to-regex-range": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
- "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==",
- "dev": true,
- "dependencies": {
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1"
+ "node": ">=10"
},
- "engines": {
- "node": ">=0.10.0"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/glsl-inject-defines": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/glsl-inject-defines/-/glsl-inject-defines-1.0.3.tgz",
"integrity": "sha512-W49jIhuDtF6w+7wCMcClk27a2hq8znvHtlGnrYkSWEr8tHe9eA2dcnohlcAmxLYBSpSSdzOkRdyPTrx9fw49+A==",
+ "license": "MIT",
"dependencies": {
"glsl-token-inject-block": "^1.0.0",
"glsl-token-string": "^1.0.1",
@@ -8735,6 +7885,7 @@
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/glsl-resolve/-/glsl-resolve-0.0.1.tgz",
"integrity": "sha512-xxFNsfnhZTK9NBhzJjSBGX6IOqYpvBHxxmo+4vapiljyGNCY0Bekzn0firQkQrazK59c1hYxMDxYS8MDlhw4gA==",
+ "license": "MIT",
"dependencies": {
"resolve": "^0.6.1",
"xtend": "^2.1.2"
@@ -8743,7 +7894,8 @@
"node_modules/glsl-resolve/node_modules/resolve": {
"version": "0.6.3",
"resolved": "https://registry.npmjs.org/resolve/-/resolve-0.6.3.tgz",
- "integrity": "sha512-UHBY3viPlJKf85YijDUcikKX6tmF4SokIDp518ZDVT92JNDcG5uKIthaT/owt3Sar0lwtOafsQuwrg22/v2Dwg=="
+ "integrity": "sha512-UHBY3viPlJKf85YijDUcikKX6tmF4SokIDp518ZDVT92JNDcG5uKIthaT/owt3Sar0lwtOafsQuwrg22/v2Dwg==",
+ "license": "MIT"
},
"node_modules/glsl-resolve/node_modules/xtend": {
"version": "2.2.0",
@@ -8756,12 +7908,14 @@
"node_modules/glsl-token-assignments": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/glsl-token-assignments/-/glsl-token-assignments-2.0.2.tgz",
- "integrity": "sha512-OwXrxixCyHzzA0U2g4btSNAyB2Dx8XrztY5aVUCjRSh4/D0WoJn8Qdps7Xub3sz6zE73W3szLrmWtQ7QMpeHEQ=="
+ "integrity": "sha512-OwXrxixCyHzzA0U2g4btSNAyB2Dx8XrztY5aVUCjRSh4/D0WoJn8Qdps7Xub3sz6zE73W3szLrmWtQ7QMpeHEQ==",
+ "license": "MIT"
},
"node_modules/glsl-token-defines": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/glsl-token-defines/-/glsl-token-defines-1.0.0.tgz",
"integrity": "sha512-Vb5QMVeLjmOwvvOJuPNg3vnRlffscq2/qvIuTpMzuO/7s5kT+63iL6Dfo2FYLWbzuiycWpbC0/KV0biqFwHxaQ==",
+ "license": "MIT",
"dependencies": {
"glsl-tokenizer": "^2.0.0"
}
@@ -8769,12 +7923,14 @@
"node_modules/glsl-token-depth": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/glsl-token-depth/-/glsl-token-depth-1.1.2.tgz",
- "integrity": "sha512-eQnIBLc7vFf8axF9aoi/xW37LSWd2hCQr/3sZui8aBJnksq9C7zMeUYHVJWMhFzXrBU7fgIqni4EhXVW4/krpg=="
+ "integrity": "sha512-eQnIBLc7vFf8axF9aoi/xW37LSWd2hCQr/3sZui8aBJnksq9C7zMeUYHVJWMhFzXrBU7fgIqni4EhXVW4/krpg==",
+ "license": "MIT"
},
"node_modules/glsl-token-descope": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/glsl-token-descope/-/glsl-token-descope-1.0.2.tgz",
"integrity": "sha512-kS2PTWkvi/YOeicVjXGgX5j7+8N7e56srNDEHDTVZ1dcESmbmpmgrnpjPcjxJjMxh56mSXYoFdZqb90gXkGjQw==",
+ "license": "MIT",
"dependencies": {
"glsl-token-assignments": "^2.0.0",
"glsl-token-depth": "^1.1.0",
@@ -8785,32 +7941,38 @@
"node_modules/glsl-token-inject-block": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/glsl-token-inject-block/-/glsl-token-inject-block-1.1.0.tgz",
- "integrity": "sha512-q/m+ukdUBuHCOtLhSr0uFb/qYQr4/oKrPSdIK2C4TD+qLaJvqM9wfXIF/OOBjuSA3pUoYHurVRNao6LTVVUPWA=="
+ "integrity": "sha512-q/m+ukdUBuHCOtLhSr0uFb/qYQr4/oKrPSdIK2C4TD+qLaJvqM9wfXIF/OOBjuSA3pUoYHurVRNao6LTVVUPWA==",
+ "license": "MIT"
},
"node_modules/glsl-token-properties": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/glsl-token-properties/-/glsl-token-properties-1.0.1.tgz",
- "integrity": "sha512-dSeW1cOIzbuUoYH0y+nxzwK9S9O3wsjttkq5ij9ZGw0OS41BirKJzzH48VLm8qLg+au6b0sINxGC0IrGwtQUcA=="
+ "integrity": "sha512-dSeW1cOIzbuUoYH0y+nxzwK9S9O3wsjttkq5ij9ZGw0OS41BirKJzzH48VLm8qLg+au6b0sINxGC0IrGwtQUcA==",
+ "license": "MIT"
},
"node_modules/glsl-token-scope": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/glsl-token-scope/-/glsl-token-scope-1.1.2.tgz",
- "integrity": "sha512-YKyOMk1B/tz9BwYUdfDoHvMIYTGtVv2vbDSLh94PT4+f87z21FVdou1KNKgF+nECBTo0fJ20dpm0B1vZB1Q03A=="
+ "integrity": "sha512-YKyOMk1B/tz9BwYUdfDoHvMIYTGtVv2vbDSLh94PT4+f87z21FVdou1KNKgF+nECBTo0fJ20dpm0B1vZB1Q03A==",
+ "license": "MIT"
},
"node_modules/glsl-token-string": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/glsl-token-string/-/glsl-token-string-1.0.1.tgz",
- "integrity": "sha512-1mtQ47Uxd47wrovl+T6RshKGkRRCYWhnELmkEcUAPALWGTFe2XZpH3r45XAwL2B6v+l0KNsCnoaZCSnhzKEksg=="
+ "integrity": "sha512-1mtQ47Uxd47wrovl+T6RshKGkRRCYWhnELmkEcUAPALWGTFe2XZpH3r45XAwL2B6v+l0KNsCnoaZCSnhzKEksg==",
+ "license": "MIT"
},
"node_modules/glsl-token-whitespace-trim": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/glsl-token-whitespace-trim/-/glsl-token-whitespace-trim-1.0.0.tgz",
- "integrity": "sha512-ZJtsPut/aDaUdLUNtmBYhaCmhIjpKNg7IgZSfX5wFReMc2vnj8zok+gB/3Quqs0TsBSX/fGnqUUYZDqyuc2xLQ=="
+ "integrity": "sha512-ZJtsPut/aDaUdLUNtmBYhaCmhIjpKNg7IgZSfX5wFReMc2vnj8zok+gB/3Quqs0TsBSX/fGnqUUYZDqyuc2xLQ==",
+ "license": "MIT"
},
"node_modules/glsl-tokenizer": {
"version": "2.1.5",
"resolved": "https://registry.npmjs.org/glsl-tokenizer/-/glsl-tokenizer-2.1.5.tgz",
"integrity": "sha512-XSZEJ/i4dmz3Pmbnpsy3cKh7cotvFlBiZnDOwnj/05EwNp2XrhQ4XKJxT7/pDt4kp4YcpRSKz8eTV7S+mwV6MA==",
+ "license": "MIT",
"dependencies": {
"through2": "^0.6.3"
}
@@ -8818,12 +7980,14 @@
"node_modules/glsl-tokenizer/node_modules/isarray": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz",
- "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ=="
+ "integrity": "sha512-D2S+3GLxWH+uhrNEcoh/fnmYeP8E8/zHl644d/jdA0g2uyXvy3sb0qxotE+ne0LtccHknQzWwZEzhak7oJ0COQ==",
+ "license": "MIT"
},
"node_modules/glsl-tokenizer/node_modules/readable-stream": {
"version": "1.0.34",
"resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-1.0.34.tgz",
"integrity": "sha512-ok1qVCJuRkNmvebYikljxJA/UEsKwLl2nI1OmaqAu4/UE+h0wKCHok4XkL/gvi39OacXvw59RJUOFUkDib2rHg==",
+ "license": "MIT",
"dependencies": {
"core-util-is": "~1.0.0",
"inherits": "~2.0.1",
@@ -8834,12 +7998,14 @@
"node_modules/glsl-tokenizer/node_modules/string_decoder": {
"version": "0.10.31",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz",
- "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ=="
+ "integrity": "sha512-ev2QzSzWPYmy9GuqfIVildA4OdcGLeFZQrq5ys6RtiuF+RQQiZWr8TZNyAcuVXyQRYfEO+MsoB/1BuQVhOJuoQ==",
+ "license": "MIT"
},
"node_modules/glsl-tokenizer/node_modules/through2": {
"version": "0.6.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-0.6.5.tgz",
"integrity": "sha512-RkK/CCESdTKQZHdmKICijdKKsCRVHs5KsLZ6pACAmF/1GPUQhonHSXWNERctxEp7RmvjdNbZTL5z9V7nSCXKcg==",
+ "license": "MIT",
"dependencies": {
"readable-stream": ">=1.0.33-1 <1.1.0-0",
"xtend": ">=4.0.0 <4.1.0-0"
@@ -8849,6 +8015,7 @@
"version": "7.1.1",
"resolved": "https://registry.npmjs.org/glslify/-/glslify-7.1.1.tgz",
"integrity": "sha512-bud98CJ6kGZcP9Yxcsi7Iz647wuDz3oN+IZsjCRi5X1PI7t/xPKeL0mOwXJjo+CRZMqvq0CkSJiywCcY7kVYog==",
+ "license": "MIT",
"dependencies": {
"bl": "^2.2.1",
"concat-stream": "^1.5.2",
@@ -8874,6 +8041,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/glslify-bundle/-/glslify-bundle-5.1.1.tgz",
"integrity": "sha512-plaAOQPv62M1r3OsWf2UbjN0hUYAB7Aph5bfH58VxJZJhloRNbxOL9tl/7H71K7OLJoSJ2ZqWOKk3ttQ6wy24A==",
+ "license": "MIT",
"dependencies": {
"glsl-inject-defines": "^1.0.1",
"glsl-token-defines": "^1.0.0",
@@ -8891,6 +8059,7 @@
"version": "1.3.2",
"resolved": "https://registry.npmjs.org/glslify-deps/-/glslify-deps-1.3.2.tgz",
"integrity": "sha512-7S7IkHWygJRjcawveXQjRXLO2FTjijPDYC7QfZyAQanY+yGLCFHYnPtsGT9bdyHiwPTw/5a1m1M9hamT2aBpag==",
+ "license": "ISC",
"dependencies": {
"@choojs/findup": "^0.2.0",
"events": "^3.2.0",
@@ -8902,6 +8071,52 @@
"resolve": "^1.0.0"
}
},
+ "node_modules/glslify/node_modules/bl": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/bl/-/bl-2.2.1.tgz",
+ "integrity": "sha512-6Pesp1w0DEX1N550i/uGV/TqucVL4AM/pgThFSN/Qq9si1/DF9aIHs1BxD8V/QU0HoeHO6cQRTAuYnLPKq1e4g==",
+ "license": "MIT",
+ "dependencies": {
+ "readable-stream": "^2.3.5",
+ "safe-buffer": "^5.1.1"
+ }
+ },
+ "node_modules/glslify/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "license": "MIT"
+ },
+ "node_modules/glslify/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/glslify/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/glslify/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
"node_modules/gopd": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz",
@@ -8915,32 +8130,38 @@
}
},
"node_modules/graceful-fs": {
- "version": "4.2.8",
- "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.8.tgz",
- "integrity": "sha512-qkIilPUYcNhJpd33n0GBXTB1MMPp14TxEsEs0pTrsSVucApsYzW5V+Q8Qxhik6KU3evy+qkAAowTByymK0avdg=="
+ "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==",
+ "license": "ISC"
},
"node_modules/grid-index": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/grid-index/-/grid-index-1.1.0.tgz",
- "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA=="
+ "integrity": "sha512-HZRwumpOGUrHyxO5bqKZL0B0GlUpwtCAzZ42sgxUPniu33R1LSFH5yrIcBCHjkctCAh3mtWKcKd9J4vDDdeVHA==",
+ "license": "ISC"
},
"node_modules/gzip-size": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-5.1.1.tgz",
- "integrity": "sha512-FNHi6mmoHvs1mxZAds4PpdCS6QG8B4C1krxJsMutgxl5t3+GlRTzzI3NEkifXx2pVsOvJdOGSmIgDhQ55FwdPA==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/gzip-size/-/gzip-size-6.0.0.tgz",
+ "integrity": "sha512-ax7ZYomf6jqPTQ4+XCpUGyXKHk5WweS+e05MBO4/y3WJ5RkmPXNKvX+bx1behVILVwr6JSQvZAku021CHPXG3Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "duplexer": "^0.1.1",
- "pify": "^4.0.1"
+ "duplexer": "^0.1.2"
},
"engines": {
- "node": ">=6"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/hammerjs": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
- "integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE= sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==",
+ "integrity": "sha512-tSQXBXS/MWQOn/RKckawJ61vvsDpCom87JgxiYdGwHdOa0ht0vzUWDlfioofFCRU0L+6NGDt6XzbgoJvZkMeRQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.8.0"
}
@@ -8949,56 +8170,14 @@
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/handle-thing/-/handle-thing-2.0.1.tgz",
"integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==",
- "dev": true
- },
- "node_modules/har-schema": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz",
- "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI= sha512-Oqluz6zhGX8cyRaTQlFMPw80bSJVG2x/cFb8ZPhUILGgHka9SsokCCOQgpveePerqidZOrT14ipqfJb7ILcW5Q==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/har-validator": {
- "version": "5.1.5",
- "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.5.tgz",
- "integrity": "sha512-nmT2T0lljbxdQZfspsno9hgrG3Uir6Ks5afism62poxqBM6sDnMEuPmzTq8XN0OEwqKLLdh1jQI3qyE66Nzb3w==",
- "deprecated": "this library is no longer supported",
- "dev": true,
- "dependencies": {
- "ajv": "^6.12.3",
- "har-schema": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/has": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/has/-/has-1.0.3.tgz",
- "integrity": "sha512-f2dvO0VU6Oej7RkWJGrehjbzMAjFp5/VKPp5tTpWIV4JHHZK1/BxbFRtf/siA2SWTe09caDmVtYYzWEIbBS4zw==",
- "dependencies": {
- "function-bind": "^1.1.1"
- },
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/has-bigints": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/has-bigints/-/has-bigints-1.0.1.tgz",
- "integrity": "sha512-LSBS2LjbNBTf6287JEbEzvJgftkF5qFkmCo9hDRpAzKhUOlJ+hx8dd4USs00SgsUNwc4617J9ki5YtEClM2ffA==",
"dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
+ "license": "MIT"
},
"node_modules/has-flag": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
- "dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -9007,6 +8186,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/has-hover/-/has-hover-1.0.1.tgz",
"integrity": "sha512-0G6w7LnlcpyDzpeGUTuT0CEw05+QlMuGVk1IHNAlHrGJITGodjZu3x8BNDUMfKJSZXNB2ZAclqc1bvrd+uUpfg==",
+ "license": "MIT",
"dependencies": {
"is-browser": "^2.0.1"
}
@@ -9015,10 +8195,24 @@
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/has-passive-events/-/has-passive-events-1.0.0.tgz",
"integrity": "sha512-2vSj6IeIsgvsRMyeQ0JaCX5Q3lX4zMn5HpoVc7MEhQ6pv8Iq9rsXjsp+E5ZwaT7T0xhMT0KmU8gtt1EFVdbJiw==",
+ "license": "MIT",
"dependencies": {
"is-browser": "^2.0.1"
}
},
+ "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,
+ "license": "MIT",
+ "dependencies": {
+ "es-define-property": "^1.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/has-symbols": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz",
@@ -9046,164 +8240,57 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/has-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-1.0.0.tgz",
- "integrity": "sha1-GLKB2lhbHFxR3vJMkw7SmgvmsXc= sha512-IBXk4GTsLYdQ7Rvt+GRBrFSVEkmuOUy4re0Xjd9kJSUQpnTrWR4/y9RpfexN9vkAPMFuQoeWKwqzPozRTlasGw==",
+ "node_modules/hash-sum": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
+ "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hasown": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.3.tgz",
+ "integrity": "sha512-ej4AhfhfL2Q2zpMmLo7U1Uv9+PyhIZpgQLGT1F9miIGmiCJIoCgSmczFdrc97mWT4kVY72KA+WnnhJ5pghSvSg==",
+ "license": "MIT",
"dependencies": {
- "get-value": "^2.0.6",
- "has-values": "^1.0.0",
- "isobject": "^3.0.0"
+ "function-bind": "^1.1.2"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 0.4"
}
},
- "node_modules/has-values": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-1.0.0.tgz",
- "integrity": "sha1-lbC2P+whRmGab+V/51Yo1aOe/k8= sha512-ODYZC64uqzmtfGMEAX/FvZiRyWLpAC3vYnNunURUnkGVTS+mI0smVsWaPydRBsE3g+ok7h960jChO8mFcWlHaQ==",
- "dev": true,
- "dependencies": {
- "is-number": "^3.0.0",
- "kind-of": "^4.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
+ "node_modules/he": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
+ "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
+ "license": "MIT",
+ "bin": {
+ "he": "bin/he"
}
},
- "node_modules/has-values/node_modules/is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/has-values/node_modules/is-number/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/has-values/node_modules/kind-of": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-4.0.0.tgz",
- "integrity": "sha1-IIE989cSkosgc3hpGkUGb65y3Vc= sha512-24XsCxmEbRwEDbz/qz3stgin8TTzZ1ESR56OMCN0ujYg+vRutNSiOj9bHH9u85DKgXguraugV5sFuvbD4FW/hw==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/hash-base": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/hash-base/-/hash-base-3.0.4.tgz",
- "integrity": "sha512-EeeoJKjTyt868liAlVmcv2ZsUfGHlE3Q+BICOXcZiwN3osr5Q/zFGYmTJpoIzuaSTAwndFy+GqhEwlU4L3j4Ow==",
- "dev": true,
- "dependencies": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/hash-sum": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-2.0.0.tgz",
- "integrity": "sha512-WdZTbAByD+pHfl/g9QSsBIIwy8IT+EsPiKDs0KNX+zSHhdDLFKdZu0BQHljvO+0QI/BasbMSUa8wYNCZTvhslg==",
- "dev": true
- },
- "node_modules/hash.js": {
- "version": "1.1.7",
- "resolved": "https://registry.npmjs.org/hash.js/-/hash.js-1.1.7.tgz",
- "integrity": "sha512-taOaskGt4z4SOANNseOviYDvjEJinIkRgmp7LbKP2YTTmVxWBl87s/uzK9r+44BclBSp2X7K1hqeNfz9JbBeXA==",
- "dev": true,
- "dependencies": {
- "inherits": "^2.0.3",
- "minimalistic-assert": "^1.0.1"
- }
- },
- "node_modules/hasown": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz",
- "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==",
- "license": "MIT",
- "dependencies": {
- "function-bind": "^1.1.2"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/he": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/he/-/he-1.2.0.tgz",
- "integrity": "sha512-F/1DnUGPopORZi0ni+CvrCgHQ5FyEAHRLSApuYWMmrbSwoN2Mn/7k+Gl38gJnR7yyDZk6WLXwiGod1JOWNDKGw==",
- "bin": {
- "he": "bin/he"
- }
- },
- "node_modules/hex-color-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/hex-color-regex/-/hex-color-regex-1.1.0.tgz",
- "integrity": "sha512-l9sfDFsuqtOqKDsQdqrMRk0U85RZc0RtOR9yPI7mRVOa4FsR/BVnZ0shmQRM96Ji99kYZP/7hn1cedc1+ApsTQ==",
- "dev": true
- },
"node_modules/highlight.js": {
"version": "10.7.3",
"resolved": "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz",
"integrity": "sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A==",
"dev": true,
+ "license": "BSD-3-Clause",
"engines": {
"node": "*"
}
},
- "node_modules/hmac-drbg": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/hmac-drbg/-/hmac-drbg-1.0.1.tgz",
- "integrity": "sha1-0nRXAQJabHdabFRXk+1QL8DGSaE= sha512-Tti3gMqLdZfhOQY1Mzf/AanLiqh1WTiJgEj26ZuYQ9fbkLomzGchCws4FyrSd4VkpBfiNhaE1On+lOz894jvXg==",
- "dev": true,
- "dependencies": {
- "hash.js": "^1.0.3",
- "minimalistic-assert": "^1.0.0",
- "minimalistic-crypto-utils": "^1.0.1"
- }
- },
- "node_modules/hoopy": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/hoopy/-/hoopy-0.1.4.tgz",
- "integrity": "sha512-HRcs+2mr52W0K+x8RzcLzuPPmVIKMSv97RGHy0Ea9y/mpcaK+xTrjICA04KAHi4GRzxliNqNJEFYWHghy3rSfQ==",
- "dev": true,
- "engines": {
- "node": ">= 6.0.0"
- }
- },
"node_modules/hosted-git-info": {
"version": "2.8.9",
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
- "dev": true
+ "dev": true,
+ "license": "ISC"
},
"node_modules/hpack.js": {
"version": "2.1.6",
"resolved": "https://registry.npmjs.org/hpack.js/-/hpack.js-2.1.6.tgz",
- "integrity": "sha1-h3dMCUnlE/QuhFdbPEVoH63ioLI= sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
+ "integrity": "sha512-zJxVehUdMGIKsRaNt7apO2Gqp0BdqW5yaiGHXXmbpvxgBYVZnAql+BJb4RO5ad2MgpbZKn5G6nMnegrH1FcNYQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"inherits": "^2.0.1",
"obuf": "^1.0.0",
@@ -9211,118 +8298,139 @@
"wbuf": "^1.1.0"
}
},
- "node_modules/hsl-regex": {
+ "node_modules/hpack.js/node_modules/isarray": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/hsl-regex/-/hsl-regex-1.0.0.tgz",
- "integrity": "sha1-1JMwx4ntgZ4nakwNJy3/owsY/m4= sha512-M5ezZw4LzXbBKMruP+BNANf0k+19hDQMgpzBIYnya//Al+fjNct9Wf3b1WedLqdEs2hKBvxq/jh+DsHJLj0F9A==",
- "dev": true
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/hsla-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/hsla-regex/-/hsla-regex-1.0.0.tgz",
- "integrity": "sha1-wc56MWjIxmFAM6S194d/OyJfnDg= sha512-7Wn5GMLuHBjZCb2bTmnDOycho0p/7UVaAeqXZGbHrBCl6Yd/xDhQJAXe6Ga9AXJH2I5zY1dEdYw2u1UptnSBJA==",
- "dev": true
+ "node_modules/hpack.js/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
+ }
+ },
+ "node_modules/hpack.js/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/hpack.js/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
},
"node_modules/hsluv": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/hsluv/-/hsluv-0.0.3.tgz",
- "integrity": "sha512-08iL2VyCRbkQKBySkSh6m8zMUa3sADAxGVWs3Z1aPcUkTJeK0ETG4Fc27tEmQBGUAXZjIsXOZqBvacuVNSC/fQ=="
+ "integrity": "sha512-08iL2VyCRbkQKBySkSh6m8zMUa3sADAxGVWs3Z1aPcUkTJeK0ETG4Fc27tEmQBGUAXZjIsXOZqBvacuVNSC/fQ==",
+ "license": "MIT"
},
"node_modules/html-entities": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-1.4.0.tgz",
- "integrity": "sha512-8nxjcBcd8wovbeKx7h3wTji4e6+rhaVuPNpMqwWgnHh+N9ToqsCs6XztWRBPQ+UtzsoMAdKZtUENoVzU/EMtZA==",
- "dev": true
+ "version": "2.6.0",
+ "resolved": "https://registry.npmjs.org/html-entities/-/html-entities-2.6.0.tgz",
+ "integrity": "sha512-kig+rMn/QOVRvr7c86gQ8lWXq+Hkv6CbAH1hLu+RG338StTpE8Z0b44SDVaqVu7HGKf27frdmUYEs9hTUX/cLQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/mdevils"
+ },
+ {
+ "type": "patreon",
+ "url": "https://patreon.com/mdevils"
+ }
+ ],
+ "license": "MIT"
+ },
+ "node_modules/html-escaper": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/html-escaper/-/html-escaper-2.0.2.tgz",
+ "integrity": "sha512-H2iMtd0I4Mt5eYiapRdIDjp+XzelXQ0tFE4JS7YFwFevXXMmOp9myNrUvCg0D6ws8iqkRPBfKHgbwig1SmlLfg==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/html-minifier": {
- "version": "3.5.21",
- "resolved": "https://registry.npmjs.org/html-minifier/-/html-minifier-3.5.21.tgz",
- "integrity": "sha512-LKUKwuJDhxNa3uf/LPR/KVjm/l3rBqtYeCOAekvG8F1vItxMUpueGd94i/asDDr8/1u7InxzFA5EeGjhhG5mMA==",
+ "node_modules/html-minifier-terser": {
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/html-minifier-terser/-/html-minifier-terser-6.1.0.tgz",
+ "integrity": "sha512-YXxSlJBZTP7RS3tWnQw74ooKa6L9b9i9QYXY21eUEvhZ3u9XLfv6OnFsQq6RxkhHygsaUMvYsZRV5rU/OVNZxw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "camel-case": "3.0.x",
- "clean-css": "4.2.x",
- "commander": "2.17.x",
- "he": "1.2.x",
- "param-case": "2.1.x",
- "relateurl": "0.2.x",
- "uglify-js": "3.4.x"
+ "camel-case": "^4.1.2",
+ "clean-css": "^5.2.2",
+ "commander": "^8.3.0",
+ "he": "^1.2.0",
+ "param-case": "^3.0.4",
+ "relateurl": "^0.2.7",
+ "terser": "^5.10.0"
},
"bin": {
- "html-minifier": "cli.js"
+ "html-minifier-terser": "cli.js"
},
"engines": {
- "node": ">=4"
+ "node": ">=12"
}
},
"node_modules/html-tags": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-3.1.0.tgz",
- "integrity": "sha512-1qYz89hW3lFDEazhjW0yVAV87lw8lVkrJocr72XmBkMKsoSVJCQx3W8BXsC7hO2qAt8BoVjYjtAcZ9perqGnNg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/html-tags/-/html-tags-2.0.0.tgz",
+ "integrity": "sha512-+Il6N8cCo2wB/Vd3gqy/8TZhTD3QvcVeQLCnZiGkGCH3JP28IgGAY41giccp2W4R3jfyJPAP318FQTa1yU7K7g==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=8"
+ "node": ">=4"
}
},
"node_modules/html-webpack-plugin": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-3.2.0.tgz",
- "integrity": "sha1-sBq71yOsqqeze2r0SS69oD2d03s= sha512-Br4ifmjQojUP4EmHnRBoUIYcZ9J7M4bTMcm7u6xoIAIuq2Nte4TzXX0533owvkQKQD1WeMTTTyD4Ni4QKxS0Bg==",
- "deprecated": "3.x is no longer supported",
+ "version": "5.6.7",
+ "resolved": "https://registry.npmjs.org/html-webpack-plugin/-/html-webpack-plugin-5.6.7.tgz",
+ "integrity": "sha512-md+vXtdCAe60s1k6AU3dUyMJnDxUyQAwfwPKoLisvgUF1IXjtlLsk2se54+qfL9Mdm26bbwvjJybpNx48NKRLw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "html-minifier": "^3.2.3",
- "loader-utils": "^0.2.16",
- "lodash": "^4.17.3",
- "pretty-error": "^2.0.2",
- "tapable": "^1.0.0",
- "toposort": "^1.0.0",
- "util.promisify": "1.0.0"
+ "@types/html-minifier-terser": "^6.0.0",
+ "html-minifier-terser": "^6.0.2",
+ "lodash": "^4.17.21",
+ "pretty-error": "^4.0.0",
+ "tapable": "^2.0.0"
},
"engines": {
- "node": ">=6.9"
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/html-webpack-plugin"
},
"peerDependencies": {
- "webpack": "^1.0.0 || ^2.0.0 || ^3.0.0 || ^4.0.0"
- }
- },
- "node_modules/html-webpack-plugin/node_modules/big.js": {
- "version": "3.2.0",
- "resolved": "https://registry.npmjs.org/big.js/-/big.js-3.2.0.tgz",
- "integrity": "sha512-+hN/Zh2D08Mx65pZ/4g5bsmNiZUuChDiQfTUQ7qJr4/kuopCr88xZsAXv6mBoZEsUI4OuGHlX59qE94K2mMW8Q==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/html-webpack-plugin/node_modules/emojis-list": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/emojis-list/-/emojis-list-2.1.0.tgz",
- "integrity": "sha1-TapNnbAPmBmIDHn6RXrlsJof04k= sha512-knHEZMgs8BB+MInokmNTg/OyPlAddghe1YBgNwJBc5zsJi/uyIcXoSDsL/W9ymOsBoBGdPIHXYJ9+qKFwRwDng==",
- "dev": true,
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/html-webpack-plugin/node_modules/json5": {
- "version": "0.5.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-0.5.1.tgz",
- "integrity": "sha1-Hq3nrMASA0rYTiOWdn6tn6VJWCE= sha512-4xrs1aW+6N5DalkqSVA8fxh458CXvR99WU8WLKmq4v8eWAL86Xo3BVqyd3SkA9wEVjCMqyvvRRkshAdOnBp5rw==",
- "dev": true,
- "bin": {
- "json5": "lib/cli.js"
- }
- },
- "node_modules/html-webpack-plugin/node_modules/loader-utils": {
- "version": "0.2.17",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-0.2.17.tgz",
- "integrity": "sha1-+G5jdNQyBabmxg6RlvF8Apm/s0g= sha512-tiv66G0SmiOx+pLWMtGEkfSEejxvb6N6uRrQjfWJIT79W9GMpgKeCAmm9aVBKtd4WEgntciI8CsGqjpDoCWJug==",
- "dev": true,
- "dependencies": {
- "big.js": "^3.1.3",
- "emojis-list": "^2.0.0",
- "json5": "^0.5.0",
- "object-assign": "^4.0.1"
+ "@rspack/core": "0.x || 1.x",
+ "webpack": "^5.20.0"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/core": {
+ "optional": true
+ },
+ "webpack": {
+ "optional": true
+ }
}
},
"node_modules/htmlparser2": {
@@ -9337,6 +8445,7 @@
"url": "https://github.com/sponsors/fb55"
}
],
+ "license": "MIT",
"dependencies": {
"domelementtype": "^2.0.1",
"domhandler": "^4.0.0",
@@ -9344,45 +8453,57 @@
"entities": "^2.0.0"
}
},
+ "node_modules/htmlparser2/node_modules/entities": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/entities/-/entities-2.2.0.tgz",
+ "integrity": "sha512-p92if5Nz619I0w+akJrLZH0MX0Pb5DX39XOwQTtXSdQQOaYH03S1uIQp4mhOZtAXrxq4ViO67YTiLBo2638o9A==",
+ "dev": true,
+ "license": "BSD-2-Clause",
+ "funding": {
+ "url": "https://github.com/fb55/entities?sponsor=1"
+ }
+ },
"node_modules/http-deceiver": {
"version": "1.2.7",
"resolved": "https://registry.npmjs.org/http-deceiver/-/http-deceiver-1.2.7.tgz",
- "integrity": "sha1-+nFolEq5pRnTN8sL7HKE3D5yPYc= sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
- "dev": true
+ "integrity": "sha512-LmpOGxTfbpgtGVxJrj5k7asXHCgNZp5nLfp+hWc8QQRqtb7fUy6kRY3BO1h9ddF6yIPYUARgxGOwB42DnxIaNw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/http-errors": {
- "version": "1.7.2",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.7.2.tgz",
- "integrity": "sha512-uUQBt3H/cSIVfch6i1EuPNy/YsRSOUBXTVfZ+yR7Zjez3qjBz6i9+i4zjNaoqcoFVI4lQJ5plg63TvGfRSDCRg==",
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz",
+ "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "depd": "~1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.1",
- "statuses": ">= 1.5.0 < 2",
- "toidentifier": "1.0.0"
+ "depd": "~2.0.0",
+ "inherits": "~2.0.4",
+ "setprototypeof": "~1.2.0",
+ "statuses": "~2.0.2",
+ "toidentifier": "~1.0.1"
},
"engines": {
- "node": ">= 0.6"
+ "node": ">= 0.8"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
- "node_modules/http-errors/node_modules/inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
- "dev": true
- },
"node_modules/http-parser-js": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.5.tgz",
- "integrity": "sha512-x+JVEkO2PoM8qqpbPbOL3cqHPwerep7OwzK7Ay+sMQjKzaKCqWvjoXm5tqMP9tXWWTnTzAjIhXg+J99XYuPhPA==",
- "dev": true
+ "version": "0.5.10",
+ "resolved": "https://registry.npmjs.org/http-parser-js/-/http-parser-js-0.5.10.tgz",
+ "integrity": "sha512-Pysuw9XpUq5dVc/2SMHpuTY01RFl8fttgcyunjL7eEMhGM3cI4eOmiCycJDVCo/7O7ClfQD3SaI6ftDzqOXYMA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/http-proxy": {
"version": "1.18.1",
"resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz",
"integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"eventemitter3": "^4.0.0",
"follow-redirects": "^1.0.0",
@@ -9393,55 +8514,58 @@
}
},
"node_modules/http-proxy-middleware": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-1.3.1.tgz",
- "integrity": "sha512-13eVVDYS4z79w7f1+NPllJtOQFx/FdUW4btIvVRMaRlUY9VGstAbo5MOhLEuUgZFRHn3x50ufn25zkj/boZnEg==",
+ "version": "2.0.9",
+ "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-2.0.9.tgz",
+ "integrity": "sha512-c1IyJYLYppU574+YI7R4QyX2ystMtVXZwIdzazUIPIJsHuWNd+mho2j+bKoHftndicGj9yh+xjd+l0yj7VeT1Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "@types/http-proxy": "^1.17.5",
+ "@types/http-proxy": "^1.17.8",
"http-proxy": "^1.18.1",
"is-glob": "^4.0.1",
"is-plain-obj": "^3.0.0",
"micromatch": "^4.0.2"
},
"engines": {
- "node": ">=8.0.0"
+ "node": ">=12.0.0"
+ },
+ "peerDependencies": {
+ "@types/express": "^4.17.13"
+ },
+ "peerDependenciesMeta": {
+ "@types/express": {
+ "optional": true
+ }
}
},
- "node_modules/http-signature": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz",
- "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE= sha512-CAbnr6Rz4CYQkLYUtSNXxQPUH2gK8f3iWexVlsnMeD+GjlsQ0Xsy1cOX+mN3dtxYomRy21CiOzU8Uhw6OwncEQ==",
+ "node_modules/http-proxy-middleware/node_modules/is-plain-obj": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
+ "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
"dev": true,
- "dependencies": {
- "assert-plus": "^1.0.0",
- "jsprim": "^1.2.2",
- "sshpk": "^1.7.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=0.8",
- "npm": ">=1.3.7"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/https-browserify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/https-browserify/-/https-browserify-1.0.0.tgz",
- "integrity": "sha1-7AbBDgo0wPL68Zn3/X/Hj//QPHM= sha512-J+FkSdyD+0mA0N+81tMotaRMfSL9SGi+xpD3T6YApKsc3bGSXJlfXri3VyFOeYkfLRQisDk1W+jIFFKBeUBbBg==",
- "dev": true
- },
"node_modules/human-signals": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-1.1.1.tgz",
- "integrity": "sha512-SEQu7vl8KjNL2eoGBLF3+wAjpsNfA9XMlXAYj/3EdaNfAlxKthD1xjEQfGOUhllCGGJVNY34bRr6lPINhNjyZw==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/human-signals/-/human-signals-2.1.0.tgz",
+ "integrity": "sha512-B4FFZ6q/T2jhhksgkbEW3HBvWIfDW85snkQgawt07S7J5QXTk6BkNV+0yAeZrM5QpMAdYlocGoljn0sJ/WQkFw==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
- "node": ">=8.12.0"
+ "node": ">=10.17.0"
}
},
"node_modules/iconv-lite": {
"version": "0.4.24",
"resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
"integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
+ "license": "MIT",
"dependencies": {
"safer-buffer": ">= 2.1.2 < 3"
},
@@ -9450,15 +8574,15 @@
}
},
"node_modules/icss-utils": {
- "version": "4.1.1",
- "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-4.1.1.tgz",
- "integrity": "sha512-4aFq7wvWyMHKgxsH8QQtGpvbASCf+eM3wPRLI6R+MgAnTCZ6STYsRvttLvRWK0Nfif5piF394St3HeJDaljGPA==",
- "dev": true,
- "dependencies": {
- "postcss": "^7.0.14"
- },
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
+ "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
+ "license": "ISC",
"engines": {
- "node": ">= 6"
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
}
},
"node_modules/ieee754": {
@@ -9478,40 +8602,25 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
- },
- "node_modules/iferr": {
- "version": "0.1.5",
- "resolved": "https://registry.npmjs.org/iferr/-/iferr-0.1.5.tgz",
- "integrity": "sha1-xg7taebY/bazEEofy8ocGS3FtQE= sha512-DUNFN5j7Tln0D+TxzloUjKB+CtVu6myn0JEFak6dG18mNt9YkQ6lzGCdafwofISZ1lLF3xRHJ98VKy9ynkcFaA==",
- "dev": true
+ ],
+ "license": "BSD-3-Clause"
},
"node_modules/ignore": {
- "version": "4.0.6",
- "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz",
- "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==",
+ "version": "5.3.2",
+ "resolved": "https://registry.npmjs.org/ignore/-/ignore-5.3.2.tgz",
+ "integrity": "sha512-hsBTNUqQTDwkWtcdYI2i06Y/nUBEsNEDJKjWdigLvegy8kDuJAS8uRlpkkcQpyEXL0Z/pjDy5HBmMjRCJ2gq+g==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 4"
}
},
- "node_modules/import-cwd": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-3.0.0.tgz",
- "integrity": "sha512-4pnzH16plW+hgvRECbDWpQl3cqtvSofHWh44met7ESfZ8UZOWWddm8hEyDTqREJ9RbYHY8gi8DqmaelApoOGMg==",
- "dev": true,
- "dependencies": {
- "import-from": "^3.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
"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==",
+ "version": "3.3.1",
+ "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-3.3.1.tgz",
+ "integrity": "sha512-TR3KfrTZTYLPB6jUjfx6MF9WcWrHL9su5TObK4ZkYgBdWKPOFoSoQIdEuTuR82pmtxH2spWG9h6etwfr1pLBqQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"parent-module": "^1.0.0",
"resolve-from": "^4.0.0"
@@ -9523,128 +8632,23 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/import-from": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/import-from/-/import-from-3.0.0.tgz",
- "integrity": "sha512-CiuXOFFSzkU5x/CR0+z7T91Iht4CXgfCxVOFRhh2Zyhg5wOpWvvDLQUsWl+gcN+QscYBjez8hDCt85O7RLDttQ==",
- "dev": true,
- "dependencies": {
- "resolve-from": "^5.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/import-from/node_modules/resolve-from": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "dev": true,
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/import-local": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/import-local/-/import-local-2.0.0.tgz",
- "integrity": "sha512-b6s04m3O+s3CGSbqDIyP4R6aAwAeYlVq9+WUWep6iHa8ETRf9yei1U48C5MmfJmV9AiLYYBKPMq/W+/WRpQmCQ==",
- "dev": true,
- "dependencies": {
- "pkg-dir": "^3.0.0",
- "resolve-cwd": "^2.0.0"
- },
- "bin": {
- "import-local-fixture": "fixtures/cli.js"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/import-local/node_modules/find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "dependencies": {
- "locate-path": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/import-local/node_modules/locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "dependencies": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/import-local/node_modules/p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
- "dependencies": {
- "p-limit": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/import-local/node_modules/path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/import-local/node_modules/pkg-dir": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
- "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
- "dev": true,
- "dependencies": {
- "find-up": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/imurmurhash": {
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
- "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o= sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.8.19"
}
},
- "node_modules/indexes-of": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/indexes-of/-/indexes-of-1.0.1.tgz",
- "integrity": "sha1-8w9xbI4r00bHtn0985FVZqfAVgc= sha512-bup+4tap3Hympa+JBJUG7XuOsdNQ6fxt0MHyXMKuLBKn0OqsTfvUxkUrroEX1+B2VsSHvCjiIcZVxRtYa4nllA==",
- "dev": true
- },
- "node_modules/infer-owner": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/infer-owner/-/infer-owner-1.0.4.tgz",
- "integrity": "sha512-IClj+Xz94+d7irH5qRyfJonOdfTzuDaifE6ZPWfx0N0+/ATZCbuTPq2prFl526urkQd90WyUKIh1DfBQ2hMz9A==",
- "dev": true
- },
"node_modules/inflight": {
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
- "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk= sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
"deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.",
"dev": true,
+ "license": "ISC",
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@@ -9653,157 +8657,40 @@
"node_modules/inherits": {
"version": "2.0.4",
"resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz",
- "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ=="
- },
- "node_modules/inquirer": {
- "version": "7.3.3",
- "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-7.3.3.tgz",
- "integrity": "sha512-JG3eIAj5V9CwcGvuOmoo6LB9kbAYT8HXffUl6memuszlwDC/qvFAJw49XJ5NROSFNPxp3iQg1GqkFhaY/CR0IA==",
- "dev": true,
- "dependencies": {
- "ansi-escapes": "^4.2.1",
- "chalk": "^4.1.0",
- "cli-cursor": "^3.1.0",
- "cli-width": "^3.0.0",
- "external-editor": "^3.0.3",
- "figures": "^3.0.0",
- "lodash": "^4.17.19",
- "mute-stream": "0.0.8",
- "run-async": "^2.4.0",
- "rxjs": "^6.6.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0",
- "through": "^2.3.6"
- },
- "engines": {
- "node": ">=8.0.0"
- }
- },
- "node_modules/internal-ip": {
- "version": "4.3.0",
- "resolved": "https://registry.npmjs.org/internal-ip/-/internal-ip-4.3.0.tgz",
- "integrity": "sha512-S1zBo1D6zcsyuC6PMmY5+55YMILQ9av8lotMx447Bq6SAgo/sDK6y6uUKmuYhW7eacnIhFfsPmCNYdDzsnnDCg==",
- "dev": true,
- "dependencies": {
- "default-gateway": "^4.2.0",
- "ipaddr.js": "^1.9.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/internal-ip/node_modules/default-gateway": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/default-gateway/-/default-gateway-4.2.0.tgz",
- "integrity": "sha512-h6sMrVB1VMWVrW13mSc6ia/DwYYw5MN6+exNu1OaJeFac5aSAvwM7lZ0NVfTABuSkQelr4h5oebg3KB1XPdjgA==",
- "dev": true,
- "dependencies": {
- "execa": "^1.0.0",
- "ip-regex": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/internal-slot": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/internal-slot/-/internal-slot-1.0.3.tgz",
- "integrity": "sha512-O0DB1JC/sPyZl7cIo78n5dR7eUSwwpYPiXRhTzNxZVAMUuB8vlnRFyLxdrVToks6XPLVnFfbzaVd5WLjhgg+vA==",
- "dev": true,
- "dependencies": {
- "get-intrinsic": "^1.1.0",
- "has": "^1.0.3",
- "side-channel": "^1.0.4"
- },
- "engines": {
- "node": ">= 0.4"
- }
- },
- "node_modules/ip": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
- "integrity": "sha1-vd7XARQpCCjAoDnnLvJfWq7ENUo= sha512-rBtCAQAJm8A110nbwn6YdveUnuZH3WrC36IwkRXxDnq53JvXA2NVQvB7IHyKomxK1MJ4VDNw3UtFDdXQ+AvLYA==",
- "dev": true
+ "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==",
+ "license": "ISC"
},
- "node_modules/ip-regex": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/ip-regex/-/ip-regex-2.1.0.tgz",
- "integrity": "sha1-+ni/XS5pE8kRzp+BnuUUa7bYROk= sha512-58yWmlHpp7VYfcdTwMTvwMmqx/Elfxjd9RXTDyMsbL7lLWmhMylLEqiYVLKuLzOZqVgiWXD9MfR62Vv89VRxkw==",
- "dev": true,
+ "node_modules/ini": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/ini/-/ini-4.1.3.tgz",
+ "integrity": "sha512-X7rqawQBvfdjS10YU1y1YVreA3SsLrW9dX2CewP2EbBJM4ypVNLDkO5y04gejPwKIY9lR+7r9gn3rFPt/kmWFg==",
+ "license": "ISC",
"engines": {
- "node": ">=4"
+ "node": "^14.17.0 || ^16.13.0 || >=18.0.0"
}
},
"node_modules/ipaddr.js": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
- "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
- "dev": true,
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/is-absolute-url": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-2.1.0.tgz",
- "integrity": "sha1-UFMN+4T8yap9vnhS6Do3uTufKqY= sha512-vOx7VprsKyllwjSkLV79NIhpyLfr3jAp7VaTCMXOJHu4m0Ew1CZ2fcjASwmV1jI3BWuWHB013M48eyeldk9gYg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-accessor-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-1.0.0.tgz",
- "integrity": "sha512-m5hnHTkcVsPfqx3AKlyttIPb7J+XykHvJP2B9bZDjlhLIoEq4XoK64Vg7boZlVWYK6LUY94dYPEE7Lh0ZkZKcQ==",
- "deprecated": "Please upgrade to v1.0.1",
- "dev": true,
- "dependencies": {
- "kind-of": "^6.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-arguments": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz",
- "integrity": "sha512-8Q7EARjzEnKpt/PCD7e1cgUS0a6X8u5tdSiMqXhojOdoV9TsMsiO+9VLC5vAmO8N7/GmXn7yjR8qnA6bVAEzfA==",
+ "version": "2.4.0",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-2.4.0.tgz",
+ "integrity": "sha512-9VGk3HGanVE6JoZXHiCpnGy5X0jYDnN4EA4lntFPj+1vIWlFhIylq2CrrCOJH9EAhc5CYhq18F2Av2tgoAPsYQ==",
"dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "has-tostringtag": "^1.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">= 10"
}
},
"node_modules/is-arrayish": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz",
- "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0= sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
- "dev": true
- },
- "node_modules/is-bigint": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/is-bigint/-/is-bigint-1.0.4.tgz",
- "integrity": "sha512-zB9CruMamjym81i2JZ3UMn54PKGsQzsJeo6xvN3HJJ4CAsQNB6iRutp2To77OfCNuoxspsIhzaPoO1zyCEhFOg==",
+ "integrity": "sha512-zz06S8t0ozoDXMG+ube26zeCTNXcKIPJZJi8hBrF4idCLms4CG9QtK7qBl1boi5ODzFpjswb5JPmHCbMpjaYzg==",
"dev": true,
- "dependencies": {
- "has-bigints": "^1.0.1"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
+ "license": "MIT"
},
"node_modules/is-binary-path": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-2.1.0.tgz",
"integrity": "sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==",
- "dev": true,
+ "license": "MIT",
"dependencies": {
"binary-extensions": "^2.0.0"
},
@@ -9811,50 +8698,18 @@
"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-browser": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/is-browser/-/is-browser-2.1.0.tgz",
- "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ=="
- },
- "node_modules/is-buffer": {
- "version": "1.1.6",
- "resolved": "https://registry.npmjs.org/is-buffer/-/is-buffer-1.1.6.tgz",
- "integrity": "sha512-NcdALwpXkTm5Zvvbk7owOUSvVvBKDgKP5/ewfXEznmQFfs4ZRmanOeKBTjRVjka3QFoN6XJ+9F3USqfHqTaU5w==",
- "dev": true
- },
- "node_modules/is-callable": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/is-callable/-/is-callable-1.2.4.tgz",
- "integrity": "sha512-nsuwtxZfMX67Oryl9LCQ+upnC0Z0BgpwntpS89m1H/TLF0zNfzfLMV/9Wa/6MZsj0acpEjAO0KF1xT6ZdLl95w==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
+ "integrity": "sha512-F5rTJxDQ2sW81fcfOR1GnCXT6sVJC104fCyfj+mjpwNEwaPYSn5fte5jiHmBg3DHsIoL/l8Kvw5VN5SsTRcRFQ==",
+ "license": "MIT"
},
"node_modules/is-ci": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/is-ci/-/is-ci-1.2.1.tgz",
"integrity": "sha512-s6tfsaQaQi3JNciBH6shVqEDvhGut0SUXr31ag8Pd8BBbVVlcGfWhpPmEOoM6RJ5TFhbypvf5yyRw/VXW1IiWg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ci-info": "^1.5.0"
},
@@ -9862,51 +8717,13 @@
"is-ci": "bin.js"
}
},
- "node_modules/is-color-stop": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-color-stop/-/is-color-stop-1.1.0.tgz",
- "integrity": "sha1-z/9HGu5N1cnhWFmPvhKWe1za00U= sha512-H1U8Vz0cfXNujrJzEcvvwMDW9Ra+biSYA3ThdQvAnMLJkEHQXn6bWzLkxHtVYJ+Sdbx0b6finn3jZiaVe7MAHA==",
- "dev": true,
- "dependencies": {
- "css-color-names": "^0.0.4",
- "hex-color-regex": "^1.1.0",
- "hsl-regex": "^1.0.0",
- "hsla-regex": "^1.0.0",
- "rgb-regex": "^1.0.1",
- "rgba-regex": "^1.0.0"
- }
- },
"node_modules/is-core-module": {
- "version": "2.8.0",
- "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.8.0.tgz",
- "integrity": "sha512-vd15qHsaqrRL7dtH6QNuy0ndJmRDrS9HAM1CAiSifNUFv4x1a0CCVsj18hJ1mShxIG6T2i1sO78MkP56r0nYRw==",
- "dependencies": {
- "has": "^1.0.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-data-descriptor": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-1.0.0.tgz",
- "integrity": "sha512-jbRXy1FmtAoCjQkVmIVYwuuqDFUbaOeDjmed1tOGPrsMhtJA4rD9tkgA0F1qJ3gRFRXcHYVkdeaP50Q5rE/jLQ==",
- "deprecated": "Please upgrade to v1.0.1",
- "dev": true,
- "dependencies": {
- "kind-of": "^6.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "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,
+ "version": "2.16.2",
+ "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.2.tgz",
+ "integrity": "sha512-evOr8xfXKxE6qSR0hSXL2r3sd7ALj8+7jQEUvPYcm5sgZFdJ+AYzT6yNmJenvIYQBgIGwfwz08sL8zoL7yq2BA==",
+ "license": "MIT",
"dependencies": {
- "has-tostringtag": "^1.0.0"
+ "hasown": "^2.0.3"
},
"engines": {
"node": ">= 0.4"
@@ -9915,34 +8732,12 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/is-descriptor": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-1.0.2.tgz",
- "integrity": "sha512-2eis5WqQGV7peooDyLmNEPUrps9+SXX5c9pL3xEB+4e9HnGuDa7mB7kHxHw4CbqS9k1T2hOH3miL8n8WtiYVtg==",
- "dev": true,
- "dependencies": {
- "is-accessor-descriptor": "^1.0.0",
- "is-data-descriptor": "^1.0.0",
- "kind-of": "^6.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/is-directory": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/is-directory/-/is-directory-0.3.1.tgz",
- "integrity": "sha1-YTObbyR1/Hcv2cnYP1yFddwVSuE= sha512-yVChGzahRFvbkscn2MlwGismPO12i9+znNruC5gVEntG3qu0xQMzsGg/JFbrsqDOHtHFPci+V5aP5T9I+yeKqw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/is-docker": {
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz",
"integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==",
"dev": true,
+ "license": "MIT",
"bin": {
"is-docker": "cli.js"
},
@@ -9953,31 +8748,30 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/is-extendable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-1.0.1.tgz",
- "integrity": "sha512-arnXMxT1hhoKo9k1LZdmlNyJdDDfy2v0fXjFlmok4+i8ul/6WlbVge9bhM74OpNPQPMGUToDtz+KXa1PneJxOA==",
- "dev": true,
- "dependencies": {
- "is-plain-object": "^2.0.4"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/is-extglob": {
"version": "2.1.1",
"resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz",
- "integrity": "sha1-qIwCU1eR8C7TfHahueqXc8gz+MI= sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
- "dev": true,
+ "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
+ "node_modules/is-file-esm": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/is-file-esm/-/is-file-esm-1.0.0.tgz",
+ "integrity": "sha512-rZlaNKb4Mr8WlRu2A9XdeoKgnO5aA53XdPHgCKVyCrQ/rWi89RET1+bq37Ru46obaQXeiX4vmFIm1vks41hoSA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "read-pkg-up": "^7.0.1"
+ }
+ },
"node_modules/is-finite": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-finite/-/is-finite-1.1.0.tgz",
"integrity": "sha512-cdyMtqX/BOqqNBBiKlIVkytNHm49MtMlYyn1zxzvJKWmFMlGzm+ry5BBfYyeY9YmNKbRSo/o7OX9w9ale0wg3w==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
},
@@ -9989,6 +8783,7 @@
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/is-firefox/-/is-firefox-1.0.3.tgz",
"integrity": "sha512-6Q9ITjvWIm0Xdqv+5U12wgOKEM2KoBw4Y926m0OFkvlCxnbG94HKAsVz8w3fWcfAS5YA2fJORXX1dLrkprCCxA==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -9998,6 +8793,7 @@
"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,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -10006,7 +8802,7 @@
"version": "4.0.3",
"resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz",
"integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==",
- "dev": true,
+ "license": "MIT",
"dependencies": {
"is-extglob": "^2.1.1"
},
@@ -10014,106 +8810,47 @@
"node": ">=0.10.0"
}
},
- "node_modules/is-iexplorer": {
+ "node_modules/is-interactive": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-iexplorer/-/is-iexplorer-1.0.0.tgz",
- "integrity": "sha512-YeLzceuwg3K6O0MLM3UyUUjKAlyULetwryFp1mHy1I5PfArK0AEqlfa+MR4gkJjcbuJXoDJCvXbyqZVf5CR2Sg==",
+ "resolved": "https://registry.npmjs.org/is-interactive/-/is-interactive-1.0.0.tgz",
+ "integrity": "sha512-2HvIEKRoqS62guEC+qBjpvRubdX910WCMuJTZ+I9yvqKU2/12eSL549HMwtabb4oupdj2sMP50k+XJfB/8JE6w==",
+ "dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
}
},
"node_modules/is-mobile": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/is-mobile/-/is-mobile-4.0.0.tgz",
- "integrity": "sha512-mlcHZA84t1qLSuWkt2v0I2l61PYdyQDt4aG1mLIXF5FDMm4+haBCxCPYSr/uwqQNRk1MiTizn0ypEuRAOLRAew=="
- },
- "node_modules/is-negative-zero": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/is-negative-zero/-/is-negative-zero-2.0.1.tgz",
- "integrity": "sha512-2z6JzQvZRa9A2Y7xC6dQQm4FSTSTNWjKIYYTt4246eMTJmIo0Q+ZyOsU66X8lxK1AbB92dFeglPLrhwpeRKO6w==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
+ "integrity": "sha512-mlcHZA84t1qLSuWkt2v0I2l61PYdyQDt4aG1mLIXF5FDMm4+haBCxCPYSr/uwqQNRk1MiTizn0ypEuRAOLRAew==",
+ "license": "MIT"
},
"node_modules/is-number": {
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
- "dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.12.0"
}
},
- "node_modules/is-number-object": {
- "version": "1.0.6",
- "resolved": "https://registry.npmjs.org/is-number-object/-/is-number-object-1.0.6.tgz",
- "integrity": "sha512-bEVOqiRcvo3zO1+G2lVMy+gkkEm9Yh7cDMRusKKu5ZJKPUYSJwICTKZrNKHA2EbSP0Tu0+6B/emsYNHZyn6K8g==",
- "dev": true,
- "dependencies": {
- "has-tostringtag": "^1.0.0"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-obj": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-obj/-/is-obj-1.0.1.tgz",
"integrity": "sha512-l4RyHgRqGN4Y3+9JHVrNqO+tN0rV5My76uW5/nuO4K1b6vw5G8d/cmFjP9tRfEsdhZNt0IFdZuK/c2Vr4Nb+Qg==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/is-path-cwd": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-2.2.0.tgz",
- "integrity": "sha512-w942bTcih8fdJPJmQHFzkS76NEP8Kzzvmw92cXsazb8intwLqPibPPdXf4ANdKV3rYMuuQYGIWtvz9JilB3NFQ==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/is-path-in-cwd": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-2.1.0.tgz",
- "integrity": "sha512-rNocXHgipO+rvnP6dk3zI20RpOtrAM/kzbB258Uw5BWr3TpXi861yzjo16Dn4hUox07iw5AyeMLHWsujkjzvRQ==",
- "dev": true,
- "dependencies": {
- "is-path-inside": "^2.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/is-path-inside": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-2.1.0.tgz",
- "integrity": "sha512-wiyhTzfDWsvwAW53OBWF5zuvaOGlZ6PwYxAbPVDhpm+gM09xKQGjBq/8uYN12aDvMxnAnq3dxTyoSoRNmg5YFg==",
- "dev": true,
- "dependencies": {
- "path-is-inside": "^1.0.2"
- },
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/is-plain-obj": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-3.0.0.tgz",
- "integrity": "sha512-gwsOE28k+23GP1B6vFl1oVh/WOzmawBrKwo5Ev6wMKzPkaXaCDIQKzLnvsA42DRlbVTWorkgTKIviAKCWkfUwA==",
- "dev": true,
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
+ "integrity": "sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
+ "license": "MIT",
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=0.10.0"
}
},
"node_modules/is-plain-object": {
@@ -10121,6 +8858,7 @@
"resolved": "https://registry.npmjs.org/is-plain-object/-/is-plain-object-2.0.4.tgz",
"integrity": "sha512-h5PpgXkWitc38BBMYawTYMWJHFZJVnBquFE57xFpjB8pJFiF6gZ+bU+WyI/yqXiFR5mdLsgYNaPe8uao6Uv9Og==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"isobject": "^3.0.1"
},
@@ -10128,111 +8866,39 @@
"node": ">=0.10.0"
}
},
- "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-resolvable": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz",
- "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==",
- "dev": true
- },
- "node_modules/is-shared-array-buffer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-shared-array-buffer/-/is-shared-array-buffer-1.0.1.tgz",
- "integrity": "sha512-IU0NmyknYZN0rChcKhRO1X8LYz5Isj/Fsqh8NJOSf+N/hCOTwy29F32Ik7a+QszE63IdvmwdTPDd6cZ5pg4cwA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/is-stream": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz",
- "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ= sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
+ "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "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-string-blank": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/is-string-blank/-/is-string-blank-1.0.1.tgz",
- "integrity": "sha512-9H+ZBCVs3L9OYqv8nuUAzpcT9OTgMD1yAWrG7ihlnibdkbtB850heAmYWxHuXc4CHy4lKeK69tN+ny1K7gBIrw=="
+ "integrity": "sha512-9H+ZBCVs3L9OYqv8nuUAzpcT9OTgMD1yAWrG7ihlnibdkbtB850heAmYWxHuXc4CHy4lKeK69tN+ny1K7gBIrw==",
+ "license": "MIT"
},
"node_modules/is-svg-path": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/is-svg-path/-/is-svg-path-1.0.2.tgz",
- "integrity": "sha512-Lj4vePmqpPR1ZnRctHv8ltSh1OrSxHkhUkd7wi+VQdcdP15/KvQFyk7LhNuM7ZW0EVbJz8kZLVmL9quLrfq4Kg=="
+ "integrity": "sha512-Lj4vePmqpPR1ZnRctHv8ltSh1OrSxHkhUkd7wi+VQdcdP15/KvQFyk7LhNuM7ZW0EVbJz8kZLVmL9quLrfq4Kg==",
+ "license": "MIT"
},
- "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==",
+ "node_modules/is-unicode-supported": {
+ "version": "0.1.0",
+ "resolved": "https://registry.npmjs.org/is-unicode-supported/-/is-unicode-supported-0.1.0.tgz",
+ "integrity": "sha512-knxG2q4UC3u8stRGyAVJCOdxFmv5DZiRcdlIaAQXAbSfJya+OhopNotLQrstBhququ4ZpuKbDc/8S6mgXgPFPw==",
"dev": true,
- "dependencies": {
- "has-symbols": "^1.0.2"
- },
+ "license": "MIT",
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-typedarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz",
- "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo= sha512-cyA56iCMHAh5CdzjJIa4aohJyeO1YbwLi3Jc35MmRU6poroFjIGZzUzupGiRPOjgHg9TLu43xbpwXk523fMxKA==",
- "dev": true
- },
- "node_modules/is-weakref": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-weakref/-/is-weakref-1.0.1.tgz",
- "integrity": "sha512-b2jKc2pQZjaeFYWEf7ScFj+Be1I+PXmlu572Q8coTXZ+LD/QQZ7ShPMst8h16riVgyXTQwUsFEl74mDvc/3MHQ==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.0"
+ "node": ">=10"
},
"funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/is-windows": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/is-windows/-/is-windows-1.0.2.tgz",
- "integrity": "sha512-eXK1UInq2bPmjyX6e3VHIzMLobc4J94i4AWn+Hpq3OU5KkrRC96OAcR3PRJ/pGu6m8TRnBHP9dkXQVsT/COVIA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/is-wsl": {
@@ -10240,6 +8906,7 @@
"resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-2.2.0.tgz",
"integrity": "sha512-fKzAra0rGJUUBwGBgNkHZuToZcn+TtXHpeCgmkMJMMYx1sQDYaCSyjJBSCa2nH1DGm7s3n1oBnohoVTBaN7Lww==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"is-docker": "^2.0.0"
},
@@ -10250,148 +8917,232 @@
"node_modules/isarray": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/isarray/-/isarray-2.0.5.tgz",
- "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw=="
+ "integrity": "sha512-xHjhDr3cNBK0BzdUJSPXZntQUx/mwMS5Rw4A7lPJ90XGAO6ISP/ePDNuo0vhqOZU+UD5JoodwCAAoZQd3FeAKw==",
+ "license": "MIT"
},
"node_modules/isexe": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz",
- "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA= sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
- "dev": true
+ "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==",
+ "dev": true,
+ "license": "ISC"
},
"node_modules/isobject": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/isobject/-/isobject-3.0.1.tgz",
- "integrity": "sha1-TkMekrEalzFjaqH5yNHMvP2reN8= sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
+ "integrity": "sha512-WhB9zCku7EGTj/HQQRz5aUQEUeoQZH2bWcltRErOpymJ4boYE6wL9Tbr23krRPSZ+C5zqNSrSw+Cc7sZZ4b7vg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/isstream": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz",
- "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo= sha512-Yljz7ffyPbrLpLngrMtZ7NduUgVvi6wG9RJ9IUcyCd59YQ911PBJphODUcbOVbqYfxe1wuYf/LJ8PauMRwsM/g==",
- "dev": true
- },
"node_modules/javascript-natural-sort": {
"version": "0.7.1",
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
- "integrity": "sha1-+eIwPUUH9tdDVac2ZNFED7Wg71k= sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="
+ "integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw==",
+ "license": "MIT"
},
"node_modules/javascript-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/javascript-stringify/-/javascript-stringify-2.1.0.tgz",
"integrity": "sha512-JVAfqNPTvNq3sB/VHQJAFxN/sPgKnsKrCwyRt15zwNCdrMMJDdcEOdubuy+DuJYYdm0ox1J4uzEuYKkN+9yhVg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/js-message": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz",
- "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==",
+ "node_modules/jest-util": {
+ "version": "29.7.0",
+ "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.7.0.tgz",
+ "integrity": "sha512-z6EbKajIpqGKU56y5KBUgy1dt1ihhQJgWzUlZHArA/+X2ad7Cb5iF+AK1EWVL/Bo7Rz9uurpqw6SiBCefUbCGA==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jest/types": "^29.6.3",
+ "@types/node": "*",
+ "chalk": "^4.0.0",
+ "ci-info": "^3.2.0",
+ "graceful-fs": "^4.2.9",
+ "picomatch": "^2.2.3"
+ },
"engines": {
- "node": ">=0.6.0"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
- "node_modules/js-queue": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/js-queue/-/js-queue-2.0.2.tgz",
- "integrity": "sha512-pbKLsbCfi7kriM3s1J4DDCo7jQkI58zPLHi0heXPzPlj0hjUsm+FesPUbE0DSbIVIK503A36aUBoCN7eMFedkA==",
+ "node_modules/jest-util/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "easy-stack": "^1.0.1"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=1.0.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
+ }
+ },
+ "node_modules/jest-util/node_modules/ci-info": {
+ "version": "3.9.0",
+ "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.9.0.tgz",
+ "integrity": "sha512-NIxF55hv4nSqQswkAeiOi1r83xy8JldOFDTWiug55KBu9Jnblncd2U6ViHmYgHf01TPZS77NJBhBMKdWj9HQMQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/sibiraj-s"
+ }
+ ],
+ "license": "MIT",
+ "engines": {
+ "node": ">=8"
+ }
+ },
+ "node_modules/jest-worker": {
+ "version": "27.5.1",
+ "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-27.5.1.tgz",
+ "integrity": "sha512-7vuh85V5cdDofPyxn58nrPjBktZo0u9x1g8WtjQol+jZDaE+fhN+cIvTj11GndBnMnyfrUOG1sZQxCdjKh+DKg==",
+ "license": "MIT",
+ "dependencies": {
+ "@types/node": "*",
+ "merge-stream": "^2.0.0",
+ "supports-color": "^8.0.0"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ }
+ },
+ "node_modules/jest-worker/node_modules/supports-color": {
+ "version": "8.1.1",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
+ "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
+ "license": "MIT",
+ "dependencies": {
+ "has-flag": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/supports-color?sponsor=1"
+ }
+ },
+ "node_modules/jiti": {
+ "version": "1.21.7",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.21.7.tgz",
+ "integrity": "sha512-/imKNG4EbWNrVjoNC/1H5/9GFy+tqjGBHCaSsN+P2RnPqjsLmv6UD3Ej+Kj8nBWaRAwyk7kK5ZUc+OEatnTR3A==",
+ "license": "MIT",
+ "bin": {
+ "jiti": "bin/jiti.js"
+ }
+ },
+ "node_modules/joi": {
+ "version": "17.13.3",
+ "resolved": "https://registry.npmjs.org/joi/-/joi-17.13.3.tgz",
+ "integrity": "sha512-otDA4ldcIx+ZXsKHWmp0YizCweVRZG96J10b0FevjfuncLO1oX59THoAmHkNubYJ+9gWsYsp5k8v4ib6oDv1fA==",
+ "dev": true,
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@hapi/hoek": "^9.3.0",
+ "@hapi/topo": "^5.1.0",
+ "@sideway/address": "^4.1.5",
+ "@sideway/formula": "^3.0.1",
+ "@sideway/pinpoint": "^2.0.0"
+ }
+ },
+ "node_modules/js-message": {
+ "version": "1.0.7",
+ "resolved": "https://registry.npmjs.org/js-message/-/js-message-1.0.7.tgz",
+ "integrity": "sha512-efJLHhLjIyKRewNS9EGZ4UpI8NguuL6fKkhRxVuMmrGV2xN/0APGdQYwLFky5w9naebSZ0OwAGp0G6/2Cg90rA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.6.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==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
- "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz",
+ "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
+ "argparse": "^2.0.1"
},
"bin": {
"js-yaml": "bin/js-yaml.js"
}
},
- "node_modules/jsbn": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz",
- "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM= sha512-UVU9dibq2JcFWxQPA6KCqj5O42VOmAY3zQUfEKxU0KpTGXwNoCjkX1e13eHNvw/xPynt6pU0rZ1htjWTNTSXsg==",
- "dev": true
- },
"node_modules/jsesc": {
- "version": "2.5.2",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
- "integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-3.1.0.tgz",
+ "integrity": "sha512-/sM3dO2FOzXjKQhJuo0Q173wf2KOo8t4I8vHy6lF9poUp7bKT0/NHE8fPX23PwfhnykfqnC2xRxOnVw5XuGIaA==",
"dev": true,
+ "license": "MIT",
"bin": {
"jsesc": "bin/jsesc"
},
"engines": {
- "node": ">=4"
+ "node": ">=6"
}
},
+ "node_modules/json-buffer": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/json-buffer/-/json-buffer-3.0.1.tgz",
+ "integrity": "sha512-4bV5BfR2mqfQTJm+V5tPPdf+ZpuhiIvTuAB5g8kcrXOZpTT/QwwVRWBywX1ozr6lEuPdbHxwaJlm9G6mI2sfSQ==",
+ "dev": true,
+ "license": "MIT"
+ },
"node_modules/json-parse-better-errors": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/json-parse-better-errors/-/json-parse-better-errors-1.0.2.tgz",
"integrity": "sha512-mrqyZKfX5EhL7hvqcV6WG1yYjnjeuYDzDhhcAAUrq8Po85NBQBJP+ZDUT75qZQ98IkUoBqdkExkukOU7Ts2wrw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/json-parse-even-better-errors": {
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/json-parse-even-better-errors/-/json-parse-even-better-errors-2.3.1.tgz",
"integrity": "sha512-xyFwyhro/JEof6Ghe2iz2NcXoj2sloNsWr/XsERDK/oiPCfaNhl5ONfp+jQdAZRQQ0IJWNzH9zIZF7li91kh2w==",
- "dev": true
- },
- "node_modules/json-schema": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.4.0.tgz",
- "integrity": "sha512-es94M3nTIfsEPisRafak+HDLfHXnKBhV3vU5eqPcS3flIWqcxJWgXHXiey3YrpaNsanY5ei1VoYEbOzijuq9BA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"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
+ "dev": true,
+ "license": "MIT"
},
"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": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE= sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
- "dev": true
- },
- "node_modules/json-stringify-safe": {
- "version": "5.0.1",
- "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz",
- "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus= sha512-ZClg6AaYvamvYEE82d3Iyd3vSSIjQ+odgjaTzRuO3s7toCdFKczob2i0zCh7JE8kWn17yvAWhUVxvqGwUalsRA==",
- "dev": true
+ "integrity": "sha512-Bdboy+l7tA3OGW6FjyFHWkP5LuByj1Tk33Ljyq0axyzdk9//JSi2u3fP1QSmd1KNwq6VOKYGlAu87CisVir6Pw==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/json3": {
- "version": "3.3.3",
- "resolved": "https://registry.npmjs.org/json3/-/json3-3.3.3.tgz",
- "integrity": "sha512-c7/8mbUsKigAbLkD5B010BK4D9LZm7A1pNItkEwiUZRpIN66exu/e7YQWysGun+TRKaJp8MhemM+VkfWv42aCA==",
- "dev": true
+ "node_modules/json-stringify-pretty-compact": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/json-stringify-pretty-compact/-/json-stringify-pretty-compact-4.0.0.tgz",
+ "integrity": "sha512-3CNZ2DnrpByG9Nqj6Xo8vqbjT4F6N+tb4Gb28ESAZjYZ5yqvmc56J+/kuIwkaAMOyblTQhUW7PxMkUb8Q36N3Q==",
+ "license": "MIT"
},
"node_modules/json5": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.0.tgz",
- "integrity": "sha512-f+8cldu7X/y7RAJurMEJmdoKXGB/X550w2Nr3tTbezL6RwEE/iMcm+tZnXeoZtKuOq6ft8+CqzEkrIgx1fPoQA==",
+ "version": "2.2.3",
+ "resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
+ "integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
"dev": true,
- "dependencies": {
- "minimist": "^1.2.5"
- },
+ "license": "MIT",
"bin": {
"json5": "lib/cli.js"
},
@@ -10400,10 +9151,11 @@
}
},
"node_modules/jsonfile": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.1.0.tgz",
- "integrity": "sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==",
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-6.2.1.tgz",
+ "integrity": "sha512-zwOTdL3rFQ/lRdBnntKVOX6k5cKJwEc1HdilT71BWEu7J41gXIB2MRp+vxduPSwZJPWBxEzv4yH1wYLJGUHX4Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"universalify": "^2.0.0"
},
@@ -10411,139 +9163,82 @@
"graceful-fs": "^4.1.6"
}
},
- "node_modules/jsprim": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.2.tgz",
- "integrity": "sha512-P2bSOMAc/ciLz6DzgjVlGJP9+BrJWu5UDGK70C2iweC5QBIeFf0ZXRvGjEj2uYgrY2MkAAhsSWHDWlFtEroZWw==",
+ "node_modules/kdbush": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-4.0.2.tgz",
+ "integrity": "sha512-WbCVYJ27Sz8zi9Q7Q0xHC+05iwkm3Znipc2XTlrnJbsHMYktW4hPhXUE8Ys1engBrvffoSCqbil1JQAa7clRpA==",
+ "license": "ISC"
+ },
+ "node_modules/keyv": {
+ "version": "4.5.4",
+ "resolved": "https://registry.npmjs.org/keyv/-/keyv-4.5.4.tgz",
+ "integrity": "sha512-oxVHkHR/EJf2CNXnWxRLW6mg7JyCCUcG0DtEGmL2ctUo1PNTin1PUil+r/+4r5MpVgC/fn1kjsx7mjSujKqIpw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "assert-plus": "1.0.0",
- "extsprintf": "1.3.0",
- "json-schema": "0.4.0",
- "verror": "1.10.0"
- },
- "engines": {
- "node": ">=0.6.0"
+ "json-buffer": "3.0.1"
}
},
- "node_modules/kdbush": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz",
- "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew=="
- },
- "node_modules/killable": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/killable/-/killable-1.0.1.tgz",
- "integrity": "sha512-LzqtLKlUwirEUyl/nicirVmNiPvYs7l5n8wOPP7fyJVpUPkvCnW/vuiXGpylGUlnPDnB7311rARzAt3Mhswpjg==",
- "dev": true
- },
"node_modules/kind-of": {
"version": "6.0.3",
"resolved": "https://registry.npmjs.org/kind-of/-/kind-of-6.0.3.tgz",
"integrity": "sha512-dcS1ul+9tmeD95T+x28/ehLgd9mENa3LsvDTtzm3vyBEO7RPptvAD+t44WVXaUjTBRcrpFeFlC8WCruUR456hw==",
- "dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/launch-editor": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.2.1.tgz",
- "integrity": "sha512-On+V7K2uZK6wK7x691ycSUbLD/FyKKelArkbaAMSSJU8JmqmhwN2+mnJDNINuJWSrh2L0kDk+ZQtbC/gOWUwLw==",
+ "node_modules/klona": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/klona/-/klona-2.0.6.tgz",
+ "integrity": "sha512-dhG34DXATL5hSxJbIexCft8FChFXtmskoZYnoPWjXQuebWYCNkVeV3KkGegCK9CP1oswI/vQibS2GY7Em/sJJA==",
"dev": true,
- "dependencies": {
- "chalk": "^2.3.0",
- "shell-quote": "^1.6.1"
- }
- },
- "node_modules/launch-editor-middleware": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.2.1.tgz",
- "integrity": "sha512-s0UO2/gEGiCgei3/2UN3SMuUj1phjQN8lcpnvgLSz26fAzNWPQ6Nf/kF5IFClnfU2ehp6LrmKdMU/beveO+2jg==",
- "dev": true,
- "dependencies": {
- "launch-editor": "^2.2.1"
- }
- },
- "node_modules/launch-editor/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/launch-editor/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">= 8"
}
},
- "node_modules/launch-editor/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "node_modules/launch-editor": {
+ "version": "2.13.2",
+ "resolved": "https://registry.npmjs.org/launch-editor/-/launch-editor-2.13.2.tgz",
+ "integrity": "sha512-4VVDnbOpLXy/s8rdRCSXb+zfMeFR0WlJWpET1iA9CQdlZDfwyLjUuGQzXU4VeOoey6AicSAluWan7Etga6Kcmg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/launch-editor/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/launch-editor/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
+ "picocolors": "^1.1.1",
+ "shell-quote": "^1.8.3"
}
},
- "node_modules/launch-editor/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "node_modules/launch-editor-middleware": {
+ "version": "2.13.2",
+ "resolved": "https://registry.npmjs.org/launch-editor-middleware/-/launch-editor-middleware-2.13.2.tgz",
+ "integrity": "sha512-kI7VqA9g6mhoeQ6YdNgd+gKLaeuWHAUR8oDM8vFtt924wG8HbI2XO0n/hSX2ML4hcJbTgUihuPHfpnPjIKMdJg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
+ "launch-editor": "^2.13.2"
}
},
"node_modules/levn": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz",
- "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4= sha512-0OO4y2iOHix2W6ujICbKIaEQXvFQHue65vUG3pb5EUomzPI90z9hsA1VsO/dbIIpC53J8gxM9Q4Oho0jrCM/yA==",
+ "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,
+ "license": "MIT",
"dependencies": {
- "prelude-ls": "~1.1.2",
- "type-check": "~0.3.2"
+ "prelude-ls": "^1.2.1",
+ "type-check": "~0.4.0"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/lilconfig": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.0.4.tgz",
- "integrity": "sha512-bfTIN7lEsiooCocSISTWXkiWJkRqtL9wYtYy+8EK3Y41qh3mpwPU0ycTOgjdY9ErwXCc8QyrQp82bdL0Xkm9yA==",
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz",
+ "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=10"
}
@@ -10552,83 +9247,27 @@
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/lines-and-columns/-/lines-and-columns-1.2.4.tgz",
"integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==",
- "dev": true
- },
- "node_modules/loader-fs-cache": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/loader-fs-cache/-/loader-fs-cache-1.0.3.tgz",
- "integrity": "sha512-ldcgZpjNJj71n+2Mf6yetz+c9bM4xpKtNds4LbqXzU/PTdeAX0g3ytnU1AJMEcTk2Lex4Smpe3Q/eCTsvUBxbA==",
- "dev": true,
- "dependencies": {
- "find-cache-dir": "^0.1.1",
- "mkdirp": "^0.5.1"
- }
- },
- "node_modules/loader-fs-cache/node_modules/find-cache-dir": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-0.1.1.tgz",
- "integrity": "sha1-yN765XyKUqinhPnjHFfHQumToLk= sha512-Z9XSBoNE7xQiV6MSgPuCfyMokH2K7JdpRkOYE1+mu3d4BFJtx3GW+f6Bo4q8IX6rlf5MYbLBKW0pjl2cWdkm2A==",
- "dev": true,
- "dependencies": {
- "commondir": "^1.0.1",
- "mkdirp": "^0.5.1",
- "pkg-dir": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/loader-fs-cache/node_modules/find-up": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-1.1.2.tgz",
- "integrity": "sha1-ay6YIrGizgpgq2TWEOzK1TyyTQ8= sha512-jvElSjyuo4EMQGoTwo1uJU5pQMwTW5lS1x05zzfJuTIyLR3zwO27LYrxNg+dlvKpGOuGy/MzBdXh80g0ve5+HA==",
- "dev": true,
- "dependencies": {
- "path-exists": "^2.0.0",
- "pinkie-promise": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/loader-fs-cache/node_modules/path-exists": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-2.1.0.tgz",
- "integrity": "sha1-D+tsZPD8UY2adU3V77YscCJ2H0s= sha512-yTltuKuhtNeFJKa1PiRzfLAU5182q1y4Eb4XCJ3PBqyzEDkAZRzBrKKBct682ls9reBVHf9udYLN5Nd+K1B9BQ==",
- "dev": true,
- "dependencies": {
- "pinkie-promise": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/loader-fs-cache/node_modules/pkg-dir": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-1.0.0.tgz",
- "integrity": "sha1-ektQio1bstYp1EcFb/TpyTFM89Q= sha512-c6pv3OE78mcZ92ckebVDqg0aWSoKhOTbwCV6qbCWMk546mAL9pZln0+QsN/yQ7fkucd4+yJPLrCBXNt8Ruk+Eg==",
- "dev": true,
- "dependencies": {
- "find-up": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
+ "license": "MIT"
},
"node_modules/loader-runner": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-2.4.0.tgz",
- "integrity": "sha512-Jsmr89RcXGIwivFY21FcRrisYZfvLMTWx5kOLc+JTxtpBOG6xML0vzbc6SEQG2FO9/4Fc3wW4LVcB5DmGflaRw==",
- "dev": true,
+ "version": "4.3.2",
+ "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.2.tgz",
+ "integrity": "sha512-DFEqQ3ihfS9blba08cLfYf1NRAIEm+dDjic073DRDc3/JspI/8wYmtDsHwd3+4hwvdxSK7PGaElfTmm0awWJ4w==",
+ "license": "MIT",
"engines": {
- "node": ">=4.3.0 <5.0.0 || >=5.10"
+ "node": ">=6.11.5"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/loader-utils": {
- "version": "1.4.0",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.0.tgz",
- "integrity": "sha512-qH0WSMBtn/oHuwjy/NucEgbx5dbxxnxup9s4PVXJUDHZBQY+s0NWA9rJf53RBnQZxfch7euUui7hpoAPvALZdA==",
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-1.4.2.tgz",
+ "integrity": "sha512-I5d00Pd/jwMD2QCduo657+YM/6L3KZu++pmX9VFncxaxvHcru9jx1lBaFft+r4Mt2jK0Yhp41XlRAihzPxHNCg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"big.js": "^5.2.2",
"emojis-list": "^3.0.0",
@@ -10638,200 +9277,268 @@
"node": ">=4.0.0"
}
},
- "node_modules/loader-utils/node_modules/json5": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/json5/-/json5-1.0.1.tgz",
- "integrity": "sha512-aKS4WQjPenRxiQsC93MNfjx+nbF4PAdYzmd/1JIj8HYzqfbu86beTuNgXDzPknWk0n0uARlyewZo4s++ES36Ow==",
- "dev": true,
- "dependencies": {
- "minimist": "^1.2.0"
- },
- "bin": {
- "json5": "lib/cli.js"
- }
- },
"node_modules/locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
+ "version": "6.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-6.0.0.tgz",
+ "integrity": "sha512-iPZK6eYjbxRu3uB4/WZ3EsEIMJFMqAoopl3R+zuq0UjcAm/MO6KCweDgPfP3elTztoKP3KtnVHxTn2NHBSDVUw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "p-locate": "^4.1.0"
+ "p-locate": "^5.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/lodash": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
- "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg=="
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.18.1.tgz",
+ "integrity": "sha512-dMInicTPVE8d1e5otfwmmjlxkZoUpiVLwyeTdUsi/Caj/gfzzblBcCE5sRHV/AsjuCmxWrte2TNGSYuCeCq+0Q==",
+ "license": "MIT"
},
"node_modules/lodash-es": {
- "version": "4.17.21",
- "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz",
- "integrity": "sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw=="
+ "version": "4.18.1",
+ "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.18.1.tgz",
+ "integrity": "sha512-J8xewKD/Gk22OZbhpOVSwcs60zhd95ESDwezOFuA3/099925PdHJ7OFHNTGtajL3AlZkykD32HykiMo+BIBI8A==",
+ "license": "MIT"
},
"node_modules/lodash.debounce": {
"version": "4.0.8",
"resolved": "https://registry.npmjs.org/lodash.debounce/-/lodash.debounce-4.0.8.tgz",
- "integrity": "sha1-gteb/zCmfEAF/9XiUVMArZyk168= sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
- "dev": true
+ "integrity": "sha512-FT1yDzDYEoYWhnSGnpE/4Kj1fLZkDFyqRb7fNt6FdYOSxlUWAtp42Eh6Wb0rGIv/m9Bgo7x4GhQbm5Ys4SG5ow==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/lodash.defaultsdeep": {
"version": "4.6.1",
"resolved": "https://registry.npmjs.org/lodash.defaultsdeep/-/lodash.defaultsdeep-4.6.1.tgz",
"integrity": "sha512-3j8wdDzYuWO3lM3Reg03MuQR957t287Rpcxp1njpEa8oDrikb+FwGdW3n+FELh/A6qib6yPit0j/pv9G/yeAqA==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/lodash.kebabcase": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/lodash.kebabcase/-/lodash.kebabcase-4.1.1.tgz",
- "integrity": "sha1-hImxyw0p/4gZXM7KRI/21swpXDY= sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
- "dev": true
+ "integrity": "sha512-N8XRTIMMqqDgSy4VLKPnJ/+hpGZN+PHQiJnSenYqPaVV/NCqEogTnAdZLQiGKhxX+JCs8waWq2t1XHWKOmlY8g==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/lodash.mapvalues": {
"version": "4.6.0",
"resolved": "https://registry.npmjs.org/lodash.mapvalues/-/lodash.mapvalues-4.6.0.tgz",
- "integrity": "sha1-G6+lAF3p3W9PJmaMMMo3IwzJaJw= sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==",
- "dev": true
+ "integrity": "sha512-JPFqXFeZQ7BfS00H58kClY7SPVeHertPE0lNuCyZ26/XlN8TvakYD7b9bGyNmXbT/D3BbtPAAmq90gPWqLkxlQ==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/lodash.memoize": {
"version": "4.1.2",
"resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz",
- "integrity": "sha1-vMbEmkKihA7Zl/Mj6tpezRguC/4= sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
- "dev": true
+ "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==",
+ "dev": true,
+ "license": "MIT"
},
"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=="
- },
- "node_modules/lodash.topath": {
- "version": "4.5.2",
- "resolved": "https://registry.npmjs.org/lodash.topath/-/lodash.topath-4.5.2.tgz",
- "integrity": "sha1-NhY1Hzu6YZlKCTGYlmC9AyVP0Ak= sha512-1/W4dM+35DwvE/iEd1M9ekewOSTlpFekhw9mhAtrwjVqUr83/ilQiyAvmg4tVX7Unkcfl1KC+i9WdaT4B6aQcg==",
- "dev": true
- },
- "node_modules/lodash.transform": {
- "version": "4.6.0",
- "resolved": "https://registry.npmjs.org/lodash.transform/-/lodash.transform-4.6.0.tgz",
- "integrity": "sha1-EjBkIvYzJK7YSD0/ODMrX2cFR6A= sha512-LO37ZnhmBVx0GvOU/caQuipEh4GN82TcWv3yHlebGDgOxbxiwwzW5Pcx2AcvpIv2WmvmSMoC492yQFNhy/l/UQ==",
- "dev": true
+ "integrity": "sha512-0KpjqXRVvrYyCsX1swR/XTK0va6VQkQM6MNo7PqW77ByjAhoARA8EfrP1N4+KlKj8YS0ZUCtRT/YUuhyYDujIQ==",
+ "license": "MIT"
},
"node_modules/lodash.uniq": {
"version": "4.5.0",
"resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz",
- "integrity": "sha1-0CJTc662Uq3BvILklFM5qEJ1R3M= sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
- "dev": true
+ "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/log-symbols": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-2.2.0.tgz",
- "integrity": "sha512-VeIAFslyIerEJLXHziedo2basKbMKtTw3vfn5IzG0XTjhAVEJyNHnL2p7vc+wBDSdQuUpNw3M2u6xb9QsAY5Eg==",
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/log-symbols/-/log-symbols-4.1.0.tgz",
+ "integrity": "sha512-8XPvpAA8uyhfteu8pIvQxpJZ7SYYdpUivZpGy6sFsBuKRY/7rQGavedeB8aK+Zkyq6upMFVL/9AW6vOYzfRyLg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "chalk": "^2.0.1"
+ "chalk": "^4.1.0",
+ "is-unicode-supported": "^0.1.0"
},
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/log-symbols/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "node_modules/log-symbols/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "color-convert": "^1.9.0"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/log-symbols/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "node_modules/log-update": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/log-update/-/log-update-2.3.0.tgz",
+ "integrity": "sha512-vlP11XfFGyeNQlmEn9tJ66rEW1coA/79m5z6BCkudjbAGE83uhAcGYrBFwfs3AdLiLzGRusRPAbSPK9xZteCmg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
+ "ansi-escapes": "^3.0.0",
+ "cli-cursor": "^2.0.0",
+ "wrap-ansi": "^3.0.1"
},
"engines": {
"node": ">=4"
}
},
- "node_modules/log-symbols/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "node_modules/log-update/node_modules/cli-cursor": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
+ "integrity": "sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "color-name": "1.1.3"
+ "restore-cursor": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=4"
}
},
- "node_modules/log-symbols/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
+ "node_modules/log-update/node_modules/is-fullwidth-code-point": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
+ "integrity": "sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
},
- "node_modules/log-symbols/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "node_modules/log-update/node_modules/mimic-fn": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
+ "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
},
- "node_modules/log-symbols/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "node_modules/log-update/node_modules/onetime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
+ "integrity": "sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-flag": "^3.0.0"
+ "mimic-fn": "^1.0.0"
},
"engines": {
"node": ">=4"
}
},
- "node_modules/loglevel": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/loglevel/-/loglevel-1.8.0.tgz",
- "integrity": "sha512-G6A/nJLRgWOuuwdNuA6koovfEV1YpqqAG4pRUlFaz3jj2QNZ8M4vBqnVA+HBTmU/AMNUtlOsMmSpF6NyOjztbA==",
+ "node_modules/log-update/node_modules/restore-cursor": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
+ "integrity": "sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==",
"dev": true,
- "engines": {
- "node": ">= 0.6.0"
+ "license": "MIT",
+ "dependencies": {
+ "onetime": "^2.0.0",
+ "signal-exit": "^3.0.2"
},
- "funding": {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/loglevel"
+ "engines": {
+ "node": ">=4"
}
},
- "node_modules/lower-case": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-1.1.4.tgz",
- "integrity": "sha1-miyr0bno4K6ZOkv31YdcOcQujqw= sha512-2Fgx1Ycm599x+WGpIYwJOvsjmXFzTSc34IwDWALRA/8AopUKAVPwfJ+h5+f85BCp0PWmmJcWzEpxOpoXycMpdA==",
- "dev": true
- },
- "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==",
+ "node_modules/log-update/node_modules/string-width": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz",
+ "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "yallist": "^3.0.2"
- }
+ "is-fullwidth-code-point": "^2.0.0",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/log-update/node_modules/strip-ansi": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz",
+ "integrity": "sha512-4XaJ2zQdCzROZDivEVIDPkcQn8LMFSa8kj8Gxb/Lnwzv9A8VctNZ+lfivC/sV3ivW8ElJTERXZoPBRrZKkNKow==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "ansi-regex": "^3.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/log-update/node_modules/wrap-ansi": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-3.0.1.tgz",
+ "integrity": "sha512-iXR3tDXpbnTpzjKSylUJRkLuOrEC7hwEB221cgn6wtF8wpmz28puFXAEfPT5zrjM3wahygB//VuWEr1vTkDcNQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "string-width": "^2.1.1",
+ "strip-ansi": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/lower-case": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/lower-case/-/lower-case-2.0.2.tgz",
+ "integrity": "sha512-7fm3l3NAF9WfN6W3JOmf5drwpVqX78JtoGJ3A6W0a6ZnldM41w2fV5D490psKFTpMds8TJse/eHLFFsNHHjHgg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "tslib": "^2.0.3"
+ }
+ },
+ "node_modules/lru-cache": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
+ "integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
+ "license": "ISC",
+ "dependencies": {
+ "yallist": "^3.0.2"
+ }
+ },
+ "node_modules/magic-string": {
+ "version": "0.30.21",
+ "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.30.21.tgz",
+ "integrity": "sha512-vd2F4YUyEXKGcLHoq+TEyCjxueSeHnFxyyjNp80yg0XV4vUhnDer/lvvlqM/arB5bXQN5K2/3oinyCRyx8T2CQ==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@jridgewell/sourcemap-codec": "^1.5.5"
+ }
},
"node_modules/make-dir": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/make-dir/-/make-dir-3.1.0.tgz",
"integrity": "sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"semver": "^6.0.0"
},
@@ -10842,19 +9549,11 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/map-cache": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/map-cache/-/map-cache-0.2.2.tgz",
- "integrity": "sha1-wyq9C9ZSXZsFFkW7TyasXcmKDb8= sha512-8y/eV9QQZCiyn1SprXSrCmqJN0yNRATe+PO8ztwqrvrbdRLA3eYJF0yaR0YayLWkMbsQSKWS9N2gPcGEc4UsZg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/map-limit": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz",
"integrity": "sha512-pJpcfLPnIF/Sk3taPW21G/RQsEEirGaFpCW3oXRwH9dnFHPHNGjNyvh++rdmC2fNqEaTw2MhYJraoJWAHx8kEg==",
+ "license": "MIT",
"dependencies": {
"once": "~1.3.0"
}
@@ -10863,28 +9562,19 @@
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/once/-/once-1.3.3.tgz",
"integrity": "sha512-6vaNInhu+CHxtONf3zw3vq4SP2DOQhjBvIa3rNcG0+P7eKWlYH6Peu7rHizSloRU2EwMz6GraLieis9Ac9+p1w==",
+ "license": "ISC",
"dependencies": {
"wrappy": "1"
}
},
- "node_modules/map-visit": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/map-visit/-/map-visit-1.0.0.tgz",
- "integrity": "sha1-7Nyo8TFE5mDxtb1B8S80edmN+48= sha512-4y7uGv8bd2WdM9vpQsiQNo41Ln1NvhvDRuVt0k2JZQ+ezN2uaQes7lZeZ+QQUHOLQAtDaBJ+7wCbi+ab/KFs+w==",
- "dev": true,
- "dependencies": {
- "object-visit": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/mapbox-gl": {
- "version": "1.10.1",
- "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-1.10.1.tgz",
- "integrity": "sha512-0aHt+lFUpYfvh0kMIqXqNXqoYMuhuAsMlw87TbhWrw78Tx2zfuPI0Lx31/YPUgJ+Ire0tzQ4JnuBL7acDNXmMg==",
+ "version": "1.13.3",
+ "resolved": "https://registry.npmjs.org/mapbox-gl/-/mapbox-gl-1.13.3.tgz",
+ "integrity": "sha512-p8lJFEiqmEQlyv+DQxFAOG/XPWN0Wp7j/Psq93Zywz7qt9CcUKFYDBOoOEKzqe6gudHVJY8/Bhqw6VDpX2lSBg==",
+ "license": "SEE LICENSE IN LICENSE.txt",
+ "peer": true,
"dependencies": {
- "@mapbox/geojson-rewind": "^0.5.0",
+ "@mapbox/geojson-rewind": "^0.5.2",
"@mapbox/geojson-types": "^1.0.2",
"@mapbox/jsonlint-lines-primitives": "^2.0.2",
"@mapbox/mapbox-gl-supported": "^1.5.0",
@@ -10898,13 +9588,12 @@
"geojson-vt": "^3.2.1",
"gl-matrix": "^3.2.1",
"grid-index": "^1.1.0",
- "minimist": "^1.2.5",
"murmurhash-js": "^1.0.0",
"pbf": "^3.2.1",
"potpack": "^1.0.1",
"quickselect": "^2.0.0",
"rw": "^1.3.3",
- "supercluster": "^7.0.0",
+ "supercluster": "^7.1.0",
"tinyqueue": "^2.0.3",
"vt-pbf": "^3.1.1"
},
@@ -10912,6 +9601,111 @@
"node": ">=6.4.0"
}
},
+ "node_modules/maplibre-gl": {
+ "version": "4.7.1",
+ "resolved": "https://registry.npmjs.org/maplibre-gl/-/maplibre-gl-4.7.1.tgz",
+ "integrity": "sha512-lgL7XpIwsgICiL82ITplfS7IGwrB1OJIw/pCvprDp2dhmSSEBgmPzYRvwYYYvJGJD7fxUv1Tvpih4nZ6VrLuaA==",
+ "license": "BSD-3-Clause",
+ "dependencies": {
+ "@mapbox/geojson-rewind": "^0.5.2",
+ "@mapbox/jsonlint-lines-primitives": "^2.0.2",
+ "@mapbox/point-geometry": "^0.1.0",
+ "@mapbox/tiny-sdf": "^2.0.6",
+ "@mapbox/unitbezier": "^0.0.1",
+ "@mapbox/vector-tile": "^1.3.1",
+ "@mapbox/whoots-js": "^3.1.0",
+ "@maplibre/maplibre-gl-style-spec": "^20.3.1",
+ "@types/geojson": "^7946.0.14",
+ "@types/geojson-vt": "3.2.5",
+ "@types/mapbox__point-geometry": "^0.1.4",
+ "@types/mapbox__vector-tile": "^1.3.4",
+ "@types/pbf": "^3.0.5",
+ "@types/supercluster": "^7.1.3",
+ "earcut": "^3.0.0",
+ "geojson-vt": "^4.0.2",
+ "gl-matrix": "^3.4.3",
+ "global-prefix": "^4.0.0",
+ "kdbush": "^4.0.2",
+ "murmurhash-js": "^1.0.0",
+ "pbf": "^3.3.0",
+ "potpack": "^2.0.0",
+ "quickselect": "^3.0.0",
+ "supercluster": "^8.0.1",
+ "tinyqueue": "^3.0.0",
+ "vt-pbf": "^3.1.3"
+ },
+ "engines": {
+ "node": ">=16.14.0",
+ "npm": ">=8.1.0"
+ },
+ "funding": {
+ "url": "https://github.com/maplibre/maplibre-gl-js?sponsor=1"
+ }
+ },
+ "node_modules/maplibre-gl/node_modules/@mapbox/tiny-sdf": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.2.0.tgz",
+ "integrity": "sha512-LVL4wgI9YAum5V+LNVQO6QgFBPw7/MIIY4XJPNsPDMrjEwcE+JfKk1LuIl8GnF197ejVdC9QdPaxrx5gfgdGXg==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/maplibre-gl/node_modules/@mapbox/unitbezier": {
+ "version": "0.0.1",
+ "resolved": "https://registry.npmjs.org/@mapbox/unitbezier/-/unitbezier-0.0.1.tgz",
+ "integrity": "sha512-nMkuDXFv60aBr9soUG5q+GvZYL+2KZHVvsqFCzqnkGEf46U2fvmytHaEVc1/YZbiLn8X+eR3QzX1+dwDO1lxlw==",
+ "license": "BSD-2-Clause"
+ },
+ "node_modules/maplibre-gl/node_modules/earcut": {
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/earcut/-/earcut-3.0.2.tgz",
+ "integrity": "sha512-X7hshQbLyMJ/3RPhyObLARM2sNxxmRALLKx1+NVFFnQ9gKzmCrxm9+uLIAdBcvc8FNLpctqlQ2V6AE92Ol9UDQ==",
+ "license": "ISC"
+ },
+ "node_modules/maplibre-gl/node_modules/geojson-vt": {
+ "version": "4.0.2",
+ "resolved": "https://registry.npmjs.org/geojson-vt/-/geojson-vt-4.0.2.tgz",
+ "integrity": "sha512-AV9ROqlNqoZEIJGfm1ncNjEXfkz2hdFlZf0qkVfmkwdKa8vj7H16YUOT81rJw1rdFhyEDlN2Tds91p/glzbl5A==",
+ "license": "ISC"
+ },
+ "node_modules/maplibre-gl/node_modules/potpack": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/potpack/-/potpack-2.1.0.tgz",
+ "integrity": "sha512-pcaShQc1Shq0y+E7GqJqvZj8DTthWV1KeHGdi0Z6IAin2Oi3JnLCOfwnCo84qc+HAp52wT9nK9H7FAJp5a44GQ==",
+ "license": "ISC"
+ },
+ "node_modules/maplibre-gl/node_modules/quickselect": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/quickselect/-/quickselect-3.0.0.tgz",
+ "integrity": "sha512-XdjUArbK4Bm5fLLvlm5KpTFOiOThgfWWI4axAZDWg4E/0mKdZyI9tNEfds27qCi1ze/vwTR16kvmmGhRra3c2g==",
+ "license": "ISC"
+ },
+ "node_modules/maplibre-gl/node_modules/supercluster": {
+ "version": "8.0.1",
+ "resolved": "https://registry.npmjs.org/supercluster/-/supercluster-8.0.1.tgz",
+ "integrity": "sha512-IiOea5kJ9iqzD2t7QJq/cREyLHTtSmUT6gQsweojg9WH2sYJqZK9SswTu6jrscO6D1G5v5vYZ9ru/eq85lXeZQ==",
+ "license": "ISC",
+ "dependencies": {
+ "kdbush": "^4.0.2"
+ }
+ },
+ "node_modules/maplibre-gl/node_modules/tinyqueue": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-3.0.0.tgz",
+ "integrity": "sha512-gRa9gwYU3ECmQYv3lslts5hxuIa90veaEcxDYuu3QGOIAEM2mOZkVHp48ANJuu1CURtRdHKUBY5Lm1tHV+sD4g==",
+ "license": "ISC"
+ },
+ "node_modules/marked": {
+ "version": "14.0.0",
+ "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz",
+ "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==",
+ "license": "MIT",
+ "peer": true,
+ "bin": {
+ "marked": "bin/marked.js"
+ },
+ "engines": {
+ "node": ">= 18"
+ }
+ },
"node_modules/math-intrinsics": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz",
@@ -10925,24 +9719,26 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/math-log2/-/math-log2-1.0.1.tgz",
"integrity": "sha512-9W0yGtkaMAkf74XGYVy4Dqw3YUMnTNB2eeiw9aQbUl4A3KmuCEHTt2DgAB07ENzOYAjsYSAYufkAq0Zd+jU7zA==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/mathjs": {
- "version": "11.5.0",
- "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-11.5.0.tgz",
- "integrity": "sha512-vJ/+SqWtxjW6/aeDRt8xL3TlOVKqwN15BIyTGVqGbIWuiqgY4SxZ0yLuna82YH9CB757iFP7uJ4m3KvVBX7Qcg==",
+ "version": "11.12.0",
+ "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-11.12.0.tgz",
+ "integrity": "sha512-UGhVw8rS1AyedyI55DGz9q1qZ0p98kyKPyc9vherBkoueLntPfKtPBh14x+V4cdUWK0NZV2TBwqRFlvadscSuw==",
+ "license": "Apache-2.0",
"dependencies": {
- "@babel/runtime": "^7.20.6",
+ "@babel/runtime": "^7.23.2",
"complex.js": "^2.1.1",
"decimal.js": "^10.4.3",
"escape-latex": "^1.2.0",
- "fraction.js": "^4.2.0",
+ "fraction.js": "4.3.4",
"javascript-natural-sort": "^0.7.1",
"seedrandom": "^3.0.5",
"tiny-emitter": "^2.1.0",
- "typed-function": "^4.1.0"
+ "typed-function": "^4.1.1"
},
"bin": {
"mathjs": "bin/cli.js"
@@ -10951,77 +9747,80 @@
"node": ">= 14"
}
},
- "node_modules/md5.js": {
- "version": "1.3.5",
- "resolved": "https://registry.npmjs.org/md5.js/-/md5.js-1.3.5.tgz",
- "integrity": "sha512-xitP+WxNPcTTOgnTJcrhM0xvdPepipPSf3I8EIpGKeFLjt3PlJLIDG3u8EX53ZIubkb+5U2+3rELYpEhHhzdkg==",
- "dev": true,
- "dependencies": {
- "hash-base": "^3.0.0",
- "inherits": "^2.0.1",
- "safe-buffer": "^5.1.2"
+ "node_modules/mathjs/node_modules/fraction.js": {
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.4.tgz",
+ "integrity": "sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==",
+ "license": "MIT",
+ "engines": {
+ "node": "*"
+ },
+ "funding": {
+ "type": "patreon",
+ "url": "https://github.com/sponsors/rawify"
}
},
"node_modules/mdn-data": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.4.tgz",
- "integrity": "sha512-iV3XNKw06j5Q7mi6h+9vbx23Tv7JkjEVgKHW4pimwyDGWm0OIQntJJ+u1C6mg6mK1EaTv42XQ7w76yuzH7M2cA==",
- "dev": true
+ "version": "2.0.14",
+ "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz",
+ "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==",
+ "dev": true,
+ "license": "CC0-1.0"
},
"node_modules/media-typer": {
"version": "0.3.0",
"resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz",
- "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g= sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
+ "integrity": "sha512-dq+qelQ9akHpcOl/gUVRTxVIOkAJ1wR3QAvb4RsVjS8oVoFjDGTc679wJYmUmknUF5HwMLOgb5O+a3KxfWapPQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
- "node_modules/memory-fs": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/memory-fs/-/memory-fs-0.4.1.tgz",
- "integrity": "sha1-OpoguEYlI+RHz7x+i7gO1me/xVI= sha512-cda4JKCxReDXFXRqOHPQscuIYg1PvxbE2S2GP45rnwfEK+vZaXC8C1OFvdHIbgw0DLzowXGVoxLaAmlgRy14GQ==",
+ "node_modules/memfs": {
+ "version": "3.5.3",
+ "resolved": "https://registry.npmjs.org/memfs/-/memfs-3.5.3.tgz",
+ "integrity": "sha512-UERzLsxzllchadvbPs5aolHh65ISpKpM+ccLbOJ8/vvpBKmAWf+la7dXFy7Mr0ySHbdHrFv5kGFCUHHe6GFEmw==",
"dev": true,
+ "license": "Unlicense",
"dependencies": {
- "errno": "^0.1.3",
- "readable-stream": "^2.0.1"
+ "fs-monkey": "^1.0.4"
+ },
+ "engines": {
+ "node": ">= 4.0.0"
}
},
"node_modules/merge-descriptors": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz",
- "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E= sha512-cCi6g3/Zr1iqQi6ySbseM1Xvooa98N0w31jzUYrXPX2xqObmFGHJ0tQ5u74H3mVh7wLouTseZyYIq39g8cNp1w==",
- "dev": true
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.3.tgz",
+ "integrity": "sha512-gaNvAS7TZ897/rVaZ0nMtAyxNyi/pdbjbAwUpFQpN70GqnVfOiXpeUUMKRBmzXaSQ8DdTX4/0ms62r2K+hE6mQ==",
+ "dev": true,
+ "license": "MIT",
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
},
"node_modules/merge-source-map": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/merge-source-map/-/merge-source-map-1.1.0.tgz",
"integrity": "sha512-Qkcp7P2ygktpMPh2mCQZaf3jhN6D3Z/qVZHSdWvQ+2Ef5HgRAPBO57A77+ENm0CPx2+1Ce/MYKi3ymqdfuqibw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"source-map": "^0.6.1"
}
},
- "node_modules/merge-source-map/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
"integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
- "dev": true
+ "license": "MIT"
},
"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,
+ "license": "MIT",
"engines": {
"node": ">= 8"
}
@@ -11029,70 +9828,55 @@
"node_modules/methods": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz",
- "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4= sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
+ "integrity": "sha512-iclAHeNqNm68zFtnZ0e+1L2yUIdvzNoauKU4WBA3VvH/vPFieF7qfRlwUZU+DA9P9bPXIS90ulxoUoCH23sV2w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/micromatch": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.4.tgz",
- "integrity": "sha512-pRmzw/XUcwXGpD9aI9q/0XOwLNygjETJ8y0ao0wdqprrzDa4YnxLcz7fQRZr8voh8V10kGhABbNcHVk5wHgWwg==",
- "dev": true,
+ "version": "4.0.8",
+ "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz",
+ "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==",
+ "license": "MIT",
"dependencies": {
- "braces": "^3.0.1",
- "picomatch": "^2.2.3"
+ "braces": "^3.0.3",
+ "picomatch": "^2.3.1"
},
"engines": {
"node": ">=8.6"
}
},
- "node_modules/miller-rabin": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/miller-rabin/-/miller-rabin-4.0.1.tgz",
- "integrity": "sha512-115fLhvZVqWwHPbClyntxEVfVDfl9DLLTuJvq3g2O/Oxi8AiNouAHvDSzHS0viUJc+V5vm3eq91Xwqn9dp4jRA==",
- "dev": true,
- "dependencies": {
- "bn.js": "^4.0.0",
- "brorand": "^1.0.1"
- },
- "bin": {
- "miller-rabin": "bin/miller-rabin"
- }
- },
- "node_modules/miller-rabin/node_modules/bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
- "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
- "dev": true
- },
"node_modules/mime": {
- "version": "2.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz",
- "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==",
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
+ "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
"dev": true,
+ "license": "MIT",
"bin": {
"mime": "cli.js"
},
"engines": {
- "node": ">=4.0.0"
+ "node": ">=4"
}
},
"node_modules/mime-db": {
- "version": "1.51.0",
- "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.51.0.tgz",
- "integrity": "sha512-5y8A56jg7XVQx2mbv1lu49NR4dokRnhZYTtL+KGfaa27uq4pSTXkwQkFJl4pkRMyNFz/EtYDSkiiEHx3F7UN6g==",
+ "version": "1.52.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.52.0.tgz",
+ "integrity": "sha512-sPU4uV7dYlvtWJxwwxHD0PuihVNiE7TyAbQ5SWxDCB9mUYvOgroQOwYQQOKPJ8CIbE+1ETVlOoK1UC2nU3gYvg==",
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/mime-types": {
- "version": "2.1.34",
- "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.34.tgz",
- "integrity": "sha512-6cP692WwGIs9XXdOO4++N+7qjqv0rqxxVvJ3VHPh/Sc9mVZcQP+ZGhkKiTvWMQRr2tbHkJP/Yn7Y0npb3ZBs4A==",
+ "version": "2.1.35",
+ "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.35.tgz",
+ "integrity": "sha512-ZDY+bPm5zTTF+YpCrAU9nK0UgICYPT0QtT1NZWFv4s++TNkcgVaT0g6+4R2uI4MjQjzysHB1zxuWL50hzaeXiw==",
+ "license": "MIT",
"dependencies": {
- "mime-db": "1.51.0"
+ "mime-db": "1.52.0"
},
"engines": {
"node": ">= 0.6"
@@ -11103,46 +9887,94 @@
"resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-2.1.0.tgz",
"integrity": "sha512-OqbOk5oEQeAZ8WXWydlu9HJjz9WVdEIvamMCcXmuqUYjTknH/sqsWvhQ3vgwKFRR1HpjvNBKQ37nbJgYzGqGcg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
},
"node_modules/mini-css-extract-plugin": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-0.9.0.tgz",
- "integrity": "sha512-lp3GeY7ygcgAmVIcRPBVhIkf8Us7FZjA+ILpal44qLdSu11wmjKQ3d9k15lfD7pO4esu9eUIAW7qiYIBppv40A==",
+ "version": "2.10.2",
+ "resolved": "https://registry.npmjs.org/mini-css-extract-plugin/-/mini-css-extract-plugin-2.10.2.tgz",
+ "integrity": "sha512-AOSS0IdEB95ayVkxn5oGzNQwqAi2J0Jb/kKm43t7H73s8+f5873g0yuj0PNvK4dO75mu5DHg4nlgp4k6Kga8eg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "loader-utils": "^1.1.0",
- "normalize-url": "1.9.1",
- "schema-utils": "^1.0.0",
- "webpack-sources": "^1.1.0"
+ "schema-utils": "^4.0.0",
+ "tapable": "^2.2.1"
},
"engines": {
- "node": ">= 6.9.0"
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
},
"peerDependencies": {
- "webpack": "^4.4.0"
+ "webpack": "^5.0.0"
}
},
- "node_modules/mini-css-extract-plugin/node_modules/schema-utils": {
+ "node_modules/mini-css-extract-plugin/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/mini-css-extract-plugin/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.3"
+ },
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/mini-css-extract-plugin/node_modules/json-schema-traverse": {
"version": "1.0.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
- "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz",
+ "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/mini-css-extract-plugin/node_modules/schema-utils": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
},
"engines": {
- "node": ">= 4"
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/mini-svg-data-uri": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.3.tgz",
- "integrity": "sha512-gSfqpMRC8IxghvMcxzzmMnWpXAChSA+vy4cia33RgerMS8Fex95akUyQZPbxJJmeBGiGmK7n/1OpUX8ksRjIdA==",
+ "version": "1.4.4",
+ "resolved": "https://registry.npmjs.org/mini-svg-data-uri/-/mini-svg-data-uri-1.4.4.tgz",
+ "integrity": "sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==",
+ "license": "MIT",
"bin": {
"mini-svg-data-uri": "cli.js"
}
@@ -11151,19 +9983,15 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/minimalistic-assert/-/minimalistic-assert-1.0.1.tgz",
"integrity": "sha512-UtJcAD4yEaGtjPezWuO9wC4nwUnVH/8/Im3yEHQP4b67cXlD/Qr9hdITCU1xDbSEXg2XKNaP8jsReV7vQd00/A==",
- "dev": true
- },
- "node_modules/minimalistic-crypto-utils": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/minimalistic-crypto-utils/-/minimalistic-crypto-utils-1.0.1.tgz",
- "integrity": "sha1-9sAMHAsIIkblxNmd+4x8CDsrWCo= sha512-JIYlbt6g8i5jKfJ3xz7rF0LXmv2TkDxBLUkiBeZ7bAx4GnnNMr8xFpGnOxn6GhTEHx3SjRrZEoU+j04prX1ktg==",
- "dev": true
+ "dev": true,
+ "license": "ISC"
},
"node_modules/minimatch": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
- "integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "version": "3.1.5",
+ "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.5.tgz",
+ "integrity": "sha512-VgjWUsnnT6n+NUk6eZq77zeFdpW2LWDzP6zFGrCbHXiYNul5Dzqk2HHQ5uFH2DNW5Xbp8+jVzaeNt94ssEEl4w==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -11175,15 +10003,17 @@
"version": "1.2.8",
"resolved": "https://registry.npmjs.org/minimist/-/minimist-1.2.8.tgz",
"integrity": "sha512-2yyAR8qBkN3YuheJanUpWC5U3bb5osDywNB8RzDVlDwDHbocAJveqqj1u8+SVD7jkWT4yvsHCpWqqWqAxb0zCA==",
+ "license": "MIT",
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/minipass": {
- "version": "3.1.5",
- "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.1.5.tgz",
- "integrity": "sha512-+8NzxD82XQoNKNrl1d/FSi+X8wAEWR+sbYAfIvub4Nz0d22plFG72CEVVaufV8PNf4qSslFTD8VMOxNVhHCjTw==",
+ "version": "3.3.6",
+ "resolved": "https://registry.npmjs.org/minipass/-/minipass-3.3.6.tgz",
+ "integrity": "sha512-DxiNidxSEK+tHG6zOIklvNOwm3hvCrbUrdtzY74U6HKTJxvIDfOUL5W5P2Ghd3DTkhhKPYGqeNUIh5qcM4YBfw==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"yallist": "^4.0.0"
},
@@ -11195,70 +10025,32 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
- "dev": true
- },
- "node_modules/mississippi": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/mississippi/-/mississippi-3.0.0.tgz",
- "integrity": "sha512-x471SsVjUtBRtcvd4BzKE9kFC+/2TeWgKCgw0bZcw1b9l2X3QX5vCWgF+KaZaYm87Ss//rHnWryupDrgLvmSkA==",
"dev": true,
- "dependencies": {
- "concat-stream": "^1.5.0",
- "duplexify": "^3.4.2",
- "end-of-stream": "^1.1.0",
- "flush-write-stream": "^1.0.0",
- "from2": "^2.1.0",
- "parallel-transform": "^1.1.0",
- "pump": "^3.0.0",
- "pumpify": "^1.3.3",
- "stream-each": "^1.1.0",
- "through2": "^2.0.0"
- },
- "engines": {
- "node": ">=4.0.0"
- }
+ "license": "ISC"
},
- "node_modules/mixin-deep": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/mixin-deep/-/mixin-deep-1.3.2.tgz",
- "integrity": "sha512-WRoDn//mXBiJ1H40rqa3vH0toePwSsGb45iInWlTySa+Uu4k3tYUSxa2v1KqAiLtvlrSzaExqS1gtk96A9zvEA==",
+ "node_modules/module-alias": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/module-alias/-/module-alias-2.3.4.tgz",
+ "integrity": "sha512-bOclZt8hkpuGgSSoG07PKmvzTizROilUTvLNyrMqvlC9snhs7y7GzjNWAVbISIOlhCP1T14rH1PDAV9iNyBq/w==",
"dev": true,
- "dependencies": {
- "for-in": "^1.0.2",
- "is-extendable": "^1.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
+ "license": "MIT"
},
- "node_modules/mkdirp": {
- "version": "0.5.5",
- "resolved": "https://registry.npmjs.org/mkdirp/-/mkdirp-0.5.5.tgz",
- "integrity": "sha512-NKmAlESf6jMGym1++R0Ra7wvhV+wFW63FaSOFPwRahvea0gMUcGUhVeAg/0BC0wiv9ih5NYPB1Wn1UEI1/L+xQ==",
- "dev": true,
+ "node_modules/monaco-editor": {
+ "version": "0.55.1",
+ "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz",
+ "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==",
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "minimist": "^1.2.5"
- },
- "bin": {
- "mkdirp": "bin/cmd.js"
- }
- },
- "node_modules/modern-normalize": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/modern-normalize/-/modern-normalize-1.1.0.tgz",
- "integrity": "sha512-2lMlY1Yc1+CUy0gw4H95uNN7vjbpoED7NNRSBHE25nWfLBdmMzFCsPshlzbxHz+gYMcBEUN8V4pU16prcdPSgA==",
- "dev": true,
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "dompurify": "3.2.7",
+ "marked": "14.0.0"
}
},
"node_modules/mouse-change": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/mouse-change/-/mouse-change-1.4.0.tgz",
"integrity": "sha512-vpN0s+zLL2ykyyUDh+fayu9Xkor5v/zRD9jhSqjRS1cJTGS0+oakVZzNm5n19JvvEj0you+MXlYTpNxUDQUjkQ==",
+ "license": "MIT",
"dependencies": {
"mouse-event": "^1.0.0"
}
@@ -11266,67 +10058,62 @@
"node_modules/mouse-event": {
"version": "1.0.5",
"resolved": "https://registry.npmjs.org/mouse-event/-/mouse-event-1.0.5.tgz",
- "integrity": "sha512-ItUxtL2IkeSKSp9cyaX2JLUuKk2uMoxBg4bbOWVd29+CskYJR9BGsUqtXenNzKbnDshvupjUewDIYVrOB6NmGw=="
+ "integrity": "sha512-ItUxtL2IkeSKSp9cyaX2JLUuKk2uMoxBg4bbOWVd29+CskYJR9BGsUqtXenNzKbnDshvupjUewDIYVrOB6NmGw==",
+ "license": "MIT"
},
"node_modules/mouse-event-offset": {
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/mouse-event-offset/-/mouse-event-offset-3.0.2.tgz",
- "integrity": "sha512-s9sqOs5B1Ykox3Xo8b3Ss2IQju4UwlW6LSR+Q5FXWpprJ5fzMLefIIItr3PH8RwzfGy6gxs/4GAmiNuZScE25w=="
+ "integrity": "sha512-s9sqOs5B1Ykox3Xo8b3Ss2IQju4UwlW6LSR+Q5FXWpprJ5fzMLefIIItr3PH8RwzfGy6gxs/4GAmiNuZScE25w==",
+ "license": "MIT"
},
"node_modules/mouse-wheel": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/mouse-wheel/-/mouse-wheel-1.2.0.tgz",
"integrity": "sha512-+OfYBiUOCTWcTECES49neZwL5AoGkXE+lFjIvzwNCnYRlso+EnfvovcBxGoyQ0yQt806eSPjS675K0EwWknXmw==",
+ "license": "MIT",
"dependencies": {
"right-now": "^1.0.0",
"signum": "^1.0.0",
"to-px": "^1.0.1"
}
},
- "node_modules/move-concurrently": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/move-concurrently/-/move-concurrently-1.0.1.tgz",
- "integrity": "sha1-viwAX9oy4LKa8fBdfEszIUxwH5I= sha512-hdrFxZOycD/g6A6SoI2bB5NA/5NEqD0569+S47WZhPvm46sD50ZHdYaFmnua5lndde9rCHGjmfK7Z8BuCt/PcQ==",
- "deprecated": "This package is no longer supported.",
+ "node_modules/mrmime": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz",
+ "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==",
"dev": true,
- "dependencies": {
- "aproba": "^1.1.1",
- "copy-concurrently": "^1.0.0",
- "fs-write-stream-atomic": "^1.0.8",
- "mkdirp": "^0.5.1",
- "rimraf": "^2.5.4",
- "run-queue": "^1.0.3"
+ "license": "MIT",
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/ms": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz",
- "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w=="
+ "version": "2.1.3",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz",
+ "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==",
+ "license": "MIT"
},
"node_modules/multicast-dns": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-6.2.3.tgz",
- "integrity": "sha512-ji6J5enbMyGRHIAkAOu3WdV8nggqviKCEKtXcOqfphZZtQrmHKycfynJ2V7eVPUA4NhJ6V7Wf4TmGbTwKE9B6g==",
+ "version": "7.2.5",
+ "resolved": "https://registry.npmjs.org/multicast-dns/-/multicast-dns-7.2.5.tgz",
+ "integrity": "sha512-2eznPJP8z2BFLX50tf0LuODrpINqP1RVIm/CObbTcBRITQgmC/TjcREF1NeTBzIcR5XO/ukWo+YHOjBbFwIupg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "dns-packet": "^1.3.1",
+ "dns-packet": "^5.2.2",
"thunky": "^1.0.2"
},
"bin": {
"multicast-dns": "cli.js"
}
},
- "node_modules/multicast-dns-service-types": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/multicast-dns-service-types/-/multicast-dns-service-types-1.1.0.tgz",
- "integrity": "sha1-iZ8R2WhuXgXLkbNdXw5jt3PPyQE= sha512-cnAsSVxIDsYt0v7HmC0hWZFwwXSh+E6PgCrREDuN/EsjgLwA5XRmlMHhSiDPrt6HxY1gTivEa/Zh7GtODoLevQ==",
- "dev": true
- },
"node_modules/mumath": {
"version": "3.3.4",
"resolved": "https://registry.npmjs.org/mumath/-/mumath-3.3.4.tgz",
"integrity": "sha512-VAFIOG6rsxoc7q/IaY3jdjmrsuX9f15KlRLYTHmixASBZkZEKC1IFqE2BC5CdhXmK6WLM1Re33z//AGmeRI6FA==",
"deprecated": "Redundant dependency in your project.",
+ "license": "Unlicense",
"dependencies": {
"almost-equal": "^1.1.0"
}
@@ -11334,41 +10121,30 @@
"node_modules/murmurhash-js": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/murmurhash-js/-/murmurhash-js-1.0.0.tgz",
- "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw=="
- },
- "node_modules/mute-stream": {
- "version": "0.0.8",
- "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.8.tgz",
- "integrity": "sha512-nnbWWOkoWyUsTjKrhgD0dcz22mdkSnpYqbEjIm2nhwhuxlSkpywJmBo8h0ZqJdkp73mb90SssHkN4rsRaBAfAA==",
- "dev": true
+ "integrity": "sha512-TvmkNhkv8yct0SVBSy+o8wYzXjE4Zz3PCesbfs8HiCXXdcTuocApFv11UWlNFWKYsP2okqrhb7JNlSm9InBhIw==",
+ "license": "MIT"
},
"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,
+ "license": "MIT",
"dependencies": {
"any-promise": "^1.0.0",
"object-assign": "^4.0.1",
"thenify-all": "^1.0.0"
}
},
- "node_modules/nan": {
- "version": "2.15.0",
- "resolved": "https://registry.npmjs.org/nan/-/nan-2.15.0.tgz",
- "integrity": "sha512-8ZtvEnA2c5aYCZYd1cvgdnU6cqwixRoYg70xPLWUws5ORTa/lnw+u4amixRS/Ac5U5mQVgp9pnlSUnbNWFaWZQ==",
- "dev": true,
- "optional": true
- },
"node_modules/nanoclone": {
"version": "0.2.1",
"resolved": "https://registry.npmjs.org/nanoclone/-/nanoclone-0.2.1.tgz",
- "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA=="
+ "integrity": "sha512-wynEP02LmIbLpcYw8uBKpcfF6dmg2vcpKqxeH5UcoKEYdExslsdUA4ugFauuaeYdTB76ez6gJW8XAZ6CgkXYxA==",
+ "license": "MIT"
},
"node_modules/nanoid": {
- "version": "3.3.9",
- "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.9.tgz",
- "integrity": "sha512-SppoicMGpZvbF1l3z4x7No3OlIjP7QJvC9XR7AhZr1kL133KHnKPztkKDc+Ir4aJ/1VhTySrtKhrsycmrMQfvg==",
+ "version": "3.3.12",
+ "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.12.tgz",
+ "integrity": "sha512-ZB9RH/39qpq5Vu6Y+NmUaFhQR6pp+M2Xt76XBnEwDaGcVAqhlvxrl3B2bKS5D3NH3QR76v3aSrKaF/Kiy7lEtQ==",
"funding": [
{
"type": "github",
@@ -11383,43 +10159,24 @@
"node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1"
}
},
- "node_modules/nanomatch": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/nanomatch/-/nanomatch-1.2.13.tgz",
- "integrity": "sha512-fpoe2T0RbHwBTBUOftAfBPaDEi06ufaUai0mE6Yn1kacc3SnTErfb/h+X94VXzI64rKFHYImXSvdwGGCmwOqCA==",
- "dev": true,
- "dependencies": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "fragment-cache": "^0.2.1",
- "is-windows": "^1.0.2",
- "kind-of": "^6.0.2",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/native-promise-only": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/native-promise-only/-/native-promise-only-0.8.1.tgz",
- "integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg=="
+ "integrity": "sha512-zkVhZUA3y8mbz652WrL5x0fB0ehrBkulWT3TomAQ9iDtyXZvzKeEA6GPxAItBYeNYl5yngKRX612qHOhvMkDeg==",
+ "license": "MIT"
},
"node_modules/natural-compare": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz",
- "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc= sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
- "dev": true
+ "integrity": "sha512-OWND8ei3VtNC9h7V60qff3SVobHr996CTwgxubgyQYEpg290h9J0buyECNNJexkFm5sOajh5G116RYA1c8ZMSw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/needle": {
"version": "2.9.1",
"resolved": "https://registry.npmjs.org/needle/-/needle-2.9.1.tgz",
"integrity": "sha512-6R9fqJ5Zcmf+uYaFgdIHmLwNldn5HbK8L5ybn7Uz+ylX/rnOsSp1AHcvQSrCaFN+qNM1wpymHqD7mVasEOlHGQ==",
+ "license": "MIT",
"dependencies": {
"debug": "^3.2.6",
"iconv-lite": "^0.4.4",
@@ -11436,15 +10193,17 @@
"version": "3.2.7",
"resolved": "https://registry.npmjs.org/debug/-/debug-3.2.7.tgz",
"integrity": "sha512-CFjzYYAi4ThfiQvizrFQevTTXHtnCqWfe7x1AhgEscTz6ZbLbfoLRLPugTQyBth6f8ZERVUSyWHFD/7Wu4t1XQ==",
+ "license": "MIT",
"dependencies": {
"ms": "^2.1.1"
}
},
"node_modules/negotiator": {
- "version": "0.6.2",
- "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.2.tgz",
- "integrity": "sha512-hZXc7K2e+PgeI1eDBe/10Ard4ekbfrrqG8Ep+8Jmf4JID2bNg7NvCPOZN+kfF574pFQI7mum2AUqDidoKqcTOw==",
+ "version": "0.6.4",
+ "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.4.tgz",
+ "integrity": "sha512-myRT3DiWPHqho5PrJaIRyaMv2kgYf0mUVgBNOYMuCH5Ki1yEiQaf/ZJuQ62nvpc44wL5WDbTX7yGJi1Neevw8w==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
@@ -11453,108 +10212,68 @@
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
"integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==",
- "dev": true
+ "license": "MIT"
},
"node_modules/next-tick": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.1.0.tgz",
- "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ=="
- },
- "node_modules/nice-try": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz",
- "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==",
- "dev": true
+ "integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
+ "license": "ISC"
},
"node_modules/no-case": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/no-case/-/no-case-2.3.2.tgz",
- "integrity": "sha512-rmTZ9kz+f3rCvK2TD1Ue/oZlns7OGoIWP4fc3llxxRXlOkHKoWPPWJOfFYpITabSow43QJbRIoHQXtt10VldyQ==",
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz",
+ "integrity": "sha512-fgAN3jGAh+RoxUGZHTSOLJIqUc2wmoBwGR4tbpNAKmmovFoWq0OdRkb0VkldReO2a2iBT/OEulG9XSUc10r3zg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "lower-case": "^1.1.1"
+ "lower-case": "^2.0.2",
+ "tslib": "^2.0.3"
}
},
- "node_modules/node-emoji": {
- "version": "1.11.0",
- "resolved": "https://registry.npmjs.org/node-emoji/-/node-emoji-1.11.0.tgz",
- "integrity": "sha512-wo2DpQkQp7Sjm2A0cq+sN7EHKO6Sl0ctXeBdFZrL9T9+UywORbufTcTZxom8YqpLQt/FqNMUkOpkZrJVYSKD3A==",
+ "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,
+ "license": "MIT",
"dependencies": {
- "lodash": "^4.17.21"
- }
- },
- "node_modules/node-forge": {
- "version": "0.10.0",
- "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-0.10.0.tgz",
- "integrity": "sha512-PPmu8eEeG9saEUvI97fm4OYxXVB6bFvyNTyiUOBichBpFG8A1Ljw3bY62+5oOjDEMHRnd0Y7HQ+x7uzxOzC6JA==",
- "dev": true,
+ "whatwg-url": "^5.0.0"
+ },
"engines": {
- "node": ">= 6.0.0"
+ "node": "4.x || >=6.0.0"
+ },
+ "peerDependencies": {
+ "encoding": "^0.1.0"
+ },
+ "peerDependenciesMeta": {
+ "encoding": {
+ "optional": true
+ }
}
},
- "node_modules/node-ipc": {
- "version": "9.2.1",
- "resolved": "https://registry.npmjs.org/node-ipc/-/node-ipc-9.2.1.tgz",
- "integrity": "sha512-mJzaM6O3xHf9VT8BULvJSbdVbmHUKRNOH7zDDkCrA1/T+CVjq2WVIDfLt0azZRXpgArJtl3rtmEozrbXPZ9GaQ==",
+ "node_modules/node-forge": {
+ "version": "1.4.0",
+ "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz",
+ "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==",
"dev": true,
- "dependencies": {
- "event-pubsub": "4.3.0",
- "js-message": "1.0.7",
- "js-queue": "2.0.2"
- },
+ "license": "(BSD-3-Clause OR GPL-2.0)",
"engines": {
- "node": ">=8.0.0"
+ "node": ">= 6.13.0"
}
},
- "node_modules/node-libs-browser": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/node-libs-browser/-/node-libs-browser-2.2.1.tgz",
- "integrity": "sha512-h/zcD8H9kaDZ9ALUWwlBUDo6TKF8a7qBSCSEGfjTVIYeqsioSKaAX+BN7NgiMGp6iSIXZ3PxgCu8KS3b71YK5Q==",
- "dev": true,
- "dependencies": {
- "assert": "^1.1.1",
- "browserify-zlib": "^0.2.0",
- "buffer": "^4.3.0",
- "console-browserify": "^1.1.0",
- "constants-browserify": "^1.0.0",
- "crypto-browserify": "^3.11.0",
- "domain-browser": "^1.1.1",
- "events": "^3.0.0",
- "https-browserify": "^1.0.0",
- "os-browserify": "^0.3.0",
- "path-browserify": "0.0.1",
- "process": "^0.11.10",
- "punycode": "^1.2.4",
- "querystring-es3": "^0.2.0",
- "readable-stream": "^2.3.3",
- "stream-browserify": "^2.0.1",
- "stream-http": "^2.7.2",
- "string_decoder": "^1.0.0",
- "timers-browserify": "^2.0.4",
- "tty-browserify": "0.0.0",
- "url": "^0.11.0",
- "util": "^0.11.0",
- "vm-browserify": "^1.0.1"
- }
- },
- "node_modules/node-libs-browser/node_modules/punycode": {
- "version": "1.4.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz",
- "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4= sha512-jmYNElW7yvO7TV33CjSmvSiE2yco3bV2czu/OzDKdMNVZQWfxCblURLhf+47syQRBntjfLdd/H0egrzIG+oaFQ==",
- "dev": true
- },
"node_modules/node-releases": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.1.tgz",
- "integrity": "sha512-CqyzN6z7Q6aMeF/ktcMVTzhAHCEpf8SOarwpzpf8pNBY2k5/oM34UHldUwp8VKI7uxct2HxSRdJjBaZeESzcxA==",
- "dev": true
+ "version": "2.0.38",
+ "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.38.tgz",
+ "integrity": "sha512-3qT/88Y3FbH/Kx4szpQQ4HzUbVrHPKTLVpVocKiLfoYvw9XSGOX2FmD2d6DrXbVYyAQTF2HeF6My8jmzx7/CRw==",
+ "license": "MIT"
},
"node_modules/normalize-package-data": {
"version": "2.5.0",
"resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.5.0.tgz",
"integrity": "sha512-/5CMN3T0R4XTj4DcGaexo+roZSdSFW/0AOOTROrjxzCG1wrWXEsGbRKevjlIL+ZDE4sZlJr5ED4YW0yqmkK+eA==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"hosted-git-info": "^2.1.4",
"resolve": "^1.10.0",
@@ -11562,29 +10281,11 @@
"validate-npm-package-license": "^3.0.1"
}
},
- "node_modules/normalize-package-data/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true,
- "bin": {
- "semver": "bin/semver"
- }
- },
"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": "sha1-LRDAa9/TEuqXd2laTShDlFa3WUI= sha512-bdok/XvKII3nUpklnV6P2hxtMNrCboOjAcyBuQnWEhO665FwrSNRxU+AqpsyvO6LgGYPspN+lu5CLtw4jPRKNA==",
- "dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -11592,33 +10293,34 @@
"node_modules/normalize-svg-path": {
"version": "0.1.0",
"resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-0.1.0.tgz",
- "integrity": "sha512-1/kmYej2iedi5+ROxkRESL/pI02pkg0OBnaR4hJkSIX6+ORzepwbuUXfrdZaPjysTsJInj0Rj5NuX027+dMBvA=="
+ "integrity": "sha512-1/kmYej2iedi5+ROxkRESL/pI02pkg0OBnaR4hJkSIX6+ORzepwbuUXfrdZaPjysTsJInj0Rj5NuX027+dMBvA==",
+ "license": "MIT"
},
"node_modules/normalize-url": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-1.9.1.tgz",
- "integrity": "sha1-LMDWazHqIwNkWENuNiDYWVTGbDw= sha512-A48My/mtCklowHBlI8Fq2jFWK4tX4lJ5E6ytFsSOq1fzpvT0SQSgKhSg7lN5c2uYFOrUAOQp6zhhJnpp1eMloQ==",
+ "version": "6.1.0",
+ "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz",
+ "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==",
"dev": true,
- "dependencies": {
- "object-assign": "^4.0.1",
- "prepend-http": "^1.0.0",
- "query-string": "^4.1.0",
- "sort-keys": "^1.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/nouislider": {
- "version": "15.6.0",
- "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-15.6.0.tgz",
- "integrity": "sha512-YJg+A6RQXTuFqhEwd42FeRaEGMGgDSSNnpIyVtT8XJrNl4VBEUkPI6Yj91bT3JjJIvNYi4VdppWeCV+z2gOnnw=="
+ "version": "15.8.1",
+ "resolved": "https://registry.npmjs.org/nouislider/-/nouislider-15.8.1.tgz",
+ "integrity": "sha512-93TweAi8kqntHJSPiSWQ1o/uZ29VWOmal9YKb6KKGGlCkugaNfAupT7o1qTHqdJvNQ7S0su5rO6qRFCjP8fxtw==",
+ "license": "MIT"
},
"node_modules/npm-run-path": {
"version": "2.0.2",
"resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz",
- "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8= sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
+ "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"path-key": "^2.0.0"
},
@@ -11626,11 +10328,22 @@
"node": ">=4"
}
},
- "node_modules/nth-check": {
+ "node_modules/npm-run-path/node_modules/path-key": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.0.1.tgz",
- "integrity": "sha512-it1vE95zF6dTT9lBsYbxvqh0Soy4SPowchj0UBGj/V6cTPnXXtQOPUbhZ6CmGzAD/rW22LQK6E96pcdJXk4A4w==",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
+ "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">=4"
+ }
+ },
+ "node_modules/nth-check": {
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz",
+ "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
"boolbase": "^1.0.0"
},
@@ -11638,16 +10351,11 @@
"url": "https://github.com/fb55/nth-check?sponsor=1"
}
},
- "node_modules/num2fraction": {
- "version": "1.2.2",
- "resolved": "https://registry.npmjs.org/num2fraction/-/num2fraction-1.2.2.tgz",
- "integrity": "sha1-b2gragJ6Tp3fpFZM0lidHU5mnt4= sha512-Y1wZESM7VUThYY+4W+X4ySH2maqcA+p7UR+w8VWNWVAd6lwuXXWz/w/Cz43J/dI2I+PS6wD5N+bJUF+gjWvIqg==",
- "dev": true
- },
"node_modules/number-is-integer": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/number-is-integer/-/number-is-integer-1.0.1.tgz",
"integrity": "sha512-Dq3iuiFBkrbmuQjGFFF3zckXNCQoSD37/SdSbgcBailUx6knDvDwb5CympBgcoWHy36sfS12u74MHYkXyHq6bg==",
+ "license": "MIT",
"dependencies": {
"is-finite": "^1.0.1"
},
@@ -11655,137 +10363,30 @@
"node": ">=0.10.0"
}
},
- "node_modules/oauth-sign": {
- "version": "0.9.0",
- "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz",
- "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
"node_modules/object-assign": {
"version": "4.1.1",
"resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz",
- "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM= sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-copy": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/object-copy/-/object-copy-0.1.0.tgz",
- "integrity": "sha1-fn2Fi3gb18mRpBupde04EnVOmYw= sha512-79LYn6VAb63zgtmAteVOWo9Vdj71ZVBy3Pbse+VqxDpEP83XuujMrGqHIwAXJ5I/aM0zU7dIyIAhifVTPrNItQ==",
- "dev": true,
- "dependencies": {
- "copy-descriptor": "^0.1.0",
- "define-property": "^0.2.5",
- "kind-of": "^3.0.3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-copy/node_modules/define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
- "dev": true,
- "dependencies": {
- "is-descriptor": "^0.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-copy/node_modules/is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==",
- "deprecated": "Please upgrade to v0.1.7",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-copy/node_modules/is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==",
- "deprecated": "Please upgrade to v0.1.5",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-copy/node_modules/is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "dev": true,
- "dependencies": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-copy/node_modules/is-descriptor/node_modules/kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object-copy/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
+ "integrity": "sha512-rJgTQnkUnH1sFw8yT6VSU3zD3sWmu6sZhIseY8VX+GRu3P6F7Fu+JNDoXfklElbLJSnc3FUQHVe4cU5hj+BcUg==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
"node_modules/object-hash": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
- "integrity": "sha512-gScRMn0bS5fH+IuwyIFgnh9zBdo4DV+6GhygmWM9HyNJSgS0hScp1f5vjtm7oIIOiT9trXrShAkLFSc2IqKNgw==",
- "dev": true,
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/object-hash/-/object-hash-3.0.0.tgz",
+ "integrity": "sha512-RSn9F68PjH9HqtltsSnqYC1XXoWe9Bju5+213R98cNGttag9q9yAOTzdbsqvIa7aNm5WffBZFpWYr2aWrklWAw==",
+ "license": "MIT",
"engines": {
"node": ">= 6"
}
},
"node_modules/object-inspect": {
- "version": "1.11.1",
- "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.11.1.tgz",
- "integrity": "sha512-If7BjFlpkzzBeV1cqgT3OSWT3azyoxDGajR+iGnFBfVV2EWyDyWaZZW2ERDjUaY2QM8i5jI3Sj7mhsM4DDAqWA==",
- "dev": true,
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object-is": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/object-is/-/object-is-1.1.5.tgz",
- "integrity": "sha512-3cyDsyHgtmi7I7DfSSI2LDp6SK2lwvtbg0p0R1e0RvTqF5ceGx+K2dfSjm1bKDMVCFEDAQvy+o8c6a7VujOddw==",
+ "version": "1.13.4",
+ "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz",
+ "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==",
"dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- },
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
},
@@ -11798,31 +10399,23 @@
"resolved": "https://registry.npmjs.org/object-keys/-/object-keys-1.1.1.tgz",
"integrity": "sha512-NuAESUOUMrlIXOfHKzD6bpPu3tYt3xvjNdRIQ+FeT0lNb4K8WR70CaDxhuNguS2XG+GjkyMwOzsN5ZktImfhLA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.4"
}
},
- "node_modules/object-visit": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/object-visit/-/object-visit-1.0.1.tgz",
- "integrity": "sha1-95xEk68MU3e1n+OdOV5BBC3QRbs= sha512-GBaMwwAVK9qbQN3Scdo0OyvgPW7l3lnaVMj84uTOZlswkX0KpF6fyDBJhtTthf7pymztoN36/KEr1DyhF96zEA==",
- "dev": true,
- "dependencies": {
- "isobject": "^3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/object.assign": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.2.tgz",
- "integrity": "sha512-ixT2L5THXsApyiUPYKmW+2EHpXXe5Ii3M+f4e+aJFAHao5amFRW6J0OO6c/LU8Be47utCx2GL89hxGB6XSmKuQ==",
+ "version": "4.1.7",
+ "resolved": "https://registry.npmjs.org/object.assign/-/object.assign-4.1.7.tgz",
+ "integrity": "sha512-nK28WOo+QIjBkDduTINE4JkF/UJJKyf2EJxvJKfblDpyg0Q+pkOHNTL0Qwy6NP6FhE/EnzV73BxxqcJaXY9anw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.0",
- "define-properties": "^1.1.3",
- "has-symbols": "^1.0.1",
+ "call-bind": "^1.0.8",
+ "call-bound": "^1.0.3",
+ "define-properties": "^1.2.1",
+ "es-object-atoms": "^1.0.0",
+ "has-symbols": "^1.1.0",
"object-keys": "^1.1.1"
},
"engines": {
@@ -11832,63 +10425,19 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/object.getownpropertydescriptors": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/object.getownpropertydescriptors/-/object.getownpropertydescriptors-2.1.3.tgz",
- "integrity": "sha512-VdDoCwvJI4QdC6ndjpqFmoL3/+HxffFBbcJzKi5hwLLqqx3mdbedRpfZDdK0SrOSauj8X4GzBvnDZl4vTN7dOw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.19.1"
- },
- "engines": {
- "node": ">= 0.8"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/object.pick": {
- "version": "1.3.0",
- "resolved": "https://registry.npmjs.org/object.pick/-/object.pick-1.3.0.tgz",
- "integrity": "sha1-h6EKxMFpS9Lhy/U1kaZhQftd10c= sha512-tqa/UMy/CCoYmj+H5qc07qvSL9dqcs/WZENZ1JbtWBlATP+iVOe778gE6MSijnyCnORzDuX6hU+LA4SZ09YjFQ==",
- "dev": true,
- "dependencies": {
- "isobject": "^3.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/object.values": {
- "version": "1.1.5",
- "resolved": "https://registry.npmjs.org/object.values/-/object.values-1.1.5.tgz",
- "integrity": "sha512-QUZRW0ilQ3PnPpbNtgdNV1PDbEqLIiSFB3l+EnGtBQ/8SUTLj1PZwtQHABZtLgwpJZTSZhuGLOGk57Drx2IvYg==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3",
- "es-abstract": "^1.19.1"
- },
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/obuf": {
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz",
"integrity": "sha512-PX1wu0AmAdPqOL1mWhqmlOd8kOIZQwGZw6rh7uby9fTc5lhaOWFLX3I6R1hrF9k3zUY40e6igsLGkDXK92LJNg==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/on-finished": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz",
- "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc= sha512-ikqdkGAAyf/X/gPhXGvfgAytDZtDbr+bkNUJ0N9h5MI/dmdgCs3l6hoHrcUv41sRKew3jIwrp4qQDXiK99Utww==",
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz",
+ "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ee-first": "1.1.1"
},
@@ -11897,10 +10446,11 @@
}
},
"node_modules/on-headers": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.2.tgz",
- "integrity": "sha512-pZAE+FJLoyITytdqK0U5s+FIpjN0JP3OzFi/u8Rx+EV5/W+JTWGXG8xFzevE7AjBfDqHv/8vL8qQsIhHnqRkrA==",
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.1.0.tgz",
+ "integrity": "sha512-737ZY3yNnXy37FHkQxPzt4UZ2UWPWiCZWLvFZ4fu5cueciegX0zGPnrlY6bwRg4FdQOe9YU8MkmJwGhoMybl8A==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
@@ -11908,7 +10458,8 @@
"node_modules/once": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz",
- "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E= sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==",
+ "license": "ISC",
"dependencies": {
"wrappy": "1"
}
@@ -11918,6 +10469,7 @@
"resolved": "https://registry.npmjs.org/onetime/-/onetime-5.1.2.tgz",
"integrity": "sha512-kbpaSSGJTWdAY5KPVeMOKXSrPtr8C8C7wodJbcsd51jRnmD+GZu8Y0VoU6Dm5Z4vWr0Ig/1NKuWRKf7j5aaYSg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"mimic-fn": "^2.1.0"
},
@@ -11929,24 +10481,21 @@
}
},
"node_modules/open": {
- "version": "6.4.0",
- "resolved": "https://registry.npmjs.org/open/-/open-6.4.0.tgz",
- "integrity": "sha512-IFenVPgF70fSm1keSd2iDBIDIBZkroLeuffXq+wKTzTJlBpesFWojV9lb8mzOfaAzM1sr7HQHuO0vtV0zYekGg==",
+ "version": "8.4.2",
+ "resolved": "https://registry.npmjs.org/open/-/open-8.4.2.tgz",
+ "integrity": "sha512-7x81NCL719oNbsq/3mh+hVrAWmFuEYUqrq/Iw3kUzH8ReypT9QQ0BLoJS7/G9k6N81XjW4qHWtjWwe/9eLy1EQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-wsl": "^1.1.0"
+ "define-lazy-prop": "^2.0.0",
+ "is-docker": "^2.1.1",
+ "is-wsl": "^2.2.0"
},
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/open/node_modules/is-wsl": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
- "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
- "dev": true,
- "engines": {
- "node": ">=4"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/opener": {
@@ -11954,263 +10503,124 @@
"resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz",
"integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==",
"dev": true,
+ "license": "(WTFPL OR MIT)",
"bin": {
"opener": "bin/opener-bin.js"
}
},
- "node_modules/opn": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/opn/-/opn-5.5.0.tgz",
- "integrity": "sha512-PqHpggC9bLV0VeWcdKhkpxY+3JTzetLSqTCWL/z/tFIbI6G8JCjondXklT1JinczLz2Xib62sSp0T/gKT4KksA==",
+ "node_modules/optionator": {
+ "version": "0.9.4",
+ "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.9.4.tgz",
+ "integrity": "sha512-6IpQ7mKUxRcZNLIObR0hz7lxsapSSIYNZJwXPGeF0mTVqGKFIXj1DQcMoT22S3ROcLyY/rz0PWaWZ9ayWmad9g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-wsl": "^1.1.0"
+ "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": ">=4"
+ "node": ">= 0.8.0"
}
},
- "node_modules/opn/node_modules/is-wsl": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
- "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/optionator": {
- "version": "0.8.3",
- "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.3.tgz",
- "integrity": "sha512-+IW9pACdk3XWmmTXG8m3upGUJst5XRGzxMRjXzAuJ1XnIFNvfhjjIuYkDvysnPQ7qzqVzLt78BCruntqRhWQbA==",
- "dependencies": {
- "deep-is": "~0.1.3",
- "fast-levenshtein": "~2.0.6",
- "levn": "~0.3.0",
- "prelude-ls": "~1.1.2",
- "type-check": "~0.3.2",
- "word-wrap": "~1.2.3"
- },
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/ora": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/ora/-/ora-3.4.0.tgz",
- "integrity": "sha512-eNwHudNbO1folBP3JsZ19v9azXWtQZjICdr3Q0TDPIaeBQ3mXLrh54wM+er0+hSp+dWKf+Z8KM58CYzEyIYxYg==",
+ "node_modules/ora": {
+ "version": "5.4.1",
+ "resolved": "https://registry.npmjs.org/ora/-/ora-5.4.1.tgz",
+ "integrity": "sha512-5b6Y85tPxZZ7QytO+BQzysW31HJku27cRIlkbAXaNx+BdcVi+LlRFmVXzeF6a7JCwJpyw5c4b+YSVImQIrBpuQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "chalk": "^2.4.2",
- "cli-cursor": "^2.1.0",
- "cli-spinners": "^2.0.0",
- "log-symbols": "^2.2.0",
- "strip-ansi": "^5.2.0",
+ "bl": "^4.1.0",
+ "chalk": "^4.1.0",
+ "cli-cursor": "^3.1.0",
+ "cli-spinners": "^2.5.0",
+ "is-interactive": "^1.0.0",
+ "is-unicode-supported": "^0.1.0",
+ "log-symbols": "^4.1.0",
+ "strip-ansi": "^6.0.0",
"wcwidth": "^1.0.1"
},
"engines": {
- "node": ">=6"
- }
- },
- "node_modules/ora/node_modules/ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/ora/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
+ "node": ">=10"
},
- "engines": {
- "node": ">=4"
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/ora/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ora/node_modules/cli-cursor": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz",
- "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU= sha512-8lgKz8LmCRYZZQDpRyT2m5rKJ08TnU4tR9FFFW2rxpxR1FzWi4PQ/NfyODchAatHaUgnSPVcx/R5w6NuTBzFiw==",
- "dev": true,
- "dependencies": {
- "restore-cursor": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ora/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/ora/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/ora/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ora/node_modules/mimic-fn": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz",
- "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ora/node_modules/onetime": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz",
- "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ= sha512-oyyPpiMaKARvvcgip+JV+7zci5L8D1W9RZIz2l1o08AM3pfspitVWnPt3mzHcBPp12oYMTy0pqrFs/C+m3EwsQ==",
- "dev": true,
- "dependencies": {
- "mimic-fn": "^1.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ora/node_modules/restore-cursor": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz",
- "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368= sha512-6IzJLuGi4+R14vwagDHX+JrXmPVtPpn4mffDJ1UdR7/Edm87fl6yi8mMBIVvFtJaNTUvjughmW4hwLhRG7gC1Q==",
- "dev": true,
- "dependencies": {
- "onetime": "^2.0.0",
- "signal-exit": "^3.0.2"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/ora/node_modules/strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-regex": "^4.1.0"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=6"
- }
- },
- "node_modules/ora/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
+ "node": ">=10"
},
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/os-browserify": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/os-browserify/-/os-browserify-0.3.0.tgz",
- "integrity": "sha1-hUNzx/XCMVkU/Jv8a9gjj92h7Cc= sha512-gjcpUc3clBf9+210TRaDWbf+rZZZEshZ+DlXMRCeAjp0xhTrnQsKHypIy1J3d5hKdUzj69t708EHtU8P6bUn0A==",
- "dev": true
- },
- "node_modules/os-tmpdir": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz",
- "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ= sha512-D2FR03Vir7FIu45XBY20mTb+/ZSWB00sjU9jdQXt83gDrI4Ztz5Fs7/yy74g2N5SVQY4xY1qDr4rNddwYRVX0g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
"node_modules/p-finally": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz",
- "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4= sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
+ "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
},
"node_modules/p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-3.1.0.tgz",
+ "integrity": "sha512-TYOanM3wGwNGsZN2cVTYPArw454xnXj5qmWF1bEoAc4+cU/ol7GVh7odevjp1FNHduHc3KZMcFduxU5Xc6uJRQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "p-try": "^2.0.0"
+ "yocto-queue": "^0.1.0"
},
"engines": {
- "node": ">=6"
+ "node": ">=10"
},
"funding": {
"url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-5.0.0.tgz",
+ "integrity": "sha512-LaNjtRWUBY++zB5nE/NwcaoMylSPk+S+ZHNB1TzdbMJMny6dynpAGt7X/tl/QYq3TIeE6nxHppbo2LGymrG5Pw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "p-limit": "^2.2.0"
+ "p-limit": "^3.0.2"
},
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/p-map": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/p-map/-/p-map-2.1.0.tgz",
- "integrity": "sha512-y3b8Kpd8OAN444hxfBbFfj1FY/RjtTd8tzYwhUqNYXx0fXx2iX4maP4Qr6qhIKbQXI02wTLAda4fYUbDagTUFw==",
- "dev": true,
- "engines": {
- "node": ">=6"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/p-retry": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-3.0.1.tgz",
- "integrity": "sha512-XE6G4+YTTkT2a0UWb2kjZe8xNwf8bIbnqpc/IS/idOBVhyves0mK5OJgeocjx7q5pvX/6m23xuzVPYT1uGM73w==",
+ "version": "4.6.2",
+ "resolved": "https://registry.npmjs.org/p-retry/-/p-retry-4.6.2.tgz",
+ "integrity": "sha512-312Id396EbJdvRONlngUx0NydfrIQ5lsYu0znKVUzVvArzEIt08V1qhtyESbGVd1FGX7UKtiFp5uwKZdM8wIuQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "retry": "^0.12.0"
+ "@types/retry": "0.12.0",
+ "retry": "^0.13.1"
},
"engines": {
- "node": ">=6"
+ "node": ">=8"
}
},
"node_modules/p-try": {
@@ -12218,34 +10628,20 @@
"resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
"integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
},
- "node_modules/pako": {
- "version": "1.0.11",
- "resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
- "integrity": "sha512-4hLB8Py4zZce5s4yd9XzopqwVv/yGNhV1Bl8NTmCq1763HeK2+EwVTv+leGeL13Dnh2wfbqowVPXCIO0z4taYw==",
- "dev": true
- },
- "node_modules/parallel-transform": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/parallel-transform/-/parallel-transform-1.2.0.tgz",
- "integrity": "sha512-P2vSmIu38uIlvdcU7fDkyrxj33gTUy/ABO5ZUbGowxNCopBq/OoD42bP4UmMrJoPyk4Uqf0mu3mtWBhHCZD8yg==",
- "dev": true,
- "dependencies": {
- "cyclist": "^1.0.1",
- "inherits": "^2.0.3",
- "readable-stream": "^2.1.5"
- }
- },
"node_modules/param-case": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/param-case/-/param-case-2.1.1.tgz",
- "integrity": "sha1-35T9jPZTHs915r75oIWPvHK+Ikc= sha512-eQE845L6ot89sk2N8liD8HAuH4ca6Vvr7VWAWwt7+kvvG5aBcPmmphQ68JsEG2qa9n1TykS2DLeMt363AAH8/w==",
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/param-case/-/param-case-3.0.4.tgz",
+ "integrity": "sha512-RXlj7zCYokReqWpOPH9oYivUzLYZ5vAPIfEmCTNViosC78F8F0H9y7T7gG2M39ymgutxF5gcFEsyZQSph9Bp3A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "no-case": "^2.2.0"
+ "dot-case": "^3.0.4",
+ "tslib": "^2.0.3"
}
},
"node_modules/parent-module": {
@@ -12253,6 +10649,7 @@
"resolved": "https://registry.npmjs.org/parent-module/-/parent-module-1.0.1.tgz",
"integrity": "sha512-GQ2EWRpQV8/o+Aw8YqtfZZPfNRWZYkbidE9k5rpl/hC3vtHHBfGm2Ifi6qWV+coDGkrUKZAxE3Lot5kcsRlh+g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"callsites": "^3.0.0"
},
@@ -12263,50 +10660,15 @@
"node_modules/parenthesis": {
"version": "3.1.8",
"resolved": "https://registry.npmjs.org/parenthesis/-/parenthesis-3.1.8.tgz",
- "integrity": "sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw=="
- },
- "node_modules/parse-asn1": {
- "version": "5.1.7",
- "resolved": "https://registry.npmjs.org/parse-asn1/-/parse-asn1-5.1.7.tgz",
- "integrity": "sha512-CTM5kuWR3sx9IFamcl5ErfPl6ea/N8IYwiJ+vpeB2g+1iknv7zBl5uPwbMbRVznRVbrNY6lGuDoE5b30grmbqg==",
- "dev": true,
- "dependencies": {
- "asn1.js": "^4.10.1",
- "browserify-aes": "^1.2.0",
- "evp_bytestokey": "^1.0.3",
- "hash-base": "~3.0",
- "pbkdf2": "^3.1.2",
- "safe-buffer": "^5.2.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/parse-asn1/node_modules/safe-buffer": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
- "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
- "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"
- }
- ]
+ "integrity": "sha512-KF/U8tk54BgQewkJPvB4s/US3VQY68BRDpH638+7O/n58TpnwiwnOtGIOsT2/i+M78s61BBpeC83STB88d8sqw==",
+ "license": "MIT"
},
"node_modules/parse-json": {
"version": "5.2.0",
"resolved": "https://registry.npmjs.org/parse-json/-/parse-json-5.2.0.tgz",
"integrity": "sha512-ayCKvm/phCGxOkYRSCM82iDwct8/EonSEgCSxWxD7ve6jHggsFl4fZVQBPRNgQoKiuV/odhFrGzQXZwbifC8Rg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@babel/code-frame": "^7.0.0",
"error-ex": "^1.3.1",
@@ -12324,6 +10686,7 @@
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/parse-rect/-/parse-rect-1.2.0.tgz",
"integrity": "sha512-4QZ6KYbnE6RTwg9E0HpLchUM9EZt6DnDxajFZZDSV4p/12ZJEvPO702DZpGvRYEPo00yKDys7jASi+/w7aO8LA==",
+ "license": "MIT",
"dependencies": {
"pick-by-alias": "^1.2.0"
}
@@ -12331,24 +10694,28 @@
"node_modules/parse-svg-path": {
"version": "0.1.2",
"resolved": "https://registry.npmjs.org/parse-svg-path/-/parse-svg-path-0.1.2.tgz",
- "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ=="
+ "integrity": "sha512-JyPSBnkTJ0AI8GGJLfMXvKq42cj5c006fnLz6fXy6zfoVjJizi8BNTpu8on8ziI1cKy9d9DGNuY17Ce7wuejpQ==",
+ "license": "MIT"
},
"node_modules/parse-unit": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/parse-unit/-/parse-unit-1.0.1.tgz",
- "integrity": "sha512-hrqldJHokR3Qj88EIlV/kAyAi/G5R2+R56TBANxNMy0uPlYcttx0jnMW6Yx5KsKPSbC3KddM/7qQm3+0wEXKxg=="
+ "integrity": "sha512-hrqldJHokR3Qj88EIlV/kAyAi/G5R2+R56TBANxNMy0uPlYcttx0jnMW6Yx5KsKPSbC3KddM/7qQm3+0wEXKxg==",
+ "license": "MIT"
},
"node_modules/parse5": {
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-5.1.1.tgz",
"integrity": "sha512-ugq4DFI0Ptb+WWjAdOK16+u/nHfiIrcE+sh8kZMaM0WllQKLI9rOUq6c2b7cwPkXdzfQESqvoqK6ug7U/Yyzug==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/parse5-htmlparser2-tree-adapter": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5-htmlparser2-tree-adapter/-/parse5-htmlparser2-tree-adapter-6.0.1.tgz",
"integrity": "sha512-qPuWvbLgvDGilKc5BoicRovlT4MtYT6JfJyBOMDsKoiT+GiuP5qyrPCnR9HcPECIJJmZh5jRndyNThnhhb/vlA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"parse5": "^6.0.1"
}
@@ -12357,43 +10724,36 @@
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/parse5/-/parse5-6.0.1.tgz",
"integrity": "sha512-Ofn/CTFzRGTTxwpNEs9PP93gXShHcTq255nzRYSKe8AkVpZY7e1fpmTfOyoIvjP5HG7Z2ZM7VS9PPhQGW2pOpw==",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/parseurl": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz",
"integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.8"
}
},
- "node_modules/pascalcase": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/pascalcase/-/pascalcase-0.1.1.tgz",
- "integrity": "sha1-s2PlXoAGym/iF4TS2yK9FdeRfxQ= sha512-XHXfu/yOQRy9vYOtUDVMN60OEJjW013GoObG1o+xwQTpB9eYJX/BjXMsdW13ZDPruFhYYn0AG22w0xgQMwl3Nw==",
+ "node_modules/pascal-case": {
+ "version": "3.1.2",
+ "resolved": "https://registry.npmjs.org/pascal-case/-/pascal-case-3.1.2.tgz",
+ "integrity": "sha512-uWlGT3YSnK9x3BQJaOdcZwrnV6hPpd8jFH1/ucpiLRPh/2zCVJKS19E4GvYHvaCcACn3foXZ0cLB9Wrx1KGe5g==",
"dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "license": "MIT",
+ "dependencies": {
+ "no-case": "^3.0.4",
+ "tslib": "^2.0.3"
}
},
- "node_modules/path-browserify": {
- "version": "0.0.1",
- "resolved": "https://registry.npmjs.org/path-browserify/-/path-browserify-0.0.1.tgz",
- "integrity": "sha512-BapA40NHICOS+USX9SN4tyhq+A2RrN/Ws5F0Z5aMHDp98Fl86lX8Oti8B7uN93L4Ifv4fHOEA+pQw87gmMO/lQ==",
- "dev": true
- },
- "node_modules/path-dirname": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/path-dirname/-/path-dirname-1.0.2.tgz",
- "integrity": "sha1-zDPSTVJeCZpTiMAzbG4yuRYGCeA= sha512-ALzNPpyNq9AqXMBjeymIjFDAkAFH06mHJH/cSBHAgU0s4vfpBn6b2nf8tiRLvagKD8RbTpq2FKTBg7cl9l3c7Q==",
- "dev": true
- },
"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,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
@@ -12401,51 +10761,51 @@
"node_modules/path-is-absolute": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
- "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18= sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/path-is-inside": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz",
- "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM= sha512-DUWJr3+ULp4zXmol/SZkFf3JGsS9/SIv+Y3Rt93/UjPpDpklB5f1er4O3POIbUuUJ3FXgqte2Q7SrU6zAqwk8w==",
- "dev": true
- },
"node_modules/path-key": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz",
- "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A= sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/path-key/-/path-key-3.1.1.tgz",
+ "integrity": "sha512-ojmeN0qd+y0jszEtoY48r0Peq5dwMEkIlCOu6Q5f41lfkswXuKtYrhgoTpLnyIcHm24Uhqx+5Tqm2InSwLhE6Q==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "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=="
+ "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==",
+ "license": "MIT"
},
"node_modules/path-to-regexp": {
- "version": "0.1.7",
- "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz",
- "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w= sha512-5DFkuoqlv1uYQKxy8omFBeJPQcdoE07Kv2sferDCrAq1ohOU+MSDswDIbnx3YAM60qIOnYa53wBhXW0EbMonrQ==",
- "dev": true
+ "version": "0.1.13",
+ "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.13.tgz",
+ "integrity": "sha512-A/AGNMFN3c8bOlvV9RreMdrv7jsmF9XIfDeCd87+I8RNg6s78BhJxMu69NEMHBSJFxKidViTEdruRwEk/WIKqA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/path-type": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-type/-/path-type-4.0.0.tgz",
"integrity": "sha512-gDKb8aZMDeD/tZWs9P6+q0J9Mwkdl6xMV8TjnGP3qJVJ06bdMgkbBlLU8IdfOsIsFz2BW1rNVT3XuNEl8zPAvw==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
}
},
"node_modules/pbf": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.2.1.tgz",
- "integrity": "sha512-ClrV7pNOn7rtmoQVF4TS1vyU0WhYRnP92fzbfF75jAIwpnzdJXf8iTd4CMEqO4yUenH6NDqLiwjqlh6QgZzgLQ==",
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/pbf/-/pbf-3.3.0.tgz",
+ "integrity": "sha512-XDF38WCH3z5OV/OVa8GKUNtLAyneuzbCisx7QUCF8Q6Nutx0WnJrQe5O+kOtBlLfRNUws98Y58Lblp+NJG5T4Q==",
+ "license": "BSD-3-Clause",
"dependencies": {
"ieee754": "^1.1.12",
"resolve-protobuf-schema": "^2.1.0"
@@ -12454,31 +10814,17 @@
"pbf": "bin/pbf"
}
},
- "node_modules/pbkdf2": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/pbkdf2/-/pbkdf2-3.1.2.tgz",
- "integrity": "sha512-iuh7L6jA7JEGu2WxDwtQP1ddOpaJNC4KlDEFfdQajSGgGPNi4OyDc2R7QnbY2bR9QjBVGwgvTdNJZoE7RaxUMA==",
- "dev": true,
- "dependencies": {
- "create-hash": "^1.1.2",
- "create-hmac": "^1.1.4",
- "ripemd160": "^2.0.1",
- "safe-buffer": "^5.0.1",
- "sha.js": "^2.4.8"
- },
- "engines": {
- "node": ">=0.12"
- }
- },
"node_modules/performance-now": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz",
- "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns= sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow=="
+ "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==",
+ "license": "MIT"
},
"node_modules/pick-by-alias": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/pick-by-alias/-/pick-by-alias-1.2.0.tgz",
- "integrity": "sha512-ESj2+eBxhGrcA1azgHs7lARG5+5iLakc/6nlfbpjcLl00HuuUOIuORhYXN4D1HfvMSKuVtFQjAlnwi1JHEeDIw=="
+ "integrity": "sha512-ESj2+eBxhGrcA1azgHs7lARG5+5iLakc/6nlfbpjcLl00HuuUOIuORhYXN4D1HfvMSKuVtFQjAlnwi1JHEeDIw==",
+ "license": "MIT"
},
"node_modules/picocolors": {
"version": "1.1.1",
@@ -12487,10 +10833,10 @@
"license": "ISC"
},
"node_modules/picomatch": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.0.tgz",
- "integrity": "sha512-lY1Q/PiJGC2zOv/z391WOTD+Z02bCgsFfvxoXXf6h7kv9o+WmsmzYqrAwY63sNgOxE4xEdq0WyUnXfKeBrSvYw==",
- "dev": true,
+ "version": "2.3.2",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz",
+ "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==",
+ "license": "MIT",
"engines": {
"node": ">=8.6"
},
@@ -12499,64 +10845,113 @@
}
},
"node_modules/pify": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/pify/-/pify-4.0.1.tgz",
- "integrity": "sha512-uB80kBFb/tfd68bVleG9T5GGsGPjJrLAUpR5PZIrhBnIaRTQRjqdJSsIKkOP6OAIFbj7GOrcudc5pNjZ+geV2g==",
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz",
+ "integrity": "sha512-udgsAY+fTnvv7kI7aaxbqwWNb0AHiB0qBO89PZKPkoTmGOgdbrHDKD+0B2X4uTfJ/FT1R09r9gTsjUjNJotuog==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
+ "node_modules/pirates": {
+ "version": "4.0.7",
+ "resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.7.tgz",
+ "integrity": "sha512-TfySrs/5nm8fQJDcBDuUng3VOUKsd7S+zqvbOTiGXHfxX4wK31ard+hoNuvkicM/2YFzlpDgABOevKSsB4G/FA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
+ }
+ },
+ "node_modules/pkg-dir": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
+ "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.0.0"
+ },
"engines": {
- "node": ">=6"
+ "node": ">=8"
}
},
- "node_modules/pinkie": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz",
- "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA= sha512-MnUuEycAemtSaeFSjXKW/aroV7akBbY+Sv+RkyqFjgAe73F+MR0TBWKBRDkmfWq/HiFmdavfZ1G7h4SPZXaCSg==",
+ "node_modules/pkg-dir/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
}
},
- "node_modules/pinkie-promise": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz",
- "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o= sha512-0Gni6D4UcLTbv9c57DfxDGdr41XfgUjqWZu492f0cIGr16zDU06BWP/RAEvOuo7CQ0CNjHaLlM59YJJFm3NWlw==",
+ "node_modules/pkg-dir/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "pinkie": "^2.0.0"
+ "p-locate": "^4.1.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
}
},
- "node_modules/pkg-dir": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-4.2.0.tgz",
- "integrity": "sha512-HRDzbaKjC+AOWVXxAU/x54COGeIv9eb+6CkDSQoNTt4XyWoIJvuPsXizxu/Fr23EiekbtZwmh1IcIG/l/a10GQ==",
+ "node_modules/pkg-dir/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "find-up": "^4.0.0"
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
+ }
+ },
+ "node_modules/pkg-dir/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "p-limit": "^2.2.0"
},
"engines": {
"node": ">=8"
}
},
"node_modules/plotly.js": {
- "version": "2.25.2",
- "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-2.25.2.tgz",
- "integrity": "sha512-Pf6dPYGl21W7A3FTgLQ52fpgvrqGhCPDT3+612bxwg4QXlvxhnoFwvuhT1BRW/l2nbYGpRoUH79K54yf2vCMVQ==",
+ "version": "2.35.3",
+ "resolved": "https://registry.npmjs.org/plotly.js/-/plotly.js-2.35.3.tgz",
+ "integrity": "sha512-7RaC6FxmCUhpD6H4MpD+QLUu3hCn76I11rotRefrh3m1iDvWqGnVqVk9dSaKmRAhFD3vsNsYea0OxnR1rc2IzQ==",
+ "license": "MIT",
"dependencies": {
- "@plotly/d3": "3.8.1",
+ "@plotly/d3": "3.8.2",
"@plotly/d3-sankey": "0.7.2",
"@plotly/d3-sankey-circular": "0.33.1",
- "@turf/area": "^6.4.0",
- "@turf/bbox": "^6.4.0",
- "@turf/centroid": "^6.0.2",
+ "@plotly/mapbox-gl": "1.13.4",
+ "@turf/area": "^7.1.0",
+ "@turf/bbox": "^7.1.0",
+ "@turf/centroid": "^7.1.0",
+ "base64-arraybuffer": "^1.0.2",
"canvas-fit": "^1.5.0",
"color-alpha": "1.0.4",
"color-normalize": "1.5.0",
- "color-parse": "1.3.8",
+ "color-parse": "2.0.0",
"color-rgba": "2.1.1",
"country-regex": "^1.1.0",
+ "css-loader": "^7.1.2",
"d3-force": "^1.2.1",
"d3-format": "^1.4.5",
"d3-geo": "^1.12.1",
@@ -12567,26 +10962,26 @@
"d3-time-format": "^2.2.3",
"fast-isnumeric": "^1.1.4",
"gl-mat4": "^1.2.0",
- "gl-text": "^1.3.1",
- "glslify": "^7.1.1",
+ "gl-text": "^1.4.0",
"has-hover": "^1.0.1",
"has-passive-events": "^1.0.0",
"is-mobile": "^4.0.0",
- "mapbox-gl": "1.10.1",
+ "maplibre-gl": "^4.5.2",
"mouse-change": "^1.4.0",
"mouse-event-offset": "^3.0.2",
"mouse-wheel": "^1.2.0",
"native-promise-only": "^0.8.1",
"parse-svg-path": "^0.1.2",
"point-in-polygon": "^1.1.0",
- "polybooljs": "^1.2.0",
+ "polybooljs": "^1.2.2",
"probe-image-size": "^7.2.3",
"regl": "npm:@plotly/regl@^2.1.2",
"regl-error2d": "^2.0.12",
- "regl-line2d": "^3.1.2",
- "regl-scatter2d": "^3.2.9",
+ "regl-line2d": "^3.1.3",
+ "regl-scatter2d": "^3.3.1",
"regl-splom": "^1.0.14",
"strongly-connected-components": "^1.0.1",
+ "style-loader": "^4.0.0",
"superscript-text": "^1.0.0",
"svg-path-sdf": "^1.1.3",
"tinycolor2": "^1.4.2",
@@ -12596,1276 +10991,980 @@
"world-calendars": "^1.0.3"
}
},
- "node_modules/pnp-webpack-plugin": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/pnp-webpack-plugin/-/pnp-webpack-plugin-1.7.0.tgz",
- "integrity": "sha512-2Rb3vm+EXble/sMXNSu6eoBx8e79gKqhNq9F5ZWW6ERNCTE/Q0wQNne5541tE5vKjfM8hpNCYL+LGc1YTfI0dg==",
- "dev": true,
+ "node_modules/plotly.js/node_modules/css-loader": {
+ "version": "7.1.4",
+ "resolved": "https://registry.npmjs.org/css-loader/-/css-loader-7.1.4.tgz",
+ "integrity": "sha512-vv3J9tlOl04WjiMvHQI/9tmIrCxVrj6PFbHemBB1iihpeRbi/I4h033eoFIhwxBBqLhI0KYFS7yvynBFhIZfTw==",
+ "license": "MIT",
"dependencies": {
- "ts-pnp": "^1.1.6"
+ "icss-utils": "^5.1.0",
+ "postcss": "^8.4.40",
+ "postcss-modules-extract-imports": "^3.1.0",
+ "postcss-modules-local-by-default": "^4.0.5",
+ "postcss-modules-scope": "^3.2.0",
+ "postcss-modules-values": "^4.0.0",
+ "postcss-value-parser": "^4.2.0",
+ "semver": "^7.6.3"
},
"engines": {
- "node": ">=6"
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "@rspack/core": "0.x || ^1.0.0 || ^2.0.0-0",
+ "webpack": "^5.27.0"
+ },
+ "peerDependenciesMeta": {
+ "@rspack/core": {
+ "optional": true
+ },
+ "webpack": {
+ "optional": true
+ }
}
},
"node_modules/point-in-polygon": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/point-in-polygon/-/point-in-polygon-1.1.0.tgz",
- "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw=="
+ "integrity": "sha512-3ojrFwjnnw8Q9242TzgXuTD+eKiutbzyslcq1ydfu82Db2y+Ogbmyrkpv0Hgj31qwT3lbS9+QAAO/pIQM35XRw==",
+ "license": "MIT"
},
"node_modules/polybooljs": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/polybooljs/-/polybooljs-1.2.0.tgz",
- "integrity": "sha512-mKjR5nolISvF+q2BtC1fi/llpxBPTQ3wLWN8+ldzdw2Hocpc8C72ZqnamCM4Z6z+68GVVjkeM01WJegQmZ8MEQ=="
+ "version": "1.2.2",
+ "resolved": "https://registry.npmjs.org/polybooljs/-/polybooljs-1.2.2.tgz",
+ "integrity": "sha512-ziHW/02J0XuNuUtmidBc6GXE8YohYydp3DWPWXYsd7O721TjcmN+k6ezjdwkDqep+gnWnFY+yqZHvzElra2oCg==",
+ "license": "MIT"
},
"node_modules/portfinder": {
- "version": "1.0.28",
- "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.28.tgz",
- "integrity": "sha512-Se+2isanIcEqf2XMHjyUKskczxbPH7dQnlMjXX6+dybayyHvAf/TCgyMRlzf/B6QDhAEFOGes0pzRo3by4AbMA==",
+ "version": "1.0.38",
+ "resolved": "https://registry.npmjs.org/portfinder/-/portfinder-1.0.38.tgz",
+ "integrity": "sha512-rEwq/ZHlJIKw++XtLAO8PPuOQA/zaPJOZJ37BVuN97nLpMJeuDVLVGRwbFoBgLudgdTMP2hdRJP++H+8QOA3vg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "async": "^2.6.2",
- "debug": "^3.1.1",
- "mkdirp": "^0.5.5"
+ "async": "^3.2.6",
+ "debug": "^4.3.6"
},
"engines": {
- "node": ">= 0.12.0"
- }
- },
- "node_modules/portfinder/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/posix-character-classes": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/posix-character-classes/-/posix-character-classes-0.1.1.tgz",
- "integrity": "sha1-AerA/jta9xoqbAL+q7jB/vfgDqs= sha512-xTgYBc3fuo7Yt7JbiuFxSYGToMoz8fLoE6TC9Wx1P/u+LfeThMOAqmuyECnlBaaJb+u1m9hHiXUEtwW4OzfUJg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node": ">= 10.12"
}
},
"node_modules/postcss": {
- "version": "7.0.39",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
- "integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
- "dev": true,
+ "version": "8.5.14",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.14.tgz",
+ "integrity": "sha512-SoSL4+OSEtR99LHFZQiJLkT59C5B1amGO1NzTwj7TT1qCUgUO6hxOvzkOYxD+vMrXBM3XJIKzokoERdqQq/Zmg==",
+ "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"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "picocolors": "^0.2.1",
- "source-map": "^0.6.1"
+ "nanoid": "^3.3.11",
+ "picocolors": "^1.1.1",
+ "source-map-js": "^1.2.1"
},
"engines": {
- "node": ">=6.0.0"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
+ "node": "^10 || ^12 || >=14"
}
},
"node_modules/postcss-calc": {
- "version": "7.0.5",
- "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-7.0.5.tgz",
- "integrity": "sha512-1tKHutbGtLtEZF6PT4JSihCHfIVldU72mZ8SdZHIYriIZ9fh9k9aWSppaT8rHsyI3dX+KSR+W+Ix9BMY3AODrg==",
+ "version": "8.2.4",
+ "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz",
+ "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "postcss": "^7.0.27",
- "postcss-selector-parser": "^6.0.2",
- "postcss-value-parser": "^4.0.2"
+ "postcss-selector-parser": "^6.0.9",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.2"
}
},
"node_modules/postcss-colormin": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-4.0.3.tgz",
- "integrity": "sha512-WyQFAdDZpExQh32j0U0feWisZ0dmOtPl44qYmJKkq9xFWY3p+4qnRzCHeNrkeRhwPHz9bQ3mo0/yVkaply0MNw==",
+ "version": "5.3.1",
+ "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz",
+ "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "browserslist": "^4.0.0",
- "color": "^3.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "browserslist": "^4.21.4",
+ "caniuse-api": "^3.0.0",
+ "colord": "^2.9.1",
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=6.9.0"
- }
- },
- "node_modules/postcss-colormin/node_modules/color": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/color/-/color-3.2.1.tgz",
- "integrity": "sha512-aBl7dZI9ENN6fUGC7mWpMTPNHmWUSNan9tuWN6ahh5ZLNk9baLJOnSMlrQkHcrfFgz2/RigjUVAjdx36VcemKA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.3",
- "color-string": "^1.6.0"
- }
- },
- "node_modules/postcss-colormin/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-colormin/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/postcss-colormin/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
"node_modules/postcss-convert-values": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-4.0.1.tgz",
- "integrity": "sha512-Kisdo1y77KUC0Jmn0OXU/COOJbzM8cImvw1ZFsBgBgMgb1iL23Zs/LXRe3r+EZqM3vGYKdQ2YJVQ5VkJI+zEJQ==",
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz",
+ "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "browserslist": "^4.21.4",
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-convert-values/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
"node_modules/postcss-discard-comments": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-4.0.2.tgz",
- "integrity": "sha512-RJutN259iuRf3IW7GZyLM5Sw4GLTOH8FmsXBnv8Ab/Tc2k4SR4qbV4DNbyyY4+Sjo362SyDmW2DQ7lBSChrpkg==",
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz",
+ "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==",
"dev": true,
- "dependencies": {
- "postcss": "^7.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
"node_modules/postcss-discard-duplicates": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-4.0.2.tgz",
- "integrity": "sha512-ZNQfR1gPNAiXZhgENFfEglF93pciw0WxMkJeVmw8eF+JZBbMD7jp6C67GqJAXVZP2BWbOztKfbsdmMp/k8c6oQ==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz",
+ "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==",
"dev": true,
- "dependencies": {
- "postcss": "^7.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
"node_modules/postcss-discard-empty": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-4.0.1.tgz",
- "integrity": "sha512-B9miTzbznhDjTfjvipfHoqbWKwd0Mj+/fL5s1QOz06wufguil+Xheo4XpOnc4NqKYBCNqqEzgPv2aPBIJLox0w==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz",
+ "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==",
"dev": true,
- "dependencies": {
- "postcss": "^7.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
"node_modules/postcss-discard-overridden": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-4.0.1.tgz",
- "integrity": "sha512-IYY2bEDD7g1XM1IDEsUT4//iEYCxAmP5oDSFMVU/JVvT7gh+l4fmjciLqGgwjdWpQIdb0Che2VX00QObS5+cTg==",
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz",
+ "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==",
"dev": true,
- "dependencies": {
- "postcss": "^7.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-functions": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/postcss-functions/-/postcss-functions-3.0.0.tgz",
- "integrity": "sha1-DpTQFERwCkgd4g3k1V+yZAVkJQ4= sha512-N5yWXWKA+uhpLQ9ZhBRl2bIAdM6oVJYpDojuI1nF2SzXBimJcdjFwiAouBVbO5VuOF3qA6BSFWFc3wXbbj72XQ==",
- "dev": true,
+ "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==",
+ "license": "MIT",
"dependencies": {
- "glob": "^7.1.2",
- "object-assign": "^4.1.1",
- "postcss": "^6.0.9",
- "postcss-value-parser": "^3.3.0"
+ "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-functions/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
+ "node_modules/postcss-js": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-4.1.0.tgz",
+ "integrity": "sha512-oIAOTqgIo7q2EOwbhb8UalYePMvYoIeRY2YKntdpFQXNosSu3vLrniGgmH9OKs/qAkfoj5oB3le/7mINW1LCfw==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "color-convert": "^1.9.0"
+ "camelcase-css": "^2.0.1"
},
"engines": {
- "node": ">=4"
+ "node": "^12 || ^14 || >= 16"
+ },
+ "peerDependencies": {
+ "postcss": "^8.4.21"
}
},
- "node_modules/postcss-functions/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
+ "node_modules/postcss-loader": {
+ "version": "6.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-6.2.1.tgz",
+ "integrity": "sha512-WbbYpmAaKcux/P66bZ40bpWsBucjx/TTgVVzRZ9yUO8yQfVBlameJ0ZGVaPfH64hNSBh63a+ICP5nqOpBA0w+Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
+ "cosmiconfig": "^7.0.0",
+ "klona": "^2.0.5",
+ "semver": "^7.3.5"
},
"engines": {
- "node": ">=4"
- }
- },
- "node_modules/postcss-functions/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "postcss": "^7.0.0 || ^8.0.1",
+ "webpack": "^5.0.0"
}
},
- "node_modules/postcss-functions/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/postcss-functions/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "node_modules/postcss-merge-longhand": {
+ "version": "5.1.7",
+ "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz",
+ "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0",
+ "stylehacks": "^5.1.1"
+ },
"engines": {
- "node": ">=4"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-functions/node_modules/postcss": {
- "version": "6.0.23",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-6.0.23.tgz",
- "integrity": "sha512-soOk1h6J3VMTZtVeVpv15/Hpdl2cBLX3CAw4TAbkpTJiNPk9YP/zWcD1ND+xEtvyuuvKzbxliTOIyvkSeSJ6ag==",
+ "node_modules/postcss-merge-rules": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz",
+ "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "chalk": "^2.4.1",
- "source-map": "^0.6.1",
- "supports-color": "^5.4.0"
+ "browserslist": "^4.21.4",
+ "caniuse-api": "^3.0.0",
+ "cssnano-utils": "^3.1.0",
+ "postcss-selector-parser": "^6.0.5"
},
"engines": {
- "node": ">=4.0.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-functions/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-functions/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==",
+ "node_modules/postcss-minify-font-values": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz",
+ "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "postcss-value-parser": "^4.2.0"
+ },
"engines": {
- "node": ">=0.10.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-functions/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
+ "node_modules/postcss-minify-gradients": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz",
+ "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has-flag": "^3.0.0"
+ "colord": "^2.9.1",
+ "cssnano-utils": "^3.1.0",
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=4"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-js": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/postcss-js/-/postcss-js-2.0.3.tgz",
- "integrity": "sha512-zS59pAk3deu6dVHyrGqmC3oDXBdNdajk4k1RyxeVXCrcEDBUBHoIhE4QTsmhxgzXxsaqFDAkUZfmMa5f/N/79w==",
+ "node_modules/postcss-minify-params": {
+ "version": "5.1.4",
+ "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz",
+ "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "camelcase-css": "^2.0.1",
- "postcss": "^7.0.18"
+ "browserslist": "^4.21.4",
+ "cssnano-utils": "^3.1.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-load-config": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.0.tgz",
- "integrity": "sha512-ipM8Ds01ZUophjDTQYSVP70slFSYg3T0/zyfII5vzhN6V57YSxMgG5syXuwi5VtS8wSf3iL30v0uBdoIVx4Q0g==",
+ "node_modules/postcss-minify-selectors": {
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz",
+ "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "import-cwd": "^3.0.0",
- "lilconfig": "^2.0.3",
- "yaml": "^1.10.2"
+ "postcss-selector-parser": "^6.0.5"
},
"engines": {
- "node": ">= 10"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
+ "node": "^10 || ^12 || >=14.0"
},
"peerDependencies": {
- "ts-node": ">=9.0.0"
- },
- "peerDependenciesMeta": {
- "ts-node": {
- "optional": true
- }
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-loader": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/postcss-loader/-/postcss-loader-3.0.0.tgz",
- "integrity": "sha512-cLWoDEY5OwHcAjDnkyRQzAXfs2jrKjXpO/HQFcc5b5u/r7aa471wdmChmwfnv7x2u840iat/wi0lQ5nbRgSkUA==",
- "dev": true,
- "dependencies": {
- "loader-utils": "^1.1.0",
- "postcss": "^7.0.0",
- "postcss-load-config": "^2.0.0",
- "schema-utils": "^1.0.0"
- },
+ "node_modules/postcss-modules-extract-imports": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.1.0.tgz",
+ "integrity": "sha512-k3kNe0aNFQDAZGbin48pL2VNidTF0w4/eASDsxlyspobzU3wZQLOGj7L9gfRe0Jo9/4uud09DsjFNH7winGv8Q==",
+ "license": "ISC",
"engines": {
- "node": ">= 6"
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
}
},
- "node_modules/postcss-loader/node_modules/cosmiconfig": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/cosmiconfig/-/cosmiconfig-5.2.1.tgz",
- "integrity": "sha512-H65gsXo1SKjf8zmrJ67eJk8aIRKV5ff2D4uKZIBZShbhGSpEmsQOPW/SKMKYhSTrqR7ufy6RP69rPogdaPh/kA==",
- "dev": true,
+ "node_modules/postcss-modules-local-by-default": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.2.0.tgz",
+ "integrity": "sha512-5kcJm/zk+GJDSfw+V/42fJ5fhjL5YbFDl8nVdXkJPLLW+Vf9mTD5Xe0wqIaDnLuL2U6cDNpTr+UQ+v2HWIBhzw==",
+ "license": "MIT",
"dependencies": {
- "import-fresh": "^2.0.0",
- "is-directory": "^0.3.1",
- "js-yaml": "^3.13.1",
- "parse-json": "^4.0.0"
+ "icss-utils": "^5.0.0",
+ "postcss-selector-parser": "^7.0.0",
+ "postcss-value-parser": "^4.1.0"
},
"engines": {
- "node": ">=4"
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
}
},
- "node_modules/postcss-loader/node_modules/import-cwd": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/import-cwd/-/import-cwd-2.1.0.tgz",
- "integrity": "sha1-qmzzbnInYShcs3HsZRn1PiQ1sKk= sha512-Ew5AZzJQFqrOV5BTW3EIoHAnoie1LojZLXKcCQ/yTRyVZosBhK1x1ViYjHGf5pAFOq8ZyChZp6m/fSN7pJyZtg==",
- "dev": true,
+ "node_modules/postcss-modules-local-by-default/node_modules/postcss-selector-parser": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
+ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
+ "license": "MIT",
"dependencies": {
- "import-from": "^2.1.0"
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
},
"engines": {
"node": ">=4"
}
},
- "node_modules/postcss-loader/node_modules/import-fresh": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/import-fresh/-/import-fresh-2.0.0.tgz",
- "integrity": "sha1-2BNVwVYS04bGH53dOSLUMEgipUY= sha512-eZ5H8rcgYazHbKC3PG4ClHNykCSxtAhxSSEM+2mb+7evD2CKF5V7c0dNum7AdpDh0ZdICwZY9sRSn8f+KH96sg==",
- "dev": true,
+ "node_modules/postcss-modules-scope": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.2.1.tgz",
+ "integrity": "sha512-m9jZstCVaqGjTAuny8MdgE88scJnCiQSlSrOWcTQgM2t32UBe+MUmFSO5t7VMSfAf/FJKImAxBav8ooCHJXCJA==",
+ "license": "ISC",
"dependencies": {
- "caller-path": "^2.0.0",
- "resolve-from": "^3.0.0"
+ "postcss-selector-parser": "^7.0.0"
},
"engines": {
- "node": ">=4"
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
}
},
- "node_modules/postcss-loader/node_modules/import-from": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/import-from/-/import-from-2.1.0.tgz",
- "integrity": "sha1-M1238qev/VOqpHHUuAId7ja387E= sha512-0vdnLL2wSGnhlRmzHJAg5JHjt1l2vYhzJ7tNLGbeVg0fse56tpGaH0uzH+r9Slej+BSXXEHvBKDEnVSLLE9/+w==",
- "dev": true,
+ "node_modules/postcss-modules-scope/node_modules/postcss-selector-parser": {
+ "version": "7.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-7.1.1.tgz",
+ "integrity": "sha512-orRsuYpJVw8LdAwqqLykBj9ecS5/cRHlI5+nvTo8LcCKmzDmqVORXtOIYEEQuL9D4BxtA1lm5isAqzQZCoQ6Eg==",
+ "license": "MIT",
"dependencies": {
- "resolve-from": "^3.0.0"
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
},
"engines": {
"node": ">=4"
}
},
- "node_modules/postcss-loader/node_modules/parse-json": {
+ "node_modules/postcss-modules-values": {
"version": "4.0.0",
- "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-4.0.0.tgz",
- "integrity": "sha1-vjX1Qlvh9/bHRxhPmKeIy5lHfuA= sha512-aOIos8bujGN93/8Ox/jPLh7RwVnPEysynVFE+fQZyg6jKELEHwzgKdLRFHUgXJL6kylijVSBC4BvN9OmsB48Rw==",
- "dev": true,
+ "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
+ "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
+ "license": "ISC",
"dependencies": {
- "error-ex": "^1.3.1",
- "json-parse-better-errors": "^1.0.1"
+ "icss-utils": "^5.0.0"
},
"engines": {
- "node": ">=4"
+ "node": "^10 || ^12 || >= 14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
}
},
- "node_modules/postcss-loader/node_modules/postcss-load-config": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-2.1.2.tgz",
- "integrity": "sha512-/rDeGV6vMUo3mwJZmeHfEDvwnTKKqQ0S7OHUi/kJvvtx3aWtyWG2/0ZWnzCt2keEclwN6Tf0DST2v9kITdOKYw==",
- "dev": true,
+ "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==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "cosmiconfig": "^5.0.0",
- "import-cwd": "^2.0.0"
+ "postcss-selector-parser": "^6.1.1"
},
"engines": {
- "node": ">= 4"
+ "node": ">=12.0"
},
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
+ "peerDependencies": {
+ "postcss": "^8.2.14"
}
},
- "node_modules/postcss-loader/node_modules/resolve-from": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
- "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g= sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==",
+ "node_modules/postcss-normalize-charset": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz",
+ "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-loader/node_modules/schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
- "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "node_modules/postcss-normalize-display-values": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz",
+ "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">= 4"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-merge-longhand": {
- "version": "4.0.11",
- "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-4.0.11.tgz",
- "integrity": "sha512-alx/zmoeXvJjp7L4mxEMjh8lxVlDFX1gqWHzaaQewwMZiVhLo42TEClKaeHbRf6J7j82ZOdTJ808RtN0ZOZwvw==",
+ "node_modules/postcss-normalize-positions": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz",
+ "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "css-color-names": "0.0.4",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0",
- "stylehacks": "^4.0.0"
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-merge-longhand/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-merge-rules": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-4.0.3.tgz",
- "integrity": "sha512-U7e3r1SbvYzO0Jr3UT/zKBVgYYyhAz0aitvGIYOYK5CPmkNih+WDSsS5tvPrJ8YMQYlEMvsZIiqmn7HdFUaeEQ==",
+ "node_modules/postcss-normalize-repeat-style": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz",
+ "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "browserslist": "^4.0.0",
- "caniuse-api": "^3.0.0",
- "cssnano-util-same-parent": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-selector-parser": "^3.0.0",
- "vendors": "^1.0.0"
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-merge-rules/node_modules/postcss-selector-parser": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
- "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==",
+ "node_modules/postcss-normalize-string": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz",
+ "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "dot-prop": "^5.2.0",
- "indexes-of": "^1.0.1",
- "uniq": "^1.0.1"
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=8"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-minify-font-values": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-4.0.2.tgz",
- "integrity": "sha512-j85oO6OnRU9zPf04+PZv1LYIYOprWm6IA6zkXkrJXyRveDEuQggG6tvoy8ir8ZwjLxLuGfNkCZEQG7zan+Hbtg==",
+ "node_modules/postcss-normalize-timing-functions": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz",
+ "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-minify-font-values/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-minify-gradients": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-4.0.2.tgz",
- "integrity": "sha512-qKPfwlONdcf/AndP1U8SJ/uzIJtowHlMaSioKzebAXSG4iJthlWC9iSWznQcX4f66gIWX44RSA841HTHj3wK+Q==",
+ "node_modules/postcss-normalize-unicode": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz",
+ "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cssnano-util-get-arguments": "^4.0.0",
- "is-color-stop": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "browserslist": "^4.21.4",
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-minify-gradients/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-minify-params": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-4.0.2.tgz",
- "integrity": "sha512-G7eWyzEx0xL4/wiBBJxJOz48zAKV2WG3iZOqVhPet/9geefm/Px5uo1fzlHu+DOjT+m0Mmiz3jkQzVHe6wxAWg==",
+ "node_modules/postcss-normalize-url": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz",
+ "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "alphanum-sort": "^1.0.0",
- "browserslist": "^4.0.0",
- "cssnano-util-get-arguments": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0",
- "uniqs": "^2.0.0"
+ "normalize-url": "^6.0.1",
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-minify-params/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-minify-selectors": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-4.0.2.tgz",
- "integrity": "sha512-D5S1iViljXBj9kflQo4YutWnJmwm8VvIsU1GeXJGiG9j8CIg9zs4voPMdQDUmIxetUOh60VilsNzCiAFTOqu3g==",
+ "node_modules/postcss-normalize-whitespace": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz",
+ "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "alphanum-sort": "^1.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-selector-parser": "^3.0.0"
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-minify-selectors/node_modules/postcss-selector-parser": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
- "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==",
+ "node_modules/postcss-ordered-values": {
+ "version": "5.1.3",
+ "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz",
+ "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "dot-prop": "^5.2.0",
- "indexes-of": "^1.0.1",
- "uniq": "^1.0.1"
+ "cssnano-utils": "^3.1.0",
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">=8"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-modules-extract-imports": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz",
- "integrity": "sha512-LaYLDNS4SG8Q5WAWqIJgdHPJrDDr/Lv775rMBFUbgjTz6j34lUznACHcdRWroPvXANP2Vj7yNK57vp9eFqzLWQ==",
+ "node_modules/postcss-reduce-initial": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz",
+ "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "postcss": "^7.0.5"
+ "browserslist": "^4.21.4",
+ "caniuse-api": "^3.0.0"
},
"engines": {
- "node": ">= 6"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-modules-local-by-default": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-3.0.3.tgz",
- "integrity": "sha512-e3xDq+LotiGesympRlKNgaJ0PCzoUIdpH0dj47iWAui/kyTgh3CiAr1qP54uodmJhl6p9rN6BoNcdEDVJx9RDw==",
+ "node_modules/postcss-reduce-transforms": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz",
+ "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "icss-utils": "^4.1.1",
- "postcss": "^7.0.32",
- "postcss-selector-parser": "^6.0.2",
- "postcss-value-parser": "^4.1.0"
+ "postcss-value-parser": "^4.2.0"
},
"engines": {
- "node": ">= 6"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-modules-scope": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-2.2.0.tgz",
- "integrity": "sha512-YyEgsTMRpNd+HmyC7H/mh3y+MeFWevy7V1evVhJWewmMbjDHIbZbOXICC2y+m1xI1UVfIT1HMW/O04Hxyu9oXQ==",
- "dev": true,
- "dependencies": {
- "postcss": "^7.0.6",
- "postcss-selector-parser": "^6.0.0"
- },
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "cssesc": "^3.0.0",
+ "util-deprecate": "^1.0.2"
+ },
"engines": {
- "node": ">= 6"
+ "node": ">=4"
}
},
- "node_modules/postcss-modules-values": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-3.0.0.tgz",
- "integrity": "sha512-1//E5jCBrZ9DmRX+zCtmQtRSV6PV42Ix7Bzj9GbwJceduuf7IqP8MgeTXuRDHOWj2m0VzZD5+roFWDuU8RQjcg==",
+ "node_modules/postcss-svgo": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz",
+ "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "icss-utils": "^4.0.0",
- "postcss": "^7.0.6"
+ "postcss-value-parser": "^4.2.0",
+ "svgo": "^2.7.0"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-nested": {
- "version": "4.2.3",
- "resolved": "https://registry.npmjs.org/postcss-nested/-/postcss-nested-4.2.3.tgz",
- "integrity": "sha512-rOv0W1HquRCamWy2kFl3QazJMMe1ku6rCFoAAH+9AcxdbpDeBr6k968MLWuLjvjMcGEip01ak09hKOEgpK9hvw==",
+ "node_modules/postcss-unique-selectors": {
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz",
+ "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "postcss": "^7.0.32",
- "postcss-selector-parser": "^6.0.2"
+ "postcss-selector-parser": "^6.0.5"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/postcss-normalize-charset": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-4.0.1.tgz",
- "integrity": "sha512-gMXCrrlWh6G27U0hF3vNvR3w8I1s2wOBILvA87iNXaPvSNo5uZAMYsZG7XjCUf1eVxuPfyL4TJ7++SGZLc9A3g==",
+ "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==",
+ "license": "MIT"
+ },
+ "node_modules/potpack": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/potpack/-/potpack-1.0.2.tgz",
+ "integrity": "sha512-choctRBIV9EMT9WGAZHn3V7t0Z2pMQyl0EZE6pFc/6ml3ssw7Dlf/oAOvFwjm1HVsqfQN8GfeFyJ+d8tRzqueQ==",
+ "license": "ISC"
+ },
+ "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,
- "dependencies": {
- "postcss": "^7.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": ">= 0.8.0"
}
},
- "node_modules/postcss-normalize-display-values": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-4.0.2.tgz",
- "integrity": "sha512-3F2jcsaMW7+VtRMAqf/3m4cPFhPD3EFRgNs18u+k3lTJJlVe7d0YPO+bnwqo2xg8YiRpDXJI2u8A0wqJxMsQuQ==",
- "dev": true,
- "dependencies": {
- "cssnano-util-get-match": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "node_modules/prettier": {
+ "version": "2.8.8",
+ "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.8.8.tgz",
+ "integrity": "sha512-tdN8qQGvNjw4CHbY+XXk0JgCXn9QiF21a55rBe5LJAU+kDyC4WQn4+awm2Xfk2lQMk5fKup9XgzTZtGkjBdP9Q==",
+ "license": "MIT",
+ "optional": true,
+ "bin": {
+ "prettier": "bin-prettier.js"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "url": "https://github.com/prettier/prettier?sponsor=1"
}
},
- "node_modules/postcss-normalize-display-values/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-normalize-positions": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-4.0.2.tgz",
- "integrity": "sha512-Dlf3/9AxpxE+NF1fJxYDeggi5WwV35MXGFnnoccP/9qDtFrTArZ0D0R+iKcg5WsUd8nUYMIl8yXDCtcrT8JrdA==",
+ "node_modules/pretty-error": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-4.0.0.tgz",
+ "integrity": "sha512-AoJ5YMAcXKYxKhuJGdcvse+Voc6v1RgnsR3nWcYU7q4t6z0Q6T86sv5Zq8VIRbOWWFpvdGE83LtdSMNd+6Y0xw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cssnano-util-get-arguments": "^4.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
+ "lodash": "^4.17.20",
+ "renderkid": "^3.0.0"
}
},
- "node_modules/postcss-normalize-positions/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
+ "node_modules/probe-image-size": {
+ "version": "7.3.0",
+ "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-7.3.0.tgz",
+ "integrity": "sha512-7CaDeBwiAbh6ohXsvLbAZhO7wzsZAmaevfxe39qvCwRh8LyaZfDlBGGLU1CCTgrTLtCOdwBBhjOrIHaIIimHfQ==",
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/puzrin"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/nodeca"
+ }
+ ],
+ "license": "MIT",
+ "dependencies": {
+ "lodash.merge": "^4.6.2",
+ "needle": "^2.5.2",
+ "stream-parser": "~0.3.1"
+ }
},
- "node_modules/postcss-normalize-repeat-style": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-4.0.2.tgz",
- "integrity": "sha512-qvigdYYMpSuoFs3Is/f5nHdRLJN/ITA7huIoCyqqENJe9PvPmLhNLMu7QTjPdtnVf6OcYYO5SHonx4+fbJE1+Q==",
+ "node_modules/process-nextick-args": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
+ "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag==",
+ "license": "MIT"
+ },
+ "node_modules/progress-webpack-plugin": {
+ "version": "1.0.16",
+ "resolved": "https://registry.npmjs.org/progress-webpack-plugin/-/progress-webpack-plugin-1.0.16.tgz",
+ "integrity": "sha512-sdiHuuKOzELcBANHfrupYo+r99iPRyOnw15qX+rNlVUqXGfjXdH4IgxriKwG1kNJwVswKQHMdj1hYZMcb9jFaA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cssnano-util-get-arguments": "^4.0.0",
- "cssnano-util-get-match": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "chalk": "^2.1.0",
+ "figures": "^2.0.0",
+ "log-update": "^2.3.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">= 10.13.0"
+ },
+ "peerDependencies": {
+ "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0 || ^5.0.0"
}
},
- "node_modules/postcss-normalize-repeat-style/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-normalize-string": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-4.0.2.tgz",
- "integrity": "sha512-RrERod97Dnwqq49WNz8qo66ps0swYZDSb6rM57kN2J+aoyEAJfZ6bMx0sx/F9TIEX0xthPGCmeyiam/jXif0eA==",
+ "node_modules/progress-webpack-plugin/node_modules/ansi-styles": {
+ "version": "3.2.1",
+ "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
+ "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "color-convert": "^1.9.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=4"
}
},
- "node_modules/postcss-normalize-string/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-normalize-timing-functions": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-4.0.2.tgz",
- "integrity": "sha512-acwJY95edP762e++00Ehq9L4sZCEcOPyaHwoaFOhIwWCDfik6YvqsYNxckee65JHLKzuNSSmAdxwD2Cud1Z54A==",
+ "node_modules/progress-webpack-plugin/node_modules/chalk": {
+ "version": "2.4.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
+ "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cssnano-util-get-match": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "ansi-styles": "^3.2.1",
+ "escape-string-regexp": "^1.0.5",
+ "supports-color": "^5.3.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=4"
}
},
- "node_modules/postcss-normalize-timing-functions/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-normalize-unicode": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-4.0.1.tgz",
- "integrity": "sha512-od18Uq2wCYn+vZ/qCOeutvHjB5jm57ToxRaMeNuf0nWVHaP9Hua56QyMF6fs/4FSUnVIw0CBPsU0K4LnBPwYwg==",
+ "node_modules/progress-webpack-plugin/node_modules/color-convert": {
+ "version": "1.9.3",
+ "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
+ "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "browserslist": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
- "engines": {
- "node": ">=6.9.0"
+ "color-name": "1.1.3"
}
},
- "node_modules/postcss-normalize-unicode/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
+ "node_modules/progress-webpack-plugin/node_modules/color-name": {
+ "version": "1.1.3",
+ "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
+ "integrity": "sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/postcss-normalize-url": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-4.0.1.tgz",
- "integrity": "sha512-p5oVaF4+IHwu7VpMan/SSpmpYxcJMtkGppYf0VbdH5B6hN8YNmVyJLuY9FmLQTzY3fag5ESUUHDqM+heid0UVA==",
+ "node_modules/progress-webpack-plugin/node_modules/escape-string-regexp": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
+ "integrity": "sha512-vbRorB5FUQWvla16U8R/qgaFIya2qGzwDrNmCZuYKrbdSUMG6I1ZCGQRefkRVhuOkIGVne7BQ35DSfo1qvJqFg==",
"dev": true,
- "dependencies": {
- "is-absolute-url": "^2.0.0",
- "normalize-url": "^3.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": ">=0.8.0"
}
},
- "node_modules/postcss-normalize-url/node_modules/normalize-url": {
- "version": "3.3.0",
- "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-3.3.0.tgz",
- "integrity": "sha512-U+JJi7duF1o+u2pynbp2zXDW2/PADgC30f0GsHZtRh+HOcXHnw137TrNlyxxRvWW5fjKd3bcLHPxofWuCjaeZg==",
+ "node_modules/progress-webpack-plugin/node_modules/has-flag": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
+ "integrity": "sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">=4"
}
},
- "node_modules/postcss-normalize-url/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-normalize-whitespace": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-4.0.2.tgz",
- "integrity": "sha512-tO8QIgrsI3p95r8fyqKV+ufKlSHh9hMJqACqbv2XknufqEDhDvbguXGBBqxw9nsQoXWf0qOqppziKJKHMD4GtA==",
+ "node_modules/progress-webpack-plugin/node_modules/supports-color": {
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
+ "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "has-flag": "^3.0.0"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">=4"
}
},
- "node_modules/postcss-normalize-whitespace/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
+ "node_modules/property-expr": {
+ "version": "2.0.6",
+ "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.6.tgz",
+ "integrity": "sha512-SVtmxhRE/CGkn3eZY1T6pC8Nln6Fr/lu1mKSgRud0eC73whjGfoAogbn78LkD8aFL0zz3bAFerKSnOl7NlErBA==",
+ "license": "MIT"
},
- "node_modules/postcss-ordered-values": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-4.1.2.tgz",
- "integrity": "sha512-2fCObh5UanxvSxeXrtLtlwVThBvHn6MQcu4ksNT2tsaV2Fg76R2CV98W7wNSlX+5/pFwEyaDwKLLoEV7uRybAw==",
+ "node_modules/protocol-buffers-schema": {
+ "version": "3.6.1",
+ "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.1.tgz",
+ "integrity": "sha512-VG2K63Igkiv9p76tk1lilczEK1cT+kCjKtkdhw1dQZV3k3IXJbd3o6Ho8b9zJZaHSnT2hKe4I+ObmX9w6m5SmQ==",
+ "license": "MIT"
+ },
+ "node_modules/proxy-addr": {
+ "version": "2.0.7",
+ "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
+ "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cssnano-util-get-arguments": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
+ "forwarded": "0.2.0",
+ "ipaddr.js": "1.9.1"
},
"engines": {
- "node": ">=6.9.0"
+ "node": ">= 0.10"
}
},
- "node_modules/postcss-ordered-values/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-reduce-initial": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-4.0.3.tgz",
- "integrity": "sha512-gKWmR5aUulSjbzOfD9AlJiHCGH6AEVLaM0AV+aSioxUDd16qXP1PCh8d1/BGVvpdWn8k/HiK7n6TjeoXN1F7DA==",
+ "node_modules/proxy-addr/node_modules/ipaddr.js": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.9.1.tgz",
+ "integrity": "sha512-0KI/607xoxSToH7GjN1FfSbLoU0+btTicjsQSWQlh/hZykN8KpmMf7uYwPW3R+akZ6R/w18ZlXSHBYXiYUPO3g==",
"dev": true,
- "dependencies": {
- "browserslist": "^4.0.0",
- "caniuse-api": "^3.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": ">= 0.10"
}
},
- "node_modules/postcss-reduce-transforms": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-4.0.2.tgz",
- "integrity": "sha512-EEVig1Q2QJ4ELpJXMZR8Vt5DQx8/mo+dGWSR7vWXqcob2gQLyQGsionYcGKATXvQzMPn6DSN1vTN7yFximdIAg==",
- "dev": true,
- "dependencies": {
- "cssnano-util-get-match": "^4.0.0",
- "has": "^1.0.0",
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0"
- },
+ "node_modules/proxy-from-env": {
+ "version": "2.1.0",
+ "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-2.1.0.tgz",
+ "integrity": "sha512-cJ+oHTW1VAEa8cJslgmUZrc+sjRKgAKl3Zyse6+PV38hZe/V6Z14TbCuXcan9F9ghlz4QrFr2c92TNF82UkYHA==",
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": ">=10"
}
},
- "node_modules/postcss-reduce-transforms/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
+ "node_modules/pseudomap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
+ "integrity": "sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
+ "dev": true,
+ "license": "ISC"
},
- "node_modules/postcss-selector-parser": {
- "version": "6.0.6",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.0.6.tgz",
- "integrity": "sha512-9LXrvaaX3+mcv5xkg5kFwqSzSH1JIObIx51PrndZwlmznwXRfxMddDvo9gve3gVR8ZTKgoFDdWkbRFmEhT4PMg==",
+ "node_modules/pump": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.4.tgz",
+ "integrity": "sha512-VS7sjc6KR7e1ukRFhQSY5LM2uBWAUPiOPa/A3mkKmiMwSmRFUITt0xuj+/lesgnCv+dPIEYlkzrcyXgquIHMcA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "cssesc": "^3.0.0",
- "util-deprecate": "^1.0.2"
- },
- "engines": {
- "node": ">=4"
+ "end-of-stream": "^1.1.0",
+ "once": "^1.3.1"
}
},
- "node_modules/postcss-svgo": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-4.0.3.tgz",
- "integrity": "sha512-NoRbrcMWTtUghzuKSoIm6XV+sJdvZ7GZSc3wdBN0W19FTtp2ko8NqLsgoh/m9CzNhU3KLPvQmjIwtaNFkaFTvw==",
+ "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,
- "dependencies": {
- "postcss": "^7.0.0",
- "postcss-value-parser": "^3.0.0",
- "svgo": "^1.0.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6.9.0"
+ "node": ">=6"
}
},
- "node_modules/postcss-svgo/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/postcss-unique-selectors": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-4.0.1.tgz",
- "integrity": "sha512-+JanVaryLo9QwZjKrmJgkI4Fn8SBgRO6WXQBJi7KiAVPlmxikB5Jzc4EvXMT2H0/m0RjrVVm9rGNhZddm/8Spg==",
+ "node_modules/qs": {
+ "version": "6.15.1",
+ "resolved": "https://registry.npmjs.org/qs/-/qs-6.15.1.tgz",
+ "integrity": "sha512-6YHEFRL9mfgcAvql/XhwTvf5jKcOiiupt2FiJxHkiX1z4j7WL8J/jRHYLluORvc1XxB5rV20KoeK00gVJamspg==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
- "alphanum-sort": "^1.0.0",
- "postcss": "^7.0.0",
- "uniqs": "^2.0.0"
+ "side-channel": "^1.1.0"
},
- "engines": {
- "node": ">=6.9.0"
- }
- },
- "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==",
- "dev": true
- },
- "node_modules/postcss/node_modules/picocolors": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
- "integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA==",
- "dev": true
- },
- "node_modules/postcss/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/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.1.2",
- "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz",
- "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ= sha512-ESF23V4SKG6lVSGZgYNpbsiaAkdab6ZgOxe52p7+Kid3W3u3bxR4Vfd/o21dmN7jSt0IwgZ4v5MUd26FEtXE9w==",
- "engines": {
- "node": ">= 0.8.0"
- }
- },
- "node_modules/prepend-http": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/prepend-http/-/prepend-http-1.0.4.tgz",
- "integrity": "sha1-1PRWKwzjaW5BrFLQ4ALlemNdxtw= sha512-PhmXi5XmoyKw1Un4E+opM2KcsJInDvKyuOumcjjw3waw86ZNjHwVUOOWLc4bCzLdcKNaWBH9e99sbWzDQsVaYg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/prettier": {
- "version": "2.5.1",
- "resolved": "https://registry.npmjs.org/prettier/-/prettier-2.5.1.tgz",
- "integrity": "sha512-vBZcPRUR5MZJwoyi3ZoyQlc1rXeEck8KgeC9AwwOn+exuxLxq5toTRDTSaVrXHxelDMHy9zlicw8u66yxoSUFg==",
- "optional": true,
- "bin": {
- "prettier": "bin-prettier.js"
- },
- "engines": {
- "node": ">=10.13.0"
- }
- },
- "node_modules/pretty-error": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/pretty-error/-/pretty-error-2.1.2.tgz",
- "integrity": "sha512-EY5oDzmsX5wvuynAByrmY0P0hcp+QpnAKbJng2A2MPjVKXCxrDSUkzghVJ4ZGPIv+JC4gX8fPUWscC0RtjsWGw==",
- "dev": true,
- "dependencies": {
- "lodash": "^4.17.20",
- "renderkid": "^2.0.4"
- }
- },
- "node_modules/pretty-hrtime": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/pretty-hrtime/-/pretty-hrtime-1.0.3.tgz",
- "integrity": "sha1-t+PqQkNaTJsnWdmeDyAesZWALuE= sha512-66hKPCr+72mlfiSjlEB1+45IjXSqvVAIy6mocupoww4tBFE9R9IhwwUGoI4G++Tc9Aq+2rxOt0RFU6gPcrte0A==",
- "dev": true,
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/probe-image-size": {
- "version": "7.2.3",
- "resolved": "https://registry.npmjs.org/probe-image-size/-/probe-image-size-7.2.3.tgz",
- "integrity": "sha512-HubhG4Rb2UH8YtV4ba0Vp5bQ7L78RTONYu/ujmCu5nBI8wGv24s4E9xSKBi0N1MowRpxk76pFCpJtW0KPzOK0w==",
- "dependencies": {
- "lodash.merge": "^4.6.2",
- "needle": "^2.5.2",
- "stream-parser": "~0.3.1"
- }
- },
- "node_modules/process": {
- "version": "0.11.10",
- "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz",
- "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI= sha512-cdGef/drWFoydD1JsMzuFf8100nZl+GT+yacc2bEced5f9Rjk4z+WtFUTBu9PhOi9j/jfmBPu0mMEY4wIdAF8A==",
- "dev": true,
- "engines": {
- "node": ">= 0.6.0"
- }
- },
- "node_modules/process-nextick-args": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.1.tgz",
- "integrity": "sha512-3ouUOpQhtgrbOa17J7+uxOTpITYWaGP7/AhoR3+A+/1e9skrzelGi/dXzEYyvbxubEF6Wn2ypscTKiKJFFn1ag=="
- },
- "node_modules/progress": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.3.tgz",
- "integrity": "sha512-7PiHtLll5LdnKIMw100I+8xJXR5gW2QwWYkT6iJva0bXitZKa/XMrSbdmg3r2Xnaidz9Qumd0VPaMrZlF9V9sA==",
- "dev": true,
- "engines": {
- "node": ">=0.4.0"
- }
- },
- "node_modules/promise-inflight": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/promise-inflight/-/promise-inflight-1.0.1.tgz",
- "integrity": "sha1-mEcocL8igTL8vdhoEputEsPAKeM= sha512-6zWPyEOFaQBJYcGMHBKTKJ3u6TBsnMFOIZSa6ce1e/ZrrsOlnHRHbabMjLiBYKp+n44X9eUI6VUPaukCXHuG4g==",
- "dev": true
- },
- "node_modules/property-expr": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/property-expr/-/property-expr-2.0.4.tgz",
- "integrity": "sha512-sFPkHQjVKheDNnPvotjQmm3KD3uk1fWKUN7CrpdbwmUx3CrG3QiM8QpTSimvig5vTXmTvjz7+TDvXOI9+4rkcg=="
- },
- "node_modules/protocol-buffers-schema": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/protocol-buffers-schema/-/protocol-buffers-schema-3.6.0.tgz",
- "integrity": "sha512-TdDRD+/QNdrCGCE7v8340QyuXd4kIWIgapsE2+n/SaGiSSbomYl4TjHlvIoCWRpE7wFt02EpB35VVA2ImcBVqw=="
- },
- "node_modules/proxy-addr": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.7.tgz",
- "integrity": "sha512-llQsMLSUDUPT44jdrU/O37qlnifitDP+ZwrmmZcoSKyLKvtZxpyV0n2/bD/N4tBAAZ/gJEdZU7KMraoK1+XYAg==",
- "dev": true,
- "dependencies": {
- "forwarded": "0.2.0",
- "ipaddr.js": "1.9.1"
- },
- "engines": {
- "node": ">= 0.10"
- }
- },
- "node_modules/proxy-from-env": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/proxy-from-env/-/proxy-from-env-1.1.0.tgz",
- "integrity": "sha512-D+zkORCbA9f1tdWRK0RaCR3GPv50cMxcrz4X8k5LTSUD1Dkw47mKJEZQNunItRTkWwgtaUSo1RVFRIG9ZXiFYg==",
- "license": "MIT"
- },
- "node_modules/prr": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/prr/-/prr-1.0.1.tgz",
- "integrity": "sha1-0/wRS6BplaRexok/SEzrHXj19HY= sha512-yPw4Sng1gWghHQWj0B3ZggWUm4qVbPwPFcRG8KyxiU7J2OHFSoEHKS+EZ3fv5l1t9CyCiop6l/ZYeWbrgoQejw==",
- "dev": true
- },
- "node_modules/pseudomap": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz",
- "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM= sha512-b/YwNhb8lk1Zz2+bXXpS/LK9OisiZZ1SNsSLxN1x2OXVEhW2Ckr/7mWE5vrC1ZTiJlD9g19jWszTmJsB+oEpFQ==",
- "dev": true
- },
- "node_modules/psl": {
- "version": "1.8.0",
- "resolved": "https://registry.npmjs.org/psl/-/psl-1.8.0.tgz",
- "integrity": "sha512-RIdOzyoavK+hA18OGGWDqUTsCLhtA7IcZ/6NCs4fFJaHBDab+pDDmDIByWFRQJq2Cd7r1OoQxBGKOaztq+hjIQ==",
- "dev": true
- },
- "node_modules/public-encrypt": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/public-encrypt/-/public-encrypt-4.0.3.tgz",
- "integrity": "sha512-zVpa8oKZSz5bTMTFClc1fQOnyyEzpl5ozpi1B5YcvBrdohMjH2rfsBtyXcuNuwjsDIXmBYlF2N5FlJYhR29t8Q==",
- "dev": true,
- "dependencies": {
- "bn.js": "^4.1.0",
- "browserify-rsa": "^4.0.0",
- "create-hash": "^1.1.0",
- "parse-asn1": "^5.0.0",
- "randombytes": "^2.0.1",
- "safe-buffer": "^5.1.2"
- }
- },
- "node_modules/public-encrypt/node_modules/bn.js": {
- "version": "4.12.0",
- "resolved": "https://registry.npmjs.org/bn.js/-/bn.js-4.12.0.tgz",
- "integrity": "sha512-c98Bf3tPniI+scsdk237ku1Dc3ujXQTSgyiPUDEOe7tRkhrqridvh8klBv0HCEso1OLOYcHuCv/cS6DNxKH+ZA==",
- "dev": true
- },
- "node_modules/pump": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz",
- "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==",
- "dev": true,
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "node_modules/pumpify": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/pumpify/-/pumpify-1.5.1.tgz",
- "integrity": "sha512-oClZI37HvuUJJxSKKrC17bZ9Cu0ZYhEAGPsPUy9KlMUmv9dKX2o77RUmq7f3XjIxbwyGwYzbzQ1L2Ks8sIradQ==",
- "dev": true,
- "dependencies": {
- "duplexify": "^3.6.0",
- "inherits": "^2.0.3",
- "pump": "^2.0.0"
- }
- },
- "node_modules/pumpify/node_modules/pump": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/pump/-/pump-2.0.1.tgz",
- "integrity": "sha512-ruPMNRkN3MHP1cWJc9OWr+T/xDP0jhXYCLfJcBuX54hhfIBnaQmAUMfDcG4DM5UMWByBbJY69QSphm3jtDKIkA==",
- "dev": true,
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "once": "^1.3.1"
- }
- },
- "node_modules/punycode": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz",
- "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/purgecss": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/purgecss/-/purgecss-4.1.3.tgz",
- "integrity": "sha512-99cKy4s+VZoXnPxaoM23e5ABcP851nC2y2GROkkjS8eJaJtlciGavd7iYAw2V84WeBqggZ12l8ef44G99HmTaw==",
- "dev": true,
- "dependencies": {
- "commander": "^8.0.0",
- "glob": "^7.1.7",
- "postcss": "^8.3.5",
- "postcss-selector-parser": "^6.0.6"
- },
- "bin": {
- "purgecss": "bin/purgecss.js"
- }
- },
- "node_modules/purgecss/node_modules/commander": {
- "version": "8.3.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-8.3.0.tgz",
- "integrity": "sha512-OkTL9umf+He2DZkUq8f8J9of7yL6RJKI24dVITBmNfZBmri9zYZQrKkuXiKhyfPSu8tUhnVBB1iKXevvnlR4Ww==",
- "dev": true,
- "engines": {
- "node": ">= 12"
- }
- },
- "node_modules/purgecss/node_modules/postcss": {
- "version": "8.4.4",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.4.tgz",
- "integrity": "sha512-joU6fBsN6EIer28Lj6GDFoC/5yOZzLCfn0zHAn/MYXI7aPt4m4hK5KC5ovEZXy+lnCjmYIbQWngvju2ddyEr8Q==",
- "dev": true,
- "dependencies": {
- "nanoid": "^3.1.30",
- "picocolors": "^1.0.0",
- "source-map-js": "^1.0.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- }
- },
- "node_modules/q": {
- "version": "1.5.1",
- "resolved": "https://registry.npmjs.org/q/-/q-1.5.1.tgz",
- "integrity": "sha1-fjL3W0E4EpHQRhHxvxQQmsAGUdc= sha512-kV/CThkXo6xyFEZUugw/+pIOywXcDbFYgSct5cT3gqlbkBE1SJdwy6UQoZvodiWF/ckQLZyDE/Bu1M6gVu5lVw==",
- "deprecated": "You or someone you depend on is using Q, the JavaScript Promise library that gave JavaScript developers strong feelings about promises. They can almost certainly migrate to the native JavaScript promise now. Thank you literally everyone for joining me in this bet against the odds. Be excellent to each other.\n\n(For a CapTP with native promises, see @endo/eventual-send and @endo/captp)",
- "dev": true,
- "engines": {
- "node": ">=0.6.0",
- "teleport": ">=0.2.0"
- }
- },
- "node_modules/qs": {
- "version": "6.5.2",
- "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz",
- "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==",
- "dev": true,
"engines": {
"node": ">=0.6"
- }
- },
- "node_modules/query-string": {
- "version": "4.3.4",
- "resolved": "https://registry.npmjs.org/query-string/-/query-string-4.3.4.tgz",
- "integrity": "sha1-u7aTucqRXCMlFbIosaArYJBD2+s= sha512-O2XLNDBIg1DnTOa+2XrIwSiXEV8h2KImXUnjhhn2+UsvZ+Es2uyd5CCRTNQlDGbzUQOW3aYCBx9rVA6dzsiY7Q==",
- "dev": true,
- "dependencies": {
- "object-assign": "^4.1.0",
- "strict-uri-encode": "^1.0.0"
},
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/querystring": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz",
- "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA= sha512-X/xY82scca2tau62i9mDyU9K+I+djTMUsvwf7xnUX5GLvVzgJybOJf4Y6o9Zx3oJK/LSXg5tTZBjwzqVPaPO2g==",
- "deprecated": "The querystring API is considered Legacy. new code should use the URLSearchParams API instead.",
- "dev": true,
- "engines": {
- "node": ">=0.4.x"
- }
- },
- "node_modules/querystring-es3": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/querystring-es3/-/querystring-es3-0.2.1.tgz",
- "integrity": "sha1-nsYfeQSYdXB9aUFFlv2Qek1xHnM= sha512-773xhDQnZBMFobEiztv8LIl70ch5MSF/jUQVlhwFyBILqq96anmoctVIYz+ZRp0qbCKATTn6ev02M3r7Ga5vqA==",
- "dev": true,
- "engines": {
- "node": ">=0.4.x"
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/querystringify": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/querystringify/-/querystringify-2.2.0.tgz",
- "integrity": "sha512-FIqgj2EUvTa7R50u0rGsyTftzjYmv/a3hO345bZNrqabNqjtgiDMgmo4mkUjd+nzU5oF3dClKqFIPUKybUyqoQ==",
- "dev": true
- },
"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",
@@ -13879,29 +11978,20 @@
"type": "consulting",
"url": "https://feross.org/support"
}
- ]
- },
- "node_modules/quick-lru": {
- "version": "5.1.1",
- "resolved": "https://registry.npmjs.org/quick-lru/-/quick-lru-5.1.1.tgz",
- "integrity": "sha512-WuyALRjWPDGtt/wzJiadO5AXY+8hZ80hVpe6MyivgraREW751X3SbhRvG3eLKOYN+8VEvqLcf3wdnt44Z4S4SA==",
- "dev": true,
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
+ ],
+ "license": "MIT"
},
"node_modules/quickselect": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/quickselect/-/quickselect-2.0.0.tgz",
- "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw=="
+ "integrity": "sha512-RKJ22hX8mHe3Y6wH/N3wCM6BWtjaxIyyUIkpHOvfFnxdI4yD4tBXEBKSbriGujF6jnSVkJrffuo6vxACiSSxIw==",
+ "license": "ISC"
},
"node_modules/raf": {
"version": "3.4.1",
"resolved": "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz",
"integrity": "sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA==",
+ "license": "MIT",
"dependencies": {
"performance-now": "^2.1.0"
}
@@ -13911,51 +12001,44 @@
"resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz",
"integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"safe-buffer": "^5.1.0"
}
},
- "node_modules/randomfill": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/randomfill/-/randomfill-1.0.4.tgz",
- "integrity": "sha512-87lcbR8+MhcWcUiQ+9e+Rwx8MyR2P7qnt15ynUlbm3TU/fjbgz4GsvfSUDTemtCCtVCqb4ZcEFlyPNTh9bBTLw==",
- "dev": true,
- "dependencies": {
- "randombytes": "^2.0.5",
- "safe-buffer": "^5.1.0"
- }
- },
"node_modules/range-parser": {
"version": "1.2.1",
"resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz",
"integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.6"
}
},
"node_modules/raw-body": {
- "version": "2.4.0",
- "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.4.0.tgz",
- "integrity": "sha512-4Oz8DUIwdvoa5qMJelxipzi/iJIi40O5cGV1wNYp5hvZP8ZN0T+jiNkL0QepXs+EsQ9XJ8ipEDoiH70ySUJP3Q==",
+ "version": "2.5.3",
+ "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.5.3.tgz",
+ "integrity": "sha512-s4VSOf6yN0rvbRZGxs8Om5CWj6seneMwK3oDb4lWDH0UPhWcxwOWw5+qk24bxq87szX1ydrwylIOp2uG1ojUpA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "bytes": "3.1.0",
- "http-errors": "1.7.2",
- "iconv-lite": "0.4.24",
- "unpipe": "1.0.0"
+ "bytes": "~3.1.2",
+ "http-errors": "~2.0.1",
+ "iconv-lite": "~0.4.24",
+ "unpipe": "~1.0.0"
},
"engines": {
"node": ">= 0.8"
}
},
- "node_modules/raw-body/node_modules/bytes": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.0.tgz",
- "integrity": "sha512-zauLjrfCG+xvoyaqLoV8bLVXXNGC4JqlxFCutSDWA6fJrTo2ZuvLYTqZ7aHBLZSMOopbzwv8f+wZcVzfVTI2Dg==",
- "dev": true,
- "engines": {
- "node": ">= 0.8"
+ "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==",
+ "license": "MIT",
+ "dependencies": {
+ "pify": "^2.3.0"
}
},
"node_modules/read-pkg": {
@@ -13963,6 +12046,7 @@
"resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-5.2.0.tgz",
"integrity": "sha512-Ug69mNOpfvKDAc2Q8DRpMjjzdtrnv9HcSMX+4VsZxD1aZ6ZzrIE7rlzXBtWTyhULSMKg076AW6WR5iZpD0JiOg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/normalize-package-data": "^2.4.0",
"normalize-package-data": "^2.5.0",
@@ -13973,186 +12057,187 @@
"node": ">=8"
}
},
- "node_modules/read-pkg/node_modules/type-fest": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
- "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
+ "node_modules/read-pkg-up": {
+ "version": "7.0.1",
+ "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-7.0.1.tgz",
+ "integrity": "sha512-zK0TB7Xd6JpCLmlLmufqykGE+/TlOePD6qKClNW7hHDKFh/J7/7gCWGR7joEQEW1bKq3a3yUZSObOoWLFQ4ohg==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "find-up": "^4.1.0",
+ "read-pkg": "^5.2.0",
+ "type-fest": "^0.8.1"
+ },
"engines": {
"node": ">=8"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/readable-stream": {
- "version": "2.3.7",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.7.tgz",
- "integrity": "sha512-Ebho8K4jIbHAxnuxi7o42OrZgF/ZTNcsZj6nRKyUmkhLFq8CHItp/fy6hQZuZmP/n3yZ9VBUbp4zz/mX8hmYPw==",
+ "node_modules/read-pkg-up/node_modules/find-up": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
+ "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "core-util-is": "~1.0.0",
- "inherits": "~2.0.3",
- "isarray": "~1.0.0",
- "process-nextick-args": "~2.0.0",
- "safe-buffer": "~5.1.1",
- "string_decoder": "~1.1.1",
- "util-deprecate": "~1.0.1"
+ "locate-path": "^5.0.0",
+ "path-exists": "^4.0.0"
+ },
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/readable-stream/node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ=="
- },
- "node_modules/readdirp": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
- "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "node_modules/read-pkg-up/node_modules/locate-path": {
+ "version": "5.0.0",
+ "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
+ "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "picomatch": "^2.2.1"
+ "p-locate": "^4.1.0"
},
"engines": {
- "node": ">=8.10.0"
+ "node": ">=8"
}
},
- "node_modules/reduce-css-calc": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/reduce-css-calc/-/reduce-css-calc-2.1.8.tgz",
- "integrity": "sha512-8liAVezDmUcH+tdzoEGrhfbGcP7nOV4NkGE3a74+qqvE7nt9i4sKLGBuZNOnpI4WiGksiNPklZxva80061QiPg==",
+ "node_modules/read-pkg-up/node_modules/p-limit": {
+ "version": "2.3.0",
+ "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
+ "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "css-unit-converter": "^1.1.1",
- "postcss-value-parser": "^3.3.0"
+ "p-try": "^2.0.0"
+ },
+ "engines": {
+ "node": ">=6"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/reduce-css-calc/node_modules/postcss-value-parser": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-3.3.1.tgz",
- "integrity": "sha512-pISE66AbVkp4fDQ7VHBwRNXzAAKJjw4Vw7nWI/+Q3vuly7SNfgYXvm6i5IgFylHGK5sP/xHAbB7N49OS4gWNyQ==",
- "dev": true
- },
- "node_modules/regenerate": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
- "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
- "dev": true
- },
- "node_modules/regenerate-unicode-properties": {
- "version": "9.0.0",
- "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-9.0.0.tgz",
- "integrity": "sha512-3E12UeNSPfjrgwjkR81m5J7Aw/T55Tu7nUyZVQYCKEOs+2dkxEY+DpPtZzO4YruuiPb7NkYLVcyJC4+zCbk5pA==",
+ "node_modules/read-pkg-up/node_modules/p-locate": {
+ "version": "4.1.0",
+ "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
+ "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "regenerate": "^1.4.2"
+ "p-limit": "^2.2.0"
},
"engines": {
- "node": ">=4"
+ "node": ">=8"
}
},
- "node_modules/regenerator-runtime": {
- "version": "0.13.11",
- "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz",
- "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg=="
- },
- "node_modules/regenerator-transform": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/regenerator-transform/-/regenerator-transform-0.14.5.tgz",
- "integrity": "sha512-eOf6vka5IO151Jfsw2NO9WpGX58W6wWmefK3I1zEGr0lOD0u8rwPaNqQL1aRxUaxLeKO3ArNh3VYg1KbaD+FFw==",
+ "node_modules/read-pkg-up/node_modules/type-fest": {
+ "version": "0.8.1",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.8.1.tgz",
+ "integrity": "sha512-4dbzIzqvjtgiM5rw1k5rEHtBANKmdudhGyBEajN01fEyhaAIhsoKNy6y7+IN93IfpFtwY9iqi7kD+xwKhQsNJA==",
"dev": true,
- "dependencies": {
- "@babel/runtime": "^7.8.4"
+ "license": "(MIT OR CC0-1.0)",
+ "engines": {
+ "node": ">=8"
}
},
- "node_modules/regex-not": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/regex-not/-/regex-not-1.0.2.tgz",
- "integrity": "sha512-J6SDjUgDxQj5NusnOtdFxDwN/+HWykR8GELwctJ7mdqhcyy1xEc4SRFHUXvxTp661YaVKAjfRLZ9cCqS6tn32A==",
+ "node_modules/readable-stream": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.2.tgz",
+ "integrity": "sha512-9u/sniCrY3D5WdsERHzHE4G2YCXqoG5FTHUiCC4SIbr6XcLZBY05ya9EKjYek9O5xOAwjGq+1JdGBAS7Q9ScoA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "extend-shallow": "^3.0.2",
- "safe-regex": "^1.1.0"
+ "inherits": "^2.0.3",
+ "string_decoder": "^1.1.1",
+ "util-deprecate": "^1.0.1"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 6"
}
},
- "node_modules/regexp.prototype.flags": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/regexp.prototype.flags/-/regexp.prototype.flags-1.3.1.tgz",
- "integrity": "sha512-JiBdRBq91WlY7uRJ0ds7R+dU02i6LKi8r3BuQhNXn+kmeLN+EfHhfjqMRis1zJxnlu88hq/4dx0P2OP3APRTOA==",
- "dev": true,
+ "node_modules/readdirp": {
+ "version": "3.6.0",
+ "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz",
+ "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==",
+ "license": "MIT",
"dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
+ "picomatch": "^2.2.1"
},
"engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "node": ">=8.10.0"
}
},
- "node_modules/regexpp": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz",
- "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==",
+ "node_modules/regenerate": {
+ "version": "1.4.2",
+ "resolved": "https://registry.npmjs.org/regenerate/-/regenerate-1.4.2.tgz",
+ "integrity": "sha512-zrceR/XhGYU/d/opr2EKO7aRHUeiBI8qjtfHqADTwZd6Szfy16la6kqD0MIUs5z5hx6AaKa+PixpPrR289+I0A==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "node_modules/regenerate-unicode-properties": {
+ "version": "10.2.2",
+ "resolved": "https://registry.npmjs.org/regenerate-unicode-properties/-/regenerate-unicode-properties-10.2.2.tgz",
+ "integrity": "sha512-m03P+zhBeQd1RGnYxrGyDAPpWX/epKirLrp8e3qevZdVkKtnCrjjWczIbYc8+xd6vcTStVlqfycTx1KR4LOr0g==",
"dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "regenerate": "^1.4.2"
+ },
"engines": {
- "node": ">=6.5.0"
+ "node": ">=4"
}
},
"node_modules/regexpu-core": {
- "version": "4.8.0",
- "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-4.8.0.tgz",
- "integrity": "sha512-1F6bYsoYiz6is+oz70NWur2Vlh9KWtswuRuzJOfeYUrfPX2o8n74AnUVaOGDbUqVGO9fNHu48/pjJO4sNVwsOg==",
+ "version": "6.4.0",
+ "resolved": "https://registry.npmjs.org/regexpu-core/-/regexpu-core-6.4.0.tgz",
+ "integrity": "sha512-0ghuzq67LI9bLXpOX/ISfve/Mq33a4aFRzoQYhnnok1JOFpmE/A2TBGkNVenOGEeSBCjIiWcc6MVOG5HEQv0sA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"regenerate": "^1.4.2",
- "regenerate-unicode-properties": "^9.0.0",
- "regjsgen": "^0.5.2",
- "regjsparser": "^0.7.0",
+ "regenerate-unicode-properties": "^10.2.2",
+ "regjsgen": "^0.8.0",
+ "regjsparser": "^0.13.0",
"unicode-match-property-ecmascript": "^2.0.0",
- "unicode-match-property-value-ecmascript": "^2.0.0"
+ "unicode-match-property-value-ecmascript": "^2.2.1"
},
"engines": {
"node": ">=4"
}
},
"node_modules/regjsgen": {
- "version": "0.5.2",
- "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.5.2.tgz",
- "integrity": "sha512-OFFT3MfrH90xIW8OOSyUrk6QHD5E9JOTeGodiJeBS3J6IwlgzJMNE/1bZklWz5oTg+9dCMyEetclvCVXOPoN3A==",
- "dev": true
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/regjsgen/-/regjsgen-0.8.0.tgz",
+ "integrity": "sha512-RvwtGe3d7LvWiDQXeQw8p5asZUmfU1G/l6WbUXeHta7Y2PEIvBTwH6E2EfmYUK8pxcxEdEmaomqyp0vZZ7C+3Q==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/regjsparser": {
- "version": "0.7.0",
- "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.7.0.tgz",
- "integrity": "sha512-A4pcaORqmNMDVwUjWoTzuhwMGpP+NykpfqAsEgI1FSH/EzC7lrN5TMd+kN8YCovX+jMpu8eaqXgXPCa0g8FQNQ==",
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/regjsparser/-/regjsparser-0.13.1.tgz",
+ "integrity": "sha512-dLsljMd9sqwRkby8zhO1gSg3PnJIBFid8f4CQj/sXx+7cKx+E7u0PKhZ+U4wmhx7EfmtvnA318oVaIkAB1lRJw==",
"dev": true,
+ "license": "BSD-2-Clause",
"dependencies": {
- "jsesc": "~0.5.0"
+ "jsesc": "~3.1.0"
},
"bin": {
"regjsparser": "bin/parser"
}
},
- "node_modules/regjsparser/node_modules/jsesc": {
- "version": "0.5.0",
- "resolved": "https://registry.npmjs.org/jsesc/-/jsesc-0.5.0.tgz",
- "integrity": "sha1-597mbjXW/Bb3EP6R1c9p9w8IkR0= sha512-uZz5UnB7u4T9LvwmFqXii7pZSouaRPorGs5who1Ip7VO0wxanFvBL7GkM6dTHlgX+jhBApRetaWpnDabOeTcnA==",
- "dev": true,
- "bin": {
- "jsesc": "bin/jsesc"
- }
- },
"node_modules/regl": {
"name": "@plotly/regl",
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/@plotly/regl/-/regl-2.1.2.tgz",
- "integrity": "sha512-Mdk+vUACbQvjd0m/1JJjOOafmkp/EpmHjISsopEz5Av44CBq7rPC05HHNbYGKVyNUF2zmEoBS/TT0pd0SPFFyw=="
+ "integrity": "sha512-Mdk+vUACbQvjd0m/1JJjOOafmkp/EpmHjISsopEz5Av44CBq7rPC05HHNbYGKVyNUF2zmEoBS/TT0pd0SPFFyw==",
+ "license": "MIT"
},
"node_modules/regl-error2d": {
"version": "2.0.12",
"resolved": "https://registry.npmjs.org/regl-error2d/-/regl-error2d-2.0.12.tgz",
"integrity": "sha512-r7BUprZoPO9AbyqM5qlJesrSRkl+hZnVKWKsVp7YhOl/3RIpi4UDGASGJY0puQ96u5fBYw/OlqV24IGcgJ0McA==",
+ "license": "MIT",
"dependencies": {
"array-bounds": "^1.0.1",
"color-normalize": "^1.5.0",
@@ -14164,9 +12249,10 @@
}
},
"node_modules/regl-line2d": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/regl-line2d/-/regl-line2d-3.1.2.tgz",
- "integrity": "sha512-nmT7WWS/WxmXAQMkgaMKWXaVmwJ65KCrjbqHGOUjjqQi6shfT96YbBOvelXwO9hG7/hjvbzjtQ2UO0L3e7YaXQ==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/regl-line2d/-/regl-line2d-3.1.3.tgz",
+ "integrity": "sha512-fkgzW+tTn4QUQLpFKsUIE0sgWdCmXAM3ctXcCgoGBZTSX5FE2A0M7aynz7nrZT5baaftLrk9te54B+MEq4QcSA==",
+ "license": "MIT",
"dependencies": {
"array-bounds": "^1.0.1",
"array-find-index": "^1.0.2",
@@ -14175,7 +12261,6 @@
"earcut": "^2.1.5",
"es6-weak-map": "^2.0.3",
"flatten-vertex-data": "^1.0.2",
- "glslify": "^7.0.0",
"object-assign": "^4.1.1",
"parse-rect": "^1.2.0",
"pick-by-alias": "^1.2.0",
@@ -14183,21 +12268,17 @@
}
},
"node_modules/regl-scatter2d": {
- "version": "3.3.1",
- "resolved": "https://registry.npmjs.org/regl-scatter2d/-/regl-scatter2d-3.3.1.tgz",
- "integrity": "sha512-seOmMIVwaCwemSYz/y4WE0dbSO9svNFSqtTh5RE57I7PjGo3tcUYKtH0MTSoshcAsreoqN8HoCtnn8wfHXXfKQ==",
+ "version": "3.4.0",
+ "resolved": "https://registry.npmjs.org/regl-scatter2d/-/regl-scatter2d-3.4.0.tgz",
+ "integrity": "sha512-DavKQlHsI+iHZuLgOL+yGkg+sPd94CS+7FCBWkcQ6s/TbaNfUsF9eN591fjjSWIoKrGNfb/SEGhsXR5lXjqZ2w==",
+ "license": "MIT",
"dependencies": {
"@plotly/point-cluster": "^3.1.9",
- "array-range": "^1.0.1",
- "array-rearrange": "^2.2.2",
- "clamp": "^1.0.1",
+ "array-bounds": "^1.0.1",
"color-id": "^1.1.0",
"color-normalize": "^1.5.0",
- "color-rgba": "^2.1.1",
"flatten-vertex-data": "^1.0.2",
"glslify": "^7.0.0",
- "is-iexplorer": "^1.0.0",
- "object-assign": "^4.1.1",
"parse-rect": "^1.2.0",
"pick-by-alias": "^1.2.0",
"to-float32": "^1.1.0",
@@ -14208,6 +12289,7 @@
"version": "1.0.14",
"resolved": "https://registry.npmjs.org/regl-splom/-/regl-splom-1.0.14.tgz",
"integrity": "sha512-OiLqjmPRYbd7kDlHC6/zDf6L8lxgDC65BhC8JirhP4ykrK4x22ZyS+BnY8EUinXKDeMgmpRwCvUmk7BK4Nweuw==",
+ "license": "MIT",
"dependencies": {
"array-bounds": "^1.0.1",
"array-range": "^1.0.1",
@@ -14222,154 +12304,72 @@
"node_modules/relateurl": {
"version": "0.2.7",
"resolved": "https://registry.npmjs.org/relateurl/-/relateurl-0.2.7.tgz",
- "integrity": "sha1-VNvzd+UUQKypCkzSdGANP/LYiKk= sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
+ "integrity": "sha512-G08Dxvm4iDN3MLM0EsP62EDV9IuhXPR6blNz6Utcp7zyV3tr4HVNINt6MpaRWbxoOHT3Q7YN2P+jaHX8vUbgog==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">= 0.10"
}
},
- "node_modules/remove-trailing-separator": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz",
- "integrity": "sha1-wkvOKig62tW8P1jg1IJJuSN52O8= sha512-/hS+Y0u3aOfIETiaiirUFwDBDzmXPvO+jAfKTitUngIPzdKc6Z0LoFjM/CK5PL4C+eKwHohlHAb6H0VFfmmUsw==",
- "dev": true
- },
"node_modules/renderkid": {
- "version": "2.0.7",
- "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-2.0.7.tgz",
- "integrity": "sha512-oCcFyxaMrKsKcTY59qnCAtmDVSLfPbrv6A3tVbPdFMMrv5jaK10V6m40cKsoPNhAqN6rmHW9sswW4o3ruSrwUQ==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/renderkid/-/renderkid-3.0.0.tgz",
+ "integrity": "sha512-q/7VIQA8lmM1hF+jn+sFSPWGlMkSAeNYcPLmDQx2zzuiDfaLrOmumR8iaUKlenFgh0XRPIUeSPlH3A+AW3Z5pg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"css-select": "^4.1.3",
"dom-converter": "^0.2.0",
"htmlparser2": "^6.1.0",
"lodash": "^4.17.21",
- "strip-ansi": "^3.0.1"
+ "strip-ansi": "^6.0.1"
}
},
- "node_modules/renderkid/node_modules/ansi-regex": {
+ "node_modules/require-directory": {
"version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8= sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/renderkid/node_modules/strip-ansi": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/repeat-element": {
- "version": "1.1.4",
- "resolved": "https://registry.npmjs.org/repeat-element/-/repeat-element-1.1.4.tgz",
- "integrity": "sha512-LFiNfRcSu7KK3evMyYOuCzv3L10TW7yC1G2/+StMjK8Y6Vqd2MG7r/Qjw4ghtuCOjFvlnms/iMmLqpvW/ES/WQ==",
+ "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
+ "integrity": "sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/repeat-string": {
- "version": "1.6.1",
- "resolved": "https://registry.npmjs.org/repeat-string/-/repeat-string-1.6.1.tgz",
- "integrity": "sha1-jcrkcOHIirwtYA//Sndihtp15jc= sha512-PV0dzCYDNfRi1jCDbJzpW7jNNDRuCOG/jI5ctQcGKt/clZD+YcPS3yIlWuTJMmESC8aevCFmWJy5wjAFgNqN6w==",
- "dev": true,
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/request": {
- "version": "2.88.2",
- "resolved": "https://registry.npmjs.org/request/-/request-2.88.2.tgz",
- "integrity": "sha512-MsvtOrfG9ZcrOwAW+Qi+F6HbD0CWXEh9ou77uOb7FM2WPhwT7smM833PzanhJLsgXjN89Ir6V2PczXNnMpwKhw==",
- "deprecated": "request has been deprecated, see https://github.com/request/request/issues/3142",
- "dev": true,
- "dependencies": {
- "aws-sign2": "~0.7.0",
- "aws4": "^1.8.0",
- "caseless": "~0.12.0",
- "combined-stream": "~1.0.6",
- "extend": "~3.0.2",
- "forever-agent": "~0.6.1",
- "form-data": "~2.3.2",
- "har-validator": "~5.1.3",
- "http-signature": "~1.2.0",
- "is-typedarray": "~1.0.0",
- "isstream": "~0.1.2",
- "json-stringify-safe": "~5.0.1",
- "mime-types": "~2.1.19",
- "oauth-sign": "~0.9.0",
- "performance-now": "^2.1.0",
- "qs": "~6.5.2",
- "safe-buffer": "^5.1.2",
- "tough-cookie": "~2.5.0",
- "tunnel-agent": "^0.6.0",
- "uuid": "^3.3.2"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/require-directory": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz",
- "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I= sha512-fGxEI7+wsG9xrvdjsrlmL22OMTTiHRwAMroiEeMgq8gzoLC/PQr7RsRDSTLUg/bZAZtF+TVIkHc6/4RIKrui+Q==",
- "dev": true,
+ "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==",
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/require-main-filename": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-2.0.0.tgz",
- "integrity": "sha512-NKN5kMDylKuldxYLSUfrbo5Tuzh4hd+2E8NPPX02mZtn1VuREQToYe/ZdlJy+J3uCpfaiGF05e7B8W0iXbQHmg==",
- "dev": true
- },
"node_modules/requires-port": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz",
- "integrity": "sha1-kl0mAdOaxIXgkc8NpcbmlNw9yv8= sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
- "dev": true
+ "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/resolve": {
- "version": "1.20.0",
- "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.20.0.tgz",
- "integrity": "sha512-wENBPt4ySzg4ybFQW2TT1zMQucPK95HSh/nq2CFTZVOGut2+pQvSsgtda4d26YrYcr067wjbmzOG8byDPBX63A==",
+ "version": "1.22.12",
+ "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.12.tgz",
+ "integrity": "sha512-TyeJ1zif53BPfHootBGwPRYT1RUt6oGWsaQr8UyZW/eAm9bKoijtvruSDEmZHm92CwS9nj7/fWttqPCgzep8CA==",
+ "license": "MIT",
"dependencies": {
- "is-core-module": "^2.2.0",
- "path-parse": "^1.0.6"
+ "es-errors": "^1.3.0",
+ "is-core-module": "^2.16.1",
+ "path-parse": "^1.0.7",
+ "supports-preserve-symlinks-flag": "^1.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/resolve-cwd": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/resolve-cwd/-/resolve-cwd-2.0.0.tgz",
- "integrity": "sha1-AKn3OHVW4nA46uIyyqNypqWbZlo= sha512-ccu8zQTrzVr954472aUVPLEcB3YpKSYR3cg/3lo1okzobPBM+1INXBbBZlDbnI/hbEocnf8j0QVo43hQKrbchg==",
- "dev": true,
- "dependencies": {
- "resolve-from": "^3.0.0"
+ "bin": {
+ "resolve": "bin/resolve"
},
"engines": {
- "node": ">=4"
- }
- },
- "node_modules/resolve-cwd/node_modules/resolve-from": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-3.0.0.tgz",
- "integrity": "sha1-six699nWiBvItuZTM17rywoYh0g= sha512-GnlH6vxLymXJNMBo7XP1fJIzBFbdYt49CuTwmB/6N53t+kMPRMFKz783LlQ4tv28XoQfMWinAJX6WCGf2IlaIw==",
- "dev": true,
- "engines": {
- "node": ">=4"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
"node_modules/resolve-from": {
@@ -14377,6 +12377,7 @@
"resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-4.0.0.tgz",
"integrity": "sha512-pb/MYmXstAkysRFx8piNI1tGFNQIFA3vkE3Gq4EuA1dF6gHp/+vgZqsCGJapvy8N3Q+4o7FwvquPJcnZ7RYy4g==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
@@ -14385,22 +12386,17 @@
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/resolve-protobuf-schema/-/resolve-protobuf-schema-2.1.0.tgz",
"integrity": "sha512-kI5ffTiZWmJaS/huM8wZfEMer1eRd7oJQhDuxeCLe3t7N7mX3z94CN0xPxBQxFYQTSNz9T0i+v6inKqSdK8xrQ==",
+ "license": "MIT",
"dependencies": {
"protocol-buffers-schema": "^3.3.1"
}
},
- "node_modules/resolve-url": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/resolve-url/-/resolve-url-0.2.1.tgz",
- "integrity": "sha1-LGN/53yJOv0qZj/iGqkIAGjiBSo= sha512-ZuF55hVUQaaczgOIwqWzkEcEidmlD/xl44x1UZnhOXcYuFN2S6+rcxpG+C1N3So0wvNI3DmJICUFfu2SxhBmvg==",
- "deprecated": "https://github.com/lydell/resolve-url#deprecated",
- "dev": true
- },
"node_modules/restore-cursor": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-3.1.0.tgz",
"integrity": "sha512-l+sSefzHpj5qimhFSE5a8nufZYAM3sBSVMAPtYkmC+4EH2anSGaEMXSD0izRQbu9nfyQ9y5JrVmp7E8oZrUjvA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"onetime": "^5.1.0",
"signal-exit": "^3.0.2"
@@ -14409,88 +12405,53 @@
"node": ">=8"
}
},
- "node_modules/ret": {
- "version": "0.1.15",
- "resolved": "https://registry.npmjs.org/ret/-/ret-0.1.15.tgz",
- "integrity": "sha512-TTlYpa+OL+vMMNG24xSlQGEJ3B/RzEfUlLct7b5G/ytav+wPrplCpVMFuwzXbkecJrb6IYo1iFb0S9v37754mg==",
- "dev": true,
- "engines": {
- "node": ">=0.12"
- }
- },
"node_modules/retry": {
- "version": "0.12.0",
- "resolved": "https://registry.npmjs.org/retry/-/retry-0.12.0.tgz",
- "integrity": "sha1-G0KmJmoh8HQh0bC1S33BZ7AcATs= sha512-9LkiTwjUh6rT555DtE9rTX+BKByPfrMzEAtnlEtdEwr3Nkffwiihqe2bWADg+OQRjt9gl6ICdmB/ZFDCGAtSow==",
+ "version": "0.13.1",
+ "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz",
+ "integrity": "sha512-XQBQ3I8W1Cge0Seh+6gjj03LbmRFWuoszgK9ooCpwYIrhhoO80pfq4cUkU5DkknwfOfFteRwlZ56PYOGYyFWdg==",
"dev": true,
+ "license": "MIT",
"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,
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/reusify/-/reusify-1.1.0.tgz",
+ "integrity": "sha512-g6QUff04oZpHs0eG5p83rFLhHeV00ug/Yf9nZM6fLeUrPguBTkTQOdpAWWspMh55TZfVQDPaN3NQJfbVRAxdIw==",
+ "license": "MIT",
"engines": {
"iojs": ">=1.0.0",
"node": ">=0.10.0"
}
},
- "node_modules/rgb-regex": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/rgb-regex/-/rgb-regex-1.0.1.tgz",
- "integrity": "sha1-wODWiC3w4jviVKR16O3UGRX+rrE= sha512-gDK5mkALDFER2YLqH6imYvK6g02gpNGM4ILDZ472EwWfXZnC2ZEpoB2ECXTyOVUKuk/bPJZMzwQPBYICzP+D3w==",
- "dev": true
- },
- "node_modules/rgba-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/rgba-regex/-/rgba-regex-1.0.0.tgz",
- "integrity": "sha1-QzdOLiyglosO8VI0YLfXMP8i7rM= sha512-zgn5OjNQXLUTdq8m17KdaicF6w89TZs8ZU8y0AYENIU6wG8GG6LLm0yLSiPY8DmaYmHdgRW8rnApjoT0fQRfMg==",
- "dev": true
- },
"node_modules/right-now": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/right-now/-/right-now-1.0.0.tgz",
- "integrity": "sha512-DA8+YS+sMIVpbsuKgy+Z67L9Lxb1p05mNxRpDPNksPDEFir4vmBlUtuN9jkTGn9YMMdlBuK7XQgFiz6ws+yhSg=="
+ "integrity": "sha512-DA8+YS+sMIVpbsuKgy+Z67L9Lxb1p05mNxRpDPNksPDEFir4vmBlUtuN9jkTGn9YMMdlBuK7XQgFiz6ws+yhSg==",
+ "license": "MIT"
},
"node_modules/rimraf": {
- "version": "2.7.1",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.7.1.tgz",
- "integrity": "sha512-uWjbaKIK3T1OSVptzX7Nl6PvQ3qAGtKEtVRjRuazjfL3Bx5eI409VZSqgND+4UNnmzLVdPj9FqFJNPqBZFve4w==",
+ "version": "3.0.2",
+ "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
+ "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
"deprecated": "Rimraf versions prior to v4 are no longer supported",
"dev": true,
+ "license": "ISC",
"dependencies": {
"glob": "^7.1.3"
},
"bin": {
"rimraf": "bin.js"
- }
- },
- "node_modules/ripemd160": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/ripemd160/-/ripemd160-2.0.2.tgz",
- "integrity": "sha512-ii4iagi25WusVoiC4B4lq7pbXfAp3D9v5CwfkY33vffw2+pkDjY1D8GaN7spsxvCSx8dkPqOZCEZyfxcmJG2IA==",
- "dev": true,
- "dependencies": {
- "hash-base": "^3.0.0",
- "inherits": "^2.0.1"
- }
- },
- "node_modules/run-async": {
- "version": "2.4.1",
- "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.4.1.tgz",
- "integrity": "sha512-tvVnVv01b8c1RrA6Ep7JkStj85Guv/YrMcwqYQnwjsAS2cTmmPGBBjAjpCW7RrSodNSoE2/qg9O4bceNvUuDgQ==",
- "dev": true,
- "engines": {
- "node": ">=0.12.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/isaacs"
}
},
"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",
@@ -14505,65 +12466,59 @@
"url": "https://feross.org/support"
}
],
+ "license": "MIT",
"dependencies": {
"queue-microtask": "^1.2.2"
}
},
- "node_modules/run-queue": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/run-queue/-/run-queue-1.0.3.tgz",
- "integrity": "sha1-6Eg5bwV9Ij8kOGkkYY4laUFh7Ec= sha512-ntymy489o0/QQplUDnpYAYUsO50K9SBrIVaKCWDOJzYJts0f9WH9RFJkyagebkw5+y1oi00R7ynNW/d12GBumg==",
- "dev": true,
- "dependencies": {
- "aproba": "^1.1.1"
- }
- },
"node_modules/rw": {
"version": "1.3.3",
"resolved": "https://registry.npmjs.org/rw/-/rw-1.3.3.tgz",
- "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ=="
- },
- "node_modules/rxjs": {
- "version": "6.6.7",
- "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.6.7.tgz",
- "integrity": "sha512-hTdwr+7yYNIT5n4AMYp85KA6yw2Va0FLa3Rguvbpa4W3I5xynaBZo41cM3XM+4Q6fRMj3sBYIR1VAmZMXYJvRQ==",
- "dev": true,
- "dependencies": {
- "tslib": "^1.9.0"
- },
- "engines": {
- "npm": ">=2.0.0"
- }
+ "integrity": "sha512-PdhdWy89SiZogBLaw42zdeqtRJ//zFd2PgQavcICDUgJT5oW10QCRKbJ6bg4r0/UY2M6BWd5tkxuGFRvCkgfHQ==",
+ "license": "BSD-3-Clause"
},
"node_modules/safe-buffer": {
- "version": "5.1.2",
- "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
- "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g=="
- },
- "node_modules/safe-regex": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/safe-regex/-/safe-regex-1.1.0.tgz",
- "integrity": "sha1-QKNmnzsHfR6UPURinhV91IAjvy4= sha512-aJXcif4xnaNUzvUuC5gcb46oTS7zvg4jpMTnuqtrEPlR3vFr4pxtdTwaF1Qs3Enjn9HK+ZlwQui+a7z0SywIzg==",
+ "version": "5.2.1",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz",
+ "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==",
"dev": true,
- "dependencies": {
- "ret": "~0.1.10"
- }
+ "funding": [
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/feross"
+ },
+ {
+ "type": "patreon",
+ "url": "https://www.patreon.com/feross"
+ },
+ {
+ "type": "consulting",
+ "url": "https://feross.org/support"
+ }
+ ],
+ "license": "MIT"
},
"node_modules/safer-buffer": {
"version": "2.1.2",
"resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz",
- "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg=="
+ "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==",
+ "license": "MIT"
},
"node_modules/sax": {
- "version": "1.2.4",
- "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz",
- "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw=="
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/sax/-/sax-1.6.0.tgz",
+ "integrity": "sha512-6R3J5M4AcbtLUdZmRv2SygeVaM7IhrLXu9BmnOGmmACak8fiUtOsYNWUS4uK7upbmHIBbLBeFeI//477BKLBzA==",
+ "license": "BlueOak-1.0.0",
+ "engines": {
+ "node": ">=11.0.0"
+ }
},
"node_modules/schema-utils": {
"version": "2.7.1",
"resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-2.7.1.tgz",
"integrity": "sha512-SHiNtMOUGWBQJwzISiVYKu82GiV4QYGePp3odlY1tuKO7gPtphAT5R/py0fA6xtbgLL/RvtJZnU9b8s0F1q0Xg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"@types/json-schema": "^7.0.5",
"ajv": "^6.12.4",
@@ -14580,51 +12535,62 @@
"node_modules/seedrandom": {
"version": "3.0.5",
"resolved": "https://registry.npmjs.org/seedrandom/-/seedrandom-3.0.5.tgz",
- "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg=="
+ "integrity": "sha512-8OwmbklUNzwezjGInmZ+2clQmExQPvomqjL7LFqOYqtmuxRgQYqOD3mHaU+MvZn5FLUeVxVfQjwLZW/n/JFuqg==",
+ "license": "MIT"
},
"node_modules/select-hose": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/select-hose/-/select-hose-2.0.0.tgz",
- "integrity": "sha1-Yl2GWPhlr0Psliv8N2o3NZpJlMo= sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
- "dev": true
+ "integrity": "sha512-mEugaLK+YfkijB4fx0e6kImuJdCIt2LxCRcbEYPqRGCs4F2ogyfZU5IAZRdjCP8JPq2AtdNoC/Dux63d9Kiryg==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/selfsigned": {
- "version": "1.10.11",
- "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-1.10.11.tgz",
- "integrity": "sha512-aVmbPOfViZqOZPgRBT0+3u4yZFHpmnIghLMlAcb5/xhp5ZtB/RVnKhz5vl2M32CLXAqR4kha9zfhNg0Lf/sxKA==",
+ "version": "2.4.1",
+ "resolved": "https://registry.npmjs.org/selfsigned/-/selfsigned-2.4.1.tgz",
+ "integrity": "sha512-th5B4L2U+eGLq1TVh7zNRGBapioSORUeymIydxgFpwww9d2qyKvtuPU2jJuHvYAwwqi2Y596QBL3eEqcPEYL8Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "node-forge": "^0.10.0"
+ "@types/node-forge": "^1.3.0",
+ "node-forge": "^1"
+ },
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/semver": {
- "version": "6.3.0",
- "resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
- "integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
- "dev": true,
+ "version": "7.7.4",
+ "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.4.tgz",
+ "integrity": "sha512-vFKC2IEtQnVhpT78h1Yp8wzwrf8CM+MzKMHGJZfBtzhZNycRFnXsHk6E5TxIkkMsgNS7mdX3AGB7x2QM2di4lA==",
+ "license": "ISC",
"bin": {
"semver": "bin/semver.js"
+ },
+ "engines": {
+ "node": ">=10"
}
},
"node_modules/send": {
- "version": "0.17.1",
- "resolved": "https://registry.npmjs.org/send/-/send-0.17.1.tgz",
- "integrity": "sha512-BsVKsiGcQMFwT8UxypobUKyv7irCNRHk1T0G680vk88yf6LBByGcZJOTJCrTP2xVN6yI+XjPJcNuE3V4fT9sAg==",
+ "version": "0.19.2",
+ "resolved": "https://registry.npmjs.org/send/-/send-0.19.2.tgz",
+ "integrity": "sha512-VMbMxbDeehAxpOtWJXlcUS5E8iXh6QmN+BkRX1GARS3wRaXEEgzCcB10gTQazO42tpNIya8xIyNx8fll1OFPrg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"debug": "2.6.9",
- "depd": "~1.1.2",
- "destroy": "~1.0.4",
- "encodeurl": "~1.0.2",
+ "depd": "2.0.0",
+ "destroy": "1.2.0",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"etag": "~1.8.1",
- "fresh": "0.5.2",
- "http-errors": "~1.7.2",
+ "fresh": "~0.5.2",
+ "http-errors": "~2.0.1",
"mime": "1.6.0",
- "ms": "2.1.1",
- "on-finished": "~2.3.0",
+ "ms": "2.1.3",
+ "on-finished": "~2.4.1",
"range-parser": "~1.2.1",
- "statuses": "~1.5.0"
+ "statuses": "~2.0.2"
},
"engines": {
"node": ">= 0.8.0"
@@ -14635,6 +12601,7 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
@@ -14642,52 +12609,41 @@
"node_modules/send/node_modules/debug/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "node_modules/send/node_modules/mime": {
- "version": "1.6.0",
- "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz",
- "integrity": "sha512-x0Vn8spI+wuJ1O6S7gnbaQg8Pxh4NNHb7KSINmEWKiPE4RKOplvijn+NkmYmmRgP68mc70j2EbeTFRsrswaQeg==",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
"dev": true,
- "bin": {
- "mime": "cli.js"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/send/node_modules/ms": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz",
- "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==",
- "dev": true
+ "license": "MIT"
},
"node_modules/serialize-javascript": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-4.0.0.tgz",
- "integrity": "sha512-GaNA54380uFefWghODBWEGisLZFj00nS5ACs6yHa9nLqlLpVLO8ChDGeKRjZnV4Nh4n0Qi7nhYZD/9fCPzEqkw==",
+ "version": "6.0.2",
+ "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz",
+ "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==",
"dev": true,
+ "license": "BSD-3-Clause",
"dependencies": {
"randombytes": "^2.1.0"
}
},
"node_modules/serve-index": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.1.tgz",
- "integrity": "sha1-03aNabHn2C5c4FD/9bRTvqEqkjk= sha512-pXHfKNP4qujrtteMrSBb0rc8HJ9Ms/GrXwcUtUtD5s4ewDJI8bT3Cz2zTVRMKtri49pLx2e0Ya8ziP5Ya2pZZw==",
+ "version": "1.9.2",
+ "resolved": "https://registry.npmjs.org/serve-index/-/serve-index-1.9.2.tgz",
+ "integrity": "sha512-KDj11HScOaLmrPxl70KYNW1PksP4Nb/CLL2yvC+Qd2kHMPEEpfc4Re2e4FOay+bC/+XQl/7zAcWON3JVo5v3KQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "accepts": "~1.3.4",
+ "accepts": "~1.3.8",
"batch": "0.6.1",
"debug": "2.6.9",
"escape-html": "~1.0.3",
- "http-errors": "~1.6.2",
- "mime-types": "~2.1.17",
- "parseurl": "~1.3.2"
+ "http-errors": "~1.8.0",
+ "mime-types": "~2.1.35",
+ "parseurl": "~1.3.3"
},
"engines": {
"node": ">= 0.8.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/express"
}
},
"node_modules/serve-index/node_modules/debug": {
@@ -14695,521 +12651,282 @@
"resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
"integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ms": "2.0.0"
}
},
+ "node_modules/serve-index/node_modules/depd": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz",
+ "integrity": "sha512-7emPTl6Dpo6JRXOXjLRxck+FlLRX5847cLKEn00PLAgc3g2hTZZgr+e4c2v6QpSmLeFP3n5yUo7ft6avBK/5jQ==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
+ },
"node_modules/serve-index/node_modules/http-errors": {
- "version": "1.6.3",
- "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz",
- "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0= sha512-lks+lVC8dgGyh97jxvxeYTWQFvh4uw4yC12gVl63Cg30sjPX4wuGcdkICVXDAESr6OJGjqGA8Iz5mkeN6zlD7A==",
+ "version": "1.8.1",
+ "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.8.1.tgz",
+ "integrity": "sha512-Kpk9Sm7NmI+RHhnj6OIWDI1d6fIoFAtFt9RLaTMRlg/8w49juAStsrBgp0Dp4OdxdVbRIeKhtCUvoi/RuAhO4g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"depd": "~1.1.2",
- "inherits": "2.0.3",
- "setprototypeof": "1.1.0",
- "statuses": ">= 1.4.0 < 2"
+ "inherits": "2.0.4",
+ "setprototypeof": "1.2.0",
+ "statuses": ">= 1.5.0 < 2",
+ "toidentifier": "1.0.1"
},
"engines": {
"node": ">= 0.6"
}
},
- "node_modules/serve-index/node_modules/inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
- "dev": true
- },
"node_modules/serve-index/node_modules/ms": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "dev": true,
+ "license": "MIT"
},
- "node_modules/serve-index/node_modules/setprototypeof": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz",
- "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==",
- "dev": true
+ "node_modules/serve-index/node_modules/statuses": {
+ "version": "1.5.0",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
+ "integrity": "sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
+ "dev": true,
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.6"
+ }
},
"node_modules/serve-static": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.14.1.tgz",
- "integrity": "sha512-JMrvUwE54emCYWlTI+hGrGv5I8dEwmco/00EvkzIIsR7MqrHonbD9pO2MOfFnpFntl7ecpZs+3mW+XbQZu9QCg==",
+ "version": "1.16.3",
+ "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.16.3.tgz",
+ "integrity": "sha512-x0RTqQel6g5SY7Lg6ZreMmsOzncHFU7nhnRWkKgWuMTu5NN0DR5oruckMqRvacAN9d5w6ARnRBXl9xhDCgfMeA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "encodeurl": "~1.0.2",
+ "encodeurl": "~2.0.0",
"escape-html": "~1.0.3",
"parseurl": "~1.3.3",
- "send": "0.17.1"
+ "send": "~0.19.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
- "node_modules/set-blocking": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz",
- "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc= sha512-KiKBS8AnWGEyLzofFfmvKwpdPzqiy16LvQfK3yv/fVH7Bj13/wl3JSR1J+rfgRE9q7xUJK4qvgS8raSOeLUehw==",
- "dev": true
- },
- "node_modules/set-value": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/set-value/-/set-value-2.0.1.tgz",
- "integrity": "sha512-JxHc1weCN68wRY0fhCoXpyK55m/XPHafOmK4UWD7m2CI14GMcFypt4w/0+NV5f/ZMby2F6S2wwA7fgynh9gWSw==",
- "dev": true,
- "dependencies": {
- "extend-shallow": "^2.0.1",
- "is-extendable": "^0.1.1",
- "is-plain-object": "^2.0.3",
- "split-string": "^3.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/set-value/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "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,
+ "license": "MIT",
"dependencies": {
- "is-extendable": "^0.1.0"
+ "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.10.0"
- }
- },
- "node_modules/set-value/node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node": ">= 0.4"
}
},
- "node_modules/setimmediate": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz",
- "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU= sha512-MATJdZp8sLqDl/68LfQmbP8zKPLQNV6BIZoIgrscFDQ+RsvK/BxeDQOgyxKKoh0y/8h3BqVFnCqQ/gd+reiIXA==",
- "dev": true
- },
"node_modules/setprototypeof": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.1.tgz",
- "integrity": "sha512-JvdAWfbXeIGaZ9cILp38HntZSFSo3mWg6xGcJJsd+d4aRMOqauag1C63dJfDw7OaMYwEbHMOxEZ1lqVRYP2OAw==",
- "dev": true
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz",
+ "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==",
+ "dev": true,
+ "license": "ISC"
},
- "node_modules/sha.js": {
- "version": "2.4.11",
- "resolved": "https://registry.npmjs.org/sha.js/-/sha.js-2.4.11.tgz",
- "integrity": "sha512-QMEp5B7cftE7APOjk5Y6xgrbWu+WkLVQwk8JNjZ8nKRciZaByEW6MubieAiToS7+dwvrjGhH8jRXz3MVd0AYqQ==",
+ "node_modules/shallow-clone": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/shallow-clone/-/shallow-clone-3.0.1.tgz",
+ "integrity": "sha512-/6KqX+GVUdqPuPPd2LxDDxzX6CAbjJehAAOKlNpqqUpAqPM6HeL8f+o3a+JsyGjn2lv0WY8UsTgUJjU9Ok55NA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "inherits": "^2.0.1",
- "safe-buffer": "^5.0.1"
+ "kind-of": "^6.0.2"
},
- "bin": {
- "sha.js": "bin.js"
+ "engines": {
+ "node": ">=8"
}
},
"node_modules/shallow-copy": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/shallow-copy/-/shallow-copy-0.0.1.tgz",
- "integrity": "sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw=="
+ "integrity": "sha512-b6i4ZpVuUxB9h5gfCxPiusKYkqTMOjEbBs4wMaFbkfia4yFv92UKZ6Df8WXcKbn08JNL/abvg3FnMAOfakDvUw==",
+ "license": "MIT"
},
"node_modules/shebang-command": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz",
- "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo= sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==",
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-2.0.0.tgz",
+ "integrity": "sha512-kHxr2zZpYtdmrN1qDjrrX/Z1rR1kG8Dx+gkpK1G4eXmvXswmcE1hTWBWYUzlraYw1/yZp6YuDY77YtvbN0dmDA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "shebang-regex": "^1.0.0"
+ "shebang-regex": "^3.0.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
}
},
"node_modules/shebang-regex": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz",
- "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM= sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==",
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-3.0.0.tgz",
+ "integrity": "sha512-7++dFhtcx3353uBaq8DDR4NuxBetBzC7ZQOhmTQInHEd6bSrXdiEyzCvG07Z44UYdLShWUyXt5M/yhz8ekcb1A==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
}
},
"node_modules/shell-quote": {
- "version": "1.7.3",
- "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.7.3.tgz",
- "integrity": "sha512-Vpfqwm4EnqGdlsBFNmHhxhElJYrdfcxPThu+ryKS5J8L/fhAwLazFZtq+S+TWZ9ANj2piSQLGj6NQg+lKPmxrw==",
- "dev": true
- },
- "node_modules/side-channel": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.0.4.tgz",
- "integrity": "sha512-q5XPytqFEIKHkGdiMIrY10mvLRvnQh42/+GoBlFW3b2LXLE2xxJpZFdm94we0BaoV3RwJyGqg5wS7epxTv0Zvw==",
+ "version": "1.8.3",
+ "resolved": "https://registry.npmjs.org/shell-quote/-/shell-quote-1.8.3.tgz",
+ "integrity": "sha512-ObmnIF4hXNg1BqhnHmgbDETF8dLPCggZWBjkQfhZpbszZnYur5DUljTcCHii5LC3J5E0yeO/1LIMyH+UvHQgyw==",
"dev": true,
- "dependencies": {
- "call-bind": "^1.0.0",
- "get-intrinsic": "^1.0.2",
- "object-inspect": "^1.9.0"
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/signal-exit": {
- "version": "3.0.6",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.6.tgz",
- "integrity": "sha512-sDl4qMFpijcGw22U5w63KmD3cZJfBuFlVNbVMKje2keoKML7X2UzWbc4XrmEbDwg0NXJc3yv4/ox7b+JWb57kQ==",
- "dev": true
- },
- "node_modules/signum": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz",
- "integrity": "sha512-yodFGwcyt59XRh7w5W3jPcIQb3Bwi21suEfT7MAWnBX3iCdklJpgDgvGT9o04UonglZN5SNMfJFkHIR/jO8GHw=="
- },
- "node_modules/simple-swizzle": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz",
- "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo= sha512-JA//kQgZtbuY83m+xT+tXJkmJncGMTFT+C+g2h2R9uxkYIrE2yy9sgmcLhCnw57/WSD+Eh3J97FPEDFnbXnDUg==",
+ "node_modules/side-channel": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz",
+ "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-arrayish": "^0.3.1"
- }
- },
- "node_modules/simple-swizzle/node_modules/is-arrayish": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz",
- "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==",
- "dev": true
- },
- "node_modules/slash": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/slash/-/slash-2.0.0.tgz",
- "integrity": "sha512-ZYKh3Wh2z1PpEXWr0MpSBZ0V6mZHAQfYevttO11c51CaWjGTaadiKZ+wVt1PbMlDV5qhMFslpZCemhwOK7C89A==",
- "dev": true,
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.3",
+ "side-channel-list": "^1.0.0",
+ "side-channel-map": "^1.0.1",
+ "side-channel-weakmap": "^1.0.2"
+ },
"engines": {
- "node": ">=6"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/slice-ansi": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-2.1.0.tgz",
- "integrity": "sha512-Qu+VC3EwYLldKa1fCxuuvULvSJOKEgk9pi8dZeCVK7TqBfUNTH4sFkk4joj8afVSfAYgJoSOetjx9QWOJ5mYoQ==",
+ "node_modules/side-channel-list": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.1.tgz",
+ "integrity": "sha512-mjn/0bi/oUURjc5Xl7IaWi/OJJJumuoJFQJfDDyO46+hBWsfaVM65TBHq2eoZBhzl9EchxOijpkbRC8SVBQU0w==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^3.2.0",
- "astral-regex": "^1.0.0",
- "is-fullwidth-code-point": "^2.0.0"
+ "es-errors": "^1.3.0",
+ "object-inspect": "^1.13.4"
},
"engines": {
- "node": ">=6"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/slice-ansi/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "node_modules/side-channel-map": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz",
+ "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "color-convert": "^1.9.0"
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3"
},
"engines": {
- "node": ">=4"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/slice-ansi/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "node_modules/side-channel-weakmap": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz",
+ "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "color-name": "1.1.3"
+ "call-bound": "^1.0.2",
+ "es-errors": "^1.3.0",
+ "get-intrinsic": "^1.2.5",
+ "object-inspect": "^1.13.3",
+ "side-channel-map": "^1.0.1"
+ },
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/slice-ansi/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/slice-ansi/node_modules/is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
+ "node_modules/signal-exit": {
+ "version": "3.0.7",
+ "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
+ "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==",
"dev": true,
- "engines": {
- "node": ">=4"
- }
+ "license": "ISC"
+ },
+ "node_modules/signum": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/signum/-/signum-1.0.0.tgz",
+ "integrity": "sha512-yodFGwcyt59XRh7w5W3jPcIQb3Bwi21suEfT7MAWnBX3iCdklJpgDgvGT9o04UonglZN5SNMfJFkHIR/jO8GHw==",
+ "license": "MIT"
},
- "node_modules/snapdragon": {
- "version": "0.8.2",
- "resolved": "https://registry.npmjs.org/snapdragon/-/snapdragon-0.8.2.tgz",
- "integrity": "sha512-FtyOnWN/wCHTVXOMwvSv26d+ko5vWlIDD6zoUJ7LW8vh+ZBC8QdljveRP+crNrtBwioEUWy/4dMtbBjA4ioNlg==",
+ "node_modules/sirv": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/sirv/-/sirv-2.0.4.tgz",
+ "integrity": "sha512-94Bdh3cC2PKrbgSOUqTiGPWVZeSiXfKOVZNJniWoqrWrRkB1CJzBU3NEbiTsPcYy1lDsANA/THzS+9WBiy5nfQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "base": "^0.11.1",
- "debug": "^2.2.0",
- "define-property": "^0.2.5",
- "extend-shallow": "^2.0.1",
- "map-cache": "^0.2.2",
- "source-map": "^0.5.6",
- "source-map-resolve": "^0.5.0",
- "use": "^3.1.0"
+ "@polka/url": "^1.0.0-next.24",
+ "mrmime": "^2.0.0",
+ "totalist": "^3.0.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 10"
}
},
- "node_modules/snapdragon-node": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/snapdragon-node/-/snapdragon-node-2.1.1.tgz",
- "integrity": "sha512-O27l4xaMYt/RSQ5TR3vpWCAB5Kb/czIcqUFOM/C4fYcLnbZUc1PkjTAMjof2pBWaSTwOUd6qUHcFGVGj7aIwnw==",
+ "node_modules/slash": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
+ "integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
"dev": true,
- "dependencies": {
- "define-property": "^1.0.0",
- "isobject": "^3.0.0",
- "snapdragon-util": "^3.0.1"
- },
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=8"
}
},
- "node_modules/snapdragon-node/node_modules/define-property": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-1.0.0.tgz",
- "integrity": "sha1-dp66rz9KY6rTr56NMEybvnm/sOY= sha512-cZTYKFWspt9jZsMscWo8sc/5lbPC9Q0N5nBLgb+Yd915iL3udB1uFgS3B8YCx66UVHq018DAVFoee7x+gxggeA==",
- "dev": true,
- "dependencies": {
- "is-descriptor": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon-util": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/snapdragon-util/-/snapdragon-util-3.0.1.tgz",
- "integrity": "sha512-mbKkMdQKsjX4BAL4bRYTj21edOf8cN7XHdYUJEe+Zn99hVEYcMvKPct1IqNe7+AZPirn8BCDOQBHQZknqmKlZQ==",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.2.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon-util/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dev": true,
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/snapdragon/node_modules/define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
- "dev": true,
- "dependencies": {
- "is-descriptor": "^0.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
- "dev": true,
- "dependencies": {
- "is-extendable": "^0.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==",
- "deprecated": "Please upgrade to v0.1.7",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/is-accessor-descriptor/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==",
- "deprecated": "Please upgrade to v0.1.5",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/is-data-descriptor/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "dev": true,
- "dependencies": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/snapdragon/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
- "dev": true
- },
- "node_modules/sockjs": {
- "version": "0.3.24",
- "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
- "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
+ "node_modules/sockjs": {
+ "version": "0.3.24",
+ "resolved": "https://registry.npmjs.org/sockjs/-/sockjs-0.3.24.tgz",
+ "integrity": "sha512-GJgLTZ7vYb/JtPSSZ10hsOYIvEYsjbNU+zPdIHcUaWVNUEPivzxku31865sSSud0Da0W4lEeOPlmw93zLQchuQ==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"faye-websocket": "^0.11.3",
"uuid": "^8.3.2",
"websocket-driver": "^0.7.4"
}
},
- "node_modules/sockjs-client": {
- "version": "1.5.2",
- "resolved": "https://registry.npmjs.org/sockjs-client/-/sockjs-client-1.5.2.tgz",
- "integrity": "sha512-ZzRxPBISQE7RpzlH4tKJMQbHM9pabHluk0WBaxAQ+wm/UieeBVBou0p4wVnSQGN9QmpAZygQ0cDIypWuqOFmFQ==",
- "dev": true,
- "dependencies": {
- "debug": "^3.2.6",
- "eventsource": "^1.0.7",
- "faye-websocket": "^0.11.3",
- "inherits": "^2.0.4",
- "json3": "^3.3.3",
- "url-parse": "^1.5.3"
- }
- },
- "node_modules/sockjs-client/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/sockjs/node_modules/uuid": {
- "version": "8.3.2",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
- "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
- "dev": true,
- "bin": {
- "uuid": "dist/bin/uuid"
- }
- },
- "node_modules/sort-keys": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/sort-keys/-/sort-keys-1.1.2.tgz",
- "integrity": "sha1-RBttTTRnmPG05J6JIK37oOVD+a0= sha512-vzn8aSqKgytVik0iwdBEi+zevbTYZogewTUM6dtpmGwEcdzbub/TX4bCzRhebDCRC3QzXgJsLRKB2V/Oof7HXg==",
- "dev": true,
- "dependencies": {
- "is-plain-obj": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/sort-keys/node_modules/is-plain-obj": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-plain-obj/-/is-plain-obj-1.1.0.tgz",
- "integrity": "sha1-caUMhCnfync8kqOQpKA7OfzVHT4= sha512-yvkRyxmFKEOQ4pNXCmJG5AEQNlXJS5LaONXo5/cLdTZdWvsZ1ioJEonLGAosKlMWE8lwUy/bJzMjcw8az73+Fg==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-list-map": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/source-list-map/-/source-list-map-2.0.1.tgz",
- "integrity": "sha512-qnQ7gVMxGNxsiL4lEuJwe/To8UnK7fAnmbGEEH8RpLouuKbeEm0lhbQVFIrNSuB+G7tVrAlVsZgETT5nljf+Iw==",
- "dev": true
- },
"node_modules/source-map": {
- "version": "0.5.7",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.5.7.tgz",
- "integrity": "sha1-igOdLRAh0i0eoUyA2OpGi6LvP8w= sha512-LbrmJOMUSdEVxIKvdcJzQC+nQhe8FUZQTXQy6+I75skNgn3OoQ0DZA8YnFa7gp8tqtL3KPf1kmo0R5DoApeSGQ==",
- "dev": true,
+ "version": "0.6.1",
+ "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
+ "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
+ "license": "BSD-3-Clause",
"engines": {
"node": ">=0.10.0"
}
@@ -15223,83 +12940,58 @@
"node": ">=0.10.0"
}
},
- "node_modules/source-map-resolve": {
- "version": "0.5.3",
- "resolved": "https://registry.npmjs.org/source-map-resolve/-/source-map-resolve-0.5.3.tgz",
- "integrity": "sha512-Htz+RnsXWk5+P2slx5Jh3Q66vhQj1Cllm0zvnaY98+NFx+Dv2CF/f5O/t8x+KaNdrdIAsruNzoh/KpialbqAnw==",
- "deprecated": "See https://github.com/lydell/source-map-resolve#deprecated",
- "dev": true,
- "dependencies": {
- "atob": "^2.1.2",
- "decode-uri-component": "^0.2.0",
- "resolve-url": "^0.2.1",
- "source-map-url": "^0.4.0",
- "urix": "^0.1.0"
- }
- },
"node_modules/source-map-support": {
"version": "0.5.21",
"resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz",
"integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==",
- "dev": true,
+ "license": "MIT",
"dependencies": {
"buffer-from": "^1.0.0",
"source-map": "^0.6.0"
}
},
- "node_modules/source-map-support/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/source-map-url": {
- "version": "0.4.1",
- "resolved": "https://registry.npmjs.org/source-map-url/-/source-map-url-0.4.1.tgz",
- "integrity": "sha512-cPiFOTLUKvJFIg4SKVScy4ilPPW6rFgMgfuZJPNoDuMs3nC1HbMUycBoJw77xFIp6z1UJQJOfx6C9GMH80DiTw==",
- "deprecated": "See https://github.com/lydell/source-map-url#deprecated",
- "dev": true
- },
"node_modules/spdx-correct": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.1.1.tgz",
- "integrity": "sha512-cOYcUWwhCuHCXi49RhFRCyJEK3iPj1Ziz9DpViV3tbZOwXD49QzIN3MpOLJNxh2qwq2lJJZaKMVw9qNi4jTC0w==",
+ "version": "3.2.0",
+ "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.2.0.tgz",
+ "integrity": "sha512-kN9dJbvnySHULIluDHy32WHRUu3Og7B9sbY7tsFLctQkIqnMh3hErYgdMjTYuqmcXX+lK5T1lnUt3G7zNswmZA==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
"spdx-expression-parse": "^3.0.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/spdx-exceptions": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.3.0.tgz",
- "integrity": "sha512-/tTrYOC7PPI1nUAgx34hUpqXuyJG+DTHJTnIULG4rDygi4xu/tfgmq1e1cIRwRzwZgo4NLySi+ricLkZkw4i5A==",
- "dev": true
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.5.0.tgz",
+ "integrity": "sha512-PiU42r+xO4UbUS1buo3LPJkjlO7430Xn5SVAhdpzzsPHsjbYVflnnFdATgabnLude+Cqu25p6N+g2lw/PFsa4w==",
+ "dev": true,
+ "license": "CC-BY-3.0"
},
"node_modules/spdx-expression-parse": {
"version": "3.0.1",
"resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.1.tgz",
"integrity": "sha512-cbqHunsQWnJNE6KhVSMsMeH5H/L9EpymbzqTQ3uLwNCLZ1Q481oWaofqH7nO6V07xlXwY6PhQdQ2IedWx/ZK4Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"spdx-exceptions": "^2.1.0",
"spdx-license-ids": "^3.0.0"
}
},
"node_modules/spdx-license-ids": {
- "version": "3.0.11",
- "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.11.tgz",
- "integrity": "sha512-Ctl2BrFiM0X3MANYgj3CkygxhRmr9mi6xhejbdO960nF6EDJApTYpn0BQnDKlnNBULKiCN1n3w9EBkHK8ZWg+g==",
- "dev": true
+ "version": "3.0.23",
+ "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.23.tgz",
+ "integrity": "sha512-CWLcCCH7VLu13TgOH+r8p1O/Znwhqv/dbb6lqWy67G+pT1kHmeD/+V36AVb/vq8QMIQwVShJ6Ssl5FPh0fuSdw==",
+ "dev": true,
+ "license": "CC0-1.0"
},
"node_modules/spdy": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/spdy/-/spdy-4.0.2.tgz",
"integrity": "sha512-r46gZQZQV+Kl9oItvl1JZZqJKGr+oEkB08A6BzkiR7593/7IbtuncXHd2YoYeTsG4157ZssMu9KYvUHLcjcDoA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"debug": "^4.1.0",
"handle-thing": "^2.0.0",
@@ -15316,6 +13008,7 @@
"resolved": "https://registry.npmjs.org/spdy-transport/-/spdy-transport-3.0.0.tgz",
"integrity": "sha512-hsLVFE5SjA6TCisWeJXFKniGGOpBgMLmerfO2aCyCU5s7nJ/rpAepqmFifv/GCbSbueEeAJJnmSQ2rKC/g8Fcw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"debug": "^4.1.0",
"detect-node": "^2.0.4",
@@ -15325,68 +13018,12 @@
"wbuf": "^1.7.3"
}
},
- "node_modules/spdy-transport/node_modules/readable-stream": {
- "version": "3.6.0",
- "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-3.6.0.tgz",
- "integrity": "sha512-BViHy7LKeTz4oNnkcLJ+lVSL6vpiFeX6/d3oSH8zCW7UxP2onchk+vTGB143xuFjHS3deTgkKoXXymXqymiIdA==",
- "dev": true,
- "dependencies": {
- "inherits": "^2.0.3",
- "string_decoder": "^1.1.1",
- "util-deprecate": "^1.0.1"
- },
- "engines": {
- "node": ">= 6"
- }
- },
- "node_modules/split-string": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/split-string/-/split-string-3.1.0.tgz",
- "integrity": "sha512-NzNVhJDYpwceVVii8/Hu6DKfD2G+NrQHlS/V/qgv763EYudVwEcMQNxd2lh+0VrUByXN/oJkl5grOhYWvQUYiw==",
- "dev": true,
- "dependencies": {
- "extend-shallow": "^3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/sprintf-js": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz",
- "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw= sha512-D9cPgkvLlV3t3IzL0D0YLvGA9Ahk4PcvVwUbN0dSGr1aP0Nrt4AEnTUbuGvquEC0mA64Gqt1fzirlRs5ibXx8g==",
- "dev": true
- },
- "node_modules/sshpk": {
- "version": "1.16.1",
- "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.16.1.tgz",
- "integrity": "sha512-HXXqVUq7+pcKeLqqZj6mHFUMvXtOJt1uoUx09pFW6011inTMxqI8BA8PM95myrIyyKwdnzjdFjLiE6KBPVtJIg==",
- "dev": true,
- "dependencies": {
- "asn1": "~0.2.3",
- "assert-plus": "^1.0.0",
- "bcrypt-pbkdf": "^1.0.0",
- "dashdash": "^1.12.0",
- "ecc-jsbn": "~0.1.1",
- "getpass": "^0.1.1",
- "jsbn": "~0.1.0",
- "safer-buffer": "^2.0.2",
- "tweetnacl": "~0.14.0"
- },
- "bin": {
- "sshpk-conv": "bin/sshpk-conv",
- "sshpk-sign": "bin/sshpk-sign",
- "sshpk-verify": "bin/sshpk-verify"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/ssri": {
"version": "8.0.1",
"resolved": "https://registry.npmjs.org/ssri/-/ssri-8.0.1.tgz",
"integrity": "sha512-97qShzy1AiyxvPNIkLWoGua7xoQzzPjQ0HAH4B0rWKo7SZ6USuPcrUiAFrws0UH8RrbWmgq3LMTObhPIHbbBeQ==",
"dev": true,
+ "license": "ISC",
"dependencies": {
"minipass": "^3.1.1"
},
@@ -15399,7 +13036,8 @@
"resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz",
"integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==",
"deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility",
- "dev": true
+ "dev": true,
+ "license": "MIT"
},
"node_modules/stack-trace": {
"version": "0.0.9",
@@ -15410,211 +13048,82 @@
}
},
"node_modules/stackframe": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.2.0.tgz",
- "integrity": "sha512-GrdeshiRmS1YLMYgzF16olf2jJ/IzxXY9lhKOskuVziubpTYcYqyOwYeJKzQkwy7uN0fYSsbsC4RQaXf9LCrYA==",
- "dev": true
+ "version": "1.3.4",
+ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz",
+ "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/state-local": {
"version": "1.0.7",
"resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz",
- "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w=="
+ "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==",
+ "license": "MIT"
},
"node_modules/static-eval": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.0.tgz",
- "integrity": "sha512-agtxZ/kWSsCkI5E4QifRwsaPs0P0JmZV6dkLz6ILYfFYQGn+5plctanRN+IC8dJRiFkyXHrwEE3W9Wmx67uDbw==",
+ "version": "2.1.1",
+ "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.1.1.tgz",
+ "integrity": "sha512-MgWpQ/ZjGieSVB3eOJVs4OA2LT/q1vx98KPCTTQPzq/aLr0YUXTsgryTXr4SLfR0ZfUUCiedM9n/ABeDIyy4mA==",
+ "license": "MIT",
"dependencies": {
- "escodegen": "^1.11.1"
+ "escodegen": "^2.1.0"
}
},
- "node_modules/static-extend": {
- "version": "0.1.2",
- "resolved": "https://registry.npmjs.org/static-extend/-/static-extend-0.1.2.tgz",
- "integrity": "sha1-YICcOcv/VTNyJv1eC1IPNB8ftcY= sha512-72E9+uLc27Mt718pMHt9VMNiAL4LMsmDbBva8mxWUCkT07fSzEGMYUCk0XWY6lp0j6RBAG4cJ3mWuZv2OE3s0g==",
+ "node_modules/statuses": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz",
+ "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==",
"dev": true,
- "dependencies": {
- "define-property": "^0.2.5",
- "object-copy": "^0.1.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 0.8"
}
},
- "node_modules/static-extend/node_modules/define-property": {
- "version": "0.2.5",
- "resolved": "https://registry.npmjs.org/define-property/-/define-property-0.2.5.tgz",
- "integrity": "sha1-w1se+RjsPJkPmlvFe+BKrOxcgRY= sha512-Rr7ADjQZenceVOAKop6ALkkRAmH1A4Gx9hV/7ZujPUN2rkATqFO0JZLZInbAjpZYoJ1gUx8MRMQVkYemcbMSTA==",
- "dev": true,
+ "node_modules/stream-parser": {
+ "version": "0.3.1",
+ "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz",
+ "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==",
+ "license": "MIT",
"dependencies": {
- "is-descriptor": "^0.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
+ "debug": "2"
}
},
- "node_modules/static-extend/node_modules/is-accessor-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-accessor-descriptor/-/is-accessor-descriptor-0.1.6.tgz",
- "integrity": "sha1-qeEss66Nh2cn7u84Q/igiXtcmNY= sha512-e1BM1qnDbMRG3ll2U9dSK0UMHuWOs3pY3AtcFsmvwPtKL3MML/Q86i+GilLfvqEs4GW+ExB91tQ3Ig9noDIZ+A==",
- "deprecated": "Please upgrade to v0.1.7",
- "dev": true,
+ "node_modules/stream-parser/node_modules/debug": {
+ "version": "2.6.9",
+ "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
+ "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
+ "license": "MIT",
"dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
+ "ms": "2.0.0"
}
},
- "node_modules/static-extend/node_modules/is-accessor-descriptor/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/static-extend/node_modules/is-data-descriptor": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/is-data-descriptor/-/is-data-descriptor-0.1.4.tgz",
- "integrity": "sha1-C17mSDiOLIYCgueT8YVv7D8wG1Y= sha512-+w9D5ulSoBNlmw9OHn3U2v51SyoCd0he+bB3xMl62oijhrspxowjU+AIcDY0N3iEJbUEkB15IlMASQsxYigvXg==",
- "deprecated": "Please upgrade to v0.1.5",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/static-extend/node_modules/is-data-descriptor/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/static-extend/node_modules/is-descriptor": {
- "version": "0.1.6",
- "resolved": "https://registry.npmjs.org/is-descriptor/-/is-descriptor-0.1.6.tgz",
- "integrity": "sha512-avDYr0SB3DwO9zsMov0gKCESFYqCnE4hq/4z3TdUlukEy5t9C0YRq7HLrsN52NAcqXKaepeCD0n+B0arnVG3Hg==",
- "dev": true,
- "dependencies": {
- "is-accessor-descriptor": "^0.1.6",
- "is-data-descriptor": "^0.1.4",
- "kind-of": "^5.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/static-extend/node_modules/kind-of": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-5.1.0.tgz",
- "integrity": "sha512-NGEErnH6F2vUuXDh+OlbcKW7/wOcfdRHaZ7VWtqCztfHri/++YKmP51OdWeGPuqCOba6kk2OTe5d02VmTB80Pw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/statuses": {
- "version": "1.5.0",
- "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz",
- "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow= sha512-OpZ3zP+jT1PI7I8nemJX4AKmAX070ZkYPVWV/AaKTJl+tXCTGyVdC1a4SL8RUQYEwk/f34ZX8UTykN68FwrqAA==",
- "dev": true,
- "engines": {
- "node": ">= 0.6"
- }
- },
- "node_modules/stream-browserify": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/stream-browserify/-/stream-browserify-2.0.2.tgz",
- "integrity": "sha512-nX6hmklHs/gr2FuxYDltq8fJA1GDlxKQCz8O/IM4atRqBH8OORmBNgfvW5gG10GT/qQ9u0CzIvr2X5Pkt6ntqg==",
- "dev": true,
- "dependencies": {
- "inherits": "~2.0.1",
- "readable-stream": "^2.0.2"
- }
- },
- "node_modules/stream-each": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/stream-each/-/stream-each-1.2.3.tgz",
- "integrity": "sha512-vlMC2f8I2u/bZGqkdfLQW/13Zihpej/7PmSiMQsbYddxuTsJp8vRe2x2FvVExZg7FaOds43ROAuFJwPR4MTZLw==",
- "dev": true,
- "dependencies": {
- "end-of-stream": "^1.1.0",
- "stream-shift": "^1.0.0"
- }
- },
- "node_modules/stream-http": {
- "version": "2.8.3",
- "resolved": "https://registry.npmjs.org/stream-http/-/stream-http-2.8.3.tgz",
- "integrity": "sha512-+TSkfINHDo4J+ZobQLWiMouQYB+UVYFttRA94FpEzzJ7ZdqcL4uUUQ7WkdkI4DSozGmgBUE/a47L+38PenXhUw==",
- "dev": true,
- "dependencies": {
- "builtin-status-codes": "^3.0.0",
- "inherits": "^2.0.1",
- "readable-stream": "^2.3.6",
- "to-arraybuffer": "^1.0.0",
- "xtend": "^4.0.0"
- }
- },
- "node_modules/stream-parser": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/stream-parser/-/stream-parser-0.3.1.tgz",
- "integrity": "sha512-bJ/HgKq41nlKvlhccD5kaCr/P+Hu0wPNKPJOH7en+YrJu/9EgqUF+88w5Jb6KNcjOFMhfX4B2asfeAtIGuHObQ==",
- "dependencies": {
- "debug": "2"
- }
- },
- "node_modules/stream-parser/node_modules/debug": {
- "version": "2.6.9",
- "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz",
- "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==",
- "dependencies": {
- "ms": "2.0.0"
- }
- },
- "node_modules/stream-parser/node_modules/ms": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
- "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g= sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A=="
+ "node_modules/stream-parser/node_modules/ms": {
+ "version": "2.0.0",
+ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz",
+ "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==",
+ "license": "MIT"
},
"node_modules/stream-shift": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.1.tgz",
- "integrity": "sha512-AiisoFqQ0vbGcZgQPY1cdP2I76glaVA/RauYR4G4thNFgkTqr90yXTo4LYX60Jl+sIlPNHHdGSwo01AvbKUSVQ=="
- },
- "node_modules/strict-uri-encode": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/strict-uri-encode/-/strict-uri-encode-1.1.0.tgz",
- "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM= sha512-R3f198pcvnB+5IpnBlRkphuE9n46WyVl8I39W/ZUTZLz4nqSP/oLYUrcnJrw462Ds8he4YKMov2efsTIw1BDGQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
+ "version": "1.0.3",
+ "resolved": "https://registry.npmjs.org/stream-shift/-/stream-shift-1.0.3.tgz",
+ "integrity": "sha512-76ORR0DO1o1hlKwTbi/DM3EXWGf3ZJYO8cXX5RJwnul2DEg2oyoZyjLNoQM8WsvZiFKCRfC1O0J7iCvie3RZmQ==",
+ "license": "MIT"
},
"node_modules/string_decoder": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
- "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "version": "1.3.0",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.3.0.tgz",
+ "integrity": "sha512-hkRX8U1WjJFd8LsDJ2yQ/wWWxaopEsABU1XfkM8A+j0+85JAGppt16cr1Whg6KIbb4okU6Mql6BOj+uup/wKeA==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "safe-buffer": "~5.1.0"
+ "safe-buffer": "~5.2.0"
}
},
"node_modules/string-split-by": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/string-split-by/-/string-split-by-1.0.0.tgz",
"integrity": "sha512-KaJKY+hfpzNyet/emP81PJA9hTVSfxNLS9SFTWxdCnnW1/zOOwiV248+EfoX7IQFcBaOp4G5YE6xTJMF+pLg6A==",
+ "license": "MIT",
"dependencies": {
"parenthesis": "^3.1.5"
}
@@ -15624,6 +13133,7 @@
"resolved": "https://registry.npmjs.org/string-width/-/string-width-4.2.3.tgz",
"integrity": "sha512-wKyQRQpjJ0sIp62ErSZdGsjMJWsap5oRNihHhu6G7JVO/9jIB6UyevL+tXuOqrng8j/cxKTWyWUwvSTriiZz/g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"emoji-regex": "^8.0.0",
"is-fullwidth-code-point": "^3.0.0",
@@ -15633,37 +13143,12 @@
"node": ">=8"
}
},
- "node_modules/string.prototype.trimend": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/string.prototype.trimend/-/string.prototype.trimend-1.0.4.tgz",
- "integrity": "sha512-y9xCjw1P23Awk8EvTpcyL2NIr1j7wJ39f+k6lvRnSMz+mz9CGz9NYPelDk42kOz6+ql8xjfK8oYzy3jAP5QU5A==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/string.prototype.trimstart": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/string.prototype.trimstart/-/string.prototype.trimstart-1.0.4.tgz",
- "integrity": "sha512-jh6e984OBfvxS50tdY2nRZnoC5/mLFKOREQfw8t5yytkoUsJRNxvI/E39qu1sD0OtWI3OC0XgKSmcWwziwYuZw==",
- "dev": true,
- "dependencies": {
- "call-bind": "^1.0.2",
- "define-properties": "^1.1.3"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
"node_modules/strip-ansi": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-6.0.1.tgz",
"integrity": "sha512-Y38VPSHcqkFrCpFnQ9vuSXmquuv5oXOKpGeT6aGrr3o3Gc9AlVa6JBfUSOCnbxGGZF+/0ooI7KrPuUSztUdU5A==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"ansi-regex": "^5.0.1"
},
@@ -15674,8 +13159,9 @@
"node_modules/strip-eof": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz",
- "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8= sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
+ "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
@@ -15685,6 +13171,7 @@
"resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz",
"integrity": "sha512-BrpvfNAE3dcvq7ll3xVumzjKjZQ5tI1sEUIKr3Uoks0XUl45St3FlatVqef9prk4jRDzhW6WZg+3bk93y6pLjA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
}
@@ -15692,8 +13179,9 @@
"node_modules/strip-indent": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/strip-indent/-/strip-indent-2.0.0.tgz",
- "integrity": "sha1-XvjbKV0B5u1sv3qrlpmNeCJSe2g= sha512-RsSNPLpq6YUL7QYy44RnPVTn/lcVZtb48Uof3X5JLbF4zD/Gs7ZFDv2HWol+leoQN2mT86LAzSshGfkTlSOpsA==",
+ "integrity": "sha512-RsSNPLpq6YUL7QYy44RnPVTn/lcVZtb48Uof3X5JLbF4zD/Gs7ZFDv2HWol+leoQN2mT86LAzSshGfkTlSOpsA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
@@ -15703,6 +13191,7 @@
"resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-3.1.1.tgz",
"integrity": "sha512-6fPc+R4ihwqP6N/aIv2f1gMH8lOVtWQHoqC4yK6oSDVVocumAsfCqjkXnqiYMhmMwS/mEHLp7Vehlt3ql6lEig==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=8"
},
@@ -15713,54 +13202,100 @@
"node_modules/strongly-connected-components": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/strongly-connected-components/-/strongly-connected-components-1.0.1.tgz",
- "integrity": "sha512-i0TFx4wPcO0FwX+4RkLJi1MxmcTv90jNZgxMu9XRnMXMeFUY1VJlIoXpZunPUvUUqbCT1pg5PEkFqqpcaElNaA=="
+ "integrity": "sha512-i0TFx4wPcO0FwX+4RkLJi1MxmcTv90jNZgxMu9XRnMXMeFUY1VJlIoXpZunPUvUUqbCT1pg5PEkFqqpcaElNaA==",
+ "license": "MIT"
+ },
+ "node_modules/style-loader": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/style-loader/-/style-loader-4.0.0.tgz",
+ "integrity": "sha512-1V4WqhhZZgjVAVJyt7TdDPZoPBPNHbekX4fWnCJL1yQukhCeZhJySUL+gL9y6sNdN95uEOS83Y55SqHcP7MzLA==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 18.12.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^5.27.0"
+ }
},
"node_modules/stylehacks": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-4.0.3.tgz",
- "integrity": "sha512-7GlLk9JwlElY4Y6a/rmbH2MhVlTyVmiJd1PfTCqFaIBEGMYNsrO/v3SeGTdhBThLg4Z+NbOk/qFMwCa+J+3p/g==",
+ "version": "5.1.1",
+ "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz",
+ "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "browserslist": "^4.0.0",
- "postcss": "^7.0.0",
- "postcss-selector-parser": "^3.0.0"
+ "browserslist": "^4.21.4",
+ "postcss-selector-parser": "^6.0.4"
},
"engines": {
- "node": ">=6.9.0"
+ "node": "^10 || ^12 || >=14.0"
+ },
+ "peerDependencies": {
+ "postcss": "^8.2.15"
}
},
- "node_modules/stylehacks/node_modules/postcss-selector-parser": {
- "version": "3.1.2",
- "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-3.1.2.tgz",
- "integrity": "sha512-h7fJ/5uWuRVyOtkO45pnt1Ih40CEleeyCHzipqAZO2e5H20g25Y48uYnFUiShvY4rZWNJ/Bib/KVPmanaCtOhA==",
- "dev": true,
+ "node_modules/sucrase": {
+ "version": "3.35.1",
+ "resolved": "https://registry.npmjs.org/sucrase/-/sucrase-3.35.1.tgz",
+ "integrity": "sha512-DhuTmvZWux4H1UOnWMB3sk0sbaCVOoQZjv8u1rDoTV0HTdGem9hkAZtl4JZy8P2z4Bg0nT+YMeOFyVr4zcG5Tw==",
+ "license": "MIT",
"dependencies": {
- "dot-prop": "^5.2.0",
- "indexes-of": "^1.0.1",
- "uniq": "^1.0.1"
+ "@jridgewell/gen-mapping": "^0.3.2",
+ "commander": "^4.0.0",
+ "lines-and-columns": "^1.1.6",
+ "mz": "^2.7.0",
+ "pirates": "^4.0.1",
+ "tinyglobby": "^0.2.11",
+ "ts-interface-checker": "^0.1.9"
+ },
+ "bin": {
+ "sucrase": "bin/sucrase",
+ "sucrase-node": "bin/sucrase-node"
},
"engines": {
- "node": ">=8"
+ "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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 6"
}
},
"node_modules/supercluster": {
"version": "7.1.5",
"resolved": "https://registry.npmjs.org/supercluster/-/supercluster-7.1.5.tgz",
"integrity": "sha512-EulshI3pGUM66o6ZdH3ReiFcvHpM3vAigyK+vcxdjpJyEbIIrtbmBdY23mGgnI24uXiGFvrGq9Gkum/8U7vJWg==",
+ "license": "ISC",
"dependencies": {
"kdbush": "^3.0.0"
}
},
+ "node_modules/supercluster/node_modules/kdbush": {
+ "version": "3.0.0",
+ "resolved": "https://registry.npmjs.org/kdbush/-/kdbush-3.0.0.tgz",
+ "integrity": "sha512-hRkd6/XW4HTsA9vjVpY9tuXJYLSlelnkTmVFu4M9/7MIYQtFcHpbugAU7UbOfjOiVSVYl2fqgBuJ32JUmRo5Ew==",
+ "license": "ISC"
+ },
"node_modules/superscript-text": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/superscript-text/-/superscript-text-1.0.0.tgz",
- "integrity": "sha512-gwu8l5MtRZ6koO0icVTlmN5pm7Dhh1+Xpe9O4x6ObMAsW+3jPbW14d1DsBq1F4wiI+WOFjXF35pslgec/G8yCQ=="
+ "integrity": "sha512-gwu8l5MtRZ6koO0icVTlmN5pm7Dhh1+Xpe9O4x6ObMAsW+3jPbW14d1DsBq1F4wiI+WOFjXF35pslgec/G8yCQ==",
+ "license": "MIT"
},
"node_modules/supports-color": {
"version": "7.2.0",
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"has-flag": "^4.0.0"
},
@@ -15768,15 +13303,29 @@
"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==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
+ }
+ },
"node_modules/svg-arc-to-cubic-bezier": {
"version": "3.2.0",
"resolved": "https://registry.npmjs.org/svg-arc-to-cubic-bezier/-/svg-arc-to-cubic-bezier-3.2.0.tgz",
- "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g=="
+ "integrity": "sha512-djbJ/vZKZO+gPoSDThGNpKDO+o+bAeA4XQKovvkNCqnIS2t+S4qnLAGQhyyrulhCFRl1WWzAp0wUDV8PpTVU3g==",
+ "license": "ISC"
},
"node_modules/svg-path-bounds": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/svg-path-bounds/-/svg-path-bounds-1.0.2.tgz",
"integrity": "sha512-H4/uAgLWrppIC0kHsb2/dWUYSmb4GE5UqH06uqWBcg6LBjX2fu0A8+JrO2/FJPZiSsNOKZAhyFFgsLTdYUvSqQ==",
+ "license": "MIT",
"dependencies": {
"abs-svg-path": "^0.1.1",
"is-svg-path": "^1.0.1",
@@ -15788,6 +13337,7 @@
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/normalize-svg-path/-/normalize-svg-path-1.1.0.tgz",
"integrity": "sha512-r9KHKG2UUeB5LoTouwDzBy2VxXlHsiM6fyLQvnJa0S5hrhzqElH/CH7TUGhT1fVvIYBIKf3OpY4YJ4CK+iaqHg==",
+ "license": "MIT",
"dependencies": {
"svg-arc-to-cubic-bezier": "^3.0.0"
}
@@ -15796,6 +13346,7 @@
"version": "1.1.3",
"resolved": "https://registry.npmjs.org/svg-path-sdf/-/svg-path-sdf-1.1.3.tgz",
"integrity": "sha512-vJJjVq/R5lSr2KLfVXVAStktfcfa1pNFjFOgyJnzZFXlO/fDZ5DmM8FpnSKKzLPfEYTVeXuVBTHF296TpxuJVg==",
+ "license": "MIT",
"dependencies": {
"bitmap-sdf": "^1.0.0",
"draw-svg-path": "^1.0.0",
@@ -15807,475 +13358,277 @@
"node_modules/svg-tags": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/svg-tags/-/svg-tags-1.0.0.tgz",
- "integrity": "sha1-WPcc7jvVGbWdSyqEO2x95krAR2Q= sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==",
+ "integrity": "sha512-ovssysQTa+luh7A5Weu3Rta6FJlFBBbInjOh722LIt6klpU2/HtdUbszju/G4devcvk8PGt7FCLv5wftu3THUA==",
"dev": true
},
"node_modules/svgo": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/svgo/-/svgo-1.3.2.tgz",
- "integrity": "sha512-yhy/sQYxR5BkC98CY7o31VGsg014AKLEPxdfhora76l36hD9Rdy5NZA/Ocn6yayNPgSamYdtX2rFJdcv07AYVw==",
- "deprecated": "This SVGO version is no longer supported. Upgrade to v2.x.x.",
- "dev": true,
- "dependencies": {
- "chalk": "^2.4.1",
- "coa": "^2.0.2",
- "css-select": "^2.0.0",
- "css-select-base-adapter": "^0.1.1",
- "css-tree": "1.0.0-alpha.37",
- "csso": "^4.0.2",
- "js-yaml": "^3.13.1",
- "mkdirp": "~0.5.1",
- "object.values": "^1.1.0",
- "sax": "~1.2.4",
- "stable": "^0.1.8",
- "unquote": "~1.1.1",
- "util.promisify": "~1.0.0"
+ "version": "2.8.2",
+ "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.2.tgz",
+ "integrity": "sha512-TyzE4NVGLUFy+H/Uy4N6c3G0HEeprsVfge6Lmq+0FdQQ/zqoVYB62IsBZORsiL+o96s6ff/V6/3UQo/C0cgCAA==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "commander": "^7.2.0",
+ "css-select": "^4.1.3",
+ "css-tree": "^1.1.3",
+ "csso": "^4.2.0",
+ "picocolors": "^1.0.0",
+ "sax": "^1.5.0",
+ "stable": "^0.1.8"
},
"bin": {
"svgo": "bin/svgo"
},
"engines": {
- "node": ">=4.0.0"
+ "node": ">=10.13.0"
}
},
- "node_modules/svgo/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "node_modules/svgo/node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">= 10"
}
},
- "node_modules/svgo/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
+ "node_modules/tailwindcss": {
+ "version": "3.4.19",
+ "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-3.4.19.tgz",
+ "integrity": "sha512-3ofp+LL8E+pK/JuPLPggVAIaEuhvIz4qNcf3nA1Xn2o/7fb7s/TYpHhwGDv1ZU3PkBluUVaF8PyCHcm48cKLWQ==",
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
+ "@alloc/quick-lru": "^5.2.0",
+ "arg": "^5.0.2",
+ "chokidar": "^3.6.0",
+ "didyoumean": "^1.2.2",
+ "dlv": "^1.1.3",
+ "fast-glob": "^3.3.2",
+ "glob-parent": "^6.0.2",
+ "is-glob": "^4.0.3",
+ "jiti": "^1.21.7",
+ "lilconfig": "^3.1.3",
+ "micromatch": "^4.0.8",
+ "normalize-path": "^3.0.0",
+ "object-hash": "^3.0.0",
+ "picocolors": "^1.1.1",
+ "postcss": "^8.4.47",
+ "postcss-import": "^15.1.0",
+ "postcss-js": "^4.0.1",
+ "postcss-load-config": "^4.0.2 || ^5.0 || ^6.0",
+ "postcss-nested": "^6.2.0",
+ "postcss-selector-parser": "^6.1.2",
+ "resolve": "^1.22.8",
+ "sucrase": "^3.35.0"
+ },
+ "bin": {
+ "tailwind": "lib/cli.js",
+ "tailwindcss": "lib/cli.js"
},
"engines": {
- "node": ">=4"
+ "node": ">=14.0.0"
}
},
- "node_modules/svgo/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
+ "node_modules/tailwindcss/node_modules/lilconfig": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz",
+ "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=14"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/antonk52"
}
},
- "node_modules/svgo/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/svgo/node_modules/css-select": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/css-select/-/css-select-2.1.0.tgz",
- "integrity": "sha512-Dqk7LQKpwLoH3VovzZnkzegqNSuAziQyNZUcrdDM401iY+R5NkGBXGmtO05/yaXQziALuPogeG0b7UAgjnTJTQ==",
- "dev": true,
+ "node_modules/tailwindcss/node_modules/postcss-load-config": {
+ "version": "6.0.1",
+ "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-6.0.1.tgz",
+ "integrity": "sha512-oPtTM4oerL+UXmx+93ytZVN82RrlY/wPUV8IeDxFrzIjXOLF1pN+EmKPLbubvKHT2HC20xXsCAH2Z+CKV6Oz/g==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "boolbase": "^1.0.0",
- "css-what": "^3.2.1",
- "domutils": "^1.7.0",
- "nth-check": "^1.0.2"
+ "lilconfig": "^3.1.1"
+ },
+ "engines": {
+ "node": ">= 18"
+ },
+ "peerDependencies": {
+ "jiti": ">=1.21.0",
+ "postcss": ">=8.0.9",
+ "tsx": "^4.8.1",
+ "yaml": "^2.4.2"
+ },
+ "peerDependenciesMeta": {
+ "jiti": {
+ "optional": true
+ },
+ "postcss": {
+ "optional": true
+ },
+ "tsx": {
+ "optional": true
+ },
+ "yaml": {
+ "optional": true
+ }
}
},
- "node_modules/svgo/node_modules/css-what": {
- "version": "3.4.2",
- "resolved": "https://registry.npmjs.org/css-what/-/css-what-3.4.2.tgz",
- "integrity": "sha512-ACUm3L0/jiZTqfzRM3Hi9Q8eZqd6IK37mMWPLz9PJxkLWllYeRf+EHUSHYEtFop2Eqytaq1FizFVh7XfBnXCDQ==",
- "dev": true,
+ "node_modules/tailwindcss/node_modules/yaml": {
+ "version": "2.8.4",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.4.tgz",
+ "integrity": "sha512-ml/JPOj9fOQK8RNnWojA67GbZ0ApXAUlN2UQclwv2eVgTgn7O9gg9o7paZWKMp4g0H3nTLtS9LVzhkpOFIKzog==",
+ "license": "ISC",
+ "optional": true,
+ "peer": true,
+ "bin": {
+ "yaml": "bin.mjs"
+ },
"engines": {
- "node": ">= 6"
+ "node": ">= 14.6"
},
"funding": {
- "url": "https://github.com/sponsors/fb55"
- }
- },
- "node_modules/svgo/node_modules/dom-serializer": {
- "version": "0.2.2",
- "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-0.2.2.tgz",
- "integrity": "sha512-2/xPb3ORsQ42nHYiSunXkDjPLBaEj/xTwUO4B7XCZQTRk7EBtTOPaygh10YAAh2OI1Qrp6NWfpAhzswj0ydt9g==",
- "dev": true,
- "dependencies": {
- "domelementtype": "^2.0.1",
- "entities": "^2.0.0"
- }
- },
- "node_modules/svgo/node_modules/domutils": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/domutils/-/domutils-1.7.0.tgz",
- "integrity": "sha512-Lgd2XcJ/NjEw+7tFvfKxOzCYKZsdct5lczQ2ZaQY8Djz7pfAD3Gbp8ySJWtreII/vDlMVmxwa6pHmdxIYgttDg==",
- "dev": true,
- "dependencies": {
- "dom-serializer": "0",
- "domelementtype": "1"
- }
- },
- "node_modules/svgo/node_modules/domutils/node_modules/domelementtype": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-1.3.1.tgz",
- "integrity": "sha512-BSKB+TSpMpFI/HOxCNr1O8aMOTZ8hT3pM3GQ0w/mWRmkhEDSFJkkyzz4XQsBV44BChwGkrDfMyjVD0eA2aFV3w==",
- "dev": true
- },
- "node_modules/svgo/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/svgo/node_modules/nth-check": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-1.0.2.tgz",
- "integrity": "sha512-WeBOdju8SnzPN5vTUJYxYUxLeXpCaVP5i5e0LF8fg7WORF2Wd7wFX/pk0tYZk7s8T+J7VLy0Da6J1+wCT0AtHg==",
- "dev": true,
- "dependencies": {
- "boolbase": "~1.0.0"
- }
- },
- "node_modules/svgo/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/table": {
- "version": "5.4.6",
- "resolved": "https://registry.npmjs.org/table/-/table-5.4.6.tgz",
- "integrity": "sha512-wmEc8m4fjnob4gt5riFRtTu/6+4rSe12TpAELNSqHMfF3IqnA+CH37USM6/YR3qRZv7e56kAEAtd6nKZaxe0Ug==",
- "dev": true,
- "dependencies": {
- "ajv": "^6.10.2",
- "lodash": "^4.17.14",
- "slice-ansi": "^2.1.0",
- "string-width": "^3.0.0"
- },
- "engines": {
- "node": ">=6.0.0"
- }
- },
- "node_modules/table/node_modules/ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/table/node_modules/emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
- "dev": true
- },
- "node_modules/table/node_modules/is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/table/node_modules/string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
- "dev": true,
- "dependencies": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/table/node_modules/strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^4.1.0"
- },
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/tailwindcss": {
- "name": "@tailwindcss/postcss7-compat",
- "version": "2.2.17",
- "resolved": "https://registry.npmjs.org/@tailwindcss/postcss7-compat/-/postcss7-compat-2.2.17.tgz",
- "integrity": "sha512-3h2svqQAqYHxRZ1KjsJjZOVTQ04m29LjfrLjXyZZEJuvUuJN+BCIF9GI8vhE1s0plS0mogd6E6YLg6mu4Wv/Vw==",
- "dev": true,
- "dependencies": {
- "arg": "^5.0.1",
- "autoprefixer": "^9",
- "bytes": "^3.0.0",
- "chalk": "^4.1.2",
- "chokidar": "^3.5.2",
- "color": "^4.0.1",
- "cosmiconfig": "^7.0.1",
- "detective": "^5.2.0",
- "didyoumean": "^1.2.2",
- "dlv": "^1.1.3",
- "fast-glob": "^3.2.7",
- "fs-extra": "^10.0.0",
- "glob-parent": "^6.0.1",
- "html-tags": "^3.1.0",
- "is-color-stop": "^1.1.0",
- "is-glob": "^4.0.1",
- "lodash": "^4.17.21",
- "lodash.topath": "^4.5.2",
- "modern-normalize": "^1.1.0",
- "node-emoji": "^1.11.0",
- "normalize-path": "^3.0.0",
- "object-hash": "^2.2.0",
- "postcss": "^7",
- "postcss-functions": "^3",
- "postcss-js": "^2",
- "postcss-load-config": "^3.1.0",
- "postcss-nested": "^4",
- "postcss-selector-parser": "^6.0.6",
- "postcss-value-parser": "^4.1.0",
- "pretty-hrtime": "^1.0.3",
- "purgecss": "^4.0.3",
- "quick-lru": "^5.1.1",
- "reduce-css-calc": "^2.1.8",
- "resolve": "^1.20.0",
- "tmp": "^0.2.1"
- },
- "bin": {
- "tailwind": "lib/cli.js",
- "tailwindcss": "lib/cli.js"
- },
- "engines": {
- "node": ">=12.13.0"
+ "url": "https://github.com/sponsors/eemeli"
}
},
"node_modules/tapable": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/tapable/-/tapable-1.1.3.tgz",
- "integrity": "sha512-4WK/bYZmj8xLr+HUCODHGF1ZFzsYffasLUgEiMBY4fgtltdO6B4WJtlSbPaDTLpYTcGVwM2qLnFTICEcNxs3kA==",
- "dev": true,
+ "version": "2.3.3",
+ "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.3.tgz",
+ "integrity": "sha512-uxc/zpqFg6x7C8vOE7lh6Lbda8eEL9zmVm/PLeTPBRhh1xCgdWaQ+J1CUieGpIfm2HdtsUpRv+HshiasBMcc6A==",
+ "license": "MIT",
"engines": {
"node": ">=6"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/terser": {
- "version": "4.8.1",
- "resolved": "https://registry.npmjs.org/terser/-/terser-4.8.1.tgz",
- "integrity": "sha512-4GnLC0x667eJG0ewJTa6z/yXrbLGv80D9Ru6HIpCQmO+Q4PfEtBFi0ObSckqwL6VyQv/7ENJieXHo2ANmdQwgw==",
- "dev": true,
+ "version": "5.46.2",
+ "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.2.tgz",
+ "integrity": "sha512-uxfo9fPcSgLDYob/w1FuL0c99MWiJDnv+5qXSQc5+Ki5NjVNsYi66INnMFBjf6uFz6OnX12piJQPF4IpjJTNTw==",
+ "license": "BSD-2-Clause",
"dependencies": {
+ "@jridgewell/source-map": "^0.3.3",
+ "acorn": "^8.15.0",
"commander": "^2.20.0",
- "source-map": "~0.6.1",
- "source-map-support": "~0.5.12"
+ "source-map-support": "~0.5.20"
},
"bin": {
"terser": "bin/terser"
},
"engines": {
- "node": ">=6.0.0"
+ "node": ">=10"
}
},
"node_modules/terser-webpack-plugin": {
- "version": "1.4.5",
- "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-1.4.5.tgz",
- "integrity": "sha512-04Rfe496lN8EYruwi6oPQkG0vo8C+HT49X687FZnpPF0qMAIHONI6HEXYPKDOE8e5HjXTyKfqRd/agHtH0kOtw==",
- "dev": true,
+ "version": "5.5.0",
+ "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.5.0.tgz",
+ "integrity": "sha512-UYhptBwhWvfIjKd/UuFo6D8uq9xpGLDK+z8EDsj/zWhrTaH34cKEbrkMKfV5YWqGBvAYA3tlzZbs2R+qYrbQJA==",
+ "license": "MIT",
"dependencies": {
- "cacache": "^12.0.2",
- "find-cache-dir": "^2.1.0",
- "is-wsl": "^1.1.0",
- "schema-utils": "^1.0.0",
- "serialize-javascript": "^4.0.0",
- "source-map": "^0.6.1",
- "terser": "^4.1.2",
- "webpack-sources": "^1.4.0",
- "worker-farm": "^1.7.0"
+ "@jridgewell/trace-mapping": "^0.3.25",
+ "jest-worker": "^27.4.5",
+ "schema-utils": "^4.3.0",
+ "terser": "^5.31.1"
},
"engines": {
- "node": ">= 6.9.0"
- },
- "peerDependencies": {
- "webpack": "^4.0.0"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/find-cache-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/find-cache-dir/-/find-cache-dir-2.1.0.tgz",
- "integrity": "sha512-Tq6PixE0w/VMFfCgbONnkiQIVol/JJL7nRMi20fqzA4NRs9AfeqMGeRdPi3wIhYkxjeBaWh2rxwapn5Tu3IqOQ==",
- "dev": true,
- "dependencies": {
- "commondir": "^1.0.1",
- "make-dir": "^2.0.0",
- "pkg-dir": "^3.0.0"
+ "node": ">= 10.13.0"
},
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
- "dependencies": {
- "locate-path": "^3.0.0"
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
},
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/is-wsl": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-1.1.0.tgz",
- "integrity": "sha1-HxbkqiKwTRM2tmGIpmrzxgDDpm0= sha512-gfygJYZ2gLTDlmbWMI0CE2MwnFzSN/2SZfkMlItC4K/JBlsWVDB0bO6XhqcY13YXE7iMcAJnzTCJjPiTeJJ0Mw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
- "dev": true,
- "dependencies": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
+ "peerDependencies": {
+ "webpack": "^5.1.0"
},
- "engines": {
- "node": ">=6"
+ "peerDependenciesMeta": {
+ "@swc/core": {
+ "optional": true
+ },
+ "esbuild": {
+ "optional": true
+ },
+ "uglify-js": {
+ "optional": true
+ }
}
},
- "node_modules/terser-webpack-plugin/node_modules/make-dir": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/make-dir/-/make-dir-2.1.0.tgz",
- "integrity": "sha512-LS9X+dc8KLxXCb8dni79fLIIUA5VyZoyjSMCwTluaXA0o27cCK0bhXkpgw+sTXVpPy/lSO57ilRixqk0vDmtRA==",
- "dev": true,
+ "node_modules/terser-webpack-plugin/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "license": "MIT",
"dependencies": {
- "pify": "^4.0.1",
- "semver": "^5.6.0"
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
},
- "engines": {
- "node": ">=6"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/terser-webpack-plugin/node_modules/p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
- "dev": true,
+ "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "license": "MIT",
"dependencies": {
- "p-limit": "^2.0.0"
+ "fast-deep-equal": "^3.1.3"
},
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
+ "peerDependencies": {
+ "ajv": "^8.8.2"
}
},
- "node_modules/terser-webpack-plugin/node_modules/pkg-dir": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/pkg-dir/-/pkg-dir-3.0.0.tgz",
- "integrity": "sha512-/E57AYkoeQ25qkxMj5PBOVgF8Kiu/h7cYS30Z5+R7WaiCCBfLq58ZI/dSeaEKb9WVJV5n/03QwrN3IeWIFllvw==",
- "dev": true,
- "dependencies": {
- "find-up": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
+ "node_modules/terser-webpack-plugin/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==",
+ "license": "MIT"
},
"node_modules/terser-webpack-plugin/node_modules/schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
- "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
- "dev": true,
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
+ "license": "MIT",
"dependencies": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
},
"engines": {
- "node": ">= 4"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/semver": {
- "version": "5.7.1",
- "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.1.tgz",
- "integrity": "sha512-sauaDf/PZdVgrLTNYHRtpXa1iRiKcaebiKQ1BJdpQlWH2lCvexQdX55snPFyK7QzpudqbCI0qXFfOasHdyNDGQ==",
- "dev": true,
- "bin": {
- "semver": "bin/semver"
- }
- },
- "node_modules/terser-webpack-plugin/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/terser/node_modules/commander": {
"version": "2.20.3",
"resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
"integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- },
- "node_modules/terser/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/text-table": {
- "version": "0.2.0",
- "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz",
- "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ= sha512-N+8UisAXDGk8PFXP4HAzVR9nbfmVJ3zYLAWiTIoqC5v5isinhr+r5uaO8+7r3BMfuNIufIsA7RdpVgacC2cSpw==",
- "dev": true
+ "license": "MIT"
},
"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,
+ "license": "MIT",
"dependencies": {
"any-promise": "^1.0.0"
}
@@ -16283,8 +13636,8 @@
"node_modules/thenify-all": {
"version": "1.6.0",
"resolved": "https://registry.npmjs.org/thenify-all/-/thenify-all-1.6.0.tgz",
- "integrity": "sha1-GhkY1ALY/D+Y+/I02wvMjMEOlyY= sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
- "dev": true,
+ "integrity": "sha512-RNxQH/qI8/t3thXJDwcstUO4zeqo64+Uy/+sNVRBx4Xn2OX+OZ9oP+iJnNFqplFra2ZUVeKCSa2oVWi3T4uVmA==",
+ "license": "MIT",
"dependencies": {
"thenify": ">= 3.1.0 < 4"
},
@@ -16293,170 +13646,199 @@
}
},
"node_modules/thread-loader": {
- "version": "2.1.3",
- "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-2.1.3.tgz",
- "integrity": "sha512-wNrVKH2Lcf8ZrWxDF/khdlLlsTMczdcwPA9VEK4c2exlEPynYWxi9op3nPTo5lAnDIkE0rQEB3VBP+4Zncc9Hg==",
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/thread-loader/-/thread-loader-3.0.4.tgz",
+ "integrity": "sha512-ByaL2TPb+m6yArpqQUZvP+5S1mZtXsEP7nWKKlAUTm7fCml8kB5s1uI3+eHRP2bk5mVYfRSBI7FFf+tWEyLZwA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "loader-runner": "^2.3.1",
- "loader-utils": "^1.1.0",
- "neo-async": "^2.6.0"
+ "json-parse-better-errors": "^1.0.2",
+ "loader-runner": "^4.1.0",
+ "loader-utils": "^2.0.0",
+ "neo-async": "^2.6.2",
+ "schema-utils": "^3.0.0"
},
"engines": {
- "node": ">= 6.9.0 <7.0.0 || >= 8.9.0"
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
},
"peerDependencies": {
- "webpack": "^2.0.0 || ^3.0.0 || ^4.0.0"
+ "webpack": "^4.27.0 || ^5.0.0"
}
},
- "node_modules/through": {
- "version": "2.3.8",
- "resolved": "https://registry.npmjs.org/through/-/through-2.3.8.tgz",
- "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU= sha512-w89qg7PI8wAdvX60bMDP+bFoD5Dvhm9oLheFp5O4a2QF0cSBGsBX4qZmadPMvVqlLJBBci+WqGGOAPvcDeNSVg==",
- "dev": true
+ "node_modules/thread-loader/node_modules/loader-utils": {
+ "version": "2.0.4",
+ "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
+ "integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "big.js": "^5.2.2",
+ "emojis-list": "^3.0.0",
+ "json5": "^2.1.2"
+ },
+ "engines": {
+ "node": ">=8.9.0"
+ }
+ },
+ "node_modules/thread-loader/node_modules/schema-utils": {
+ "version": "3.3.0",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-3.3.0.tgz",
+ "integrity": "sha512-pN/yOAvcC+5rQ5nERGuwrjLlYvLTbCibnZ1I7B1LaiAz9BRBlE9GMgE/eqV30P7aJQUf7Ddimy/RsbYO/GrVGg==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "@types/json-schema": "^7.0.8",
+ "ajv": "^6.12.5",
+ "ajv-keywords": "^3.5.2"
+ },
+ "engines": {
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ }
},
"node_modules/through2": {
"version": "2.0.5",
"resolved": "https://registry.npmjs.org/through2/-/through2-2.0.5.tgz",
"integrity": "sha512-/mrRod8xqpA+IHSLyGCQ2s8SPHiCDEeQJSep1jqLYeEUClOFG2Qsh+4FU6G9VeqpZnGW/Su8LQGc4YKni5rYSQ==",
+ "license": "MIT",
"dependencies": {
"readable-stream": "~2.3.6",
"xtend": "~4.0.1"
}
},
- "node_modules/thunky": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
- "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
- "dev": true
+ "node_modules/through2/node_modules/isarray": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
+ "integrity": "sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
+ "license": "MIT"
},
- "node_modules/timers-browserify": {
- "version": "2.0.12",
- "resolved": "https://registry.npmjs.org/timers-browserify/-/timers-browserify-2.0.12.tgz",
- "integrity": "sha512-9phl76Cqm6FhSX9Xe1ZUAMLtm1BLkKj2Qd5ApyWkXzsMRaA7dgr81kf4wJmQf/hAvg8EEyJxDo3du/0KlhPiKQ==",
- "dev": true,
+ "node_modules/through2/node_modules/readable-stream": {
+ "version": "2.3.8",
+ "resolved": "https://registry.npmjs.org/readable-stream/-/readable-stream-2.3.8.tgz",
+ "integrity": "sha512-8p0AUk4XODgIewSi0l8Epjs+EVnWiK7NoDIEGU0HhE7+ZyY8D1IMY7odu5lRrFXGg71L15KG8QrPmum45RTtdA==",
+ "license": "MIT",
"dependencies": {
- "setimmediate": "^1.0.4"
- },
- "engines": {
- "node": ">=0.6.0"
+ "core-util-is": "~1.0.0",
+ "inherits": "~2.0.3",
+ "isarray": "~1.0.0",
+ "process-nextick-args": "~2.0.0",
+ "safe-buffer": "~5.1.1",
+ "string_decoder": "~1.1.1",
+ "util-deprecate": "~1.0.1"
}
},
- "node_modules/timsort": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/timsort/-/timsort-0.3.0.tgz",
- "integrity": "sha1-QFQRqOfmM5/mTbmiNN4R3DHgK9Q= sha512-qsdtZH+vMoCARQtyod4imc2nIJwg9Cc7lPRrw9CzF8ZKR0khdr8+2nX80PBhET3tcyTtJDxAffGh2rXH4tyU8A==",
- "dev": true
+ "node_modules/through2/node_modules/safe-buffer": {
+ "version": "5.1.2",
+ "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz",
+ "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==",
+ "license": "MIT"
+ },
+ "node_modules/through2/node_modules/string_decoder": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz",
+ "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==",
+ "license": "MIT",
+ "dependencies": {
+ "safe-buffer": "~5.1.0"
+ }
+ },
+ "node_modules/thunky": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/thunky/-/thunky-1.1.0.tgz",
+ "integrity": "sha512-eHY7nBftgThBqOyHGVN+l8gF0BucP09fMo0oO/Lb0w1OF80dJv+lDVpXG60WMQvkcxAkNybKsrEIE3ZtKGmPrA==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
- "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q=="
+ "integrity": "sha512-NB6Dk1A9xgQPMoGqC5CVXn123gWyte215ONT5Pp5a0yt4nlEoO1ZWeCwpncaekPHXO60i47ihFnZPiRPjRMq4Q==",
+ "license": "MIT"
},
"node_modules/tinycolor2": {
- "version": "1.4.2",
- "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.4.2.tgz",
- "integrity": "sha512-vJhccZPs965sV/L2sU4oRQVAos0pQXwsvTLkWYdqJ+a8Q5kPFzJTuOFwy7UniPli44NKQGAglksjvOcpo95aZA==",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/tinyqueue": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz",
- "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA=="
+ "version": "1.6.0",
+ "resolved": "https://registry.npmjs.org/tinycolor2/-/tinycolor2-1.6.0.tgz",
+ "integrity": "sha512-XPaBkWQJdsf3pLKJV9p4qN/S+fm2Oj8AIPo1BTUhg5oxkvm9+SVEGFdhyOz7tTdUTfvxMiAs4sp6/eZO2Ew+pw==",
+ "license": "MIT"
},
- "node_modules/tmp": {
- "version": "0.2.1",
- "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.2.1.tgz",
- "integrity": "sha512-76SUhtfqR2Ijn+xllcI5P1oyannHNHByD80W1q447gU3mp9G9PSpGdWmjUOHRDPiHYacIk66W7ubDTuPF3BEtQ==",
- "dev": true,
+ "node_modules/tinyglobby": {
+ "version": "0.2.16",
+ "resolved": "https://registry.npmjs.org/tinyglobby/-/tinyglobby-0.2.16.tgz",
+ "integrity": "sha512-pn99VhoACYR8nFHhxqix+uvsbXineAasWm5ojXoN8xEwK5Kd3/TrhNn1wByuD52UxWRLy8pu+kRMniEi6Eq9Zg==",
+ "license": "MIT",
"dependencies": {
- "rimraf": "^3.0.0"
+ "fdir": "^6.5.0",
+ "picomatch": "^4.0.4"
},
"engines": {
- "node": ">=8.17.0"
+ "node": ">=12.0.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/SuperchupuDev"
}
},
- "node_modules/tmp/node_modules/rimraf": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-3.0.2.tgz",
- "integrity": "sha512-JZkJMZkAGFFPP2YqXZXPbMlMBgsxzE8ILs4lMIX/2o0L9UBw9O/Y3o6wFw/i9YLapcUJWwqbi3kdxIPdC62TIA==",
- "deprecated": "Rimraf versions prior to v4 are no longer supported",
- "dev": true,
- "dependencies": {
- "glob": "^7.1.3"
+ "node_modules/tinyglobby/node_modules/fdir": {
+ "version": "6.5.0",
+ "resolved": "https://registry.npmjs.org/fdir/-/fdir-6.5.0.tgz",
+ "integrity": "sha512-tIbYtZbucOs0BRGqPJkshJUYdL+SDH7dVM8gjy+ERp3WAUjLEFJE+02kanyHtwjWOnwrKYBiwAmM0p4kLJAnXg==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12.0.0"
},
- "bin": {
- "rimraf": "bin.js"
+ "peerDependencies": {
+ "picomatch": "^3 || ^4"
+ },
+ "peerDependenciesMeta": {
+ "picomatch": {
+ "optional": true
+ }
+ }
+ },
+ "node_modules/tinyglobby/node_modules/picomatch": {
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.4.tgz",
+ "integrity": "sha512-QP88BAKvMam/3NxH6vj2o21R6MjxZUAd6nlwAS/pnGvN9IVLocLHxGYIzFhg6fUQ+5th6P4dv4eW9jX3DSIj7A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">=12"
},
"funding": {
- "url": "https://github.com/sponsors/isaacs"
+ "url": "https://github.com/sponsors/jonschlinkert"
}
},
- "node_modules/to-arraybuffer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/to-arraybuffer/-/to-arraybuffer-1.0.1.tgz",
- "integrity": "sha1-fSKbH8xjfkZsoIEYCDanqr/4P0M= sha512-okFlQcoGTi4LQBG/PgSYblw9VOyptsz2KJZqc6qtgGdes8VktzUQkj4BI2blit072iS8VODNcMA+tvnS9dnuMA==",
- "dev": true
+ "node_modules/tinyqueue": {
+ "version": "2.0.3",
+ "resolved": "https://registry.npmjs.org/tinyqueue/-/tinyqueue-2.0.3.tgz",
+ "integrity": "sha512-ppJZNDuKGgxzkHihX8v9v9G5f+18gzaTfrukGrq6ueg0lmH4nqVnA2IPG0AEH3jKEk2GRJCUhDoqpoiw3PHLBA==",
+ "license": "ISC"
},
"node_modules/to-float32": {
"version": "1.1.0",
"resolved": "https://registry.npmjs.org/to-float32/-/to-float32-1.1.0.tgz",
- "integrity": "sha512-keDnAusn/vc+R3iEiSDw8TOF7gPiTLdK1ArvWtYbJQiVfmRg6i/CAvbKq3uIS0vWroAC7ZecN3DjQKw3aSklUg=="
- },
- "node_modules/to-object-path": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/to-object-path/-/to-object-path-0.3.0.tgz",
- "integrity": "sha1-KXWIt7Dn4KwI4E5nL4XB9JmeF68= sha512-9mWHdnGRuh3onocaHzukyvCZhzvr6tiflAy/JRFXcJX0TjgfWA9pk9t8CMbzmBE4Jfw58pXbkngtBtqYxzNEyg==",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/to-object-path/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
+ "integrity": "sha512-keDnAusn/vc+R3iEiSDw8TOF7gPiTLdK1ArvWtYbJQiVfmRg6i/CAvbKq3uIS0vWroAC7ZecN3DjQKw3aSklUg==",
+ "license": "MIT"
},
"node_modules/to-px": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/to-px/-/to-px-1.0.1.tgz",
"integrity": "sha512-2y3LjBeIZYL19e5gczp14/uRWFDtDUErJPVN3VU9a7SJO+RjGRtYR47aMN2bZgGlxvW4ZcEz2ddUPVHXcMfuXw==",
+ "license": "MIT",
"dependencies": {
"parse-unit": "^1.0.1"
}
},
- "node_modules/to-regex": {
- "version": "3.0.2",
- "resolved": "https://registry.npmjs.org/to-regex/-/to-regex-3.0.2.tgz",
- "integrity": "sha512-FWtleNAtZ/Ki2qtqej2CXTOayOH9bHDQF+Q48VpWyDXjbYxA4Yz8iDB31zXOBUlOHHKidDbqGVrTUvQMPmBGBw==",
- "dev": true,
- "dependencies": {
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "regex-not": "^1.0.2",
- "safe-regex": "^1.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"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,
+ "license": "MIT",
"dependencies": {
"is-number": "^7.0.0"
},
@@ -16465,10 +13847,11 @@
}
},
"node_modules/toidentifier": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.0.tgz",
- "integrity": "sha512-yaOH/Pk/VEhBWWTlhI+qXxDFXlejDGcQipMlyxda9nthulaxLZUNcUqFxokp0vcYnvteJln5FNQDRrxj3YcbVw==",
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz",
+ "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.6"
}
@@ -16477,6 +13860,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/topojson-client/-/topojson-client-3.1.0.tgz",
"integrity": "sha512-605uxS6bcYxGXw9qi62XyrV6Q3xwbndjachmNxu8HWTtVPxZfEJN9fd/SZS1Q54Sn2y0TMyMxFj/cJINqGHrKw==",
+ "license": "ISC",
"dependencies": {
"commander": "2"
},
@@ -16486,101 +13870,74 @@
"topoquantize": "bin/topoquantize"
}
},
- "node_modules/toposort": {
- "version": "1.0.7",
- "resolved": "https://registry.npmjs.org/toposort/-/toposort-1.0.7.tgz",
- "integrity": "sha1-LmhELZ9k7HILjMieZEOsbKqVACk= sha512-FclLrw8b9bMWf4QlCJuHBEVhSRsqDj6u3nIjAzPeJvgl//1hBlffdlk0MALceL14+koWEdU4ofRAXofbODxQzg==",
- "dev": true
- },
- "node_modules/tough-cookie": {
- "version": "2.5.0",
- "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.5.0.tgz",
- "integrity": "sha512-nlLsUzgm1kfLXSXfRZMc1KLAugd4hqJHDTvc2hDIwS3mZAfMEuMbc03SujMF+GEcpaX/qboeycw6iO8JwVv2+g==",
- "dev": true,
- "dependencies": {
- "psl": "^1.1.28",
- "punycode": "^2.1.1"
- },
- "engines": {
- "node": ">=0.8"
- }
+ "node_modules/topojson-client/node_modules/commander": {
+ "version": "2.20.3",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
+ "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
+ "license": "MIT"
},
- "node_modules/tryer": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/tryer/-/tryer-1.0.1.tgz",
- "integrity": "sha512-c3zayb8/kWWpycWYg87P71E1S1ZL6b6IJxfb5fvsUgsf0S2MVGaDhDXXjDMpdCpfWXqptc+4mXwmiy1ypXqRAA==",
- "dev": true
+ "node_modules/toposort": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
+ "integrity": "sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg==",
+ "license": "MIT"
},
- "node_modules/ts-pnp": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/ts-pnp/-/ts-pnp-1.2.0.tgz",
- "integrity": "sha512-csd+vJOb/gkzvcCHgTGSChYpy5f1/XKNsmvBGO4JXS+z1v2HobugDz4s1IeFXM3wZB44uczs+eazB5Q/ccdhQw==",
+ "node_modules/totalist": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz",
+ "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=6"
- },
- "peerDependenciesMeta": {
- "typescript": {
- "optional": true
- }
}
},
- "node_modules/tslib": {
- "version": "1.14.1",
- "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.14.1.tgz",
- "integrity": "sha512-Xni35NKzjgMrwevysHTCArtLDpPvye8zV/0E4EyYn43P7/7qvQwPh9BGkHewbMulVntbigmcT7rdX3BNo9wRJg==",
- "dev": true
- },
- "node_modules/tty-browserify": {
- "version": "0.0.0",
- "resolved": "https://registry.npmjs.org/tty-browserify/-/tty-browserify-0.0.0.tgz",
- "integrity": "sha1-oVe6QC2iTpv5V/mqadUk7tQpAaY= sha512-JVa5ijo+j/sOoHGjw0sxw734b1LhBkQ3bvUGNdxnVXDCX81Yx7TFgnZygxrIIWn23hbfTaMYLwRmAxFyDuFmIw==",
- "dev": true
- },
- "node_modules/tunnel-agent": {
- "version": "0.6.0",
- "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz",
- "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0= sha512-McnNiV1l8RYeY8tBgEpuodCC1mLUdbSN+CYBL7kJsJNInOP8UjDDEwdk6Mw60vdLLrr5NHKZhMAOSrR2NZuQ+w==",
+ "node_modules/tr46": {
+ "version": "0.0.3",
+ "resolved": "https://registry.npmjs.org/tr46/-/tr46-0.0.3.tgz",
+ "integrity": "sha512-N3WMsuqV66lT30CrXNbEjx4GEwlow3v6rr4mCcv6prnfwhS01rkgyFdjPNBYd9br7LpXV1+Emh01fHnq2Gdgrw==",
"dev": true,
- "dependencies": {
- "safe-buffer": "^5.0.1"
- },
- "engines": {
- "node": "*"
- }
+ "license": "MIT"
},
- "node_modules/tweetnacl": {
- "version": "0.14.5",
- "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz",
- "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q= sha512-KXXFFdAbFXY4geFIwoyNK+f5Z1b7swfXABfL7HXCmoIWMKU3dmS26672A4EeQtDzLKy7SXmfBu51JolvEKwtGA==",
- "dev": true
+ "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==",
+ "license": "Apache-2.0"
+ },
+ "node_modules/tslib": {
+ "version": "2.8.1",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.8.1.tgz",
+ "integrity": "sha512-oJFu94HQb+KVduSUQL7wnpmqnfmLsOA/nAh6b6EH0wCEoK0/mPeXU6c3wKDV83MkOuHPRHtSXKKU99IBazS/2w==",
+ "license": "0BSD"
},
"node_modules/type": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/type/-/type-1.2.0.tgz",
- "integrity": "sha512-+5nt5AAniqsCnu2cEQQdpzCAh33kVx8n0VoFidKpB1dVVLAN/F+bgVOqOJqOnEnrhp222clB5p3vUlD+1QAnfg=="
+ "version": "2.7.3",
+ "resolved": "https://registry.npmjs.org/type/-/type-2.7.3.tgz",
+ "integrity": "sha512-8j+1QmAbPvLZow5Qpi6NCaN8FB60p/6x8/vfNqOk/hC+HuvFZhL4+WfekuhQLiqFZXOgQdrs3B+XxEmCc6b3FQ==",
+ "license": "ISC"
},
"node_modules/type-check": {
- "version": "0.3.2",
- "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz",
- "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I= sha512-ZCmOJdvOWDBYJlzAoFkC+Q0+bUyEOS1ltgp1MGU03fqHG+dbi9tBFU2Rd9QKiDZFAYrhPh2JUf7rZRIuHRKtOg==",
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.4.0.tgz",
+ "integrity": "sha512-XleUoc9uwGXqjWwXaUTZAmzMcFZ5858QA2vvx1Ur5xIcixXIP+8LnFDgRplU30us6teqdlskFfu+ae4K79Ooew==",
+ "dev": true,
+ "license": "MIT",
"dependencies": {
- "prelude-ls": "~1.1.2"
+ "prelude-ls": "^1.2.1"
},
"engines": {
"node": ">= 0.8.0"
}
},
"node_modules/type-fest": {
- "version": "0.21.3",
- "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.21.3.tgz",
- "integrity": "sha512-t0rzBq87m3fVcduHDUFhKmyyX+9eo6WQjZvf51Ea/M0Q7+T374Jp1aUiyUl0GKxp8M/OETVHSDvmkyPgvX+X2w==",
+ "version": "0.6.0",
+ "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-0.6.0.tgz",
+ "integrity": "sha512-q+MB8nYR1KDLrgr4G5yemftpMC7/QLqVndBmEEdqzmNj5dcFOO4Oo8qlwZE3ULT3+Zim1F8Kq4cBnikNhlCMlg==",
"dev": true,
+ "license": "(MIT OR CC0-1.0)",
"engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
+ "node": ">=8"
}
},
"node_modules/type-is": {
@@ -16588,6 +13945,7 @@
"resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.18.tgz",
"integrity": "sha512-TkRKr9sUTxEH8MdfuCSP7VizJyzRNMjj2J2do2Jr3Kym598JVdEksuzPQCnlFPW4ky9Q+iA+ma9BGm06XQBy8g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"media-typer": "0.3.0",
"mime-types": "~2.1.24"
@@ -16597,2024 +13955,891 @@
}
},
"node_modules/typed-function": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.0.tgz",
- "integrity": "sha512-DGwUl6cioBW5gw2L+6SMupGwH/kZOqivy17E4nsh1JI9fKF87orMmlQx3KISQPmg3sfnOUGlwVkroosvgddrlg==",
- "engines": {
- "node": ">= 14"
- }
- },
- "node_modules/typedarray": {
- "version": "0.0.6",
- "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
- "integrity": "sha1-hnrHTjhkGHsdPUfZlqeOxciDB3c= sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA=="
- },
- "node_modules/typedarray-pool": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/typedarray-pool/-/typedarray-pool-1.2.0.tgz",
- "integrity": "sha512-YTSQbzX43yvtpfRtIDAYygoYtgT+Rpjuxy9iOpczrjpXLgGoyG7aS5USJXV2d3nn8uHTeb9rXDvzS27zUg5KYQ==",
- "dependencies": {
- "bit-twiddle": "^1.0.0",
- "dup": "^1.0.0"
- }
- },
- "node_modules/uglify-js": {
- "version": "3.4.10",
- "resolved": "https://registry.npmjs.org/uglify-js/-/uglify-js-3.4.10.tgz",
- "integrity": "sha512-Y2VsbPVs0FIshJztycsO2SfPk7/KAF/T72qzv9u5EpQ4kB2hQoHlhNQTsNyy6ul7lQtqJN/AoWeS23OzEiEFxw==",
- "dev": true,
- "dependencies": {
- "commander": "~2.19.0",
- "source-map": "~0.6.1"
- },
- "bin": {
- "uglifyjs": "bin/uglifyjs"
- },
- "engines": {
- "node": ">=0.8.0"
- }
- },
- "node_modules/uglify-js/node_modules/commander": {
- "version": "2.19.0",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz",
- "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==",
- "dev": true
- },
- "node_modules/uglify-js/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/unbox-primitive": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/unbox-primitive/-/unbox-primitive-1.0.1.tgz",
- "integrity": "sha512-tZU/3NqK3dA5gpE1KtyiJUrEB0lxnGkMFHptJ7q6ewdZ8s12QrODwNbhIJStmJkd1QDXa1NRA8aF2A1zk/Ypyw==",
- "dev": true,
- "dependencies": {
- "function-bind": "^1.1.1",
- "has-bigints": "^1.0.1",
- "has-symbols": "^1.0.2",
- "which-boxed-primitive": "^1.0.2"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/unicode-canonical-property-names-ecmascript": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.0.tgz",
- "integrity": "sha512-yY5PpDlfVIU5+y/BSCxAJRBIS1Zc2dDG3Ujq+sR0U+JjUevW2JhocOF+soROYDSaAezOzOKuyyixhD6mBknSmQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-match-property-ecmascript": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
- "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
- "dev": true,
- "dependencies": {
- "unicode-canonical-property-names-ecmascript": "^2.0.0",
- "unicode-property-aliases-ecmascript": "^2.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-match-property-value-ecmascript": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.0.0.tgz",
- "integrity": "sha512-7Yhkc0Ye+t4PNYzOGKedDhXbYIBe1XEQYQxOPyhcXNMJ0WCABqqj6ckydd6pWRZTHV4GuCPKdBAUiMc60tsKVw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/unicode-property-aliases-ecmascript": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.0.0.tgz",
- "integrity": "sha512-5Zfuy9q/DFr4tfO7ZPeVXb1aPoeQSdeFMLpYuFebehDAhbuevLs5yxSZmIFN1tP5F9Wl4IpJrYojg85/zgyZHQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/union-value": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/union-value/-/union-value-1.0.1.tgz",
- "integrity": "sha512-tJfXmxMeWYnczCVs7XAEvIV7ieppALdyepWMkHkwciRpZraG/xwT+s2JN8+pr1+8jCRf80FFzvr+MpQeeoF4Xg==",
- "dev": true,
- "dependencies": {
- "arr-union": "^3.1.0",
- "get-value": "^2.0.6",
- "is-extendable": "^0.1.1",
- "set-value": "^2.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/union-value/node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/uniq": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/uniq/-/uniq-1.0.1.tgz",
- "integrity": "sha1-sxxa6CVIRKOoKBVBzisEuGWnNP8= sha512-Gw+zz50YNKPDKXs+9d+aKAjVwpjNwqzvNpLigIruT4HA9lMZNdMqs9x07kKHB/L9WRzqp4+DlTU5s4wG2esdoA==",
- "dev": true
- },
- "node_modules/uniqs": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/uniqs/-/uniqs-2.0.0.tgz",
- "integrity": "sha1-/+3ks2slKQaW5uFl1KWe25mOawI= sha512-mZdDpf3vBV5Efh29kMw5tXoup/buMgxLzOt/XKFKcVmi+15ManNQWr6HfZ2aiZTYlYixbdNJ0KFmIZIv52tHSQ==",
- "dev": true
- },
- "node_modules/unique-filename": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/unique-filename/-/unique-filename-1.1.1.tgz",
- "integrity": "sha512-Vmp0jIp2ln35UTXuryvjzkjGdRyf9b2lTXuSYUiPmzRcl3FDtYqAwOnTJkAngD9SWhnoJzDbTKwaOrZ+STtxNQ==",
- "dev": true,
- "dependencies": {
- "unique-slug": "^2.0.0"
- }
- },
- "node_modules/unique-slug": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/unique-slug/-/unique-slug-2.0.2.tgz",
- "integrity": "sha512-zoWr9ObaxALD3DOPfjPSqxt4fnZiWblxHIgeWqW8x7UqDzEtHEQLzji2cuJYQFCU6KmoJikOYAZlrTHHebjx2w==",
- "dev": true,
- "dependencies": {
- "imurmurhash": "^0.1.4"
- }
- },
- "node_modules/universalify": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.0.tgz",
- "integrity": "sha512-hAZsKq7Yy11Zu1DE0OzWjw7nnLZmJZYTDZZyEFHZdUhV8FkH5MCfoU1XMaxXovpyW5nq5scPqq0ZDP9Zyl04oQ==",
- "dev": true,
- "engines": {
- "node": ">= 10.0.0"
- }
- },
- "node_modules/unpipe": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
- "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw= sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
- "dev": true,
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/unquote": {
- "version": "1.1.1",
- "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
- "integrity": "sha1-j97XMk7G6IoP+LkF58CYzcCG1UQ= sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg=="
- },
- "node_modules/unset-value": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/unset-value/-/unset-value-1.0.0.tgz",
- "integrity": "sha1-g3aHP30jNRef+x5vw6jtDfyKtVk= sha512-PcA2tsuGSF9cnySLHTLSh2qrQiJ70mn+r+Glzxv2TWZblxsxCC52BDlZoPCsz7STd9pN7EZetkWZBAvk4cgZdQ==",
- "dev": true,
- "dependencies": {
- "has-value": "^0.3.1",
- "isobject": "^3.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/unset-value/node_modules/has-value": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/has-value/-/has-value-0.3.1.tgz",
- "integrity": "sha1-ex9YutpiyoJ+wKIHgCVlSEWZXh8= sha512-gpG936j8/MzaeID5Yif+577c17TxaDmhuyVgSwtnL/q8UUTySg8Mecb+8Cf1otgLoD7DDH75axp86ER7LFsf3Q==",
- "dev": true,
- "dependencies": {
- "get-value": "^2.0.3",
- "has-values": "^0.1.4",
- "isobject": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/unset-value/node_modules/has-value/node_modules/isobject": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/isobject/-/isobject-2.1.0.tgz",
- "integrity": "sha1-8GVWEJaj8dou9GJy+BXIQNh+DIk= sha512-+OUdGJlgjOBZDfxnDjYYG6zp487z0JGNQq3cYQYg5f5hKR+syHMsaztzGeml/4kGG55CSpKSpWTY+jYGgsHLgA==",
- "dev": true,
- "dependencies": {
- "isarray": "1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/unset-value/node_modules/has-values": {
- "version": "0.1.4",
- "resolved": "https://registry.npmjs.org/has-values/-/has-values-0.1.4.tgz",
- "integrity": "sha1-bWHeldkd/Km5oCCJrThL/49it3E= sha512-J8S0cEdWuQbqD9//tlZxiMuMNmxB8PlEwvYwuxsTmR1G5RXUePEX/SJn7aD0GMLieuZYSwNH0cQuJGwnYunXRQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/unset-value/node_modules/isarray": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz",
- "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE= sha512-VLghIWNM6ELQzo7zwmcg0NmTVyWKYjvIeM83yjp0wRDTmUnrM678fQbcKBo6n2CJEF0szoG//ytg+TKla89ALQ==",
- "dev": true
- },
- "node_modules/upath": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/upath/-/upath-1.2.0.tgz",
- "integrity": "sha512-aZwGpamFO61g3OlfT7OQCHqhGnW43ieH9WZeP7QxN/G/jS4jfqUkZxoryvJgVPEcrl5NL/ggHsSmLMHuH64Lhg==",
- "dev": true,
- "engines": {
- "node": ">=4",
- "yarn": "*"
- }
- },
- "node_modules/update-diff": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/update-diff/-/update-diff-1.1.0.tgz",
- "integrity": "sha512-rCiBPiHxZwT4+sBhEbChzpO5hYHjm91kScWgdHf4Qeafs6Ba7MBl+d9GlGv72bcTZQO0sLmtQS1pHSWoCLtN/A=="
- },
- "node_modules/upper-case": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/upper-case/-/upper-case-1.1.3.tgz",
- "integrity": "sha1-9rRQHC7EzdJrp4vnIilh3ndiFZg= sha512-WRbjgmYzgXkCV7zNVpy5YgrHgbBv126rMALQQMrmzOVC4GM2waQ9x7xtm8VU+1yF2kWyPzI9zbZ48n4vSxwfSA==",
- "dev": true
- },
- "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/urix": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/urix/-/urix-0.1.0.tgz",
- "integrity": "sha1-2pN/emLiH+wf0Y1Js1wpNQZ6bHI= sha512-Am1ousAhSLBeB9cG/7k7r2R0zj50uDRlZHPGbazid5s9rlF1F/QKYObEKSIunSjIOkJZqwRRLpvewjEkM7pSqg==",
- "deprecated": "Please see https://github.com/lydell/urix#deprecated",
- "dev": true
- },
- "node_modules/url": {
- "version": "0.11.0",
- "resolved": "https://registry.npmjs.org/url/-/url-0.11.0.tgz",
- "integrity": "sha1-ODjpfPxgUh63PFJajlW/3Z4uKPE= sha512-kbailJa29QrtXnxgq+DdCEGlbTeYM2eJUxsz6vjZavrCYPMIFHMKQmSKYAIuUK2i7hgPm28a8piX5NTUtM/LKQ==",
- "dev": true,
- "dependencies": {
- "punycode": "1.3.2",
- "querystring": "0.2.0"
- }
- },
- "node_modules/url-loader": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/url-loader/-/url-loader-2.3.0.tgz",
- "integrity": "sha512-goSdg8VY+7nPZKUEChZSEtW5gjbS66USIGCeSJ1OVOJ7Yfuh/36YxCwMi5HVEJh6mqUYOoy3NJ0vlOMrWsSHog==",
- "dev": true,
- "dependencies": {
- "loader-utils": "^1.2.3",
- "mime": "^2.4.4",
- "schema-utils": "^2.5.0"
- },
- "engines": {
- "node": ">= 8.9.0"
- },
- "peerDependencies": {
- "file-loader": "*",
- "webpack": "^4.0.0"
- },
- "peerDependenciesMeta": {
- "file-loader": {
- "optional": true
- }
- }
- },
- "node_modules/url-parse": {
- "version": "1.5.10",
- "resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.10.tgz",
- "integrity": "sha512-WypcfiRhfeUP9vvF0j6rw0J3hrWrw6iZv3+22h6iRMJ/8z1Tj6XfLP4DsUix5MhMPnXpiHDoKyoZ/bdCkwBCiQ==",
- "dev": true,
- "dependencies": {
- "querystringify": "^2.1.1",
- "requires-port": "^1.0.0"
- }
- },
- "node_modules/url/node_modules/punycode": {
- "version": "1.3.2",
- "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.3.2.tgz",
- "integrity": "sha1-llOgNvt8HuQjQvIyXM7v6jkmxI0= sha512-RofWgt/7fL5wP1Y7fxE7/EmTLzQVnB0ycyibJ0OOHIlJqTNzglYFxVwETOcIoJqJmpDXJ9xImDv+Fq34F/d4Dw==",
- "dev": true
- },
- "node_modules/use": {
- "version": "3.1.1",
- "resolved": "https://registry.npmjs.org/use/-/use-3.1.1.tgz",
- "integrity": "sha512-cwESVXlO3url9YWlFW/TA9cshCEhtu7IKJ/p5soJ/gGpj7vbvFrAY/eIioQ6Dw23KjZhYgiIo8HOs1nQ2vr/oQ==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/util": {
- "version": "0.11.1",
- "resolved": "https://registry.npmjs.org/util/-/util-0.11.1.tgz",
- "integrity": "sha512-HShAsny+zS2TZfaXxD9tYj4HQGlBezXZMZuM/S5PKLLoZkShZiGk9o5CzukI1LVHZvjdvZ2Sj1aW/Ndn2NB/HQ==",
- "dev": true,
- "dependencies": {
- "inherits": "2.0.3"
- }
- },
- "node_modules/util-deprecate": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz",
- "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8= sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw=="
- },
- "node_modules/util.promisify": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/util.promisify/-/util.promisify-1.0.0.tgz",
- "integrity": "sha512-i+6qA2MPhvoKLuxnJNpXAGhg7HphQOSUq2LKMZD0m15EiskXUkMvKdF4Uui0WYeCUGea+o2cw/ZuwehtfsrNkA==",
- "dev": true,
- "dependencies": {
- "define-properties": "^1.1.2",
- "object.getownpropertydescriptors": "^2.0.3"
- }
- },
- "node_modules/util/node_modules/inherits": {
- "version": "2.0.3",
- "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz",
- "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4= sha512-x00IRNXNy63jwGkJmzPigoySHbaqpNuzKbBOmzK+g2OdZpQ9w+sxCN+VSB3ja7IAge2OP2qpfxTjeNcyjmW1uw==",
- "dev": true
- },
- "node_modules/utila": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
- "integrity": "sha1-ihagXURWV6Oupe7MWxKk+lN5dyw= sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==",
- "dev": true
- },
- "node_modules/utils-merge": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
- "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM= sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
- "dev": true,
- "engines": {
- "node": ">= 0.4.0"
- }
- },
- "node_modules/uuid": {
- "version": "3.4.0",
- "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.4.0.tgz",
- "integrity": "sha512-HjSDRw6gZE5JMggctHBcjVak08+KEVhSIiDzFnT9S9aegmp85S/bReBVTb4QTFaRNptJ9kuYaNhnbNEOkbKb/A==",
- "deprecated": "Please upgrade to version 7 or higher. Older versions may use Math.random() in certain circumstances, which is known to be problematic. See https://v8.dev/blog/math-random for details.",
- "dev": true,
- "bin": {
- "uuid": "bin/uuid"
- }
- },
- "node_modules/v8-compile-cache": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/v8-compile-cache/-/v8-compile-cache-2.3.0.tgz",
- "integrity": "sha512-l8lCEmLcLYZh4nbunNZvQCJc5pv7+RCwa8q/LdUx8u7lsWvPDKmpodJAJNwkAhJC//dFY48KuIEmjtd4RViDrA==",
- "dev": true
- },
- "node_modules/validate-npm-package-license": {
- "version": "3.0.4",
- "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
- "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
- "dev": true,
- "dependencies": {
- "spdx-correct": "^3.0.0",
- "spdx-expression-parse": "^3.0.0"
- }
- },
- "node_modules/vary": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
- "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw= sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
- "dev": true,
- "engines": {
- "node": ">= 0.8"
- }
- },
- "node_modules/vendors": {
- "version": "1.0.4",
- "resolved": "https://registry.npmjs.org/vendors/-/vendors-1.0.4.tgz",
- "integrity": "sha512-/juG65kTL4Cy2su4P8HjtkTxk6VmJDiOPBufWniqQ6wknac6jNiXS9vU+hO3wgusiyqWlzTbVHi0dyJqRONg3w==",
- "dev": true,
- "funding": {
- "type": "github",
- "url": "https://github.com/sponsors/wooorm"
- }
- },
- "node_modules/verror": {
- "version": "1.10.0",
- "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz",
- "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA= sha512-ZZKSmDAEFOijERBLkmYfJ+vmk3w+7hOLYDNkRCuRuMJGEmqYNCNLyBBFwWKVMhfwaEF3WOd0Zlw86U/WC/+nYw==",
- "dev": true,
- "engines": [
- "node >=0.6.0"
- ],
- "dependencies": {
- "assert-plus": "^1.0.0",
- "core-util-is": "1.0.2",
- "extsprintf": "^1.2.0"
- }
- },
- "node_modules/verror/node_modules/core-util-is": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz",
- "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac= sha512-3lqz5YjWTYnW6dlDa5TLaTCcShfar1e40rmcJVwCBJC6mWlFuj0eCHIElmG1g5kyuJ/GD+8Wn4FFCcz4gJPfaQ==",
- "dev": true
- },
- "node_modules/vm-browserify": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/vm-browserify/-/vm-browserify-1.1.2.tgz",
- "integrity": "sha512-2ham8XPWTONajOR0ohOKOHXkm3+gaBmGut3SRuu75xLd/RRaY6vqgh8NBYYk7+RW3u5AtzPQZG8F10LHkl0lAQ==",
- "dev": true
- },
- "node_modules/vt-pbf": {
- "version": "3.1.3",
- "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz",
- "integrity": "sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==",
- "dependencies": {
- "@mapbox/point-geometry": "0.1.0",
- "@mapbox/vector-tile": "^1.3.1",
- "pbf": "^3.2.1"
- }
- },
- "node_modules/vue": {
- "version": "2.7.16",
- "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
- "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
- "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
- "license": "MIT",
- "dependencies": {
- "@vue/compiler-sfc": "2.7.16",
- "csstype": "^3.1.0"
- }
- },
- "node_modules/vue-demi": {
- "version": "0.14.10",
- "resolved": "https://registry.npmjs.org/vue-demi/-/vue-demi-0.14.10.tgz",
- "integrity": "sha512-nMZBOwuzabUO0nLgIcc6rycZEebF6eeUfaiQx9+WSk8e29IbLvPU9feI6tqW4kTo3hvoYAJkMh8n8D0fuISphg==",
- "hasInstallScript": true,
- "license": "MIT",
- "bin": {
- "vue-demi-fix": "bin/vue-demi-fix.js",
- "vue-demi-switch": "bin/vue-demi-switch.js"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/sponsors/antfu"
- },
- "peerDependencies": {
- "@vue/composition-api": "^1.0.0-rc.1",
- "vue": "^3.0.0-0 || ^2.6.0"
- },
- "peerDependenciesMeta": {
- "@vue/composition-api": {
- "optional": true
- }
- }
- },
- "node_modules/vue-eslint-parser": {
- "version": "7.11.0",
- "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-7.11.0.tgz",
- "integrity": "sha512-qh3VhDLeh773wjgNTl7ss0VejY9bMMa0GoDG2fQVyDzRFdiU3L7fw74tWZDHNQXdZqxO3EveQroa9ct39D2nqg==",
- "dev": true,
- "dependencies": {
- "debug": "^4.1.1",
- "eslint-scope": "^5.1.1",
- "eslint-visitor-keys": "^1.1.0",
- "espree": "^6.2.1",
- "esquery": "^1.4.0",
- "lodash": "^4.17.21",
- "semver": "^6.3.0"
- },
- "engines": {
- "node": ">=8.10"
- },
- "funding": {
- "url": "https://github.com/sponsors/mysticatea"
- },
- "peerDependencies": {
- "eslint": ">=5.0.0"
- }
- },
- "node_modules/vue-hot-reload-api": {
- "version": "2.3.4",
- "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
- "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==",
- "dev": true
- },
- "node_modules/vue-loader": {
- "version": "15.9.8",
- "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-15.9.8.tgz",
- "integrity": "sha512-GwSkxPrihfLR69/dSV3+5CdMQ0D+jXg8Ma1S4nQXKJAznYFX14vHdc/NetQc34Dw+rBbIJyP7JOuVb9Fhprvog==",
- "dev": true,
- "dependencies": {
- "@vue/component-compiler-utils": "^3.1.0",
- "hash-sum": "^1.0.2",
- "loader-utils": "^1.1.0",
- "vue-hot-reload-api": "^2.3.0",
- "vue-style-loader": "^4.1.0"
- },
- "peerDependencies": {
- "css-loader": "*",
- "webpack": "^3.0.0 || ^4.1.0 || ^5.0.0-0"
- },
- "peerDependenciesMeta": {
- "cache-loader": {
- "optional": true
- },
- "vue-template-compiler": {
- "optional": true
- }
- }
- },
- "node_modules/vue-loader-v16": {
- "name": "vue-loader",
- "version": "16.8.3",
- "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.8.3.tgz",
- "integrity": "sha512-7vKN45IxsKxe5GcVCbc2qFU5aWzyiLrYJyUuMz4BQLKctCj/fmCa0w6fGiiQ2cLFetNcek1ppGJQDCup0c1hpA==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "chalk": "^4.1.0",
- "hash-sum": "^2.0.0",
- "loader-utils": "^2.0.0"
- },
- "peerDependencies": {
- "webpack": "^4.1.0 || ^5.0.0-0"
- }
- },
- "node_modules/vue-loader-v16/node_modules/loader-utils": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.2.tgz",
- "integrity": "sha512-TM57VeHptv569d/GKh6TAYdzKblwDNiumOdkFnejjD0XwTH87K90w3O7AiJRqdQoXygvi1VQTJTLGhJl7WqA7A==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "big.js": "^5.2.2",
- "emojis-list": "^3.0.0",
- "json5": "^2.1.2"
- },
- "engines": {
- "node": ">=8.9.0"
- }
- },
- "node_modules/vue-loader/node_modules/hash-sum": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
- "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ= sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
- "dev": true
- },
- "node_modules/vue-reactive-provide": {
- "version": "0.3.0",
- "resolved": "https://registry.npmjs.org/vue-reactive-provide/-/vue-reactive-provide-0.3.0.tgz",
- "integrity": "sha512-hx2JtRPRvne9NY4s1r7ASsCaO8CIby30qwC1kGQRxsrWApO3he+rziGOzTDSfvmr852zWMb11n6qAwHCz6C/vw==",
- "peerDependencies": {
- "vue": ">=2.6"
- }
- },
- "node_modules/vue-router": {
- "version": "3.5.3",
- "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.5.3.tgz",
- "integrity": "sha512-FUlILrW3DGitS2h+Xaw8aRNvGTwtuaxrRkNSHWTizOfLUie7wuYwezeZ50iflRn8YPV5kxmU2LQuu3nM/b3Zsg=="
- },
- "node_modules/vue-select": {
- "version": "3.16.0",
- "resolved": "https://registry.npmjs.org/vue-select/-/vue-select-3.16.0.tgz",
- "integrity": "sha512-F0x7HXTUc5eq7YSjR0uX77RGA+Yk2+I8aMW+NePyPqRX9OPSiDtKpezFIFhnhxqrOvMh4uVR0jHkXIDmzs6nYQ==",
- "peerDependencies": {
- "vue": "2.x"
- }
- },
- "node_modules/vue-style-loader": {
- "version": "4.1.3",
- "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
- "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==",
- "dev": true,
- "dependencies": {
- "hash-sum": "^1.0.2",
- "loader-utils": "^1.0.2"
- }
- },
- "node_modules/vue-style-loader/node_modules/hash-sum": {
- "version": "1.0.2",
- "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
- "integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ= sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
- "dev": true
- },
- "node_modules/vue-template-compiler": {
- "version": "2.7.16",
- "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz",
- "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==",
- "license": "MIT",
- "dependencies": {
- "de-indent": "^1.0.2",
- "he": "^1.2.0"
- }
- },
- "node_modules/vue-template-es2015-compiler": {
- "version": "1.9.1",
- "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz",
- "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
- "dev": true
- },
- "node_modules/vue/node_modules/@vue/compiler-sfc": {
- "version": "2.7.16",
- "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
- "integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==",
- "dependencies": {
- "@babel/parser": "^7.23.5",
- "postcss": "^8.4.14",
- "source-map": "^0.6.1"
- },
- "optionalDependencies": {
- "prettier": "^1.18.2 || ^2.0.0"
- }
- },
- "node_modules/vue/node_modules/postcss": {
- "version": "8.5.3",
- "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.3.tgz",
- "integrity": "sha512-dle9A3yYxlBSrt8Fu+IpjGT8SY8hN0mlaA6GY8t0P5PjIOZemULz/E2Bnm/2dcUOena75OTNkHI76uZBNUUq3A==",
- "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"
- }
- ],
- "license": "MIT",
- "dependencies": {
- "nanoid": "^3.3.8",
- "picocolors": "^1.1.1",
- "source-map-js": "^1.2.1"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- }
- },
- "node_modules/vue/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==",
- "license": "BSD-3-Clause",
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/vuex": {
- "version": "3.6.2",
- "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
- "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==",
- "peerDependencies": {
- "vue": "^2.0.0"
- }
- },
- "node_modules/watchpack": {
- "version": "1.7.5",
- "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-1.7.5.tgz",
- "integrity": "sha512-9P3MWk6SrKjHsGkLT2KHXdQ/9SNkyoJbabxnKOoJepsvJjJG8uYTR3yTPxPQvNDI3w4Nz1xnE0TLHK4RIVe/MQ==",
- "dev": true,
- "dependencies": {
- "graceful-fs": "^4.1.2",
- "neo-async": "^2.5.0"
- },
- "optionalDependencies": {
- "chokidar": "^3.4.1",
- "watchpack-chokidar2": "^2.0.1"
- }
- },
- "node_modules/watchpack-chokidar2": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/watchpack-chokidar2/-/watchpack-chokidar2-2.0.1.tgz",
- "integrity": "sha512-nCFfBIPKr5Sh61s4LPpy1Wtfi0HE8isJ3d2Yb5/Ppw2P2B/3eVSEBjKfN0fmHJSK14+31KwMKmcrzs2GM4P0Ww==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "chokidar": "^2.1.8"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/anymatch": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
- "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "micromatch": "^3.1.4",
- "normalize-path": "^2.1.1"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/anymatch/node_modules/normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "remove-trailing-separator": "^1.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/binary-extensions": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
- "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
- "dev": true,
- "optional": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "arr-flatten": "^1.1.0",
- "array-unique": "^0.3.2",
- "extend-shallow": "^2.0.1",
- "fill-range": "^4.0.0",
- "isobject": "^3.0.1",
- "repeat-element": "^1.1.2",
- "snapdragon": "^0.8.1",
- "snapdragon-node": "^2.0.1",
- "split-string": "^3.0.2",
- "to-regex": "^3.0.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/braces/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "is-extendable": "^0.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/chokidar": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
- "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "anymatch": "^2.0.0",
- "async-each": "^1.0.1",
- "braces": "^2.3.2",
- "glob-parent": "^3.1.0",
- "inherits": "^2.0.3",
- "is-binary-path": "^1.0.0",
- "is-glob": "^4.0.0",
- "normalize-path": "^3.0.0",
- "path-is-absolute": "^1.0.0",
- "readdirp": "^2.2.1",
- "upath": "^1.1.1"
- },
- "optionalDependencies": {
- "fsevents": "^1.2.7"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/fill-range": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/fill-range/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "is-extendable": "^0.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
- "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
- "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
- "dependencies": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- },
- "engines": {
- "node": ">= 4.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/glob-parent/node_modules/is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "is-extglob": "^2.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/is-binary-path": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
- "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "binary-extensions": "^1.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
- "dev": true,
- "optional": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/is-number/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "braces": "^2.3.1",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "extglob": "^2.0.4",
- "fragment-cache": "^0.2.1",
- "kind-of": "^6.0.2",
- "nanomatch": "^1.2.9",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/readdirp": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
- "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "graceful-fs": "^4.1.11",
- "micromatch": "^3.1.10",
- "readable-stream": "^2.0.2"
- },
- "engines": {
- "node": ">=0.10"
- }
- },
- "node_modules/watchpack-chokidar2/node_modules/to-regex-range": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
- "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==",
- "dev": true,
- "optional": true,
- "dependencies": {
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/wbuf": {
- "version": "1.7.3",
- "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
- "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
- "dev": true,
- "dependencies": {
- "minimalistic-assert": "^1.0.0"
- }
- },
- "node_modules/wcwidth": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
- "integrity": "sha1-8LDc+RW8X/FSivrbLA4XtTLaL+g= sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
- "dev": true,
- "dependencies": {
- "defaults": "^1.0.3"
- }
- },
- "node_modules/weak-map": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.8.tgz",
- "integrity": "sha512-lNR9aAefbGPpHO7AEnY0hCFjz1eTkWCXYvkTRrTHs9qv8zJp+SkVYpzfLIFXQQiG3tVvbNFQgVg2bQS8YGgxyw=="
- },
- "node_modules/webgl-context": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/webgl-context/-/webgl-context-2.2.0.tgz",
- "integrity": "sha512-q/fGIivtqTT7PEoF07axFIlHNk/XCPaYpq64btnepopSWvKNFkoORlQYgqDigBIuGA1ExnFd/GnSUnBNEPQY7Q==",
- "dependencies": {
- "get-canvas-context": "^1.0.1"
- }
- },
- "node_modules/webpack": {
- "version": "4.46.0",
- "resolved": "https://registry.npmjs.org/webpack/-/webpack-4.46.0.tgz",
- "integrity": "sha512-6jJuJjg8znb/xRItk7bkT0+Q7AHCYjjFnvKIWQPkNIOyRqoCGvkOs0ipeQzrqz4l5FtN5ZI/ukEHroeX/o1/5Q==",
- "dev": true,
- "dependencies": {
- "@webassemblyjs/ast": "1.9.0",
- "@webassemblyjs/helper-module-context": "1.9.0",
- "@webassemblyjs/wasm-edit": "1.9.0",
- "@webassemblyjs/wasm-parser": "1.9.0",
- "acorn": "^6.4.1",
- "ajv": "^6.10.2",
- "ajv-keywords": "^3.4.1",
- "chrome-trace-event": "^1.0.2",
- "enhanced-resolve": "^4.5.0",
- "eslint-scope": "^4.0.3",
- "json-parse-better-errors": "^1.0.2",
- "loader-runner": "^2.4.0",
- "loader-utils": "^1.2.3",
- "memory-fs": "^0.4.1",
- "micromatch": "^3.1.10",
- "mkdirp": "^0.5.3",
- "neo-async": "^2.6.1",
- "node-libs-browser": "^2.2.1",
- "schema-utils": "^1.0.0",
- "tapable": "^1.1.3",
- "terser-webpack-plugin": "^1.4.3",
- "watchpack": "^1.7.4",
- "webpack-sources": "^1.4.1"
- },
- "bin": {
- "webpack": "bin/webpack.js"
- },
- "engines": {
- "node": ">=6.11.5"
- },
- "funding": {
- "type": "opencollective",
- "url": "https://opencollective.com/webpack"
- },
- "peerDependenciesMeta": {
- "webpack-cli": {
- "optional": true
- },
- "webpack-command": {
- "optional": true
- }
- }
- },
- "node_modules/webpack-bundle-analyzer": {
- "version": "3.9.0",
- "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-3.9.0.tgz",
- "integrity": "sha512-Ob8amZfCm3rMB1ScjQVlbYYUEJyEjdEtQ92jqiFUYt5VkEeO2v5UMbv49P/gnmCZm3A6yaFQzCBvpZqN4MUsdA==",
- "dev": true,
- "dependencies": {
- "acorn": "^7.1.1",
- "acorn-walk": "^7.1.1",
- "bfj": "^6.1.1",
- "chalk": "^2.4.1",
- "commander": "^2.18.0",
- "ejs": "^2.6.1",
- "express": "^4.16.3",
- "filesize": "^3.6.1",
- "gzip-size": "^5.0.0",
- "lodash": "^4.17.19",
- "mkdirp": "^0.5.1",
- "opener": "^1.5.1",
- "ws": "^6.0.0"
- },
- "bin": {
- "webpack-bundle-analyzer": "lib/bin/analyzer.js"
- },
- "engines": {
- "node": ">= 6.14.4"
- }
- },
- "node_modules/webpack-bundle-analyzer/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
- "dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/webpack-bundle-analyzer/node_modules/chalk": {
- "version": "2.4.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
- "integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
- "dev": true,
- "dependencies": {
- "ansi-styles": "^3.2.1",
- "escape-string-regexp": "^1.0.5",
- "supports-color": "^5.3.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/webpack-bundle-analyzer/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
- "dev": true,
- "dependencies": {
- "color-name": "1.1.3"
- }
- },
- "node_modules/webpack-bundle-analyzer/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/webpack-bundle-analyzer/node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "dev": true
- },
- "node_modules/webpack-bundle-analyzer/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/webpack-bundle-analyzer/node_modules/supports-color": {
- "version": "5.5.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
- "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
- "dev": true,
- "dependencies": {
- "has-flag": "^3.0.0"
- },
- "engines": {
- "node": ">=4"
- }
- },
- "node_modules/webpack-chain": {
- "version": "6.5.1",
- "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz",
- "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==",
- "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
- "dev": true,
- "dependencies": {
- "deepmerge": "^1.5.2",
- "javascript-stringify": "^2.0.1"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/webpack-dev-middleware": {
- "version": "3.7.3",
- "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-3.7.3.tgz",
- "integrity": "sha512-djelc/zGiz9nZj/U7PTBi2ViorGJXEWo/3ltkPbDyxCXhhEXkW0ce99falaok4TPj+AsxLiXJR0EBOb0zh9fKQ==",
- "dev": true,
- "dependencies": {
- "memory-fs": "^0.4.1",
- "mime": "^2.4.4",
- "mkdirp": "^0.5.1",
- "range-parser": "^1.2.1",
- "webpack-log": "^2.0.0"
- },
- "engines": {
- "node": ">= 6"
- },
- "peerDependencies": {
- "webpack": "^4.0.0 || ^5.0.0"
- }
- },
- "node_modules/webpack-dev-server": {
- "version": "3.11.3",
- "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-3.11.3.tgz",
- "integrity": "sha512-3x31rjbEQWKMNzacUZRE6wXvUFuGpH7vr0lIEbYpMAG9BOxi0928QU1BBswOAP3kg3H1O4hiS+sq4YyAn6ANnA==",
- "dev": true,
- "dependencies": {
- "ansi-html-community": "0.0.8",
- "bonjour": "^3.5.0",
- "chokidar": "^2.1.8",
- "compression": "^1.7.4",
- "connect-history-api-fallback": "^1.6.0",
- "debug": "^4.1.1",
- "del": "^4.1.1",
- "express": "^4.17.1",
- "html-entities": "^1.3.1",
- "http-proxy-middleware": "0.19.1",
- "import-local": "^2.0.0",
- "internal-ip": "^4.3.0",
- "ip": "^1.1.5",
- "is-absolute-url": "^3.0.3",
- "killable": "^1.0.1",
- "loglevel": "^1.6.8",
- "opn": "^5.5.0",
- "p-retry": "^3.0.1",
- "portfinder": "^1.0.26",
- "schema-utils": "^1.0.0",
- "selfsigned": "^1.10.8",
- "semver": "^6.3.0",
- "serve-index": "^1.9.1",
- "sockjs": "^0.3.21",
- "sockjs-client": "^1.5.0",
- "spdy": "^4.0.2",
- "strip-ansi": "^3.0.1",
- "supports-color": "^6.1.0",
- "url": "^0.11.0",
- "webpack-dev-middleware": "^3.7.2",
- "webpack-log": "^2.0.0",
- "ws": "^6.2.1",
- "yargs": "^13.3.2"
- },
- "bin": {
- "webpack-dev-server": "bin/webpack-dev-server.js"
- },
- "engines": {
- "node": ">= 6.11.5"
- },
- "peerDependencies": {
- "webpack": "^4.0.0 || ^5.0.0"
- },
- "peerDependenciesMeta": {
- "webpack-cli": {
- "optional": true
- }
+ "version": "4.2.2",
+ "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.2.2.tgz",
+ "integrity": "sha512-VwaXim9Gp1bngi/q3do8hgttYn2uC3MoT/gfuMWylnj1IeZBUAyPddHZlo1K05BDoj8DYPpMdiHqH1dDYdJf2A==",
+ "license": "MIT",
+ "engines": {
+ "node": ">= 18"
}
},
- "node_modules/webpack-dev-server/node_modules/ansi-regex": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz",
- "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8= sha512-TIGnTpdo+E3+pCyAluZvtED5p5wCqLdezCyhPZzKPcxvFplEt4i+W7OONCKgeZFT3+y5NZZfOOS/Bdcanm1MYA==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node_modules/typedarray": {
+ "version": "0.0.6",
+ "resolved": "https://registry.npmjs.org/typedarray/-/typedarray-0.0.6.tgz",
+ "integrity": "sha512-/aCDEGatGvZ2BIk+HmLf4ifCJFwvKFNb9/JeZPMulfgFracn9QFcAf5GO8B/mweUjSoblS5In0cWhqpfs/5PQA==",
+ "license": "MIT"
+ },
+ "node_modules/typedarray-pool": {
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/typedarray-pool/-/typedarray-pool-1.2.0.tgz",
+ "integrity": "sha512-YTSQbzX43yvtpfRtIDAYygoYtgT+Rpjuxy9iOpczrjpXLgGoyG7aS5USJXV2d3nn8uHTeb9rXDvzS27zUg5KYQ==",
+ "license": "MIT",
+ "dependencies": {
+ "bit-twiddle": "^1.0.0",
+ "dup": "^1.0.0"
}
},
- "node_modules/webpack-dev-server/node_modules/ansi-styles": {
- "version": "3.2.1",
- "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
- "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
+ "node_modules/undici-types": {
+ "version": "7.19.2",
+ "resolved": "https://registry.npmjs.org/undici-types/-/undici-types-7.19.2.tgz",
+ "integrity": "sha512-qYVnV5OEm2AW8cJMCpdV20CDyaN3g0AjDlOGf1OW4iaDEx8MwdtChUp4zu4H0VP3nDRF/8RKWH+IPp9uW0YGZg==",
+ "license": "MIT"
+ },
+ "node_modules/unicode-canonical-property-names-ecmascript": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/unicode-canonical-property-names-ecmascript/-/unicode-canonical-property-names-ecmascript-2.0.1.tgz",
+ "integrity": "sha512-dA8WbNeb2a6oQzAQ55YlT5vQAWGV9WXOsi3SskE3bcCdM0P4SDd+24zS/OCacdRq5BkdsRj9q3Pg6YyQoxIGqg==",
"dev": true,
- "dependencies": {
- "color-convert": "^1.9.0"
- },
+ "license": "MIT",
"engines": {
"node": ">=4"
}
},
- "node_modules/webpack-dev-server/node_modules/anymatch": {
+ "node_modules/unicode-match-property-ecmascript": {
"version": "2.0.0",
- "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-2.0.0.tgz",
- "integrity": "sha512-5teOsQWABXHHBFP9y3skS5P3d/WfWXpv3FUpy+LorMrNYaT9pI4oLMQX7jzQ2KklNpGpWHzdCXTDT2Y3XGlZBw==",
- "dev": true,
- "dependencies": {
- "micromatch": "^3.1.4",
- "normalize-path": "^2.1.1"
- }
- },
- "node_modules/webpack-dev-server/node_modules/anymatch/node_modules/normalize-path": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-2.1.1.tgz",
- "integrity": "sha1-GrKLVW4Zg2Oowab35vogE3/mrtk= sha512-3pKJwH184Xo/lnH6oyP1q2pMd7HcypqqmRs91/6/i2CGtWwIKGCkOOMTm/zXbgTEWHw1uNpNi/igc3ePOYHb6w==",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-ecmascript/-/unicode-match-property-ecmascript-2.0.0.tgz",
+ "integrity": "sha512-5kaZCrbp5mmbz5ulBkDkbY0SsPOjKqVS35VpL9ulMPfSl0J0Xsm+9Evphv9CoIZFwre7aJoa94AY6seMKGVN5Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "remove-trailing-separator": "^1.0.1"
+ "unicode-canonical-property-names-ecmascript": "^2.0.0",
+ "unicode-property-aliases-ecmascript": "^2.0.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=4"
}
},
- "node_modules/webpack-dev-server/node_modules/binary-extensions": {
- "version": "1.13.1",
- "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-1.13.1.tgz",
- "integrity": "sha512-Un7MIEDdUC5gNpcGDV97op1Ywk748MpHcFTHoYs6qnj1Z3j7I53VG3nwZhKzoBZmbdRNnb6WRdFlwl7tSDuZGw==",
+ "node_modules/unicode-match-property-value-ecmascript": {
+ "version": "2.2.1",
+ "resolved": "https://registry.npmjs.org/unicode-match-property-value-ecmascript/-/unicode-match-property-value-ecmascript-2.2.1.tgz",
+ "integrity": "sha512-JQ84qTuMg4nVkx8ga4A16a1epI9H6uTXAknqxkGF/aFfRLw1xC/Bp24HNLaZhHSkWd3+84t8iXnp1J0kYcZHhg==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=4"
}
},
- "node_modules/webpack-dev-server/node_modules/braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "node_modules/unicode-property-aliases-ecmascript": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/unicode-property-aliases-ecmascript/-/unicode-property-aliases-ecmascript-2.2.0.tgz",
+ "integrity": "sha512-hpbDzxUY9BFwX+UeBnxv3Sh1q7HFxj48DTmXchNgRa46lO8uj3/1iEn3MiNUYTg1g9ctIqXCCERn8gYZhHC5lQ==",
"dev": true,
- "dependencies": {
- "arr-flatten": "^1.1.0",
- "array-unique": "^0.3.2",
- "extend-shallow": "^2.0.1",
- "fill-range": "^4.0.0",
- "isobject": "^3.0.1",
- "repeat-element": "^1.1.2",
- "snapdragon": "^0.8.1",
- "snapdragon-node": "^2.0.1",
- "split-string": "^3.0.2",
- "to-regex": "^3.0.1"
- },
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=4"
}
},
- "node_modules/webpack-dev-server/node_modules/braces/node_modules/extend-shallow": {
+ "node_modules/universalify": {
"version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "resolved": "https://registry.npmjs.org/universalify/-/universalify-2.0.1.tgz",
+ "integrity": "sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==",
"dev": true,
- "dependencies": {
- "is-extendable": "^0.1.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 10.0.0"
}
},
- "node_modules/webpack-dev-server/node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
+ "node_modules/unpipe": {
+ "version": "1.0.0",
+ "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz",
+ "integrity": "sha512-pjy2bYhSsufwWlKwPc+l3cN7+wuJlK6uz0YdJEOlQDbl6jo/YlPi4mb8agUkVC8BF7V8NuzeyPNqRksA3hztKQ==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">= 0.8"
}
},
- "node_modules/webpack-dev-server/node_modules/chokidar": {
- "version": "2.1.8",
- "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-2.1.8.tgz",
- "integrity": "sha512-ZmZUazfOzf0Nve7duiCKD23PFSCs4JPoYyccjUFF3aQkQadqBhfzhjkwBH2mNOG9cTBwhamM37EIsIkZw3nRgg==",
- "dev": true,
+ "node_modules/unquote": {
+ "version": "1.1.1",
+ "resolved": "https://registry.npmjs.org/unquote/-/unquote-1.1.1.tgz",
+ "integrity": "sha512-vRCqFv6UhXpWxZPyGDh/F3ZpNv8/qo7w6iufLpQg9aKnQ71qM4B5KiI7Mia9COcjEhrO9LueHpMYjYzsWH3OIg==",
+ "license": "MIT"
+ },
+ "node_modules/update-browserslist-db": {
+ "version": "1.2.3",
+ "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz",
+ "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/browserslist"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/browserslist"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "license": "MIT",
"dependencies": {
- "anymatch": "^2.0.0",
- "async-each": "^1.0.1",
- "braces": "^2.3.2",
- "glob-parent": "^3.1.0",
- "inherits": "^2.0.3",
- "is-binary-path": "^1.0.0",
- "is-glob": "^4.0.0",
- "normalize-path": "^3.0.0",
- "path-is-absolute": "^1.0.0",
- "readdirp": "^2.2.1",
- "upath": "^1.1.1"
+ "escalade": "^3.2.0",
+ "picocolors": "^1.1.1"
},
- "optionalDependencies": {
- "fsevents": "^1.2.7"
+ "bin": {
+ "update-browserslist-db": "cli.js"
+ },
+ "peerDependencies": {
+ "browserslist": ">= 4.21.0"
}
},
- "node_modules/webpack-dev-server/node_modules/cliui": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-5.0.0.tgz",
- "integrity": "sha512-PYeGSEmmHM6zvoef2w8TPzlrnNpXIjTipYK780YswmIP9vjxmd6Y2a3CB2Ks6/AU8NHjZugXvo8w3oWM2qnwXA==",
+ "node_modules/update-diff": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/update-diff/-/update-diff-1.1.0.tgz",
+ "integrity": "sha512-rCiBPiHxZwT4+sBhEbChzpO5hYHjm91kScWgdHf4Qeafs6Ba7MBl+d9GlGv72bcTZQO0sLmtQS1pHSWoCLtN/A==",
+ "license": "MIT"
+ },
+ "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,
+ "license": "BSD-2-Clause",
"dependencies": {
- "string-width": "^3.1.0",
- "strip-ansi": "^5.2.0",
- "wrap-ansi": "^5.1.0"
+ "punycode": "^2.1.0"
}
},
- "node_modules/webpack-dev-server/node_modules/cliui/node_modules/ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "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==",
+ "license": "MIT"
+ },
+ "node_modules/utila": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/utila/-/utila-0.4.0.tgz",
+ "integrity": "sha512-Z0DbgELS9/L/75wZbro8xAnT50pBVFQZ+hUEueGDU5FN51YSCYM+jdxsfCiHjwNP/4LCDD0i/graKpeBnOXKRA==",
"dev": true,
- "engines": {
- "node": ">=6"
- }
+ "license": "MIT"
},
- "node_modules/webpack-dev-server/node_modules/cliui/node_modules/strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "node_modules/utils-merge": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz",
+ "integrity": "sha512-pMZTvIkT1d+TFGvDOqodOclx0QWkkgi6Tdoa8gC8ffGAAqz9pzPTZWAybbsHHoED/ztMtkv/VoYTYyShUn81hA==",
"dev": true,
- "dependencies": {
- "ansi-regex": "^4.1.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">= 0.4.0"
}
},
- "node_modules/webpack-dev-server/node_modules/color-convert": {
- "version": "1.9.3",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz",
- "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==",
+ "node_modules/uuid": {
+ "version": "8.3.2",
+ "resolved": "https://registry.npmjs.org/uuid/-/uuid-8.3.2.tgz",
+ "integrity": "sha512-+NYs2QeMWy+GWFOEm9xnn6HCDp0l7QBD7ml8zLUmJ+93Q5NF0NocErnwkTkXVFNiX3/fpC6afS8Dhb/gz7R7eg==",
+ "deprecated": "uuid@10 and below is no longer supported. For ESM codebases, update to uuid@latest. For CommonJS codebases, use uuid@11 (but be aware this version will likely be deprecated in 2028).",
"dev": true,
- "dependencies": {
- "color-name": "1.1.3"
+ "license": "MIT",
+ "bin": {
+ "uuid": "dist/bin/uuid"
}
},
- "node_modules/webpack-dev-server/node_modules/color-name": {
- "version": "1.1.3",
- "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz",
- "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU= sha512-72fSenhMw2HZMTVHeCA9KCmpEIbzWiQsjN+BHcBbS9vr1mtt+vJjPdksIBNUmKAW8TFUDPJK5SUU3QhE9NEXDw==",
- "dev": true
- },
- "node_modules/webpack-dev-server/node_modules/emoji-regex": {
- "version": "7.0.3",
- "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-7.0.3.tgz",
- "integrity": "sha512-CwBLREIQ7LvYFB0WyRvwhq5N5qPhc6PMjD6bYggFlI5YyDgl+0vxq5VHbMOFqLg7hfWzmu8T5Z1QofhmTIhItA==",
- "dev": true
- },
- "node_modules/webpack-dev-server/node_modules/fill-range": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
+ "node_modules/validate-npm-package-license": {
+ "version": "3.0.4",
+ "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz",
+ "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
- },
- "engines": {
- "node": ">=0.10.0"
+ "spdx-correct": "^3.0.0",
+ "spdx-expression-parse": "^3.0.0"
}
},
- "node_modules/webpack-dev-server/node_modules/fill-range/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "node_modules/vary": {
+ "version": "1.1.2",
+ "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz",
+ "integrity": "sha512-BNGbWLfd0eUPabhkXUVm0j8uuvREyTh5ovRa/dyow/BqAbZJyC+5fU+IzQOzmAKzYqYRAISoRhdQr3eIZ/PXqg==",
"dev": true,
- "dependencies": {
- "is-extendable": "^0.1.0"
- },
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 0.8"
}
},
- "node_modules/webpack-dev-server/node_modules/find-up": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-3.0.0.tgz",
- "integrity": "sha512-1yD6RmLI1XBfxugvORwlck6f75tYL+iR0jqwsOrOxMZyGYqUuDhJ0l4AXdO1iX/FTs9cBAMEk1gWSEx1kSbylg==",
- "dev": true,
+ "node_modules/vt-pbf": {
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/vt-pbf/-/vt-pbf-3.1.3.tgz",
+ "integrity": "sha512-2LzDFzt0mZKZ9IpVF2r69G9bXaP2Q2sArJCmcCgvfTdCCZzSyz4aCLoQyUilu37Ll56tCblIZrXFIjNUpGIlmA==",
+ "license": "MIT",
"dependencies": {
- "locate-path": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
+ "@mapbox/point-geometry": "0.1.0",
+ "@mapbox/vector-tile": "^1.3.1",
+ "pbf": "^3.2.1"
}
},
- "node_modules/webpack-dev-server/node_modules/fsevents": {
- "version": "1.2.13",
- "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-1.2.13.tgz",
- "integrity": "sha512-oWb1Z6mkHIskLzEJ/XWX0srkpkTQ7vaopMQkyaEIoq0fmtFVxOthb8cCxeT+p3ynTdkk/RZwbgG4brR5BeWECw==",
- "deprecated": "Upgrade to fsevents v2 to mitigate potential security issues",
- "dev": true,
- "hasInstallScript": true,
- "optional": true,
- "os": [
- "darwin"
- ],
+ "node_modules/vue": {
+ "version": "2.7.16",
+ "resolved": "https://registry.npmjs.org/vue/-/vue-2.7.16.tgz",
+ "integrity": "sha512-4gCtFXaAA3zYZdTp5s4Hl2sozuySsgz4jy1EnpBHNfpMa9dK1ZCG7viqBPCwXtmgc8nHqUsAu3G4gtmXkkY3Sw==",
+ "deprecated": "Vue 2 has reached EOL and is no longer actively maintained. See https://v2.vuejs.org/eol/ for more details.",
+ "license": "MIT",
"dependencies": {
- "bindings": "^1.5.0",
- "nan": "^2.12.1"
- },
- "engines": {
- "node": ">= 4.0"
+ "@vue/compiler-sfc": "2.7.16",
+ "csstype": "^3.1.0"
}
},
- "node_modules/webpack-dev-server/node_modules/glob-parent": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-3.1.0.tgz",
- "integrity": "sha1-nmr2KZ2NO9K9QEMIMr0RPfkGxa4= sha512-E8Ak/2+dZY6fnzlR7+ueWvhsH1SjHr4jjss4YS/h4py44jY9MhK/VFdaZJAWDz6BbL21KeteKxFSFpq8OS5gVA==",
+ "node_modules/vue-eslint-parser": {
+ "version": "10.4.0",
+ "resolved": "https://registry.npmjs.org/vue-eslint-parser/-/vue-eslint-parser-10.4.0.tgz",
+ "integrity": "sha512-Vxi9pJdbN3ZnVGLODVtZ7y4Y2kzAAE2Cm0CZ3ZDRvydVYxZ6VrnBhLikBsRS+dpwj4Jv4UCv21PTEwF5rQ9WXg==",
"dev": true,
+ "license": "MIT",
+ "peer": true,
"dependencies": {
- "is-glob": "^3.1.0",
- "path-dirname": "^1.0.0"
+ "debug": "^4.4.0",
+ "eslint-scope": "^8.2.0 || ^9.0.0",
+ "eslint-visitor-keys": "^4.2.0 || ^5.0.0",
+ "espree": "^10.3.0 || ^11.0.0",
+ "esquery": "^1.6.0",
+ "semver": "^7.6.3"
+ },
+ "engines": {
+ "node": "^18.18.0 || ^20.9.0 || >=21.1.0"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/mysticatea"
+ },
+ "peerDependencies": {
+ "eslint": "^8.57.0 || ^9.0.0 || ^10.0.0"
}
},
- "node_modules/webpack-dev-server/node_modules/glob-parent/node_modules/is-glob": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-3.1.0.tgz",
- "integrity": "sha1-e6WuJCF4BKxwcHuWkiVnSGzD6Eo= sha512-UFpDDrPgM6qpnFNI+rh/p3bUaq9hKLZN8bMUWzxmcnZVS3omf4IPK+BrewlnWjO1WmUsMYuSjKh4UJuV4+Lqmw==",
+ "node_modules/vue-eslint-parser/node_modules/eslint-scope": {
+ "version": "9.1.2",
+ "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-9.1.2.tgz",
+ "integrity": "sha512-xS90H51cKw0jltxmvmHy2Iai1LIqrfbw57b79w/J7MfvDfkIkFZ+kj6zC3BjtUwh150HsSSdxXZcsuv72miDFQ==",
"dev": true,
+ "license": "BSD-2-Clause",
+ "peer": true,
"dependencies": {
- "is-extglob": "^2.1.0"
+ "@types/esrecurse": "^4.3.1",
+ "@types/estree": "^1.0.8",
+ "esrecurse": "^4.3.0",
+ "estraverse": "^5.2.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/webpack-dev-server/node_modules/has-flag": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
- "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0= sha512-sKJf1+ceQBr4SMkvQnBDNDtf4TXpVhVGateu0t918bl30FnbE2m4vNLX+VWe/dpjlb+HugGYzW7uQXH98HPEYw==",
+ "node_modules/vue-eslint-parser/node_modules/eslint-visitor-keys": {
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-5.0.1.tgz",
+ "integrity": "sha512-tD40eHxA35h0PEIZNeIjkHoDR4YjjJp34biM0mDvplBe//mB+IHCqHDGV7pxF+7MklTvighcCPPZC7ynWyjdTA==",
"dev": true,
+ "license": "Apache-2.0",
+ "peer": true,
"engines": {
- "node": ">=4"
+ "node": "^20.19.0 || ^22.13.0 || >=24"
+ },
+ "funding": {
+ "url": "https://opencollective.com/eslint"
}
},
- "node_modules/webpack-dev-server/node_modules/http-proxy-middleware": {
- "version": "0.19.1",
- "resolved": "https://registry.npmjs.org/http-proxy-middleware/-/http-proxy-middleware-0.19.1.tgz",
- "integrity": "sha512-yHYTgWMQO8VvwNS22eLLloAkvungsKdKTLO8AJlftYIKNfJr3GK3zK0ZCfzDDGUBttdGc8xFy1mCitvNKQtC3Q==",
+ "node_modules/vue-eslint-parser/node_modules/estraverse": {
+ "version": "5.3.0",
+ "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-5.3.0.tgz",
+ "integrity": "sha512-MMdARuVEQziNTeJD8DgMqmhwR11BRQ/cBP+pLtYdSTnf3MIO8fFeiINEbX36ZdNlfU/7A9f3gUw49B3oQsvwBA==",
"dev": true,
- "dependencies": {
- "http-proxy": "^1.17.0",
- "is-glob": "^4.0.0",
- "lodash": "^4.17.11",
- "micromatch": "^3.1.10"
- },
+ "license": "BSD-2-Clause",
+ "peer": true,
"engines": {
- "node": ">=4.0.0"
+ "node": ">=4.0"
}
},
- "node_modules/webpack-dev-server/node_modules/is-absolute-url": {
- "version": "3.0.3",
- "resolved": "https://registry.npmjs.org/is-absolute-url/-/is-absolute-url-3.0.3.tgz",
- "integrity": "sha512-opmNIX7uFnS96NtPmhWQgQx6/NYFgsUXYMllcfzwWKUMwfo8kku1TvE6hkNcH+Q1ts5cMVrsY7j0bxXQDciu9Q==",
+ "node_modules/vue-hot-reload-api": {
+ "version": "2.3.4",
+ "resolved": "https://registry.npmjs.org/vue-hot-reload-api/-/vue-hot-reload-api-2.3.4.tgz",
+ "integrity": "sha512-BXq3jwIagosjgNVae6tkHzzIk6a8MHFtzAdwhnV5VlvPTFxDCvIttgSiHWjdGoTJvXtmRu5HacExfdarRcFhog==",
"dev": true,
- "engines": {
- "node": ">=8"
+ "license": "MIT"
+ },
+ "node_modules/vue-loader": {
+ "version": "17.4.2",
+ "resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-17.4.2.tgz",
+ "integrity": "sha512-yTKOA4R/VN4jqjw4y5HrynFL8AK0Z3/Jt7eOJXEitsm0GMRHDBjCfCiuTiLP7OESvsZYo2pATCWhDqxC5ZrM6w==",
+ "dev": true,
+ "license": "MIT",
+ "dependencies": {
+ "chalk": "^4.1.0",
+ "hash-sum": "^2.0.0",
+ "watchpack": "^2.4.0"
+ },
+ "peerDependencies": {
+ "webpack": "^4.1.0 || ^5.0.0-0"
+ },
+ "peerDependenciesMeta": {
+ "@vue/compiler-sfc": {
+ "optional": true
+ },
+ "vue": {
+ "optional": true
+ }
}
},
- "node_modules/webpack-dev-server/node_modules/is-binary-path": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/is-binary-path/-/is-binary-path-1.0.1.tgz",
- "integrity": "sha1-dfFmQrSA8YenEcgUFh/TpKdlWJg= sha512-9fRVlXc0uCxEDj1nQzaWONSpbTfx0FmJfzHF7pwlI8DkWGoHBBea4Pg5Ky0ojwwxQmnSifgbKkI06Qv0Ljgj+Q==",
+ "node_modules/vue-loader/node_modules/chalk": {
+ "version": "4.1.2",
+ "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
+ "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "binary-extensions": "^1.0.0"
+ "ansi-styles": "^4.1.0",
+ "supports-color": "^7.1.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/chalk?sponsor=1"
}
},
- "node_modules/webpack-dev-server/node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
+ "node_modules/vue-reactive-provide": {
+ "version": "0.3.0",
+ "resolved": "https://registry.npmjs.org/vue-reactive-provide/-/vue-reactive-provide-0.3.0.tgz",
+ "integrity": "sha512-hx2JtRPRvne9NY4s1r7ASsCaO8CIby30qwC1kGQRxsrWApO3he+rziGOzTDSfvmr852zWMb11n6qAwHCz6C/vw==",
+ "peerDependencies": {
+ "vue": ">=2.6"
}
},
- "node_modules/webpack-dev-server/node_modules/is-fullwidth-code-point": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz",
- "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8= sha512-VHskAKYM8RfSFXwee5t5cbN5PZeq1Wrh6qd5bkyiXIf6UQcN6w/A0eXM9r6t8d+GYOh+o6ZhiEnb88LN/Y8m2w==",
- "dev": true,
- "engines": {
- "node": ">=4"
- }
+ "node_modules/vue-router": {
+ "version": "3.6.5",
+ "resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.6.5.tgz",
+ "integrity": "sha512-VYXZQLtjuvKxxcshuRAwjHnciqZVoXAjTjcqBTz4rKc8qih9g9pI3hbDjmqXaHdgL3v8pV6P8Z335XvHzESxLQ==",
+ "license": "MIT"
},
- "node_modules/webpack-dev-server/node_modules/is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
- "dev": true,
- "dependencies": {
- "kind-of": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
+ "node_modules/vue-select": {
+ "version": "3.20.4",
+ "resolved": "https://registry.npmjs.org/vue-select/-/vue-select-3.20.4.tgz",
+ "integrity": "sha512-pXIsDUnBR1075qHNEM7mKgX7YnHI3MfCO+7VmXSA1Hywplpqi52jOa0j6EHWQU6MnaW/mBZPuaQtgp3yvks2Kw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "vue": "2.x"
}
},
- "node_modules/webpack-dev-server/node_modules/is-number/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
+ "node_modules/vue-style-loader": {
+ "version": "4.1.3",
+ "resolved": "https://registry.npmjs.org/vue-style-loader/-/vue-style-loader-4.1.3.tgz",
+ "integrity": "sha512-sFuh0xfbtpRlKfm39ss/ikqs9AbKCoXZBpHeVZ8Tx650o0k0q/YCM7FRvigtxpACezfq6af+a7JeqVTWvncqDg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-buffer": "^1.1.5"
- },
- "engines": {
- "node": ">=0.10.0"
+ "hash-sum": "^1.0.2",
+ "loader-utils": "^1.0.2"
}
},
- "node_modules/webpack-dev-server/node_modules/locate-path": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-3.0.0.tgz",
- "integrity": "sha512-7AO748wWnIhNqAuaty2ZWHkQHRSNfPVIsPIfwEOWO22AmaoVrWavlOcMR5nzTLNYvp36X220/maaRsrec1G65A==",
+ "node_modules/vue-style-loader/node_modules/hash-sum": {
+ "version": "1.0.2",
+ "resolved": "https://registry.npmjs.org/hash-sum/-/hash-sum-1.0.2.tgz",
+ "integrity": "sha512-fUs4B4L+mlt8/XAtSOGMUO1TXmAelItBPtJG7CyHJfYTdDjwisntGO2JQz7oUsatOY9o68+57eziUVNw/mRHmA==",
"dev": true,
- "dependencies": {
- "p-locate": "^3.0.0",
- "path-exists": "^3.0.0"
- },
- "engines": {
- "node": ">=6"
- }
+ "license": "MIT"
},
- "node_modules/webpack-dev-server/node_modules/micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
- "dev": true,
+ "node_modules/vue-template-compiler": {
+ "version": "2.7.16",
+ "resolved": "https://registry.npmjs.org/vue-template-compiler/-/vue-template-compiler-2.7.16.tgz",
+ "integrity": "sha512-AYbUWAJHLGGQM7+cNTELw+KsOG9nl2CnSv467WobS5Cv9uk3wFcnr1Etsz2sEIHEZvw1U+o9mRlEO6QbZvUPGQ==",
+ "license": "MIT",
"dependencies": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "braces": "^2.3.1",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "extglob": "^2.0.4",
- "fragment-cache": "^0.2.1",
- "kind-of": "^6.0.2",
- "nanomatch": "^1.2.9",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.2"
- },
- "engines": {
- "node": ">=0.10.0"
+ "de-indent": "^1.0.2",
+ "he": "^1.2.0"
}
},
- "node_modules/webpack-dev-server/node_modules/p-locate": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-3.0.0.tgz",
- "integrity": "sha512-x+12w/To+4GFfgJhBEpiDcLozRJGegY+Ei7/z0tSLkMmxGZNybVMSfWj9aJn8Z5Fc7dBUNJOOVgPv2H7IwulSQ==",
+ "node_modules/vue-template-es2015-compiler": {
+ "version": "1.9.1",
+ "resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz",
+ "integrity": "sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/vue/node_modules/@vue/compiler-sfc": {
+ "version": "2.7.16",
+ "resolved": "https://registry.npmjs.org/@vue/compiler-sfc/-/compiler-sfc-2.7.16.tgz",
+ "integrity": "sha512-KWhJ9k5nXuNtygPU7+t1rX6baZeqOYLEforUPjgNDBnLicfHCoi48H87Q8XyLZOrNNsmhuwKqtpDQWjEFe6Ekg==",
"dependencies": {
- "p-limit": "^2.0.0"
+ "@babel/parser": "^7.23.5",
+ "postcss": "^8.4.14",
+ "source-map": "^0.6.1"
},
- "engines": {
- "node": ">=6"
+ "optionalDependencies": {
+ "prettier": "^1.18.2 || ^2.0.0"
}
},
- "node_modules/webpack-dev-server/node_modules/path-exists": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz",
- "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU= sha512-bpC7GYwiDYQ4wYLe+FA8lhRjhQCMcQGuSgGGqDkg/QerRWw9CmGRT0iSOVRSZJ29NMLZgIzqaljJ63oaL4NIJQ==",
- "dev": true,
- "engines": {
- "node": ">=4"
+ "node_modules/vuex": {
+ "version": "3.6.2",
+ "resolved": "https://registry.npmjs.org/vuex/-/vuex-3.6.2.tgz",
+ "integrity": "sha512-ETW44IqCgBpVomy520DT5jf8n0zoCac+sxWnn+hMe/CzaSejb/eVw2YToiXYX+Ex/AuHHia28vWTq4goAexFbw==",
+ "license": "MIT",
+ "peerDependencies": {
+ "vue": "^2.0.0"
}
},
- "node_modules/webpack-dev-server/node_modules/readdirp": {
- "version": "2.2.1",
- "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-2.2.1.tgz",
- "integrity": "sha512-1JU/8q+VgFZyxwrJ+SVIOsh+KywWGpds3NTqikiKpDMZWScmAYyKIgqkO+ARvNWJfXeXR1zxz7aHF4u4CyH6vQ==",
- "dev": true,
+ "node_modules/watchpack": {
+ "version": "2.5.1",
+ "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz",
+ "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==",
+ "license": "MIT",
"dependencies": {
- "graceful-fs": "^4.1.11",
- "micromatch": "^3.1.10",
- "readable-stream": "^2.0.2"
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.1.2"
},
"engines": {
- "node": ">=0.10"
+ "node": ">=10.13.0"
}
},
- "node_modules/webpack-dev-server/node_modules/schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
- "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
+ "node_modules/wbuf": {
+ "version": "1.7.3",
+ "resolved": "https://registry.npmjs.org/wbuf/-/wbuf-1.7.3.tgz",
+ "integrity": "sha512-O84QOnr0icsbFGLS0O3bI5FswxzRr8/gHwWkDlQFskhSPryQXvrTMxjxGP4+iWYoauLoBvfDpkrOauZ+0iZpDA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
- },
- "engines": {
- "node": ">= 4"
+ "minimalistic-assert": "^1.0.0"
}
},
- "node_modules/webpack-dev-server/node_modules/string-width": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/string-width/-/string-width-3.1.0.tgz",
- "integrity": "sha512-vafcv6KjVZKSgz06oM/H6GDBrAtz8vdhQakGjFIvNrHA6y3HCF1CInLy+QLq8dTJPQ1b+KDUqDFctkdRW44e1w==",
+ "node_modules/wcwidth": {
+ "version": "1.0.1",
+ "resolved": "https://registry.npmjs.org/wcwidth/-/wcwidth-1.0.1.tgz",
+ "integrity": "sha512-XHPEwS0q6TaxcvG85+8EYkbiCux2XtWG2mkc47Ng2A77BQu9+DqIOJldST4HgPkuea7dvKSj5VgX3P1d4rW8Tg==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "emoji-regex": "^7.0.1",
- "is-fullwidth-code-point": "^2.0.0",
- "strip-ansi": "^5.1.0"
- },
- "engines": {
- "node": ">=6"
+ "defaults": "^1.0.3"
}
},
- "node_modules/webpack-dev-server/node_modules/string-width/node_modules/ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
- "dev": true,
- "engines": {
- "node": ">=6"
- }
+ "node_modules/weak-map": {
+ "version": "1.0.8",
+ "resolved": "https://registry.npmjs.org/weak-map/-/weak-map-1.0.8.tgz",
+ "integrity": "sha512-lNR9aAefbGPpHO7AEnY0hCFjz1eTkWCXYvkTRrTHs9qv8zJp+SkVYpzfLIFXQQiG3tVvbNFQgVg2bQS8YGgxyw==",
+ "license": "Apache-2.0"
},
- "node_modules/webpack-dev-server/node_modules/string-width/node_modules/strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
- "dev": true,
+ "node_modules/webgl-context": {
+ "version": "2.2.0",
+ "resolved": "https://registry.npmjs.org/webgl-context/-/webgl-context-2.2.0.tgz",
+ "integrity": "sha512-q/fGIivtqTT7PEoF07axFIlHNk/XCPaYpq64btnepopSWvKNFkoORlQYgqDigBIuGA1ExnFd/GnSUnBNEPQY7Q==",
+ "license": "MIT",
"dependencies": {
- "ansi-regex": "^4.1.0"
- },
- "engines": {
- "node": ">=6"
+ "get-canvas-context": "^1.0.1"
}
},
- "node_modules/webpack-dev-server/node_modules/strip-ansi": {
+ "node_modules/webidl-conversions": {
"version": "3.0.1",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz",
- "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8= sha512-VhumSSbBqDTP8p2ZLKj40UjBCV4+v8bUSEpUb4KjRgWk9pbqGF4REFj6KEagidb2f/M6AzC0EmFyDNGaw9OCzg==",
+ "resolved": "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-3.0.1.tgz",
+ "integrity": "sha512-2JAn3z8AR6rjK8Sm8orRC0h/bcl/DqL7tRPdGZ4I1CjdF+EaMLmYxBHyXuKL849eucPFhvBoxMsflfOb8kxaeQ==",
"dev": true,
- "dependencies": {
- "ansi-regex": "^2.0.0"
- },
- "engines": {
- "node": ">=0.10.0"
- }
+ "license": "BSD-2-Clause"
},
- "node_modules/webpack-dev-server/node_modules/supports-color": {
- "version": "6.1.0",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
- "integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
- "dev": true,
+ "node_modules/webpack": {
+ "version": "5.106.2",
+ "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.106.2.tgz",
+ "integrity": "sha512-wGN3qcrBQIFmQ/c0AiOAQBvrZ5lmY8vbbMv4Mxfgzqd/B6+9pXtLo73WuS1dSGXM5QYY3hZnIbvx+K1xxe6FyA==",
+ "license": "MIT",
"dependencies": {
- "has-flag": "^3.0.0"
+ "@types/eslint-scope": "^3.7.7",
+ "@types/estree": "^1.0.8",
+ "@types/json-schema": "^7.0.15",
+ "@webassemblyjs/ast": "^1.14.1",
+ "@webassemblyjs/wasm-edit": "^1.14.1",
+ "@webassemblyjs/wasm-parser": "^1.14.1",
+ "acorn": "^8.16.0",
+ "acorn-import-phases": "^1.0.3",
+ "browserslist": "^4.28.1",
+ "chrome-trace-event": "^1.0.2",
+ "enhanced-resolve": "^5.20.0",
+ "es-module-lexer": "^2.0.0",
+ "eslint-scope": "5.1.1",
+ "events": "^3.2.0",
+ "glob-to-regexp": "^0.4.1",
+ "graceful-fs": "^4.2.11",
+ "loader-runner": "^4.3.1",
+ "mime-db": "^1.54.0",
+ "neo-async": "^2.6.2",
+ "schema-utils": "^4.3.3",
+ "tapable": "^2.3.0",
+ "terser-webpack-plugin": "^5.3.17",
+ "watchpack": "^2.5.1",
+ "webpack-sources": "^3.3.4"
},
- "engines": {
- "node": ">=6"
- }
- },
- "node_modules/webpack-dev-server/node_modules/to-regex-range": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
- "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==",
- "dev": true,
- "dependencies": {
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1"
+ "bin": {
+ "webpack": "bin/webpack.js"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependenciesMeta": {
+ "webpack-cli": {
+ "optional": true
+ }
}
},
- "node_modules/webpack-dev-server/node_modules/wrap-ansi": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-5.1.0.tgz",
- "integrity": "sha512-QC1/iN/2/RPVJ5jYK8BGttj5z83LmSKmvbvrXPNCLZSEb32KKVDJDl/MOt2N01qU2H/FkzEa9PKto1BqDjtd7Q==",
+ "node_modules/webpack-bundle-analyzer": {
+ "version": "4.10.2",
+ "resolved": "https://registry.npmjs.org/webpack-bundle-analyzer/-/webpack-bundle-analyzer-4.10.2.tgz",
+ "integrity": "sha512-vJptkMm9pk5si4Bv922ZbKLV8UTT4zib4FPgXMhgzUny0bfDDkLXAVQs3ly3fS4/TN9ROFtb0NFrm04UXFE/Vw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-styles": "^3.2.0",
- "string-width": "^3.0.0",
- "strip-ansi": "^5.0.0"
+ "@discoveryjs/json-ext": "0.5.7",
+ "acorn": "^8.0.4",
+ "acorn-walk": "^8.0.0",
+ "commander": "^7.2.0",
+ "debounce": "^1.2.1",
+ "escape-string-regexp": "^4.0.0",
+ "gzip-size": "^6.0.0",
+ "html-escaper": "^2.0.2",
+ "opener": "^1.5.2",
+ "picocolors": "^1.0.0",
+ "sirv": "^2.0.3",
+ "ws": "^7.3.1"
+ },
+ "bin": {
+ "webpack-bundle-analyzer": "lib/bin/analyzer.js"
},
"engines": {
- "node": ">=6"
+ "node": ">= 10.13.0"
}
},
- "node_modules/webpack-dev-server/node_modules/wrap-ansi/node_modules/ansi-regex": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-4.1.0.tgz",
- "integrity": "sha512-1apePfXM1UOSqw0o9IiFAovVz9M5S1Dg+4TrDwfMewQ6p/rmMueb7tWZjQ1rx4Loy1ArBggoqGpfqqdI4rondg==",
+ "node_modules/webpack-bundle-analyzer/node_modules/commander": {
+ "version": "7.2.0",
+ "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz",
+ "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=6"
+ "node": ">= 10"
}
},
- "node_modules/webpack-dev-server/node_modules/wrap-ansi/node_modules/strip-ansi": {
- "version": "5.2.0",
- "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-5.2.0.tgz",
- "integrity": "sha512-DuRs1gKbBqsMKIZlrffwlug8MHkcnpjs5VPmL1PAh+mA30U0DTotfDZ0d2UUsXpPmPmMMJ6W773MaA3J+lbiWA==",
+ "node_modules/webpack-chain": {
+ "version": "6.5.1",
+ "resolved": "https://registry.npmjs.org/webpack-chain/-/webpack-chain-6.5.1.tgz",
+ "integrity": "sha512-7doO/SRtLu8q5WM0s7vPKPWX580qhi0/yBHkOxNkv50f6qB76Zy9o2wRTrrPULqYTvQlVHuvbA8v+G5ayuUDsA==",
+ "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.",
"dev": true,
+ "license": "MPL-2.0",
"dependencies": {
- "ansi-regex": "^4.1.0"
+ "deepmerge": "^1.5.2",
+ "javascript-stringify": "^2.0.1"
},
"engines": {
- "node": ">=6"
- }
- },
- "node_modules/webpack-dev-server/node_modules/yargs": {
- "version": "13.3.2",
- "resolved": "https://registry.npmjs.org/yargs/-/yargs-13.3.2.tgz",
- "integrity": "sha512-AX3Zw5iPruN5ie6xGRIDgqkT+ZhnRlZMLMHAs8tg7nRruy2Nb+i5o9bwghAogtM08q1dpr2LVoS8KSTMYpWXUw==",
- "dev": true,
- "dependencies": {
- "cliui": "^5.0.0",
- "find-up": "^3.0.0",
- "get-caller-file": "^2.0.1",
- "require-directory": "^2.1.1",
- "require-main-filename": "^2.0.0",
- "set-blocking": "^2.0.0",
- "string-width": "^3.0.0",
- "which-module": "^2.0.0",
- "y18n": "^4.0.0",
- "yargs-parser": "^13.1.2"
- }
- },
- "node_modules/webpack-dev-server/node_modules/yargs-parser": {
- "version": "13.1.2",
- "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-13.1.2.tgz",
- "integrity": "sha512-3lbsNRf/j+A4QuSZfDRA7HRSfWrzO0YjqTJd5kjAq37Zep1CEgaYmrH9Q3GwPiB9cHyd1Y1UwggGhJGoxipbzg==",
- "dev": true,
- "dependencies": {
- "camelcase": "^5.0.0",
- "decamelize": "^1.2.0"
+ "node": ">=8"
}
},
- "node_modules/webpack-log": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/webpack-log/-/webpack-log-2.0.0.tgz",
- "integrity": "sha512-cX8G2vR/85UYG59FgkoMamwHUIkSSlV3bBMRsbxVXVUk2j6NleCKjQ/WE9eYg9WY4w25O9w8wKP4rzNZFmUcUg==",
+ "node_modules/webpack-dev-middleware": {
+ "version": "5.3.4",
+ "resolved": "https://registry.npmjs.org/webpack-dev-middleware/-/webpack-dev-middleware-5.3.4.tgz",
+ "integrity": "sha512-BVdTqhhs+0IfoeAf7EoH5WE+exCmqGerHfDM0IL096Px60Tq2Mn9MAbnaGUe6HiMa41KMCYF19gyzZmBcq/o4Q==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "ansi-colors": "^3.0.0",
- "uuid": "^3.3.2"
+ "colorette": "^2.0.10",
+ "memfs": "^3.4.3",
+ "mime-types": "^2.1.31",
+ "range-parser": "^1.2.1",
+ "schema-utils": "^4.0.0"
},
"engines": {
- "node": ">= 6"
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^4.0.0 || ^5.0.0"
}
},
- "node_modules/webpack-merge": {
- "version": "4.2.2",
- "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-4.2.2.tgz",
- "integrity": "sha512-TUE1UGoTX2Cd42j3krGYqObZbOD+xF7u28WB7tfUordytSjbWTIjK/8V0amkBfTYN4/pB/GIDlJZZ657BGG19g==",
+ "node_modules/webpack-dev-middleware/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "lodash": "^4.17.15"
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/webpack-sources": {
- "version": "1.4.3",
- "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-1.4.3.tgz",
- "integrity": "sha512-lgTS3Xhv1lCOKo7SA5TjKXMjpSM4sBjNV5+q2bqesbSPs5FjGmU6jjtBSkX9b4qW87vDIsCIlUPOEhbZrMdjeQ==",
+ "node_modules/webpack-dev-middleware/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "source-list-map": "^2.0.0",
- "source-map": "~0.6.1"
- }
- },
- "node_modules/webpack-sources/node_modules/source-map": {
- "version": "0.6.1",
- "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
- "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==",
- "dev": true,
- "engines": {
- "node": ">=0.10.0"
- }
- },
- "node_modules/webpack/node_modules/acorn": {
- "version": "6.4.2",
- "resolved": "https://registry.npmjs.org/acorn/-/acorn-6.4.2.tgz",
- "integrity": "sha512-XtGIhXwF8YM8bJhGxG5kXgjkEuNGLTkoYqVE+KMR+aspr4KGYmKYg7yUe3KghyQ9yheNwLnjmzh/7+gfDBmHCQ==",
- "dev": true,
- "bin": {
- "acorn": "bin/acorn"
+ "fast-deep-equal": "^3.1.3"
},
- "engines": {
- "node": ">=0.4.0"
+ "peerDependencies": {
+ "ajv": "^8.8.2"
}
},
- "node_modules/webpack/node_modules/braces": {
- "version": "2.3.2",
- "resolved": "https://registry.npmjs.org/braces/-/braces-2.3.2.tgz",
- "integrity": "sha512-aNdbnj9P8PjdXU4ybaWLK2IF3jc/EoDYbC7AazW6to3TRsfXxscC9UXOB5iDiEQrkyIbWp2SLQda4+QAa7nc3w==",
+ "node_modules/webpack-dev-middleware/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,
+ "license": "MIT"
+ },
+ "node_modules/webpack-dev-middleware/node_modules/schema-utils": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "arr-flatten": "^1.1.0",
- "array-unique": "^0.3.2",
- "extend-shallow": "^2.0.1",
- "fill-range": "^4.0.0",
- "isobject": "^3.0.1",
- "repeat-element": "^1.1.2",
- "snapdragon": "^0.8.1",
- "snapdragon-node": "^2.0.1",
- "split-string": "^3.0.2",
- "to-regex": "^3.0.1"
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
- "node_modules/webpack/node_modules/braces/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "node_modules/webpack-dev-server": {
+ "version": "4.15.2",
+ "resolved": "https://registry.npmjs.org/webpack-dev-server/-/webpack-dev-server-4.15.2.tgz",
+ "integrity": "sha512-0XavAZbNJ5sDrCbkpWL8mia0o5WPOd2YGtxrEiZkBK9FjLppIUK2TgxK6qGD2P3hUXTJNNPVibrerKcx5WkR1g==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-extendable": "^0.1.0"
+ "@types/bonjour": "^3.5.9",
+ "@types/connect-history-api-fallback": "^1.3.5",
+ "@types/express": "^4.17.13",
+ "@types/serve-index": "^1.9.1",
+ "@types/serve-static": "^1.13.10",
+ "@types/sockjs": "^0.3.33",
+ "@types/ws": "^8.5.5",
+ "ansi-html-community": "^0.0.8",
+ "bonjour-service": "^1.0.11",
+ "chokidar": "^3.5.3",
+ "colorette": "^2.0.10",
+ "compression": "^1.7.4",
+ "connect-history-api-fallback": "^2.0.0",
+ "default-gateway": "^6.0.3",
+ "express": "^4.17.3",
+ "graceful-fs": "^4.2.6",
+ "html-entities": "^2.3.2",
+ "http-proxy-middleware": "^2.0.3",
+ "ipaddr.js": "^2.0.1",
+ "launch-editor": "^2.6.0",
+ "open": "^8.0.9",
+ "p-retry": "^4.5.0",
+ "rimraf": "^3.0.2",
+ "schema-utils": "^4.0.0",
+ "selfsigned": "^2.1.1",
+ "serve-index": "^1.9.1",
+ "sockjs": "^0.3.24",
+ "spdy": "^4.0.2",
+ "webpack-dev-middleware": "^5.3.4",
+ "ws": "^8.13.0"
+ },
+ "bin": {
+ "webpack-dev-server": "bin/webpack-dev-server.js"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 12.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
+ },
+ "peerDependencies": {
+ "webpack": "^4.37.0 || ^5.0.0"
+ },
+ "peerDependenciesMeta": {
+ "webpack": {
+ "optional": true
+ },
+ "webpack-cli": {
+ "optional": true
+ }
}
},
- "node_modules/webpack/node_modules/eslint-scope": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.3.tgz",
- "integrity": "sha512-p7VutNr1O/QrxysMo3E45FjYDTeXBy0iTltPFNSqKAIfjDSXC+4dj+qfyuD8bfAXrW/y6lW3O76VaYNPKfpKrg==",
+ "node_modules/webpack-dev-server/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "esrecurse": "^4.1.0",
- "estraverse": "^4.1.1"
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
},
- "engines": {
- "node": ">=4.0.0"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/webpack/node_modules/fill-range": {
- "version": "4.0.0",
- "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-4.0.0.tgz",
- "integrity": "sha1-1USBHUKPmOsGpj3EAtJAPDKMOPc= sha512-VcpLTWqWDiTerugjj8e3+esbg+skS3M9e54UuR3iCeIDMXCLTsAH8hTSzDQU/X6/6t3eYkOKoZSef2PlU6U1XQ==",
+ "node_modules/webpack-dev-server/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "extend-shallow": "^2.0.1",
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1",
- "to-regex-range": "^2.1.0"
+ "fast-deep-equal": "^3.1.3"
},
- "engines": {
- "node": ">=0.10.0"
+ "peerDependencies": {
+ "ajv": "^8.8.2"
}
},
- "node_modules/webpack/node_modules/fill-range/node_modules/extend-shallow": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/extend-shallow/-/extend-shallow-2.0.1.tgz",
- "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8= sha512-zCnTtlxNoAiDc3gqY2aYAWFx7XWWiasuF2K8Me5WbN8otHKTUKBwjPtNpRs/rbUZm7KxWAaNj7P1a/p52GbVug==",
+ "node_modules/webpack-dev-server/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,
+ "license": "MIT"
+ },
+ "node_modules/webpack-dev-server/node_modules/schema-utils": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "is-extendable": "^0.1.0"
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
- "node_modules/webpack/node_modules/is-extendable": {
- "version": "0.1.1",
- "resolved": "https://registry.npmjs.org/is-extendable/-/is-extendable-0.1.1.tgz",
- "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik= sha512-5BMULNob1vgFX6EjQw5izWDxrecWK9AM72rugNr0TFldMOi0fj6Jk+zeKIt0xGj4cEfQIJth4w3OKWOJ4f+AFw==",
+ "node_modules/webpack-dev-server/node_modules/ws": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-8.20.0.tgz",
+ "integrity": "sha512-sAt8BhgNbzCtgGbt2OxmpuryO63ZoDk/sqaB/znQm94T4fCEsy/yV+7CdC1kJhOU9lboAEU7R3kquuycDoibVA==",
"dev": true,
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=10.0.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": ">=5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
}
},
- "node_modules/webpack/node_modules/is-number": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/is-number/-/is-number-3.0.0.tgz",
- "integrity": "sha1-JP1iAaR4LPUFYcgQJ2r8fRLXEZU= sha512-4cboCqIpliH+mAvFNegjZQ4kgKc3ZUhQVr3HvWbSh5q3WH2v82ct+T2Y1hdU5Gdtorx/cLifQjqCbL7bpznLTg==",
+ "node_modules/webpack-merge": {
+ "version": "5.10.0",
+ "resolved": "https://registry.npmjs.org/webpack-merge/-/webpack-merge-5.10.0.tgz",
+ "integrity": "sha512-+4zXKdx7UnO+1jaN4l2lHVD+mFvnlZQP/6ljaJVb4SZiwIKeUnrT5l0gkT8z+n4hKpC+jpOv6O9R+gLtag7pSA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
- "kind-of": "^3.0.2"
+ "clone-deep": "^4.0.1",
+ "flat": "^5.0.2",
+ "wildcard": "^2.0.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">=10.0.0"
}
},
- "node_modules/webpack/node_modules/is-number/node_modules/kind-of": {
- "version": "3.2.2",
- "resolved": "https://registry.npmjs.org/kind-of/-/kind-of-3.2.2.tgz",
- "integrity": "sha1-MeohpzS6ubuw8yRm2JOupR5KPGQ= sha512-NOW9QQXMoZGg/oqnVNoNTTIFEIid1627WCffUBJEdMxYApq7mNE7CpzucIPc+ZQg25Phej7IJSmX3hO+oblOtQ==",
- "dev": true,
- "dependencies": {
- "is-buffer": "^1.1.5"
- },
+ "node_modules/webpack-sources": {
+ "version": "3.4.1",
+ "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.4.1.tgz",
+ "integrity": "sha512-eACpxRN02yaawnt+uUNIF7Qje6A9zArxBbcAJjK1PK3S9Ycg5jIuJ8pW4q8EMnwNZCEGltcjkRx1QzOxOkKD8A==",
+ "license": "MIT",
"engines": {
- "node": ">=0.10.0"
+ "node": ">=10.13.0"
}
},
- "node_modules/webpack/node_modules/micromatch": {
- "version": "3.1.10",
- "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-3.1.10.tgz",
- "integrity": "sha512-MWikgl9n9M3w+bpsY3He8L+w9eF9338xRl8IAO5viDizwSzziFEyUzo2xrrloB64ADbTf8uA8vRqqttDTOmccg==",
+ "node_modules/webpack-virtual-modules": {
+ "version": "0.4.6",
+ "resolved": "https://registry.npmjs.org/webpack-virtual-modules/-/webpack-virtual-modules-0.4.6.tgz",
+ "integrity": "sha512-5tyDlKLqPfMqjT3Q9TAqf2YqjwmnUleZwzJi1A5qXnlBCdj2AtOJ6wAWdglTIDOPgOiOrXeBeFcsQ8+aGQ6QbA==",
"dev": true,
+ "license": "MIT"
+ },
+ "node_modules/webpack/node_modules/ajv": {
+ "version": "8.20.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.20.0.tgz",
+ "integrity": "sha512-Thbli+OlOj+iMPYFBVBfJ3OmCAnaSyNn4M1vz9T6Gka5Jt9ba/HIR56joy65tY6kx/FCF5VXNB819Y7/GUrBGA==",
+ "license": "MIT",
"dependencies": {
- "arr-diff": "^4.0.0",
- "array-unique": "^0.3.2",
- "braces": "^2.3.1",
- "define-property": "^2.0.2",
- "extend-shallow": "^3.0.2",
- "extglob": "^2.0.4",
- "fragment-cache": "^0.2.1",
- "kind-of": "^6.0.2",
- "nanomatch": "^1.2.9",
- "object.pick": "^1.3.0",
- "regex-not": "^1.0.0",
- "snapdragon": "^0.8.1",
- "to-regex": "^3.0.2"
+ "fast-deep-equal": "^3.1.3",
+ "fast-uri": "^3.0.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2"
},
- "engines": {
- "node": ">=0.10.0"
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
}
},
- "node_modules/webpack/node_modules/schema-utils": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-1.0.0.tgz",
- "integrity": "sha512-i27Mic4KovM/lnGsy8whRCHhc7VicJajAjTrYg11K9zfZXnYIt4k5F+kZkwjnrhKzLic/HLU4j11mjsz2G/75g==",
- "dev": true,
+ "node_modules/webpack/node_modules/ajv-keywords": {
+ "version": "5.1.0",
+ "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz",
+ "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==",
+ "license": "MIT",
"dependencies": {
- "ajv": "^6.1.0",
- "ajv-errors": "^1.0.0",
- "ajv-keywords": "^3.1.0"
+ "fast-deep-equal": "^3.1.3"
},
+ "peerDependencies": {
+ "ajv": "^8.8.2"
+ }
+ },
+ "node_modules/webpack/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==",
+ "license": "MIT"
+ },
+ "node_modules/webpack/node_modules/mime-db": {
+ "version": "1.54.0",
+ "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.54.0.tgz",
+ "integrity": "sha512-aU5EJuIN2WDemCcAp2vFBfp/m4EAhWJnUNSSw0ixs7/kXbd6Pg64EmwJkNdFhB8aWt1sH2CTXrLxo/iAGV3oPQ==",
+ "license": "MIT",
"engines": {
- "node": ">= 4"
+ "node": ">= 0.6"
}
},
- "node_modules/webpack/node_modules/to-regex-range": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-2.1.1.tgz",
- "integrity": "sha1-fIDBe53+vlmeJzZ+DU3VWQFB2zg= sha512-ZZWNfCjUokXXDGXFpZehJIkZqq91BcULFq/Pi7M5i4JnxXdhMKAK682z8bCW3o8Hj1wuuzoKcW3DfVzaP6VuNg==",
- "dev": true,
+ "node_modules/webpack/node_modules/schema-utils": {
+ "version": "4.3.3",
+ "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz",
+ "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==",
+ "license": "MIT",
"dependencies": {
- "is-number": "^3.0.0",
- "repeat-string": "^1.6.1"
+ "@types/json-schema": "^7.0.9",
+ "ajv": "^8.9.0",
+ "ajv-formats": "^2.1.1",
+ "ajv-keywords": "^5.1.0"
},
"engines": {
- "node": ">=0.10.0"
+ "node": ">= 10.13.0"
+ },
+ "funding": {
+ "type": "opencollective",
+ "url": "https://opencollective.com/webpack"
}
},
"node_modules/websocket-driver": {
@@ -18622,6 +14847,7 @@
"resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz",
"integrity": "sha512-b17KeDIQVjvb0ssuSDF2cYXSg2iztliJ4B9WdsuB6J952qCPKmnVq4DyW5motImXHDC1cBT/1UezrJVsKw5zjg==",
"dev": true,
+ "license": "Apache-2.0",
"dependencies": {
"http-parser-js": ">=0.5.1",
"safe-buffer": ">=5.1.0",
@@ -18636,134 +14862,159 @@
"resolved": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.4.tgz",
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
"dev": true,
+ "license": "Apache-2.0",
"engines": {
"node": ">=0.8.0"
}
},
- "node_modules/which": {
- "version": "1.3.1",
- "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
- "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==",
+ "node_modules/whatwg-fetch": {
+ "version": "3.6.20",
+ "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.20.tgz",
+ "integrity": "sha512-EqhiFU6daOA8kpjOWTL0olhVOF3i7OrFzSYiGsEMB8GcXS+RrzauAERX65xMeNWVqxA6HXH2m69Z9LaKKdisfg==",
+ "dev": true,
+ "license": "MIT"
+ },
+ "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,
+ "license": "MIT",
"dependencies": {
- "isexe": "^2.0.0"
- },
- "bin": {
- "which": "bin/which"
+ "tr46": "~0.0.3",
+ "webidl-conversions": "^3.0.0"
}
},
- "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==",
+ "node_modules/which": {
+ "version": "2.0.2",
+ "resolved": "https://registry.npmjs.org/which/-/which-2.0.2.tgz",
+ "integrity": "sha512-BLI3Tl1TW3Pvl70l3yq3Y64i+awpwXqsGBYWkkqMtnbXgrMD+yj7rhW0kuEDxzJaYXGjEW5ogapKNMEKNMjibA==",
"dev": true,
+ "license": "ISC",
"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"
+ "isexe": "^2.0.0"
},
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
+ "bin": {
+ "node-which": "bin/node-which"
+ },
+ "engines": {
+ "node": ">= 8"
}
},
- "node_modules/which-module": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz",
- "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho= sha512-B+enWhmw6cjfVC7kS8Pj9pCrKSc5txArRyaYGe088shv/FGWH+0Rjx/xPgtsWfsUtS27FkP697E4DDhgrgoc0Q==",
- "dev": true
+ "node_modules/wildcard": {
+ "version": "2.0.1",
+ "resolved": "https://registry.npmjs.org/wildcard/-/wildcard-2.0.1.tgz",
+ "integrity": "sha512-CC1bOL87PIWSBhDcTrdeLo6eGT7mCFtrg0uIJtqJUFyK+eJnzl8A1niH56uu7KMa5XFrtiV+AQuHO3n7DsHnLQ==",
+ "dev": true,
+ "license": "MIT"
},
"node_modules/word-wrap": {
- "version": "1.2.3",
- "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.3.tgz",
- "integrity": "sha512-Hz/mrNwitNRh/HUAtM/VT/5VH+ygD6DV7mYKZAtHOrbs8U7lvPS6xf7EJKMF0uW1KJCl0H701g3ZGus+muE5vQ==",
+ "version": "1.2.5",
+ "resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
+ "integrity": "sha512-BN22B5eaMMI9UMtjrGd5g5eCYPpCPDUy0FJXbYsaT5zYxjFOckS53SQDE3pWkVoWpHXVb3BrYcEN4Twa55B5cA==",
+ "dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/worker-farm": {
- "version": "1.7.0",
- "resolved": "https://registry.npmjs.org/worker-farm/-/worker-farm-1.7.0.tgz",
- "integrity": "sha512-rvw3QTZc8lAxyVrqcSGVm5yP/IJ2UcB3U0graE3LCFoZ0Yn2x4EoVSqJKdB/T5M+FLcRPjz4TDacRf3OCfNUzw==",
- "dev": true,
- "dependencies": {
- "errno": "~0.1.7"
- }
- },
"node_modules/world-calendars": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/world-calendars/-/world-calendars-1.0.3.tgz",
- "integrity": "sha512-sAjLZkBnsbHkHWVhrsCU5Sa/EVuf9QqgvrN8zyJ2L/F9FR9Oc6CvVK0674+PGAtmmmYQMH98tCUSO4QLQv3/TQ==",
+ "version": "1.0.4",
+ "resolved": "https://registry.npmjs.org/world-calendars/-/world-calendars-1.0.4.tgz",
+ "integrity": "sha512-VGRnLJS+xJmGDPodgJRnGIDwGu0s+Cr9V2HB3EzlDZ5n0qb8h5SJtGUEkjrphZYAglEiXZ6kiXdmk0H/h/uu/w==",
+ "license": "MIT",
"dependencies": {
"object-assign": "^4.1.0"
}
},
"node_modules/wrap-ansi": {
- "version": "6.2.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
- "integrity": "sha512-r6lPcBGxZXlIcymEu7InxDMhdW0KDxpLgoFLcguasxCaJ/SOIZwINatK9KY/tf+ZrlywOKU0UDj3ATXUBfxJXA==",
+ "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,
+ "license": "MIT",
"dependencies": {
"ansi-styles": "^4.0.0",
"string-width": "^4.1.0",
"strip-ansi": "^6.0.0"
},
"engines": {
- "node": ">=8"
+ "node": ">=10"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
}
},
"node_modules/wrappy": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
- "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8= sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
+ "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==",
+ "license": "ISC"
},
- "node_modules/write": {
- "version": "1.0.3",
- "resolved": "https://registry.npmjs.org/write/-/write-1.0.3.tgz",
- "integrity": "sha512-/lg70HAjtkUgWPVZhZcm+T4hkL8Zbtp1nFNOn3lRrxnlv50SRBv7cR7RqR+GMsd3hUXy9hWBo4CHTbFTcOYwig==",
+ "node_modules/ws": {
+ "version": "7.5.10",
+ "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz",
+ "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==",
"dev": true,
- "dependencies": {
- "mkdirp": "^0.5.1"
- },
+ "license": "MIT",
"engines": {
- "node": ">=4"
+ "node": ">=8.3.0"
+ },
+ "peerDependencies": {
+ "bufferutil": "^4.0.1",
+ "utf-8-validate": "^5.0.2"
+ },
+ "peerDependenciesMeta": {
+ "bufferutil": {
+ "optional": true
+ },
+ "utf-8-validate": {
+ "optional": true
+ }
}
},
- "node_modules/ws": {
- "version": "6.2.3",
- "resolved": "https://registry.npmjs.org/ws/-/ws-6.2.3.tgz",
- "integrity": "sha512-jmTjYU0j60B+vHey6TfR3Z7RD61z/hmxBS3VMSGIrroOWXQEneK1zNuotOUrGyBHQj0yrpsLHPWtigEFd13ndA==",
+ "node_modules/xml-name-validator": {
+ "version": "4.0.0",
+ "resolved": "https://registry.npmjs.org/xml-name-validator/-/xml-name-validator-4.0.0.tgz",
+ "integrity": "sha512-ICP2e+jsHvAj2E2lIHxa5tjXRlKDJo4IdvPvCXbXQGdzSfmSpNVyIKMvoZHjDY9DP0zV17iI85o90vRFXNccRw==",
"dev": true,
- "dependencies": {
- "async-limiter": "~1.0.0"
+ "license": "Apache-2.0",
+ "engines": {
+ "node": ">=12"
}
},
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
"integrity": "sha512-LKYU1iAXJXUgAXn9URjiu+MWhyUXHsvfp7mcuYm9dSUKK0/CjtrUwFAxD82/mCWbtLsGjFIad0wIsod4zrTAEQ==",
+ "license": "MIT",
"engines": {
"node": ">=0.4"
}
},
"node_modules/y18n": {
- "version": "4.0.3",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
- "integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
- "dev": true
+ "version": "5.0.8",
+ "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
+ "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
+ "dev": true,
+ "license": "ISC",
+ "engines": {
+ "node": ">=10"
+ }
},
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
"integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
- "dev": true
+ "dev": true,
+ "license": "ISC"
},
"node_modules/yaml": {
- "version": "1.10.2",
- "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz",
- "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==",
+ "version": "1.10.3",
+ "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz",
+ "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==",
"dev": true,
+ "license": "ISC",
"engines": {
"node": ">= 6"
}
@@ -18773,6 +15024,7 @@
"resolved": "https://registry.npmjs.org/yargs/-/yargs-16.2.0.tgz",
"integrity": "sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"cliui": "^7.0.2",
"escalade": "^3.1.1",
@@ -18791,45 +15043,22 @@
"resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-20.2.9.tgz",
"integrity": "sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==",
"dev": true,
+ "license": "ISC",
"engines": {
"node": ">=10"
}
},
- "node_modules/yargs/node_modules/cliui": {
- "version": "7.0.4",
- "resolved": "https://registry.npmjs.org/cliui/-/cliui-7.0.4.tgz",
- "integrity": "sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==",
- "dev": true,
- "dependencies": {
- "string-width": "^4.2.0",
- "strip-ansi": "^6.0.0",
- "wrap-ansi": "^7.0.0"
- }
- },
- "node_modules/yargs/node_modules/wrap-ansi": {
- "version": "7.0.0",
- "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-7.0.0.tgz",
- "integrity": "sha512-YVGIj2kamLSTxw6NsZjoBxfSwsn0ycdesmc4p+Q21c5zPuZ1pl+NfxVdxPtdHvmNVOQ6XSYG4AUtyt/Fi7D16Q==",
+ "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,
- "dependencies": {
- "ansi-styles": "^4.0.0",
- "string-width": "^4.1.0",
- "strip-ansi": "^6.0.0"
- },
+ "license": "MIT",
"engines": {
"node": ">=10"
},
"funding": {
- "url": "https://github.com/chalk/wrap-ansi?sponsor=1"
- }
- },
- "node_modules/yargs/node_modules/y18n": {
- "version": "5.0.8",
- "resolved": "https://registry.npmjs.org/y18n/-/y18n-5.0.8.tgz",
- "integrity": "sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==",
- "dev": true,
- "engines": {
- "node": ">=10"
+ "url": "https://github.com/sponsors/sindresorhus"
}
},
"node_modules/yorkie": {
@@ -18838,6 +15067,7 @@
"integrity": "sha512-jcKpkthap6x63MB4TxwCyuIGkV0oYP/YRyuQU5UO0Yz/E/ZAu+653/uov+phdmO54n6BcvFRyyt0RRrWdN2mpw==",
"dev": true,
"hasInstallScript": true,
+ "license": "MIT",
"dependencies": {
"execa": "^0.8.0",
"is-ci": "^1.0.10",
@@ -18848,22 +15078,12 @@
"node": ">=4"
}
},
- "node_modules/yorkie/node_modules/cross-spawn": {
- "version": "5.1.0",
- "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz",
- "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk= sha512-pTgQJ5KC0d2hcY8eyL1IzlBPYjTkyH72XRZPnLyKus2mBfNjQs3klqbJU2VILqZryAZUt9JOb3h/mWMy23/f5A==",
- "dev": true,
- "dependencies": {
- "lru-cache": "^4.0.1",
- "shebang-command": "^1.2.0",
- "which": "^1.2.9"
- }
- },
"node_modules/yorkie/node_modules/execa": {
"version": "0.8.0",
"resolved": "https://registry.npmjs.org/execa/-/execa-0.8.0.tgz",
- "integrity": "sha1-2NdrvBtVIX7RkP1t1J08d07PyNo= sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==",
+ "integrity": "sha512-zDWS+Rb1E8BlqqhALSt9kUhss8Qq4nN3iof3gsOdyINksElaPyNBtKUMTR62qhvgVWR0CqCX7sdnKe4MnUbFEA==",
"dev": true,
+ "license": "MIT",
"dependencies": {
"cross-spawn": "^5.0.1",
"get-stream": "^3.0.0",
@@ -18880,41 +15100,28 @@
"node_modules/yorkie/node_modules/get-stream": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz",
- "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ= sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
+ "integrity": "sha512-GlhdIUuVakc8SJ6kK0zAFbiGzRFzNnY4jUuEbV9UROo4Y+0Ny4fjvcZFVTeDA4odpFyOQzaw6hXukJSq/f28sQ==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=4"
}
},
- "node_modules/yorkie/node_modules/lru-cache": {
- "version": "4.1.5",
- "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.5.tgz",
- "integrity": "sha512-sWZlbEP2OsHNkXrMl5GYk/jKk70MBng6UU4YI/qGDYbgf6YbP4EvmqISbXCoJiRKs+1bSpFHVgQxvJ17F2li5g==",
- "dev": true,
- "dependencies": {
- "pseudomap": "^1.0.2",
- "yallist": "^2.1.2"
- }
- },
"node_modules/yorkie/node_modules/normalize-path": {
"version": "1.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-1.0.0.tgz",
- "integrity": "sha1-MtDkcvkf80VwHBWoMRAY07CpA3k= sha512-7WyT0w8jhpDStXRq5836AMmihQwq2nrUVQrgjvUo/p/NZf9uy/MeJ246lBJVmWuYXMlJuG9BNZHF0hWjfTbQUA==",
+ "integrity": "sha512-7WyT0w8jhpDStXRq5836AMmihQwq2nrUVQrgjvUo/p/NZf9uy/MeJ246lBJVmWuYXMlJuG9BNZHF0hWjfTbQUA==",
"dev": true,
+ "license": "MIT",
"engines": {
"node": ">=0.10.0"
}
},
- "node_modules/yorkie/node_modules/yallist": {
- "version": "2.1.2",
- "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz",
- "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI= sha512-ncTzHV7NvsQZkYe1DW7cbDLm0YpzHmZF5r/iyP3ZnQtMiJ+pjzisCiMNI+Sj+xQF5pXhSHxSB3uDbsBTzY/c2A==",
- "dev": true
- },
"node_modules/yup": {
"version": "0.32.11",
"resolved": "https://registry.npmjs.org/yup/-/yup-0.32.11.tgz",
"integrity": "sha512-Z2Fe1bn+eLstG8DRR6FTavGD+MeAwyfmouhHsIUgaADz8jvFKbO/fXc2trJKZg+5EBjh4gGm3iU/t3onKlXHIg==",
+ "license": "MIT",
"dependencies": {
"@babel/runtime": "^7.15.4",
"@types/lodash": "^4.14.175",
@@ -18927,11 +15134,6 @@
"engines": {
"node": ">=10"
}
- },
- "node_modules/yup/node_modules/toposort": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/toposort/-/toposort-2.0.2.tgz",
- "integrity": "sha1-riF2gXXRVZ1IvvNUILL0li8JwzA= sha512-0a5EOkAUp8D4moMi2W8ZF8jcga7BgZd91O/yabJCFY8az+XSzeGyTKs0Aoo897iV1Nj6guFq8orWDS96z91oGg=="
}
}
}
diff --git a/web/package.json b/web/package.json
index f85bf34..1c6de7d 100644
--- a/web/package.json
+++ b/web/package.json
@@ -3,16 +3,15 @@
"version": "0.1.0",
"private": true,
"scripts": {
- "serve": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service serve",
- "build": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service build",
- "lint": "NODE_OPTIONS=--openssl-legacy-provider vue-cli-service lint"
+ "serve": "vue-cli-service serve",
+ "build": "vue-cli-service build",
+ "lint": "eslint src/"
},
"dependencies": {
"@guolao/vue-monaco-editor": "^1.5.4",
- "@tailwindcss/forms": "^0.3.4",
+ "@tailwindcss/forms": "^0.5.x",
"@vue-hero-icons/outline": "^1.7.2",
"@vue-hero-icons/solid": "^1.7.2",
- "@vue/composition-api": "^1.7.2",
"axios": "^1.8.3",
"chart.js": "^3.7.1",
"chartjs-plugin-zoom": "^1.2.0",
@@ -29,31 +28,52 @@
"vuex": "3",
"yup": "^0.32.11"
},
- "devDependencies": {
- "@tailwindcss/postcss7-compat": "^2.2.17",
- "@vue/cli-plugin-babel": "~4.5.0",
- "@vue/cli-plugin-eslint": "~4.5.0",
- "@vue/cli-service": "~4.5.0",
- "autoprefixer": "^9",
- "babel-eslint": "^10.1.0",
- "eslint": "^6.7.2",
- "eslint-plugin-vue": "^6.2.2",
- "postcss": "^7.0.39",
- "tailwindcss": "npm:@tailwindcss/postcss7-compat"
- },
- "eslintConfig": {
- "root": true,
- "env": {
- "node": true
+ "overrides": {
+ "@babel/helpers": "^7.26.10",
+ "@babel/runtime": "^7.26.10",
+ "ansi-regex": "^5.0.1",
+ "axios": "^1.8.3",
+ "body-parser": "^1.20.3",
+ "brace-expansion": "^2.0.1",
+ "braces": "^3.0.3",
+ "cookie": "^0.7.1",
+ "cross-spawn": "^7.0.6",
+ "ejs": "^3.1.10",
+ "elliptic": "^6.6.1",
+ "es5-ext": "^0.10.64",
+ "eslint-webpack-plugin": "^4.0.0",
+ "express": "^4.21.2",
+ "form-data": "^4.0.4",
+ "ip": "^2.0.1",
+ "js-yaml": "^4.1.0",
+ "cosmiconfig": {
+ "js-yaml": "^3.14.1"
},
- "extends": [
- "plugin:vue/essential",
- "eslint:recommended"
- ],
- "parserOptions": {
- "parser": "babel-eslint"
+ "svgo": {
+ "js-yaml": "^3.14.1"
},
- "rules": {}
+ "json5": "^2.2.3",
+ "node-forge": "^1.3.2",
+ "nth-check": "^2.1.1",
+ "on-headers": "^1.1.0",
+ "path-to-regexp": "^0.1.12",
+ "qs": "^6.14.1",
+ "semver": "^7.6.3",
+ "send": "^0.19.1",
+ "tmp": "^0.2.4",
+ "tough-cookie": "^5.0.0",
+ "word-wrap": "^1.2.5"
+ },
+ "devDependencies": {
+ "@babel/eslint-parser": "^7.x",
+ "@vue/cli-plugin-babel": "~5.0.0",
+ "@vue/cli-plugin-eslint": "~5.0.0",
+ "@vue/cli-service": "~5.0.0",
+ "autoprefixer": "^10",
+ "eslint": "^9.0.0",
+ "eslint-plugin-vue": "^10.0.0",
+ "globals": "^16.0.0",
+ "tailwindcss": "^3.x"
},
"browserslist": [
"> 1%",
diff --git a/web/src/components/Form.vue b/web/src/components/Form.vue
index 593ebb0..d4ab27d 100755
--- a/web/src/components/Form.vue
+++ b/web/src/components/Form.vue
@@ -68,7 +68,7 @@ export default {
this.rootError = rootError
}).bind(this),
})
- } catch (e) {
+ } catch {
// this.errors = errors
} finally {
this.loading = false
diff --git a/web/src/components/StatusBadge.vue b/web/src/components/StatusBadge.vue
index f7f8b16..d4c9b77 100755
--- a/web/src/components/StatusBadge.vue
+++ b/web/src/components/StatusBadge.vue
@@ -7,7 +7,7 @@
'badge-default': !['in_stock', 'in_study', 'in_operation', 'defunct', 'done', 'in_progress', 'failed'].includes(status),
}">
- {{ status | statusName }}
+ {{ $filters.statusName(status) }}
diff --git a/web/src/filters.js b/web/src/filters.js
new file mode 100644
index 0000000..dd6422c
--- /dev/null
+++ b/web/src/filters.js
@@ -0,0 +1,34 @@
+export function datetime(date) {
+ if (!date) return
+
+ return new Intl.DateTimeFormat('en-US', {
+ year: 'numeric',
+ month: 'long',
+ day: 'numeric',
+ hour: 'numeric',
+ minute: 'numeric',
+ }).format(date instanceof Date ? date : new Date(date))
+}
+
+export function statusName(status) {
+ return {
+ in_stock: 'In stock',
+ in_study: 'In study',
+ in_operation: 'In operation',
+ defunct: 'Defunct',
+ pending: 'Pending',
+ in_progress: 'In progress',
+ done: 'Done',
+ failed: 'Failed',
+ scheduled: 'Scheduled',
+ }[status]
+}
+
+export function roleName(role) {
+ return {
+ guest: 'Guest',
+ user: 'User',
+ designer: 'Designer',
+ admin: 'Admin',
+ }[role]
+}
diff --git a/web/src/main.js b/web/src/main.js
index 8304203..5e46335 100755
--- a/web/src/main.js
+++ b/web/src/main.js
@@ -8,6 +8,7 @@ import App from './App.vue'
import router from './router'
import store from './store'
import './main.css'
+import * as filters from './filters'
Chart.register(...registerables, zoomPlugin)
@@ -21,39 +22,7 @@ Vue.use(VueMonacoEditorPlugin, {
},
})
-
-Vue.filter('datetime', (date) => {
- if (!date) {
- return
- }
-
- return new Intl.DateTimeFormat('en-US', {
- year: 'numeric',
- month: 'long',
- day: 'numeric',
- hour: 'numeric',
- minute: 'numeric',
- }).format(date instanceof Date ? date : new Date(date))
-})
-
-Vue.filter('statusName', (status) => ({
- in_stock: 'In stock',
- in_study: 'In study',
- in_operation: 'In operation',
- defunct: 'Defunct',
- pending: 'Pending',
- in_progress: 'In progress',
- done: 'Done',
- failed: 'Failed',
- scheduled: 'Scheduled',
-}[status]))
-
-Vue.filter('roleName', (role) => ({
- guest: 'Guest',
- user: 'User',
- designer: 'Designer',
- admin: 'Admin',
-}[role]))
+Vue.prototype.$filters = filters
new Vue({
render: h => h(App),
diff --git a/web/src/router.js b/web/src/router.js
index a44a543..ca3c4b3 100755
--- a/web/src/router.js
+++ b/web/src/router.js
@@ -14,7 +14,6 @@ const router = new VueRouter({
{ name: 'magnets', path: '/magnets', component: () => import('./views/magnets/list') },
{ name: 'new_magnet', path: '/magnets/new', component: () => import('./views/magnets/new') },
{ name: 'magnet', path: '/magnets/:id', component: () => import('./views/magnets/show') },
- { name: 'probe', path: '/probes/:id', component: () => import('./views/probes/show') },
{ name: 'materials', path: '/materials', component: () => import('./views/materials/list') },
{ name: 'new_material', path: '/materials/new', component: () => import('./views/materials/new') },
{ name: 'material', path: '/materials/:id', component: () => import('./views/materials/show') },
diff --git a/web/src/views/admin/audit-logs.vue b/web/src/views/admin/audit-logs.vue
index f65b774..ca69456 100755
--- a/web/src/views/admin/audit-logs.vue
+++ b/web/src/views/admin/audit-logs.vue
@@ -7,7 +7,7 @@
- {{ item.created_at | datetime }}
+ {{ $filters.datetime(item.created_at) }}
{{ item.message }}
diff --git a/web/src/views/admin/users/list.vue b/web/src/views/admin/users/list.vue
index 93b98ed..6d7dbca 100755
--- a/web/src/views/admin/users/list.vue
+++ b/web/src/views/admin/users/list.vue
@@ -22,13 +22,13 @@
{{ item.email }}
- {{ item.role | roleName }}
+ {{ $filters.roleName(item.role) }}
- {{ item.created_at | datetime }}
+ {{ $filters.datetime(item.created_at) }}
- {{ item.updated_at | datetime }}
+ {{ $filters.datetime(item.updated_at) }}
diff --git a/web/src/views/magnets/list.vue b/web/src/views/magnets/list.vue
index 57832c4..4c8a931 100755
--- a/web/src/views/magnets/list.vue
+++ b/web/src/views/magnets/list.vue
@@ -29,16 +29,16 @@
Not available
- {{ item.created_at | datetime }}
+ {{ $filters.datetime(item.created_at) }}
- {{ item.updated_at | datetime }}
+ {{ $filters.datetime(item.updated_at) }}
- {{ item.commissioned_at | datetime }}
+ {{ $filters.datetime(item.commissioned_at) }}
- {{ item.decommissioned_at | datetime }}
+ {{ $filters.datetime(item.decommissioned_at) }}
diff --git a/web/src/views/magnets/show/index.vue b/web/src/views/magnets/show/index.vue
index 9a897e6..c747c91 100644
--- a/web/src/views/magnets/show/index.vue
+++ b/web/src/views/magnets/show/index.vue
@@ -170,11 +170,11 @@
Not set
|
- {{ magnetPart.commissioned_at | datetime }}
+ {{ $filters.datetime(magnetPart.commissioned_at) }}
Not available
|
- {{ magnetPart.decommissioned_at | datetime }}
+ {{ $filters.datetime(magnetPart.decommissioned_at) }}
Not available
|
diff --git a/web/src/views/materials/list.vue b/web/src/views/materials/list.vue
index a206531..48b4325 100755
--- a/web/src/views/materials/list.vue
+++ b/web/src/views/materials/list.vue
@@ -22,10 +22,10 @@
Not available
- {{ item.created_at | datetime }}
+ {{ $filters.datetime(item.created_at) }}
- {{ item.updated_at | datetime }}
+ {{ $filters.datetime(item.updated_at) }}
diff --git a/web/src/views/parts/list.vue b/web/src/views/parts/list.vue
index 6c90224..83218cf 100755
--- a/web/src/views/parts/list.vue
+++ b/web/src/views/parts/list.vue
@@ -32,10 +32,10 @@
- {{ item.created_at | datetime }}
+ {{ $filters.datetime(item.created_at) }}
- {{ item.updated_at | datetime }}
+ {{ $filters.datetime(item.updated_at) }}
diff --git a/web/src/views/records/list.vue b/web/src/views/records/list.vue
index a03ba1e..660eb08 100755
--- a/web/src/views/records/list.vue
+++ b/web/src/views/records/list.vue
@@ -22,10 +22,10 @@
Not available
- {{ item.created_at | datetime }}
+ {{ $filters.datetime(item.created_at) }}
- {{ item.updated_at | datetime }}
+ {{ $filters.datetime(item.updated_at) }}
diff --git a/web/src/views/servers/list.vue b/web/src/views/servers/list.vue
index 2d6abf6..9d40ff2 100755
--- a/web/src/views/servers/list.vue
+++ b/web/src/views/servers/list.vue
@@ -23,10 +23,10 @@
- {{ item.created_at | datetime }}
+ {{ $filters.datetime(item.created_at) }}
- {{ item.updated_at | datetime }}
+ {{ $filters.datetime(item.updated_at) }}
diff --git a/web/src/views/simulations/list.vue b/web/src/views/simulations/list.vue
index 6528066..14a3eda 100755
--- a/web/src/views/simulations/list.vue
+++ b/web/src/views/simulations/list.vue
@@ -40,10 +40,10 @@
{{ item.owner.name }}
- {{ item.created_at | datetime }}
+ {{ $filters.datetime(item.created_at) }}
- {{ item.updated_at | datetime }}
+ {{ $filters.datetime(item.updated_at) }}
diff --git a/web/src/views/sites/list.vue b/web/src/views/sites/list.vue
index c484fdf..9f2bcd8 100755
--- a/web/src/views/sites/list.vue
+++ b/web/src/views/sites/list.vue
@@ -25,16 +25,16 @@
- {{ item.created_at | datetime }}
+ {{ $filters.datetime(item.created_at) }}
- {{ item.updated_at | datetime }}
+ {{ $filters.datetime(item.updated_at) }}
- {{ item.commissioned_at | datetime }}
+ {{ $filters.datetime(item.commissioned_at) }}
- {{ item.decommissioned_at | datetime }}
+ {{ $filters.datetime(item.decommissioned_at) }}
diff --git a/web/tailwind.config.js b/web/tailwind.config.js
index d07a4c7..81c100f 100755
--- a/web/tailwind.config.js
+++ b/web/tailwind.config.js
@@ -1,14 +1,10 @@
module.exports = {
- purge: [
+ content: [
'./src/**/*.{vue,js}'
],
- darkMode: false,
theme: {
extend: {},
},
- variants: {
- extend: {},
- },
plugins: [
require("@tailwindcss/forms"),
],
diff --git a/web/vue.config.js b/web/vue.config.js
index 5b6c691..dc61372 100755
--- a/web/vue.config.js
+++ b/web/vue.config.js
@@ -1,8 +1,20 @@
module.exports = {
+ lintOnSave: false,
devServer: {
allowedHosts: [
'lncmig.local',
'magnetdb-dev.local',
- ]
- }
+ ],
+ client: {
+ webSocketURL: 'auto://0.0.0.0:0/ws',
+ },
+ },
+ configureWebpack: {
+ resolve: {
+ fallback: {
+ stream: false,
+ assert: false,
+ },
+ },
+ },
}
|