diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml index 13f2b530..7d40a544 100644 --- a/.github/workflows/docs.yml +++ b/.github/workflows/docs.yml @@ -32,24 +32,24 @@ jobs: uses: actions/checkout@v6 - name: Set up uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v7 with: enable-cache: true - name: Install MkDocs run: uv tool install mkdocs --with mkdocs-material --with mkdocs-mermaid2-plugin --with mkdocs-swagger-ui-tag - - name: Download OpenAPI spec - run: | - curl -s https://api.integr8scode.cc/openapi.json | \ - jq '. + {servers: [{url: "https://api.integr8scode.cc", description: "Production"}]}' \ - > docs/reference/openapi.json + - name: Install backend dependencies + run: cd backend && uv sync --frozen + + - name: Generate OpenAPI spec + run: ./deploy.sh openapi - name: Build documentation run: uv tool run mkdocs build --strict - name: Upload artifact - uses: actions/upload-pages-artifact@v3 + uses: actions/upload-pages-artifact@v4 with: path: site/ diff --git a/.github/workflows/mypy.yml b/.github/workflows/mypy.yml index 786cdb3c..4d814177 100644 --- a/.github/workflows/mypy.yml +++ b/.github/workflows/mypy.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v6 - name: Set up uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: "backend/uv.lock" diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml index b3db04a2..3ddec835 100644 --- a/.github/workflows/ruff.yml +++ b/.github/workflows/ruff.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v6 - name: Set up uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: "backend/uv.lock" diff --git a/.github/workflows/security.yml b/.github/workflows/security.yml index 73265ff7..4452c432 100644 --- a/.github/workflows/security.yml +++ b/.github/workflows/security.yml @@ -15,7 +15,7 @@ jobs: - uses: actions/checkout@v6 - name: Set up uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: "backend/uv.lock" diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml index 56a5df4a..153e51c6 100644 --- a/.github/workflows/tests.yml +++ b/.github/workflows/tests.yml @@ -60,7 +60,7 @@ jobs: run: | echo "Pre-pulling base images to speed up builds..." docker pull python:3.12-slim & - docker pull ghcr.io/astral-sh/uv:0.9.17 & + docker pull ghcr.io/astral-sh/uv:0.9.18 & docker pull alpine:latest & docker pull confluentinc/cp-kafka:7.5.0 & docker pull confluentinc/cp-zookeeper:7.5.0 & @@ -161,7 +161,7 @@ jobs: kubectl get rolebindings -n default - name: Set up uv - uses: astral-sh/setup-uv@v5 + uses: astral-sh/setup-uv@v7 with: enable-cache: true cache-dependency-glob: "backend/uv.lock" @@ -216,7 +216,7 @@ jobs: - name: Upload logs if: always() - uses: actions/upload-artifact@v4 + uses: actions/upload-artifact@v6 with: name: integration-test-logs path: logs/ diff --git a/.gitignore b/.gitignore index f93af750..4249f3c0 100644 --- a/.gitignore +++ b/.gitignore @@ -13,8 +13,8 @@ dist/ downloads/ eggs/ .eggs/ -lib/ -lib64/ +/lib/ +/lib64/ parts/ sdist/ var/ diff --git a/backend/app/api/routes/auth.py b/backend/app/api/routes/auth.py index a4d46953..e898caad 100644 --- a/backend/app/api/routes/auth.py +++ b/backend/app/api/routes/auth.py @@ -1,5 +1,4 @@ from datetime import datetime, timedelta, timezone -from typing import Dict, Union from uuid import uuid4 from dishka import FromDishka @@ -12,7 +11,13 @@ from app.core.utils import get_client_ip from app.db.repositories import UserRepository from app.domain.user import User as DomainAdminUser -from app.schemas_pydantic.user import UserCreate, UserResponse +from app.schemas_pydantic.user import ( + LoginResponse, + MessageResponse, + TokenValidationResponse, + UserCreate, + UserResponse, +) from app.services.auth_service import AuthService from app.settings import get_settings @@ -21,13 +26,13 @@ route_class=DishkaRoute) -@router.post("/login") +@router.post("/login", response_model=LoginResponse) async def login( request: Request, response: Response, user_repo: FromDishka[UserRepository], form_data: OAuth2PasswordRequestForm = Depends(), -) -> Dict[str, str]: +) -> LoginResponse: logger.info( "Login attempt", extra={ @@ -112,14 +117,12 @@ async def login( response.headers["Cache-Control"] = "no-store" response.headers["Pragma"] = "no-cache" - # Return minimal authentication response - # Detailed user info should be fetched from GET /me endpoint - return { - "message": "Login successful", - "username": user.username, - "role": "admin" if user.is_superuser else "user", # Coarse-grained role - "csrf_token": csrf_token - } + return LoginResponse( + message="Login successful", + username=user.username, + role="admin" if user.is_superuser else "user", + csrf_token=csrf_token + ) @router.post("/register", response_model=UserResponse) @@ -224,11 +227,11 @@ async def get_current_user_profile( return current_user -@router.get("/verify-token") +@router.get("/verify-token", response_model=TokenValidationResponse) async def verify_token( request: Request, auth_service: FromDishka[AuthService], -) -> Dict[str, Union[str, bool]]: +) -> TokenValidationResponse: current_user = await auth_service.get_current_user(request) logger.info( "Token verification attempt", @@ -249,15 +252,14 @@ async def verify_token( "user_agent": request.headers.get("user-agent"), }, ) - # Return existing CSRF token from cookie csrf_token = request.cookies.get("csrf_token", "") - return { - "valid": True, - "username": current_user.username, - "role": "admin" if current_user.is_superuser else "user", # Coarse-grained role - "csrf_token": csrf_token - } + return TokenValidationResponse( + valid=True, + username=current_user.username, + role="admin" if current_user.is_superuser else "user", + csrf_token=csrf_token + ) except Exception as e: logger.error( @@ -278,11 +280,11 @@ async def verify_token( -@router.post("/logout") +@router.post("/logout", response_model=MessageResponse) async def logout( request: Request, response: Response, -) -> Dict[str, str]: +) -> MessageResponse: logger.info( "Logout attempt", extra={ @@ -312,4 +314,4 @@ async def logout( }, ) - return {"message": "Logout successful"} + return MessageResponse(message="Logout successful") diff --git a/backend/app/core/providers.py b/backend/app/core/providers.py index 8c37a45f..47cdbde3 100644 --- a/backend/app/core/providers.py +++ b/backend/app/core/providers.py @@ -127,7 +127,7 @@ async def get_redis_client(self, settings: Settings) -> AsyncIterator[redis.Redi socket_timeout=5, ) # Test connection - await client.ping() + await client.execute_command("PING") logger.info( f"Redis connected: {settings.REDIS_HOST}:{settings.REDIS_PORT}/{settings.REDIS_DB}" ) diff --git a/backend/app/schemas_pydantic/user.py b/backend/app/schemas_pydantic/user.py index 2899ee7c..1c966b06 100644 --- a/backend/app/schemas_pydantic/user.py +++ b/backend/app/schemas_pydantic/user.py @@ -130,3 +130,23 @@ class MessageResponse(BaseModel): model_config = ConfigDict( from_attributes=True ) + + +class LoginResponse(BaseModel): + """Response model for successful login""" + message: str + username: str + role: str + csrf_token: str + + model_config = ConfigDict(from_attributes=True) + + +class TokenValidationResponse(BaseModel): + """Response model for token validation""" + valid: bool + username: str + role: str + csrf_token: str + + model_config = ConfigDict(from_attributes=True) diff --git a/backend/app/services/idempotency/redis_repository.py b/backend/app/services/idempotency/redis_repository.py index ac144778..d33c9704 100644 --- a/backend/app/services/idempotency/redis_repository.py +++ b/backend/app/services/idempotency/redis_repository.py @@ -138,4 +138,4 @@ async def aggregate_status_counts(self, key_prefix: str) -> dict[str, int]: return counts async def health_check(self) -> None: - await self._r.ping() + await self._r.execute_command("PING") diff --git a/backend/pyproject.toml b/backend/pyproject.toml index b64ce4d9..40d2d05f 100644 --- a/backend/pyproject.toml +++ b/backend/pyproject.toml @@ -57,7 +57,7 @@ dependencies = [ "mdurl==0.1.2", "motor==3.6.0", "msgpack==1.1.0", - "multidict==6.6.3", + "multidict==6.7.0", "oauthlib==3.2.2", "opentelemetry-api==1.22.0", "opentelemetry-exporter-otlp==1.22.0", @@ -101,7 +101,7 @@ dependencies = [ "python-multipart==0.0.18", "PyYAML==6.0.2", "pyzmq==26.2.0", - "redis==5.2.1", + "redis==7.1.0", "regex==2025.8.29", "requests==2.32.3", "requests-oauthlib==2.0.0", @@ -134,7 +134,7 @@ packages = ["app", "workers"] [dependency-groups] dev = [ - "coverage==7.6.2", + "coverage==7.13.0", "hypothesis==6.103.4", "iniconfig==2.0.0", "matplotlib==3.9.2", @@ -143,10 +143,10 @@ dev = [ "pipdeptree==2.23.4", "pluggy==1.5.0", "pytest==8.3.3", - "pytest-asyncio==0.24.0", + "pytest-asyncio==1.3.0", "pytest-cov==5.0.0", "pytest-xdist==3.6.1", - "ruff==0.12.7", + "ruff==0.14.9", "types-cachetools==6.2.0.20250827", "types-confluent-kafka==1.3.6", ] diff --git a/backend/tests/fixtures/real_services.py b/backend/tests/fixtures/real_services.py index 214dfc13..ea1bd905 100644 --- a/backend/tests/fixtures/real_services.py +++ b/backend/tests/fixtures/real_services.py @@ -52,7 +52,7 @@ async def connect_redis(self, host: str = "localhost", port: int = 6379, db: int socket_timeout=5 ) # Verify connection - await self.redis_client.ping() + await self.redis_client.execute_command("PING") # Clear test namespace await self.redis_client.flushdb() return self.redis_client @@ -328,13 +328,13 @@ async def ensure_services_running(): # Check Redis try: r = redis.Redis(host="localhost", port=6379, socket_connect_timeout=5) - await r.ping() + await r.execute_command("PING") await r.aclose() except Exception: print("Starting Redis...") subprocess.run(["docker-compose", "up", "-d", "redis"], check=False) await wait_for_service( - lambda: redis.Redis(host="localhost", port=6379).ping(), + lambda: redis.Redis(host="localhost", port=6379).execute_command("PING"), service_name="Redis" ) diff --git a/backend/tests/unit/events/test_event_dispatcher.py b/backend/tests/unit/events/test_event_dispatcher.py index 61c733d3..a38b6224 100644 --- a/backend/tests/unit/events/test_event_dispatcher.py +++ b/backend/tests/unit/events/test_event_dispatcher.py @@ -35,7 +35,7 @@ async def handler(ev: BaseEvent) -> None: # noqa: ARG001 assert len(disp.get_handlers(EventType.EXECUTION_REQUESTED)) == 1 -def test_dispatch_metrics_processed_and_skipped(event_loop) -> None: # type: ignore[no-redef] +async def test_dispatch_metrics_processed_and_skipped() -> None: disp = EventDispatcher() called = {"n": 0} @@ -43,15 +43,12 @@ def test_dispatch_metrics_processed_and_skipped(event_loop) -> None: # type: ig async def handler(_: BaseEvent) -> None: called["n"] += 1 - async def run() -> None: - await disp.dispatch(make_event()) - # Dispatch event with no handlers (different type) - # Reuse base event but fake type by replacing value - e = make_event() - e.event_type = EventType.EXECUTION_FAILED # type: ignore[attr-defined] - await disp.dispatch(e) - - event_loop.run_until_complete(run()) + await disp.dispatch(make_event()) + # Dispatch event with no handlers (different type) + # Reuse base event but fake type by replacing value + e = make_event() + e.event_type = EventType.EXECUTION_FAILED # type: ignore[attr-defined] + await disp.dispatch(e) metrics = disp.get_metrics() assert called["n"] == 1 diff --git a/backend/uv.lock b/backend/uv.lock index 5ee32591..ea8851e6 100644 --- a/backend/uv.lock +++ b/backend/uv.lock @@ -473,40 +473,76 @@ wheels = [ [[package]] name = "coverage" -version = "7.6.2" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/9a/60/e781e8302e7b28f21ce06e30af077f856aa2cb4cf2253287dae9a593d509/coverage-7.6.2.tar.gz", hash = "sha256:a5f81e68aa62bc0cfca04f7b19eaa8f9c826b53fc82ab9e2121976dc74f131f3", size = 797872, upload-time = "2024-10-09T11:33:30.113Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/3f/ac/1cca5ed5cf512a71cdd6e3afb75a5ef196f7ef9772be9192dadaaa5cfc1c/coverage-7.6.2-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:ebc94fadbd4a3f4215993326a6a00e47d79889391f5659bf310f55fe5d9f581c", size = 206856, upload-time = "2024-10-09T11:32:26.083Z" }, - { url = "https://files.pythonhosted.org/packages/e4/58/030354d250f107a95e7aca24c7fd238709a3c7df3083cb206368798e637a/coverage-7.6.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:9681516288e3dcf0aa7c26231178cc0be6cac9705cac06709f2353c5b406cfea", size = 207098, upload-time = "2024-10-09T11:32:28.303Z" }, - { url = "https://files.pythonhosted.org/packages/03/df/5f2cd6048d44a54bb5f58f8ece4efbc5b686ed49f8bd8dbf41eb2a6a687f/coverage-7.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d9c5d13927d77af4fbe453953810db766f75401e764727e73a6ee4f82527b3e", size = 240109, upload-time = "2024-10-09T11:32:29.451Z" }, - { url = "https://files.pythonhosted.org/packages/d3/18/7c53887643d921faa95529643b1b33e60ebba30ab835c8b5abd4e54d946b/coverage-7.6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b92f9ca04b3e719d69b02dc4a69debb795af84cb7afd09c5eb5d54b4a1ae2191", size = 237141, upload-time = "2024-10-09T11:32:31.276Z" }, - { url = "https://files.pythonhosted.org/packages/d2/79/339bdf597d128374e6150c089b37436ba694585d769cabf6d5abd73a1365/coverage-7.6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ff2ef83d6d0b527b5c9dad73819b24a2f76fdddcfd6c4e7a4d7e73ecb0656b4", size = 239210, upload-time = "2024-10-09T11:32:33.187Z" }, - { url = "https://files.pythonhosted.org/packages/a9/62/7310c6de2bcb8a42f91094d41f0d4793ccda5a54621be3db76a156556cf2/coverage-7.6.2-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:47ccb6e99a3031ffbbd6e7cc041e70770b4fe405370c66a54dbf26a500ded80b", size = 238698, upload-time = "2024-10-09T11:32:34.292Z" }, - { url = "https://files.pythonhosted.org/packages/f2/cb/ccb23c084d7f581f770dc7ed547dc5b50763334ad6ce26087a9ad0b5b26d/coverage-7.6.2-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a867d26f06bcd047ef716175b2696b315cb7571ccb951006d61ca80bbc356e9e", size = 237000, upload-time = "2024-10-09T11:32:36.737Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ab/58de9e2f94e4dc91b84d6e2705aa1e9d5447a2669fe113b4bbce6d2224a1/coverage-7.6.2-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:cdfcf2e914e2ba653101157458afd0ad92a16731eeba9a611b5cbb3e7124e74b", size = 238666, upload-time = "2024-10-09T11:32:38.027Z" }, - { url = "https://files.pythonhosted.org/packages/6c/dc/8be87b9ed5dbd4892b603f41088b41982768e928734e5bdce67d2ddd460a/coverage-7.6.2-cp312-cp312-win32.whl", hash = "sha256:f9035695dadfb397bee9eeaf1dc7fbeda483bf7664a7397a629846800ce6e276", size = 209489, upload-time = "2024-10-09T11:32:39.345Z" }, - { url = "https://files.pythonhosted.org/packages/64/3a/3f44e55273a58bfb39b87ad76541bbb81d14de916b034fdb39971cc99ffe/coverage-7.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:5ed69befa9a9fc796fe015a7040c9398722d6b97df73a6b608e9e275fa0932b0", size = 210270, upload-time = "2024-10-09T11:32:40.569Z" }, - { url = "https://files.pythonhosted.org/packages/ae/99/c9676a75b57438a19c5174dfcf39798b42728ad56650497286379dc0c2c3/coverage-7.6.2-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:4eea60c79d36a8f39475b1af887663bc3ae4f31289cd216f514ce18d5938df40", size = 206888, upload-time = "2024-10-09T11:32:42.417Z" }, - { url = "https://files.pythonhosted.org/packages/e0/de/820ecb42e892049c5f384430e98b35b899da3451dd0cdb2f867baf26abfa/coverage-7.6.2-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:aa68a6cdbe1bc6793a9dbfc38302c11599bbe1837392ae9b1d238b9ef3dafcf1", size = 207142, upload-time = "2024-10-09T11:32:43.623Z" }, - { url = "https://files.pythonhosted.org/packages/dd/59/81fc7ad855d65eeb68fe9e7809cbb339946adb07be7ac32d3fc24dc17bd7/coverage-7.6.2-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3ec528ae69f0a139690fad6deac8a7d33629fa61ccce693fdd07ddf7e9931fba", size = 239658, upload-time = "2024-10-09T11:32:45.479Z" }, - { url = "https://files.pythonhosted.org/packages/cd/a7/865de3eb9e78ffbf7afd92f86d2580b18edfb6f0481bd3c39b205e05a762/coverage-7.6.2-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ed5ac02126f74d190fa2cc14a9eb2a5d9837d5863920fa472b02eb1595cdc925", size = 236802, upload-time = "2024-10-09T11:32:46.868Z" }, - { url = "https://files.pythonhosted.org/packages/36/94/3b8f3abf88b7c451f97fd14c98f536bcee364e74250d928d57cc97c38ddd/coverage-7.6.2-cp313-cp313-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21c0ea0d4db8a36b275cb6fb2437a3715697a4ba3cb7b918d3525cc75f726304", size = 238793, upload-time = "2024-10-09T11:32:48.095Z" }, - { url = "https://files.pythonhosted.org/packages/d5/4b/57f95e41a10525002f524f3dbd577a3a9871d67998f8a8eb192fe697dc7b/coverage-7.6.2-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:35a51598f29b2a19e26d0908bd196f771a9b1c5d9a07bf20be0adf28f1ad4f77", size = 238455, upload-time = "2024-10-09T11:32:50.784Z" }, - { url = "https://files.pythonhosted.org/packages/99/c9/9fbe5b841628e1d9030c8044844afef4f4735586289eb9237eeb5b97f0d7/coverage-7.6.2-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:c9192925acc33e146864b8cf037e2ed32a91fdf7644ae875f5d46cd2ef086a5f", size = 236538, upload-time = "2024-10-09T11:32:52.072Z" }, - { url = "https://files.pythonhosted.org/packages/43/0d/2200a0d447e30de94d48e4851c04d8dce37340815e7eda27457a7043c037/coverage-7.6.2-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:bf4eeecc9e10f5403ec06138978235af79c9a79af494eb6b1d60a50b49ed2869", size = 238383, upload-time = "2024-10-09T11:32:53.25Z" }, - { url = "https://files.pythonhosted.org/packages/ec/8a/106c66faafb4a87002b698769d6de3c4db0b6c29a7aeb72de13b893c333e/coverage-7.6.2-cp313-cp313-win32.whl", hash = "sha256:e4ee15b267d2dad3e8759ca441ad450c334f3733304c55210c2a44516e8d5530", size = 209551, upload-time = "2024-10-09T11:32:54.455Z" }, - { url = "https://files.pythonhosted.org/packages/c4/f5/1b39e2faaf5b9cc7eed568c444df5991ce7ff7138e2e735a6801be1bdadb/coverage-7.6.2-cp313-cp313-win_amd64.whl", hash = "sha256:c71965d1ced48bf97aab79fad56df82c566b4c498ffc09c2094605727c4b7e36", size = 210282, upload-time = "2024-10-09T11:32:55.661Z" }, - { url = "https://files.pythonhosted.org/packages/79/a3/8dd4e6c09f5286094cd6c7edb115b3fbf06ad8304d45431722a4e3bc2508/coverage-7.6.2-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:7571e8bbecc6ac066256f9de40365ff833553e2e0c0c004f4482facb131820ef", size = 207629, upload-time = "2024-10-09T11:32:57.543Z" }, - { url = "https://files.pythonhosted.org/packages/8e/db/a9aa7009bbdc570a235e1ac781c0a83aa323cac6db8f8f13c2127b110978/coverage-7.6.2-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:078a87519057dacb5d77e333f740708ec2a8f768655f1db07f8dfd28d7a005f0", size = 207902, upload-time = "2024-10-09T11:32:58.787Z" }, - { url = "https://files.pythonhosted.org/packages/54/08/d0962be62d4335599ca2ff3a48bb68c9bfb80df74e28ca689ff5f392087b/coverage-7.6.2-cp313-cp313t-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e5e92e3e84a8718d2de36cd8387459cba9a4508337b8c5f450ce42b87a9e760", size = 250617, upload-time = "2024-10-09T11:33:02.145Z" }, - { url = "https://files.pythonhosted.org/packages/a5/a2/158570aff1dd88b661a6c11281cbb190e8696e77798b4b2e47c74bfb2f39/coverage-7.6.2-cp313-cp313t-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ebabdf1c76593a09ee18c1a06cd3022919861365219ea3aca0247ededf6facd6", size = 246334, upload-time = "2024-10-09T11:33:03.943Z" }, - { url = "https://files.pythonhosted.org/packages/aa/fe/b00428cca325b6585ca77422e4f64d7d86a225b14664b98682ea501efb57/coverage-7.6.2-cp313-cp313t-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:12179eb0575b8900912711688e45474f04ab3934aaa7b624dea7b3c511ecc90f", size = 248692, upload-time = "2024-10-09T11:33:05.216Z" }, - { url = "https://files.pythonhosted.org/packages/30/21/0a15fefc13039450bc45e7159f3add92489f004555eb7dab9c7ad4365dd0/coverage-7.6.2-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:39d3b964abfe1519b9d313ab28abf1d02faea26cd14b27f5283849bf59479ff5", size = 248188, upload-time = "2024-10-09T11:33:07.139Z" }, - { url = "https://files.pythonhosted.org/packages/de/b8/5c093526046a8450a7a3d62ad09517cf38e638f6b3ee9433dd6a73360501/coverage-7.6.2-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:84c4315577f7cd511d6250ffd0f695c825efe729f4205c0340f7004eda51191f", size = 246072, upload-time = "2024-10-09T11:33:08.425Z" }, - { url = "https://files.pythonhosted.org/packages/1e/8b/542b607d2cff56e5a90a6948f5a9040b693761d2be2d3c3bf88957b02361/coverage-7.6.2-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:ff797320dcbff57caa6b2301c3913784a010e13b1f6cf4ab3f563f3c5e7919db", size = 247354, upload-time = "2024-10-09T11:33:09.719Z" }, - { url = "https://files.pythonhosted.org/packages/95/82/2e9111aa5e59f42b332d387f64e3205c2263518d1e660154d0c9fc54390e/coverage-7.6.2-cp313-cp313t-win32.whl", hash = "sha256:2b636a301e53964550e2f3094484fa5a96e699db318d65398cfba438c5c92171", size = 210194, upload-time = "2024-10-09T11:33:10.935Z" }, - { url = "https://files.pythonhosted.org/packages/9d/46/aabe4305cfc57cab4865f788ceceef746c422469720c32ed7a5b44e20f5e/coverage-7.6.2-cp313-cp313t-win_amd64.whl", hash = "sha256:d03a060ac1a08e10589c27d509bbdb35b65f2d7f3f8d81cf2fa199877c7bc58a", size = 211346, upload-time = "2024-10-09T11:33:12.889Z" }, +version = "7.13.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/b6/45/2c665ca77ec32ad67e25c77daf1cee28ee4558f3bc571cdbaf88a00b9f23/coverage-7.13.0.tar.gz", hash = "sha256:a394aa27f2d7ff9bc04cf703817773a59ad6dfbd577032e690f961d2460ee936", size = 820905, upload-time = "2025-12-08T13:14:38.055Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/9b/f1/2619559f17f31ba00fc40908efd1fbf1d0a5536eb75dc8341e7d660a08de/coverage-7.13.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:0b3d67d31383c4c68e19a88e28fc4c2e29517580f1b0ebec4a069d502ce1e0bf", size = 218274, upload-time = "2025-12-08T13:12:52.095Z" }, + { url = "https://files.pythonhosted.org/packages/2b/11/30d71ae5d6e949ff93b2a79a2c1b4822e00423116c5c6edfaeef37301396/coverage-7.13.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:581f086833d24a22c89ae0fe2142cfaa1c92c930adf637ddf122d55083fb5a0f", size = 218638, upload-time = "2025-12-08T13:12:53.418Z" }, + { url = "https://files.pythonhosted.org/packages/79/c2/fce80fc6ded8d77e53207489d6065d0fed75db8951457f9213776615e0f5/coverage-7.13.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0a3a30f0e257df382f5f9534d4ce3d4cf06eafaf5192beb1a7bd066cb10e78fb", size = 250129, upload-time = "2025-12-08T13:12:54.744Z" }, + { url = "https://files.pythonhosted.org/packages/5b/b6/51b5d1eb6fcbb9a1d5d6984e26cbe09018475c2922d554fd724dd0f056ee/coverage-7.13.0-cp312-cp312-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:583221913fbc8f53b88c42e8dbb8fca1d0f2e597cb190ce45916662b8b9d9621", size = 252885, upload-time = "2025-12-08T13:12:56.401Z" }, + { url = "https://files.pythonhosted.org/packages/0d/f8/972a5affea41de798691ab15d023d3530f9f56a72e12e243f35031846ff7/coverage-7.13.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:5f5d9bd30756fff3e7216491a0d6d520c448d5124d3d8e8f56446d6412499e74", size = 253974, upload-time = "2025-12-08T13:12:57.718Z" }, + { url = "https://files.pythonhosted.org/packages/8a/56/116513aee860b2c7968aa3506b0f59b22a959261d1dbf3aea7b4450a7520/coverage-7.13.0-cp312-cp312-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:a23e5a1f8b982d56fa64f8e442e037f6ce29322f1f9e6c2344cd9e9f4407ee57", size = 250538, upload-time = "2025-12-08T13:12:59.254Z" }, + { url = "https://files.pythonhosted.org/packages/d6/75/074476d64248fbadf16dfafbf93fdcede389ec821f74ca858d7c87d2a98c/coverage-7.13.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9b01c22bc74a7fb44066aaf765224c0d933ddf1f5047d6cdfe4795504a4493f8", size = 251912, upload-time = "2025-12-08T13:13:00.604Z" }, + { url = "https://files.pythonhosted.org/packages/f2/d2/aa4f8acd1f7c06024705c12609d8698c51b27e4d635d717cd1934c9668e2/coverage-7.13.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:898cce66d0836973f48dda4e3514d863d70142bdf6dfab932b9b6a90ea5b222d", size = 250054, upload-time = "2025-12-08T13:13:01.892Z" }, + { url = "https://files.pythonhosted.org/packages/19/98/8df9e1af6a493b03694a1e8070e024e7d2cdc77adedc225a35e616d505de/coverage-7.13.0-cp312-cp312-musllinux_1_2_riscv64.whl", hash = "sha256:3ab483ea0e251b5790c2aac03acde31bff0c736bf8a86829b89382b407cd1c3b", size = 249619, upload-time = "2025-12-08T13:13:03.236Z" }, + { url = "https://files.pythonhosted.org/packages/d8/71/f8679231f3353018ca66ef647fa6fe7b77e6bff7845be54ab84f86233363/coverage-7.13.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:1d84e91521c5e4cb6602fe11ece3e1de03b2760e14ae4fcf1a4b56fa3c801fcd", size = 251496, upload-time = "2025-12-08T13:13:04.511Z" }, + { url = "https://files.pythonhosted.org/packages/04/86/9cb406388034eaf3c606c22094edbbb82eea1fa9d20c0e9efadff20d0733/coverage-7.13.0-cp312-cp312-win32.whl", hash = "sha256:193c3887285eec1dbdb3f2bd7fbc351d570ca9c02ca756c3afbc71b3c98af6ef", size = 220808, upload-time = "2025-12-08T13:13:06.422Z" }, + { url = "https://files.pythonhosted.org/packages/1c/59/af483673df6455795daf5f447c2f81a3d2fcfc893a22b8ace983791f6f34/coverage-7.13.0-cp312-cp312-win_amd64.whl", hash = "sha256:4f3e223b2b2db5e0db0c2b97286aba0036ca000f06aca9b12112eaa9af3d92ae", size = 221616, upload-time = "2025-12-08T13:13:07.95Z" }, + { url = "https://files.pythonhosted.org/packages/64/b0/959d582572b30a6830398c60dd419c1965ca4b5fb38ac6b7093a0d50ca8d/coverage-7.13.0-cp312-cp312-win_arm64.whl", hash = "sha256:086cede306d96202e15a4b77ace8472e39d9f4e5f9fd92dd4fecdfb2313b2080", size = 220261, upload-time = "2025-12-08T13:13:09.581Z" }, + { url = "https://files.pythonhosted.org/packages/7c/cc/bce226595eb3bf7d13ccffe154c3c487a22222d87ff018525ab4dd2e9542/coverage-7.13.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:28ee1c96109974af104028a8ef57cec21447d42d0e937c0275329272e370ebcf", size = 218297, upload-time = "2025-12-08T13:13:10.977Z" }, + { url = "https://files.pythonhosted.org/packages/3b/9f/73c4d34600aae03447dff3d7ad1d0ac649856bfb87d1ca7d681cfc913f9e/coverage-7.13.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:d1e97353dcc5587b85986cda4ff3ec98081d7e84dd95e8b2a6d59820f0545f8a", size = 218673, upload-time = "2025-12-08T13:13:12.562Z" }, + { url = "https://files.pythonhosted.org/packages/63/ab/8fa097db361a1e8586535ae5073559e6229596b3489ec3ef2f5b38df8cb2/coverage-7.13.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:99acd4dfdfeb58e1937629eb1ab6ab0899b131f183ee5f23e0b5da5cba2fec74", size = 249652, upload-time = "2025-12-08T13:13:13.909Z" }, + { url = "https://files.pythonhosted.org/packages/90/3a/9bfd4de2ff191feb37ef9465855ca56a6f2f30a3bca172e474130731ac3d/coverage-7.13.0-cp313-cp313-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:ff45e0cd8451e293b63ced93161e189780baf444119391b3e7d25315060368a6", size = 252251, upload-time = "2025-12-08T13:13:15.553Z" }, + { url = "https://files.pythonhosted.org/packages/df/61/b5d8105f016e1b5874af0d7c67542da780ccd4a5f2244a433d3e20ceb1ad/coverage-7.13.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f4f72a85316d8e13234cafe0a9f81b40418ad7a082792fa4165bd7d45d96066b", size = 253492, upload-time = "2025-12-08T13:13:16.849Z" }, + { url = "https://files.pythonhosted.org/packages/f3/b8/0fad449981803cc47a4694768b99823fb23632150743f9c83af329bb6090/coverage-7.13.0-cp313-cp313-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:11c21557d0e0a5a38632cbbaca5f008723b26a89d70db6315523df6df77d6232", size = 249850, upload-time = "2025-12-08T13:13:18.142Z" }, + { url = "https://files.pythonhosted.org/packages/9a/e9/8d68337c3125014d918cf4327d5257553a710a2995a6a6de2ac77e5aa429/coverage-7.13.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:76541dc8d53715fb4f7a3a06b34b0dc6846e3c69bc6204c55653a85dd6220971", size = 251633, upload-time = "2025-12-08T13:13:19.56Z" }, + { url = "https://files.pythonhosted.org/packages/55/14/d4112ab26b3a1bc4b3c1295d8452dcf399ed25be4cf649002fb3e64b2d93/coverage-7.13.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:6e9e451dee940a86789134b6b0ffbe31c454ade3b849bb8a9d2cca2541a8e91d", size = 249586, upload-time = "2025-12-08T13:13:20.883Z" }, + { url = "https://files.pythonhosted.org/packages/2c/a9/22b0000186db663b0d82f86c2f1028099ae9ac202491685051e2a11a5218/coverage-7.13.0-cp313-cp313-musllinux_1_2_riscv64.whl", hash = "sha256:5c67dace46f361125e6b9cace8fe0b729ed8479f47e70c89b838d319375c8137", size = 249412, upload-time = "2025-12-08T13:13:22.22Z" }, + { url = "https://files.pythonhosted.org/packages/a1/2e/42d8e0d9e7527fba439acdc6ed24a2b97613b1dc85849b1dd935c2cffef0/coverage-7.13.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:f59883c643cb19630500f57016f76cfdcd6845ca8c5b5ea1f6e17f74c8e5f511", size = 251191, upload-time = "2025-12-08T13:13:23.899Z" }, + { url = "https://files.pythonhosted.org/packages/a4/af/8c7af92b1377fd8860536aadd58745119252aaaa71a5213e5a8e8007a9f5/coverage-7.13.0-cp313-cp313-win32.whl", hash = "sha256:58632b187be6f0be500f553be41e277712baa278147ecb7559983c6d9faf7ae1", size = 220829, upload-time = "2025-12-08T13:13:25.182Z" }, + { url = "https://files.pythonhosted.org/packages/58/f9/725e8bf16f343d33cbe076c75dc8370262e194ff10072c0608b8e5cf33a3/coverage-7.13.0-cp313-cp313-win_amd64.whl", hash = "sha256:73419b89f812f498aca53f757dd834919b48ce4799f9d5cad33ca0ae442bdb1a", size = 221640, upload-time = "2025-12-08T13:13:26.836Z" }, + { url = "https://files.pythonhosted.org/packages/8a/ff/e98311000aa6933cc79274e2b6b94a2fe0fe3434fca778eba82003675496/coverage-7.13.0-cp313-cp313-win_arm64.whl", hash = "sha256:eb76670874fdd6091eedcc856128ee48c41a9bbbb9c3f1c7c3cf169290e3ffd6", size = 220269, upload-time = "2025-12-08T13:13:28.116Z" }, + { url = "https://files.pythonhosted.org/packages/cf/cf/bbaa2e1275b300343ea865f7d424cc0a2e2a1df6925a070b2b2d5d765330/coverage-7.13.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:6e63ccc6e0ad8986386461c3c4b737540f20426e7ec932f42e030320896c311a", size = 218990, upload-time = "2025-12-08T13:13:29.463Z" }, + { url = "https://files.pythonhosted.org/packages/21/1d/82f0b3323b3d149d7672e7744c116e9c170f4957e0c42572f0366dbb4477/coverage-7.13.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:494f5459ffa1bd45e18558cd98710c36c0b8fbfa82a5eabcbe671d80ecffbfe8", size = 219340, upload-time = "2025-12-08T13:13:31.524Z" }, + { url = "https://files.pythonhosted.org/packages/fb/e3/fe3fd4702a3832a255f4d43013eacb0ef5fc155a5960ea9269d8696db28b/coverage-7.13.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:06cac81bf10f74034e055e903f5f946e3e26fc51c09fc9f584e4a1605d977053", size = 260638, upload-time = "2025-12-08T13:13:32.965Z" }, + { url = "https://files.pythonhosted.org/packages/ad/01/63186cb000307f2b4da463f72af9b85d380236965574c78e7e27680a2593/coverage-7.13.0-cp313-cp313t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f2ffc92b46ed6e6760f1d47a71e56b5664781bc68986dbd1836b2b70c0ce2071", size = 262705, upload-time = "2025-12-08T13:13:34.378Z" }, + { url = "https://files.pythonhosted.org/packages/7c/a1/c0dacef0cc865f2455d59eed3548573ce47ed603205ffd0735d1d78b5906/coverage-7.13.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:0602f701057c6823e5db1b74530ce85f17c3c5be5c85fc042ac939cbd909426e", size = 265125, upload-time = "2025-12-08T13:13:35.73Z" }, + { url = "https://files.pythonhosted.org/packages/ef/92/82b99223628b61300bd382c205795533bed021505eab6dd86e11fb5d7925/coverage-7.13.0-cp313-cp313t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:25dc33618d45456ccb1d37bce44bc78cf269909aa14c4db2e03d63146a8a1493", size = 259844, upload-time = "2025-12-08T13:13:37.69Z" }, + { url = "https://files.pythonhosted.org/packages/cf/2c/89b0291ae4e6cd59ef042708e1c438e2290f8c31959a20055d8768349ee2/coverage-7.13.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:71936a8b3b977ddd0b694c28c6a34f4fff2e9dd201969a4ff5d5fc7742d614b0", size = 262700, upload-time = "2025-12-08T13:13:39.525Z" }, + { url = "https://files.pythonhosted.org/packages/bf/f9/a5f992efae1996245e796bae34ceb942b05db275e4b34222a9a40b9fbd3b/coverage-7.13.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:936bc20503ce24770c71938d1369461f0c5320830800933bc3956e2a4ded930e", size = 260321, upload-time = "2025-12-08T13:13:41.172Z" }, + { url = "https://files.pythonhosted.org/packages/4c/89/a29f5d98c64fedbe32e2ac3c227fbf78edc01cc7572eee17d61024d89889/coverage-7.13.0-cp313-cp313t-musllinux_1_2_riscv64.whl", hash = "sha256:af0a583efaacc52ae2521f8d7910aff65cdb093091d76291ac5820d5e947fc1c", size = 259222, upload-time = "2025-12-08T13:13:43.282Z" }, + { url = "https://files.pythonhosted.org/packages/b3/c3/940fe447aae302a6701ee51e53af7e08b86ff6eed7631e5740c157ee22b9/coverage-7.13.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f1c23e24a7000da892a312fb17e33c5f94f8b001de44b7cf8ba2e36fbd15859e", size = 261411, upload-time = "2025-12-08T13:13:44.72Z" }, + { url = "https://files.pythonhosted.org/packages/eb/31/12a4aec689cb942a89129587860ed4d0fd522d5fda81237147fde554b8ae/coverage-7.13.0-cp313-cp313t-win32.whl", hash = "sha256:5f8a0297355e652001015e93be345ee54393e45dc3050af4a0475c5a2b767d46", size = 221505, upload-time = "2025-12-08T13:13:46.332Z" }, + { url = "https://files.pythonhosted.org/packages/65/8c/3b5fe3259d863572d2b0827642c50c3855d26b3aefe80bdc9eba1f0af3b0/coverage-7.13.0-cp313-cp313t-win_amd64.whl", hash = "sha256:6abb3a4c52f05e08460bd9acf04fec027f8718ecaa0d09c40ffbc3fbd70ecc39", size = 222569, upload-time = "2025-12-08T13:13:47.79Z" }, + { url = "https://files.pythonhosted.org/packages/b0/39/f71fa8316a96ac72fc3908839df651e8eccee650001a17f2c78cdb355624/coverage-7.13.0-cp313-cp313t-win_arm64.whl", hash = "sha256:3ad968d1e3aa6ce5be295ab5fe3ae1bf5bb4769d0f98a80a0252d543a2ef2e9e", size = 220841, upload-time = "2025-12-08T13:13:49.243Z" }, + { url = "https://files.pythonhosted.org/packages/f8/4b/9b54bedda55421449811dcd5263a2798a63f48896c24dfb92b0f1b0845bd/coverage-7.13.0-cp314-cp314-macosx_10_15_x86_64.whl", hash = "sha256:453b7ec753cf5e4356e14fe858064e5520c460d3bbbcb9c35e55c0d21155c256", size = 218343, upload-time = "2025-12-08T13:13:50.811Z" }, + { url = "https://files.pythonhosted.org/packages/59/df/c3a1f34d4bba2e592c8979f924da4d3d4598b0df2392fbddb7761258e3dc/coverage-7.13.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:af827b7cbb303e1befa6c4f94fd2bf72f108089cfa0f8abab8f4ca553cf5ca5a", size = 218672, upload-time = "2025-12-08T13:13:52.284Z" }, + { url = "https://files.pythonhosted.org/packages/07/62/eec0659e47857698645ff4e6ad02e30186eb8afd65214fd43f02a76537cb/coverage-7.13.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:9987a9e4f8197a1000280f7cc089e3ea2c8b3c0a64d750537809879a7b4ceaf9", size = 249715, upload-time = "2025-12-08T13:13:53.791Z" }, + { url = "https://files.pythonhosted.org/packages/23/2d/3c7ff8b2e0e634c1f58d095f071f52ed3c23ff25be524b0ccae8b71f99f8/coverage-7.13.0-cp314-cp314-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:3188936845cd0cb114fa6a51842a304cdbac2958145d03be2377ec41eb285d19", size = 252225, upload-time = "2025-12-08T13:13:55.274Z" }, + { url = "https://files.pythonhosted.org/packages/aa/ac/fb03b469d20e9c9a81093575003f959cf91a4a517b783aab090e4538764b/coverage-7.13.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a2bdb3babb74079f021696cb46b8bb5f5661165c385d3a238712b031a12355be", size = 253559, upload-time = "2025-12-08T13:13:57.161Z" }, + { url = "https://files.pythonhosted.org/packages/29/62/14afa9e792383c66cc0a3b872a06ded6e4ed1079c7d35de274f11d27064e/coverage-7.13.0-cp314-cp314-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:7464663eaca6adba4175f6c19354feea61ebbdd735563a03d1e472c7072d27bb", size = 249724, upload-time = "2025-12-08T13:13:58.692Z" }, + { url = "https://files.pythonhosted.org/packages/31/b7/333f3dab2939070613696ab3ee91738950f0467778c6e5a5052e840646b7/coverage-7.13.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:8069e831f205d2ff1f3d355e82f511eb7c5522d7d413f5db5756b772ec8697f8", size = 251582, upload-time = "2025-12-08T13:14:00.642Z" }, + { url = "https://files.pythonhosted.org/packages/81/cb/69162bda9381f39b2287265d7e29ee770f7c27c19f470164350a38318764/coverage-7.13.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:6fb2d5d272341565f08e962cce14cdf843a08ac43bd621783527adb06b089c4b", size = 249538, upload-time = "2025-12-08T13:14:02.556Z" }, + { url = "https://files.pythonhosted.org/packages/e0/76/350387b56a30f4970abe32b90b2a434f87d29f8b7d4ae40d2e8a85aacfb3/coverage-7.13.0-cp314-cp314-musllinux_1_2_riscv64.whl", hash = "sha256:5e70f92ef89bac1ac8a99b3324923b4749f008fdbd7aa9cb35e01d7a284a04f9", size = 249349, upload-time = "2025-12-08T13:14:04.015Z" }, + { url = "https://files.pythonhosted.org/packages/86/0d/7f6c42b8d59f4c7e43ea3059f573c0dcfed98ba46eb43c68c69e52ae095c/coverage-7.13.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:4b5de7d4583e60d5fd246dd57fcd3a8aa23c6e118a8c72b38adf666ba8e7e927", size = 251011, upload-time = "2025-12-08T13:14:05.505Z" }, + { url = "https://files.pythonhosted.org/packages/d7/f1/4bb2dff379721bb0b5c649d5c5eaf438462cad824acf32eb1b7ca0c7078e/coverage-7.13.0-cp314-cp314-win32.whl", hash = "sha256:a6c6e16b663be828a8f0b6c5027d36471d4a9f90d28444aa4ced4d48d7d6ae8f", size = 221091, upload-time = "2025-12-08T13:14:07.127Z" }, + { url = "https://files.pythonhosted.org/packages/ba/44/c239da52f373ce379c194b0ee3bcc121020e397242b85f99e0afc8615066/coverage-7.13.0-cp314-cp314-win_amd64.whl", hash = "sha256:0900872f2fdb3ee5646b557918d02279dc3af3dfb39029ac4e945458b13f73bc", size = 221904, upload-time = "2025-12-08T13:14:08.542Z" }, + { url = "https://files.pythonhosted.org/packages/89/1f/b9f04016d2a29c2e4a0307baefefad1a4ec5724946a2b3e482690486cade/coverage-7.13.0-cp314-cp314-win_arm64.whl", hash = "sha256:3a10260e6a152e5f03f26db4a407c4c62d3830b9af9b7c0450b183615f05d43b", size = 220480, upload-time = "2025-12-08T13:14:10.958Z" }, + { url = "https://files.pythonhosted.org/packages/16/d4/364a1439766c8e8647860584171c36010ca3226e6e45b1753b1b249c5161/coverage-7.13.0-cp314-cp314t-macosx_10_15_x86_64.whl", hash = "sha256:9097818b6cc1cfb5f174e3263eba4a62a17683bcfe5c4b5d07f4c97fa51fbf28", size = 219074, upload-time = "2025-12-08T13:14:13.345Z" }, + { url = "https://files.pythonhosted.org/packages/ce/f4/71ba8be63351e099911051b2089662c03d5671437a0ec2171823c8e03bec/coverage-7.13.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:0018f73dfb4301a89292c73be6ba5f58722ff79f51593352759c1790ded1cabe", size = 219342, upload-time = "2025-12-08T13:14:15.02Z" }, + { url = "https://files.pythonhosted.org/packages/5e/25/127d8ed03d7711a387d96f132589057213e3aef7475afdaa303412463f22/coverage-7.13.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:166ad2a22ee770f5656e1257703139d3533b4a0b6909af67c6b4a3adc1c98657", size = 260713, upload-time = "2025-12-08T13:14:16.907Z" }, + { url = "https://files.pythonhosted.org/packages/fd/db/559fbb6def07d25b2243663b46ba9eb5a3c6586c0c6f4e62980a68f0ee1c/coverage-7.13.0-cp314-cp314t-manylinux1_x86_64.manylinux_2_28_x86_64.manylinux_2_5_x86_64.whl", hash = "sha256:f6aaef16d65d1787280943f1c8718dc32e9cf141014e4634d64446702d26e0ff", size = 262825, upload-time = "2025-12-08T13:14:18.68Z" }, + { url = "https://files.pythonhosted.org/packages/37/99/6ee5bf7eff884766edb43bd8736b5e1c5144d0fe47498c3779326fe75a35/coverage-7.13.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e999e2dcc094002d6e2c7bbc1fb85b58ba4f465a760a8014d97619330cdbbbf3", size = 265233, upload-time = "2025-12-08T13:14:20.55Z" }, + { url = "https://files.pythonhosted.org/packages/d8/90/92f18fe0356ea69e1f98f688ed80cec39f44e9f09a1f26a1bbf017cc67f2/coverage-7.13.0-cp314-cp314t-manylinux_2_31_riscv64.manylinux_2_39_riscv64.whl", hash = "sha256:00c3d22cf6fb1cf3bf662aaaa4e563be8243a5ed2630339069799835a9cc7f9b", size = 259779, upload-time = "2025-12-08T13:14:22.367Z" }, + { url = "https://files.pythonhosted.org/packages/90/5d/b312a8b45b37a42ea7d27d7d3ff98ade3a6c892dd48d1d503e773503373f/coverage-7.13.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:22ccfe8d9bb0d6134892cbe1262493a8c70d736b9df930f3f3afae0fe3ac924d", size = 262700, upload-time = "2025-12-08T13:14:24.309Z" }, + { url = "https://files.pythonhosted.org/packages/63/f8/b1d0de5c39351eb71c366f872376d09386640840a2e09b0d03973d791e20/coverage-7.13.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:9372dff5ea15930fea0445eaf37bbbafbc771a49e70c0aeed8b4e2c2614cc00e", size = 260302, upload-time = "2025-12-08T13:14:26.068Z" }, + { url = "https://files.pythonhosted.org/packages/aa/7c/d42f4435bc40c55558b3109a39e2d456cddcec37434f62a1f1230991667a/coverage-7.13.0-cp314-cp314t-musllinux_1_2_riscv64.whl", hash = "sha256:69ac2c492918c2461bc6ace42d0479638e60719f2a4ef3f0815fa2df88e9f940", size = 259136, upload-time = "2025-12-08T13:14:27.604Z" }, + { url = "https://files.pythonhosted.org/packages/b8/d3/23413241dc04d47cfe19b9a65b32a2edd67ecd0b817400c2843ebc58c847/coverage-7.13.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:739c6c051a7540608d097b8e13c76cfa85263ced467168dc6b477bae3df7d0e2", size = 261467, upload-time = "2025-12-08T13:14:29.09Z" }, + { url = "https://files.pythonhosted.org/packages/13/e6/6e063174500eee216b96272c0d1847bf215926786f85c2bd024cf4d02d2f/coverage-7.13.0-cp314-cp314t-win32.whl", hash = "sha256:fe81055d8c6c9de76d60c94ddea73c290b416e061d40d542b24a5871bad498b7", size = 221875, upload-time = "2025-12-08T13:14:31.106Z" }, + { url = "https://files.pythonhosted.org/packages/3b/46/f4fb293e4cbe3620e3ac2a3e8fd566ed33affb5861a9b20e3dd6c1896cbc/coverage-7.13.0-cp314-cp314t-win_amd64.whl", hash = "sha256:445badb539005283825959ac9fa4a28f712c214b65af3a2c464f1adc90f5fcbc", size = 222982, upload-time = "2025-12-08T13:14:33.1Z" }, + { url = "https://files.pythonhosted.org/packages/68/62/5b3b9018215ed9733fbd1ae3b2ed75c5de62c3b55377a52cae732e1b7805/coverage-7.13.0-cp314-cp314t-win_arm64.whl", hash = "sha256:de7f6748b890708578fc4b7bb967d810aeb6fcc9bff4bb77dbca77dab2f9df6a", size = 221016, upload-time = "2025-12-08T13:14:34.601Z" }, + { url = "https://files.pythonhosted.org/packages/8d/4c/1968f32fb9a2604645827e11ff84a31e59d532e01995f904723b4f5328b3/coverage-7.13.0-py3-none-any.whl", hash = "sha256:850d2998f380b1e266459ca5b47bc9e7daf9af1d070f66317972f382d46f1904", size = 210068, upload-time = "2025-12-08T13:14:36.236Z" }, ] [[package]] @@ -1128,7 +1164,7 @@ requires-dist = [ { name = "mdurl", specifier = "==0.1.2" }, { name = "motor", specifier = "==3.6.0" }, { name = "msgpack", specifier = "==1.1.0" }, - { name = "multidict", specifier = "==6.6.3" }, + { name = "multidict", specifier = "==6.7.0" }, { name = "oauthlib", specifier = "==3.2.2" }, { name = "opentelemetry-api", specifier = "==1.22.0" }, { name = "opentelemetry-exporter-otlp", specifier = "==1.22.0" }, @@ -1172,7 +1208,7 @@ requires-dist = [ { name = "python-multipart", specifier = "==0.0.18" }, { name = "pyyaml", specifier = "==6.0.2" }, { name = "pyzmq", specifier = "==26.2.0" }, - { name = "redis", specifier = "==5.2.1" }, + { name = "redis", specifier = "==7.1.0" }, { name = "regex", specifier = "==2025.8.29" }, { name = "requests", specifier = "==2.32.3" }, { name = "requests-oauthlib", specifier = "==2.0.0" }, @@ -1198,7 +1234,7 @@ requires-dist = [ [package.metadata.requires-dev] dev = [ - { name = "coverage", specifier = "==7.6.2" }, + { name = "coverage", specifier = "==7.13.0" }, { name = "hypothesis", specifier = "==6.103.4" }, { name = "iniconfig", specifier = "==2.0.0" }, { name = "matplotlib", specifier = "==3.9.2" }, @@ -1207,10 +1243,10 @@ dev = [ { name = "pipdeptree", specifier = "==2.23.4" }, { name = "pluggy", specifier = "==1.5.0" }, { name = "pytest", specifier = "==8.3.3" }, - { name = "pytest-asyncio", specifier = "==0.24.0" }, + { name = "pytest-asyncio", specifier = "==1.3.0" }, { name = "pytest-cov", specifier = "==5.0.0" }, { name = "pytest-xdist", specifier = "==3.6.1" }, - { name = "ruff", specifier = "==0.12.7" }, + { name = "ruff", specifier = "==0.14.9" }, { name = "types-cachetools", specifier = "==6.2.0.20250827" }, { name = "types-confluent-kafka", specifier = "==1.3.6" }, ] @@ -1484,65 +1520,101 @@ wheels = [ [[package]] name = "multidict" -version = "6.6.3" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/3d/2c/5dad12e82fbdf7470f29bff2171484bf07cb3b16ada60a6589af8f376440/multidict-6.6.3.tar.gz", hash = "sha256:798a9eb12dab0a6c2e29c1de6f3468af5cb2da6053a20dfa3344907eed0937cc", size = 101006, upload-time = "2025-06-30T15:53:46.929Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/0e/a0/6b57988ea102da0623ea814160ed78d45a2645e4bbb499c2896d12833a70/multidict-6.6.3-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:056bebbeda16b2e38642d75e9e5310c484b7c24e3841dc0fb943206a72ec89d6", size = 76514, upload-time = "2025-06-30T15:51:48.728Z" }, - { url = "https://files.pythonhosted.org/packages/07/7a/d1e92665b0850c6c0508f101f9cf0410c1afa24973e1115fe9c6a185ebf7/multidict-6.6.3-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:e5f481cccb3c5c5e5de5d00b5141dc589c1047e60d07e85bbd7dea3d4580d63f", size = 45394, upload-time = "2025-06-30T15:51:49.986Z" }, - { url = "https://files.pythonhosted.org/packages/52/6f/dd104490e01be6ef8bf9573705d8572f8c2d2c561f06e3826b081d9e6591/multidict-6.6.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:10bea2ee839a759ee368b5a6e47787f399b41e70cf0c20d90dfaf4158dfb4e55", size = 43590, upload-time = "2025-06-30T15:51:51.331Z" }, - { url = "https://files.pythonhosted.org/packages/44/fe/06e0e01b1b0611e6581b7fd5a85b43dacc08b6cea3034f902f383b0873e5/multidict-6.6.3-cp312-cp312-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:2334cfb0fa9549d6ce2c21af2bfbcd3ac4ec3646b1b1581c88e3e2b1779ec92b", size = 237292, upload-time = "2025-06-30T15:51:52.584Z" }, - { url = "https://files.pythonhosted.org/packages/ce/71/4f0e558fb77696b89c233c1ee2d92f3e1d5459070a0e89153c9e9e804186/multidict-6.6.3-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b8fee016722550a2276ca2cb5bb624480e0ed2bd49125b2b73b7010b9090e888", size = 258385, upload-time = "2025-06-30T15:51:53.913Z" }, - { url = "https://files.pythonhosted.org/packages/e3/25/cca0e68228addad24903801ed1ab42e21307a1b4b6dd2cf63da5d3ae082a/multidict-6.6.3-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:e5511cb35f5c50a2db21047c875eb42f308c5583edf96bd8ebf7d770a9d68f6d", size = 242328, upload-time = "2025-06-30T15:51:55.672Z" }, - { url = "https://files.pythonhosted.org/packages/6e/a3/46f2d420d86bbcb8fe660b26a10a219871a0fbf4d43cb846a4031533f3e0/multidict-6.6.3-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:712b348f7f449948e0a6c4564a21c7db965af900973a67db432d724619b3c680", size = 268057, upload-time = "2025-06-30T15:51:57.037Z" }, - { url = "https://files.pythonhosted.org/packages/9e/73/1c743542fe00794a2ec7466abd3f312ccb8fad8dff9f36d42e18fb1ec33e/multidict-6.6.3-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e4e15d2138ee2694e038e33b7c3da70e6b0ad8868b9f8094a72e1414aeda9c1a", size = 269341, upload-time = "2025-06-30T15:51:59.111Z" }, - { url = "https://files.pythonhosted.org/packages/a4/11/6ec9dcbe2264b92778eeb85407d1df18812248bf3506a5a1754bc035db0c/multidict-6.6.3-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:8df25594989aebff8a130f7899fa03cbfcc5d2b5f4a461cf2518236fe6f15961", size = 256081, upload-time = "2025-06-30T15:52:00.533Z" }, - { url = "https://files.pythonhosted.org/packages/9b/2b/631b1e2afeb5f1696846d747d36cda075bfdc0bc7245d6ba5c319278d6c4/multidict-6.6.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:159ca68bfd284a8860f8d8112cf0521113bffd9c17568579e4d13d1f1dc76b65", size = 253581, upload-time = "2025-06-30T15:52:02.43Z" }, - { url = "https://files.pythonhosted.org/packages/bf/0e/7e3b93f79efeb6111d3bf9a1a69e555ba1d07ad1c11bceb56b7310d0d7ee/multidict-6.6.3-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:e098c17856a8c9ade81b4810888c5ad1914099657226283cab3062c0540b0643", size = 250750, upload-time = "2025-06-30T15:52:04.26Z" }, - { url = "https://files.pythonhosted.org/packages/ad/9e/086846c1d6601948e7de556ee464a2d4c85e33883e749f46b9547d7b0704/multidict-6.6.3-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:67c92ed673049dec52d7ed39f8cf9ebbadf5032c774058b4406d18c8f8fe7063", size = 251548, upload-time = "2025-06-30T15:52:06.002Z" }, - { url = "https://files.pythonhosted.org/packages/8c/7b/86ec260118e522f1a31550e87b23542294880c97cfbf6fb18cc67b044c66/multidict-6.6.3-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:bd0578596e3a835ef451784053cfd327d607fc39ea1a14812139339a18a0dbc3", size = 262718, upload-time = "2025-06-30T15:52:07.707Z" }, - { url = "https://files.pythonhosted.org/packages/8c/bd/22ce8f47abb0be04692c9fc4638508b8340987b18691aa7775d927b73f72/multidict-6.6.3-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:346055630a2df2115cd23ae271910b4cae40f4e336773550dca4889b12916e75", size = 259603, upload-time = "2025-06-30T15:52:09.58Z" }, - { url = "https://files.pythonhosted.org/packages/07/9c/91b7ac1691be95cd1f4a26e36a74b97cda6aa9820632d31aab4410f46ebd/multidict-6.6.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:555ff55a359302b79de97e0468e9ee80637b0de1fce77721639f7cd9440b3a10", size = 251351, upload-time = "2025-06-30T15:52:10.947Z" }, - { url = "https://files.pythonhosted.org/packages/6f/5c/4d7adc739884f7a9fbe00d1eac8c034023ef8bad71f2ebe12823ca2e3649/multidict-6.6.3-cp312-cp312-win32.whl", hash = "sha256:73ab034fb8d58ff85c2bcbadc470efc3fafeea8affcf8722855fb94557f14cc5", size = 41860, upload-time = "2025-06-30T15:52:12.334Z" }, - { url = "https://files.pythonhosted.org/packages/6a/a3/0fbc7afdf7cb1aa12a086b02959307848eb6bcc8f66fcb66c0cb57e2a2c1/multidict-6.6.3-cp312-cp312-win_amd64.whl", hash = "sha256:04cbcce84f63b9af41bad04a54d4cc4e60e90c35b9e6ccb130be2d75b71f8c17", size = 45982, upload-time = "2025-06-30T15:52:13.6Z" }, - { url = "https://files.pythonhosted.org/packages/b8/95/8c825bd70ff9b02462dc18d1295dd08d3e9e4eb66856d292ffa62cfe1920/multidict-6.6.3-cp312-cp312-win_arm64.whl", hash = "sha256:0f1130b896ecb52d2a1e615260f3ea2af55fa7dc3d7c3003ba0c3121a759b18b", size = 43210, upload-time = "2025-06-30T15:52:14.893Z" }, - { url = "https://files.pythonhosted.org/packages/52/1d/0bebcbbb4f000751fbd09957257903d6e002943fc668d841a4cf2fb7f872/multidict-6.6.3-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:540d3c06d48507357a7d57721e5094b4f7093399a0106c211f33540fdc374d55", size = 75843, upload-time = "2025-06-30T15:52:16.155Z" }, - { url = "https://files.pythonhosted.org/packages/07/8f/cbe241b0434cfe257f65c2b1bcf9e8d5fb52bc708c5061fb29b0fed22bdf/multidict-6.6.3-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:9c19cea2a690f04247d43f366d03e4eb110a0dc4cd1bbeee4d445435428ed35b", size = 45053, upload-time = "2025-06-30T15:52:17.429Z" }, - { url = "https://files.pythonhosted.org/packages/32/d2/0b3b23f9dbad5b270b22a3ac3ea73ed0a50ef2d9a390447061178ed6bdb8/multidict-6.6.3-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:7af039820cfd00effec86bda5d8debef711a3e86a1d3772e85bea0f243a4bd65", size = 43273, upload-time = "2025-06-30T15:52:19.346Z" }, - { url = "https://files.pythonhosted.org/packages/fd/fe/6eb68927e823999e3683bc49678eb20374ba9615097d085298fd5b386564/multidict-6.6.3-cp313-cp313-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:500b84f51654fdc3944e936f2922114349bf8fdcac77c3092b03449f0e5bc2b3", size = 237124, upload-time = "2025-06-30T15:52:20.773Z" }, - { url = "https://files.pythonhosted.org/packages/e7/ab/320d8507e7726c460cb77117848b3834ea0d59e769f36fdae495f7669929/multidict-6.6.3-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:f3fc723ab8a5c5ed6c50418e9bfcd8e6dceba6c271cee6728a10a4ed8561520c", size = 256892, upload-time = "2025-06-30T15:52:22.242Z" }, - { url = "https://files.pythonhosted.org/packages/76/60/38ee422db515ac69834e60142a1a69111ac96026e76e8e9aa347fd2e4591/multidict-6.6.3-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:94c47ea3ade005b5976789baaed66d4de4480d0a0bf31cef6edaa41c1e7b56a6", size = 240547, upload-time = "2025-06-30T15:52:23.736Z" }, - { url = "https://files.pythonhosted.org/packages/27/fb/905224fde2dff042b030c27ad95a7ae744325cf54b890b443d30a789b80e/multidict-6.6.3-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:dbc7cf464cc6d67e83e136c9f55726da3a30176f020a36ead246eceed87f1cd8", size = 266223, upload-time = "2025-06-30T15:52:25.185Z" }, - { url = "https://files.pythonhosted.org/packages/76/35/dc38ab361051beae08d1a53965e3e1a418752fc5be4d3fb983c5582d8784/multidict-6.6.3-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:900eb9f9da25ada070f8ee4a23f884e0ee66fe4e1a38c3af644256a508ad81ca", size = 267262, upload-time = "2025-06-30T15:52:26.969Z" }, - { url = "https://files.pythonhosted.org/packages/1f/a3/0a485b7f36e422421b17e2bbb5a81c1af10eac1d4476f2ff92927c730479/multidict-6.6.3-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:7c6df517cf177da5d47ab15407143a89cd1a23f8b335f3a28d57e8b0a3dbb884", size = 254345, upload-time = "2025-06-30T15:52:28.467Z" }, - { url = "https://files.pythonhosted.org/packages/b4/59/bcdd52c1dab7c0e0d75ff19cac751fbd5f850d1fc39172ce809a74aa9ea4/multidict-6.6.3-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:4ef421045f13879e21c994b36e728d8e7d126c91a64b9185810ab51d474f27e7", size = 252248, upload-time = "2025-06-30T15:52:29.938Z" }, - { url = "https://files.pythonhosted.org/packages/bb/a4/2d96aaa6eae8067ce108d4acee6f45ced5728beda55c0f02ae1072c730d1/multidict-6.6.3-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:6c1e61bb4f80895c081790b6b09fa49e13566df8fbff817da3f85b3a8192e36b", size = 250115, upload-time = "2025-06-30T15:52:31.416Z" }, - { url = "https://files.pythonhosted.org/packages/25/d2/ed9f847fa5c7d0677d4f02ea2c163d5e48573de3f57bacf5670e43a5ffaa/multidict-6.6.3-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:e5e8523bb12d7623cd8300dbd91b9e439a46a028cd078ca695eb66ba31adee3c", size = 249649, upload-time = "2025-06-30T15:52:32.996Z" }, - { url = "https://files.pythonhosted.org/packages/1f/af/9155850372563fc550803d3f25373308aa70f59b52cff25854086ecb4a79/multidict-6.6.3-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:ef58340cc896219e4e653dade08fea5c55c6df41bcc68122e3be3e9d873d9a7b", size = 261203, upload-time = "2025-06-30T15:52:34.521Z" }, - { url = "https://files.pythonhosted.org/packages/36/2f/c6a728f699896252cf309769089568a33c6439626648843f78743660709d/multidict-6.6.3-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:fc9dc435ec8699e7b602b94fe0cd4703e69273a01cbc34409af29e7820f777f1", size = 258051, upload-time = "2025-06-30T15:52:35.999Z" }, - { url = "https://files.pythonhosted.org/packages/d0/60/689880776d6b18fa2b70f6cc74ff87dd6c6b9b47bd9cf74c16fecfaa6ad9/multidict-6.6.3-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:9e864486ef4ab07db5e9cb997bad2b681514158d6954dd1958dfb163b83d53e6", size = 249601, upload-time = "2025-06-30T15:52:37.473Z" }, - { url = "https://files.pythonhosted.org/packages/75/5e/325b11f2222a549019cf2ef879c1f81f94a0d40ace3ef55cf529915ba6cc/multidict-6.6.3-cp313-cp313-win32.whl", hash = "sha256:5633a82fba8e841bc5c5c06b16e21529573cd654f67fd833650a215520a6210e", size = 41683, upload-time = "2025-06-30T15:52:38.927Z" }, - { url = "https://files.pythonhosted.org/packages/b1/ad/cf46e73f5d6e3c775cabd2a05976547f3f18b39bee06260369a42501f053/multidict-6.6.3-cp313-cp313-win_amd64.whl", hash = "sha256:e93089c1570a4ad54c3714a12c2cef549dc9d58e97bcded193d928649cab78e9", size = 45811, upload-time = "2025-06-30T15:52:40.207Z" }, - { url = "https://files.pythonhosted.org/packages/c5/c9/2e3fe950db28fb7c62e1a5f46e1e38759b072e2089209bc033c2798bb5ec/multidict-6.6.3-cp313-cp313-win_arm64.whl", hash = "sha256:c60b401f192e79caec61f166da9c924e9f8bc65548d4246842df91651e83d600", size = 43056, upload-time = "2025-06-30T15:52:41.575Z" }, - { url = "https://files.pythonhosted.org/packages/3a/58/aaf8114cf34966e084a8cc9517771288adb53465188843d5a19862cb6dc3/multidict-6.6.3-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:02fd8f32d403a6ff13864b0851f1f523d4c988051eea0471d4f1fd8010f11134", size = 82811, upload-time = "2025-06-30T15:52:43.281Z" }, - { url = "https://files.pythonhosted.org/packages/71/af/5402e7b58a1f5b987a07ad98f2501fdba2a4f4b4c30cf114e3ce8db64c87/multidict-6.6.3-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:f3aa090106b1543f3f87b2041eef3c156c8da2aed90c63a2fbed62d875c49c37", size = 48304, upload-time = "2025-06-30T15:52:45.026Z" }, - { url = "https://files.pythonhosted.org/packages/39/65/ab3c8cafe21adb45b24a50266fd747147dec7847425bc2a0f6934b3ae9ce/multidict-6.6.3-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:e924fb978615a5e33ff644cc42e6aa241effcf4f3322c09d4f8cebde95aff5f8", size = 46775, upload-time = "2025-06-30T15:52:46.459Z" }, - { url = "https://files.pythonhosted.org/packages/49/ba/9fcc1b332f67cc0c0c8079e263bfab6660f87fe4e28a35921771ff3eea0d/multidict-6.6.3-cp313-cp313t-manylinux1_i686.manylinux2014_i686.manylinux_2_17_i686.manylinux_2_5_i686.whl", hash = "sha256:b9fe5a0e57c6dbd0e2ce81ca66272282c32cd11d31658ee9553849d91289e1c1", size = 229773, upload-time = "2025-06-30T15:52:47.88Z" }, - { url = "https://files.pythonhosted.org/packages/a4/14/0145a251f555f7c754ce2dcbcd012939bbd1f34f066fa5d28a50e722a054/multidict-6.6.3-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b24576f208793ebae00280c59927c3b7c2a3b1655e443a25f753c4611bc1c373", size = 250083, upload-time = "2025-06-30T15:52:49.366Z" }, - { url = "https://files.pythonhosted.org/packages/9e/d4/d5c0bd2bbb173b586c249a151a26d2fb3ec7d53c96e42091c9fef4e1f10c/multidict-6.6.3-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:135631cb6c58eac37d7ac0df380294fecdc026b28837fa07c02e459c7fb9c54e", size = 228980, upload-time = "2025-06-30T15:52:50.903Z" }, - { url = "https://files.pythonhosted.org/packages/21/32/c9a2d8444a50ec48c4733ccc67254100c10e1c8ae8e40c7a2d2183b59b97/multidict-6.6.3-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:274d416b0df887aef98f19f21578653982cfb8a05b4e187d4a17103322eeaf8f", size = 257776, upload-time = "2025-06-30T15:52:52.764Z" }, - { url = "https://files.pythonhosted.org/packages/68/d0/14fa1699f4ef629eae08ad6201c6b476098f5efb051b296f4c26be7a9fdf/multidict-6.6.3-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:e252017a817fad7ce05cafbe5711ed40faeb580e63b16755a3a24e66fa1d87c0", size = 256882, upload-time = "2025-06-30T15:52:54.596Z" }, - { url = "https://files.pythonhosted.org/packages/da/88/84a27570fbe303c65607d517a5f147cd2fc046c2d1da02b84b17b9bdc2aa/multidict-6.6.3-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:2e4cc8d848cd4fe1cdee28c13ea79ab0ed37fc2e89dd77bac86a2e7959a8c3bc", size = 247816, upload-time = "2025-06-30T15:52:56.175Z" }, - { url = "https://files.pythonhosted.org/packages/1c/60/dca352a0c999ce96a5d8b8ee0b2b9f729dcad2e0b0c195f8286269a2074c/multidict-6.6.3-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:9e236a7094b9c4c1b7585f6b9cca34b9d833cf079f7e4c49e6a4a6ec9bfdc68f", size = 245341, upload-time = "2025-06-30T15:52:57.752Z" }, - { url = "https://files.pythonhosted.org/packages/50/ef/433fa3ed06028f03946f3993223dada70fb700f763f70c00079533c34578/multidict-6.6.3-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:e0cb0ab69915c55627c933f0b555a943d98ba71b4d1c57bc0d0a66e2567c7471", size = 235854, upload-time = "2025-06-30T15:52:59.74Z" }, - { url = "https://files.pythonhosted.org/packages/1b/1f/487612ab56fbe35715320905215a57fede20de7db40a261759690dc80471/multidict-6.6.3-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:81ef2f64593aba09c5212a3d0f8c906a0d38d710a011f2f42759704d4557d3f2", size = 243432, upload-time = "2025-06-30T15:53:01.602Z" }, - { url = "https://files.pythonhosted.org/packages/da/6f/ce8b79de16cd885c6f9052c96a3671373d00c59b3ee635ea93e6e81b8ccf/multidict-6.6.3-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:b9cbc60010de3562545fa198bfc6d3825df430ea96d2cc509c39bd71e2e7d648", size = 252731, upload-time = "2025-06-30T15:53:03.517Z" }, - { url = "https://files.pythonhosted.org/packages/bb/fe/a2514a6aba78e5abefa1624ca85ae18f542d95ac5cde2e3815a9fbf369aa/multidict-6.6.3-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:70d974eaaa37211390cd02ef93b7e938de564bbffa866f0b08d07e5e65da783d", size = 247086, upload-time = "2025-06-30T15:53:05.48Z" }, - { url = "https://files.pythonhosted.org/packages/8c/22/b788718d63bb3cce752d107a57c85fcd1a212c6c778628567c9713f9345a/multidict-6.6.3-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:3713303e4a6663c6d01d648a68f2848701001f3390a030edaaf3fc949c90bf7c", size = 243338, upload-time = "2025-06-30T15:53:07.522Z" }, - { url = "https://files.pythonhosted.org/packages/22/d6/fdb3d0670819f2228f3f7d9af613d5e652c15d170c83e5f1c94fbc55a25b/multidict-6.6.3-cp313-cp313t-win32.whl", hash = "sha256:639ecc9fe7cd73f2495f62c213e964843826f44505a3e5d82805aa85cac6f89e", size = 47812, upload-time = "2025-06-30T15:53:09.263Z" }, - { url = "https://files.pythonhosted.org/packages/b6/d6/a9d2c808f2c489ad199723197419207ecbfbc1776f6e155e1ecea9c883aa/multidict-6.6.3-cp313-cp313t-win_amd64.whl", hash = "sha256:9f97e181f344a0ef3881b573d31de8542cc0dbc559ec68c8f8b5ce2c2e91646d", size = 53011, upload-time = "2025-06-30T15:53:11.038Z" }, - { url = "https://files.pythonhosted.org/packages/f2/40/b68001cba8188dd267590a111f9661b6256debc327137667e832bf5d66e8/multidict-6.6.3-cp313-cp313t-win_arm64.whl", hash = "sha256:ce8b7693da41a3c4fde5871c738a81490cea5496c671d74374c8ab889e1834fb", size = 45254, upload-time = "2025-06-30T15:53:12.421Z" }, - { url = "https://files.pythonhosted.org/packages/d8/30/9aec301e9772b098c1f5c0ca0279237c9766d94b97802e9888010c64b0ed/multidict-6.6.3-py3-none-any.whl", hash = "sha256:8db10f29c7541fc5da4defd8cd697e1ca429db743fa716325f236079b96f775a", size = 12313, upload-time = "2025-06-30T15:53:45.437Z" }, +version = "6.7.0" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/80/1e/5492c365f222f907de1039b91f922b93fa4f764c713ee858d235495d8f50/multidict-6.7.0.tar.gz", hash = "sha256:c6e99d9a65ca282e578dfea819cfa9c0a62b2499d8677392e09feaf305e9e6f5", size = 101834, upload-time = "2025-10-06T14:52:30.657Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/c2/9e/9f61ac18d9c8b475889f32ccfa91c9f59363480613fc807b6e3023d6f60b/multidict-6.7.0-cp312-cp312-macosx_10_13_universal2.whl", hash = "sha256:8a3862568a36d26e650a19bb5cbbba14b71789032aebc0423f8cc5f150730184", size = 76877, upload-time = "2025-10-06T14:49:20.884Z" }, + { url = "https://files.pythonhosted.org/packages/38/6f/614f09a04e6184f8824268fce4bc925e9849edfa654ddd59f0b64508c595/multidict-6.7.0-cp312-cp312-macosx_10_13_x86_64.whl", hash = "sha256:960c60b5849b9b4f9dcc9bea6e3626143c252c74113df2c1540aebce70209b45", size = 45467, upload-time = "2025-10-06T14:49:22.054Z" }, + { url = "https://files.pythonhosted.org/packages/b3/93/c4f67a436dd026f2e780c433277fff72be79152894d9fc36f44569cab1a6/multidict-6.7.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2049be98fb57a31b4ccf870bf377af2504d4ae35646a19037ec271e4c07998aa", size = 43834, upload-time = "2025-10-06T14:49:23.566Z" }, + { url = "https://files.pythonhosted.org/packages/7f/f5/013798161ca665e4a422afbc5e2d9e4070142a9ff8905e482139cd09e4d0/multidict-6.7.0-cp312-cp312-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:0934f3843a1860dd465d38895c17fce1f1cb37295149ab05cd1b9a03afacb2a7", size = 250545, upload-time = "2025-10-06T14:49:24.882Z" }, + { url = "https://files.pythonhosted.org/packages/71/2f/91dbac13e0ba94669ea5119ba267c9a832f0cb65419aca75549fcf09a3dc/multidict-6.7.0-cp312-cp312-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:b3e34f3a1b8131ba06f1a73adab24f30934d148afcd5f5de9a73565a4404384e", size = 258305, upload-time = "2025-10-06T14:49:26.778Z" }, + { url = "https://files.pythonhosted.org/packages/ef/b0/754038b26f6e04488b48ac621f779c341338d78503fb45403755af2df477/multidict-6.7.0-cp312-cp312-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:efbb54e98446892590dc2458c19c10344ee9a883a79b5cec4bc34d6656e8d546", size = 242363, upload-time = "2025-10-06T14:49:28.562Z" }, + { url = "https://files.pythonhosted.org/packages/87/15/9da40b9336a7c9fa606c4cf2ed80a649dffeb42b905d4f63a1d7eb17d746/multidict-6.7.0-cp312-cp312-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a35c5fc61d4f51eb045061e7967cfe3123d622cd500e8868e7c0c592a09fedc4", size = 268375, upload-time = "2025-10-06T14:49:29.96Z" }, + { url = "https://files.pythonhosted.org/packages/82/72/c53fcade0cc94dfaad583105fd92b3a783af2091eddcb41a6d5a52474000/multidict-6.7.0-cp312-cp312-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:29fe6740ebccba4175af1b9b87bf553e9c15cd5868ee967e010efcf94e4fd0f1", size = 269346, upload-time = "2025-10-06T14:49:31.404Z" }, + { url = "https://files.pythonhosted.org/packages/0d/e2/9baffdae21a76f77ef8447f1a05a96ec4bc0a24dae08767abc0a2fe680b8/multidict-6.7.0-cp312-cp312-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:123e2a72e20537add2f33a79e605f6191fba2afda4cbb876e35c1a7074298a7d", size = 256107, upload-time = "2025-10-06T14:49:32.974Z" }, + { url = "https://files.pythonhosted.org/packages/3c/06/3f06f611087dc60d65ef775f1fb5aca7c6d61c6db4990e7cda0cef9b1651/multidict-6.7.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:b284e319754366c1aee2267a2036248b24eeb17ecd5dc16022095e747f2f4304", size = 253592, upload-time = "2025-10-06T14:49:34.52Z" }, + { url = "https://files.pythonhosted.org/packages/20/24/54e804ec7945b6023b340c412ce9c3f81e91b3bf5fa5ce65558740141bee/multidict-6.7.0-cp312-cp312-musllinux_1_2_armv7l.whl", hash = "sha256:803d685de7be4303b5a657b76e2f6d1240e7e0a8aa2968ad5811fa2285553a12", size = 251024, upload-time = "2025-10-06T14:49:35.956Z" }, + { url = "https://files.pythonhosted.org/packages/14/48/011cba467ea0b17ceb938315d219391d3e421dfd35928e5dbdc3f4ae76ef/multidict-6.7.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:c04a328260dfd5db8c39538f999f02779012268f54614902d0afc775d44e0a62", size = 251484, upload-time = "2025-10-06T14:49:37.631Z" }, + { url = "https://files.pythonhosted.org/packages/0d/2f/919258b43bb35b99fa127435cfb2d91798eb3a943396631ef43e3720dcf4/multidict-6.7.0-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8a19cdb57cd3df4cd865849d93ee14920fb97224300c88501f16ecfa2604b4e0", size = 263579, upload-time = "2025-10-06T14:49:39.502Z" }, + { url = "https://files.pythonhosted.org/packages/31/22/a0e884d86b5242b5a74cf08e876bdf299e413016b66e55511f7a804a366e/multidict-6.7.0-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:9b2fd74c52accced7e75de26023b7dccee62511a600e62311b918ec5c168fc2a", size = 259654, upload-time = "2025-10-06T14:49:41.32Z" }, + { url = "https://files.pythonhosted.org/packages/b2/e5/17e10e1b5c5f5a40f2fcbb45953c9b215f8a4098003915e46a93f5fcaa8f/multidict-6.7.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:3e8bfdd0e487acf992407a140d2589fe598238eaeffa3da8448d63a63cd363f8", size = 251511, upload-time = "2025-10-06T14:49:46.021Z" }, + { url = "https://files.pythonhosted.org/packages/e3/9a/201bb1e17e7af53139597069c375e7b0dcbd47594604f65c2d5359508566/multidict-6.7.0-cp312-cp312-win32.whl", hash = "sha256:dd32a49400a2c3d52088e120ee00c1e3576cbff7e10b98467962c74fdb762ed4", size = 41895, upload-time = "2025-10-06T14:49:48.718Z" }, + { url = "https://files.pythonhosted.org/packages/46/e2/348cd32faad84eaf1d20cce80e2bb0ef8d312c55bca1f7fa9865e7770aaf/multidict-6.7.0-cp312-cp312-win_amd64.whl", hash = "sha256:92abb658ef2d7ef22ac9f8bb88e8b6c3e571671534e029359b6d9e845923eb1b", size = 46073, upload-time = "2025-10-06T14:49:50.28Z" }, + { url = "https://files.pythonhosted.org/packages/25/ec/aad2613c1910dce907480e0c3aa306905830f25df2e54ccc9dea450cb5aa/multidict-6.7.0-cp312-cp312-win_arm64.whl", hash = "sha256:490dab541a6a642ce1a9d61a4781656b346a55c13038f0b1244653828e3a83ec", size = 43226, upload-time = "2025-10-06T14:49:52.304Z" }, + { url = "https://files.pythonhosted.org/packages/d2/86/33272a544eeb36d66e4d9a920602d1a2f57d4ebea4ef3cdfe5a912574c95/multidict-6.7.0-cp313-cp313-macosx_10_13_universal2.whl", hash = "sha256:bee7c0588aa0076ce77c0ea5d19a68d76ad81fcd9fe8501003b9a24f9d4000f6", size = 76135, upload-time = "2025-10-06T14:49:54.26Z" }, + { url = "https://files.pythonhosted.org/packages/91/1c/eb97db117a1ebe46d457a3d235a7b9d2e6dcab174f42d1b67663dd9e5371/multidict-6.7.0-cp313-cp313-macosx_10_13_x86_64.whl", hash = "sha256:7ef6b61cad77091056ce0e7ce69814ef72afacb150b7ac6a3e9470def2198159", size = 45117, upload-time = "2025-10-06T14:49:55.82Z" }, + { url = "https://files.pythonhosted.org/packages/f1/d8/6c3442322e41fb1dd4de8bd67bfd11cd72352ac131f6368315617de752f1/multidict-6.7.0-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:9c0359b1ec12b1d6849c59f9d319610b7f20ef990a6d454ab151aa0e3b9f78ca", size = 43472, upload-time = "2025-10-06T14:49:57.048Z" }, + { url = "https://files.pythonhosted.org/packages/75/3f/e2639e80325af0b6c6febdf8e57cc07043ff15f57fa1ef808f4ccb5ac4cd/multidict-6.7.0-cp313-cp313-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:cd240939f71c64bd658f186330603aac1a9a81bf6273f523fca63673cb7378a8", size = 249342, upload-time = "2025-10-06T14:49:58.368Z" }, + { url = "https://files.pythonhosted.org/packages/5d/cc/84e0585f805cbeaa9cbdaa95f9a3d6aed745b9d25700623ac89a6ecff400/multidict-6.7.0-cp313-cp313-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:a60a4d75718a5efa473ebd5ab685786ba0c67b8381f781d1be14da49f1a2dc60", size = 257082, upload-time = "2025-10-06T14:49:59.89Z" }, + { url = "https://files.pythonhosted.org/packages/b0/9c/ac851c107c92289acbbf5cfb485694084690c1b17e555f44952c26ddc5bd/multidict-6.7.0-cp313-cp313-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:53a42d364f323275126aff81fb67c5ca1b7a04fda0546245730a55c8c5f24bc4", size = 240704, upload-time = "2025-10-06T14:50:01.485Z" }, + { url = "https://files.pythonhosted.org/packages/50/cc/5f93e99427248c09da95b62d64b25748a5f5c98c7c2ab09825a1d6af0e15/multidict-6.7.0-cp313-cp313-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:3b29b980d0ddbecb736735ee5bef69bb2ddca56eff603c86f3f29a1128299b4f", size = 266355, upload-time = "2025-10-06T14:50:02.955Z" }, + { url = "https://files.pythonhosted.org/packages/ec/0c/2ec1d883ceb79c6f7f6d7ad90c919c898f5d1c6ea96d322751420211e072/multidict-6.7.0-cp313-cp313-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:f8a93b1c0ed2d04b97a5e9336fd2d33371b9a6e29ab7dd6503d63407c20ffbaf", size = 267259, upload-time = "2025-10-06T14:50:04.446Z" }, + { url = "https://files.pythonhosted.org/packages/c6/2d/f0b184fa88d6630aa267680bdb8623fb69cb0d024b8c6f0d23f9a0f406d3/multidict-6.7.0-cp313-cp313-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:9ff96e8815eecacc6645da76c413eb3b3d34cfca256c70b16b286a687d013c32", size = 254903, upload-time = "2025-10-06T14:50:05.98Z" }, + { url = "https://files.pythonhosted.org/packages/06/c9/11ea263ad0df7dfabcad404feb3c0dd40b131bc7f232d5537f2fb1356951/multidict-6.7.0-cp313-cp313-musllinux_1_2_aarch64.whl", hash = "sha256:7516c579652f6a6be0e266aec0acd0db80829ca305c3d771ed898538804c2036", size = 252365, upload-time = "2025-10-06T14:50:07.511Z" }, + { url = "https://files.pythonhosted.org/packages/41/88/d714b86ee2c17d6e09850c70c9d310abac3d808ab49dfa16b43aba9d53fd/multidict-6.7.0-cp313-cp313-musllinux_1_2_armv7l.whl", hash = "sha256:040f393368e63fb0f3330e70c26bfd336656bed925e5cbe17c9da839a6ab13ec", size = 250062, upload-time = "2025-10-06T14:50:09.074Z" }, + { url = "https://files.pythonhosted.org/packages/15/fe/ad407bb9e818c2b31383f6131ca19ea7e35ce93cf1310fce69f12e89de75/multidict-6.7.0-cp313-cp313-musllinux_1_2_i686.whl", hash = "sha256:b3bc26a951007b1057a1c543af845f1c7e3e71cc240ed1ace7bf4484aa99196e", size = 249683, upload-time = "2025-10-06T14:50:10.714Z" }, + { url = "https://files.pythonhosted.org/packages/8c/a4/a89abdb0229e533fb925e7c6e5c40201c2873efebc9abaf14046a4536ee6/multidict-6.7.0-cp313-cp313-musllinux_1_2_ppc64le.whl", hash = "sha256:7b022717c748dd1992a83e219587aabe45980d88969f01b316e78683e6285f64", size = 261254, upload-time = "2025-10-06T14:50:12.28Z" }, + { url = "https://files.pythonhosted.org/packages/8d/aa/0e2b27bd88b40a4fb8dc53dd74eecac70edaa4c1dd0707eb2164da3675b3/multidict-6.7.0-cp313-cp313-musllinux_1_2_s390x.whl", hash = "sha256:9600082733859f00d79dee64effc7aef1beb26adb297416a4ad2116fd61374bd", size = 257967, upload-time = "2025-10-06T14:50:14.16Z" }, + { url = "https://files.pythonhosted.org/packages/d0/8e/0c67b7120d5d5f6d874ed85a085f9dc770a7f9d8813e80f44a9fec820bb7/multidict-6.7.0-cp313-cp313-musllinux_1_2_x86_64.whl", hash = "sha256:94218fcec4d72bc61df51c198d098ce2b378e0ccbac41ddbed5ef44092913288", size = 250085, upload-time = "2025-10-06T14:50:15.639Z" }, + { url = "https://files.pythonhosted.org/packages/ba/55/b73e1d624ea4b8fd4dd07a3bb70f6e4c7c6c5d9d640a41c6ffe5cdbd2a55/multidict-6.7.0-cp313-cp313-win32.whl", hash = "sha256:a37bd74c3fa9d00be2d7b8eca074dc56bd8077ddd2917a839bd989612671ed17", size = 41713, upload-time = "2025-10-06T14:50:17.066Z" }, + { url = "https://files.pythonhosted.org/packages/32/31/75c59e7d3b4205075b4c183fa4ca398a2daf2303ddf616b04ae6ef55cffe/multidict-6.7.0-cp313-cp313-win_amd64.whl", hash = "sha256:30d193c6cc6d559db42b6bcec8a5d395d34d60c9877a0b71ecd7c204fcf15390", size = 45915, upload-time = "2025-10-06T14:50:18.264Z" }, + { url = "https://files.pythonhosted.org/packages/31/2a/8987831e811f1184c22bc2e45844934385363ee61c0a2dcfa8f71b87e608/multidict-6.7.0-cp313-cp313-win_arm64.whl", hash = "sha256:ea3334cabe4d41b7ccd01e4d349828678794edbc2d3ae97fc162a3312095092e", size = 43077, upload-time = "2025-10-06T14:50:19.853Z" }, + { url = "https://files.pythonhosted.org/packages/e8/68/7b3a5170a382a340147337b300b9eb25a9ddb573bcdfff19c0fa3f31ffba/multidict-6.7.0-cp313-cp313t-macosx_10_13_universal2.whl", hash = "sha256:ad9ce259f50abd98a1ca0aa6e490b58c316a0fce0617f609723e40804add2c00", size = 83114, upload-time = "2025-10-06T14:50:21.223Z" }, + { url = "https://files.pythonhosted.org/packages/55/5c/3fa2d07c84df4e302060f555bbf539310980362236ad49f50eeb0a1c1eb9/multidict-6.7.0-cp313-cp313t-macosx_10_13_x86_64.whl", hash = "sha256:07f5594ac6d084cbb5de2df218d78baf55ef150b91f0ff8a21cc7a2e3a5a58eb", size = 48442, upload-time = "2025-10-06T14:50:22.871Z" }, + { url = "https://files.pythonhosted.org/packages/fc/56/67212d33239797f9bd91962bb899d72bb0f4c35a8652dcdb8ed049bef878/multidict-6.7.0-cp313-cp313t-macosx_11_0_arm64.whl", hash = "sha256:0591b48acf279821a579282444814a2d8d0af624ae0bc600aa4d1b920b6e924b", size = 46885, upload-time = "2025-10-06T14:50:24.258Z" }, + { url = "https://files.pythonhosted.org/packages/46/d1/908f896224290350721597a61a69cd19b89ad8ee0ae1f38b3f5cd12ea2ac/multidict-6.7.0-cp313-cp313t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:749a72584761531d2b9467cfbdfd29487ee21124c304c4b6cb760d8777b27f9c", size = 242588, upload-time = "2025-10-06T14:50:25.716Z" }, + { url = "https://files.pythonhosted.org/packages/ab/67/8604288bbd68680eee0ab568fdcb56171d8b23a01bcd5cb0c8fedf6e5d99/multidict-6.7.0-cp313-cp313t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:6b4c3d199f953acd5b446bf7c0de1fe25d94e09e79086f8dc2f48a11a129cdf1", size = 249966, upload-time = "2025-10-06T14:50:28.192Z" }, + { url = "https://files.pythonhosted.org/packages/20/33/9228d76339f1ba51e3efef7da3ebd91964d3006217aae13211653193c3ff/multidict-6.7.0-cp313-cp313t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:9fb0211dfc3b51efea2f349ec92c114d7754dd62c01f81c3e32b765b70c45c9b", size = 228618, upload-time = "2025-10-06T14:50:29.82Z" }, + { url = "https://files.pythonhosted.org/packages/f8/2d/25d9b566d10cab1c42b3b9e5b11ef79c9111eaf4463b8c257a3bd89e0ead/multidict-6.7.0-cp313-cp313t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:a027ec240fe73a8d6281872690b988eed307cd7d91b23998ff35ff577ca688b5", size = 257539, upload-time = "2025-10-06T14:50:31.731Z" }, + { url = "https://files.pythonhosted.org/packages/b6/b1/8d1a965e6637fc33de3c0d8f414485c2b7e4af00f42cab3d84e7b955c222/multidict-6.7.0-cp313-cp313t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:d1d964afecdf3a8288789df2f5751dc0a8261138c3768d9af117ed384e538fad", size = 256345, upload-time = "2025-10-06T14:50:33.26Z" }, + { url = "https://files.pythonhosted.org/packages/ba/0c/06b5a8adbdeedada6f4fb8d8f193d44a347223b11939b42953eeb6530b6b/multidict-6.7.0-cp313-cp313t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:caf53b15b1b7df9fbd0709aa01409000a2b4dd03a5f6f5cc548183c7c8f8b63c", size = 247934, upload-time = "2025-10-06T14:50:34.808Z" }, + { url = "https://files.pythonhosted.org/packages/8f/31/b2491b5fe167ca044c6eb4b8f2c9f3b8a00b24c432c365358eadac5d7625/multidict-6.7.0-cp313-cp313t-musllinux_1_2_aarch64.whl", hash = "sha256:654030da3197d927f05a536a66186070e98765aa5142794c9904555d3a9d8fb5", size = 245243, upload-time = "2025-10-06T14:50:36.436Z" }, + { url = "https://files.pythonhosted.org/packages/61/1a/982913957cb90406c8c94f53001abd9eafc271cb3e70ff6371590bec478e/multidict-6.7.0-cp313-cp313t-musllinux_1_2_armv7l.whl", hash = "sha256:2090d3718829d1e484706a2f525e50c892237b2bf9b17a79b059cb98cddc2f10", size = 235878, upload-time = "2025-10-06T14:50:37.953Z" }, + { url = "https://files.pythonhosted.org/packages/be/c0/21435d804c1a1cf7a2608593f4d19bca5bcbd7a81a70b253fdd1c12af9c0/multidict-6.7.0-cp313-cp313t-musllinux_1_2_i686.whl", hash = "sha256:2d2cfeec3f6f45651b3d408c4acec0ebf3daa9bc8a112a084206f5db5d05b754", size = 243452, upload-time = "2025-10-06T14:50:39.574Z" }, + { url = "https://files.pythonhosted.org/packages/54/0a/4349d540d4a883863191be6eb9a928846d4ec0ea007d3dcd36323bb058ac/multidict-6.7.0-cp313-cp313t-musllinux_1_2_ppc64le.whl", hash = "sha256:4ef089f985b8c194d341eb2c24ae6e7408c9a0e2e5658699c92f497437d88c3c", size = 252312, upload-time = "2025-10-06T14:50:41.612Z" }, + { url = "https://files.pythonhosted.org/packages/26/64/d5416038dbda1488daf16b676e4dbfd9674dde10a0cc8f4fc2b502d8125d/multidict-6.7.0-cp313-cp313t-musllinux_1_2_s390x.whl", hash = "sha256:e93a0617cd16998784bf4414c7e40f17a35d2350e5c6f0bd900d3a8e02bd3762", size = 246935, upload-time = "2025-10-06T14:50:43.972Z" }, + { url = "https://files.pythonhosted.org/packages/9f/8c/8290c50d14e49f35e0bd4abc25e1bc7711149ca9588ab7d04f886cdf03d9/multidict-6.7.0-cp313-cp313t-musllinux_1_2_x86_64.whl", hash = "sha256:f0feece2ef8ebc42ed9e2e8c78fc4aa3cf455733b507c09ef7406364c94376c6", size = 243385, upload-time = "2025-10-06T14:50:45.648Z" }, + { url = "https://files.pythonhosted.org/packages/ef/a0/f83ae75e42d694b3fbad3e047670e511c138be747bc713cf1b10d5096416/multidict-6.7.0-cp313-cp313t-win32.whl", hash = "sha256:19a1d55338ec1be74ef62440ca9e04a2f001a04d0cc49a4983dc320ff0f3212d", size = 47777, upload-time = "2025-10-06T14:50:47.154Z" }, + { url = "https://files.pythonhosted.org/packages/dc/80/9b174a92814a3830b7357307a792300f42c9e94664b01dee8e457551fa66/multidict-6.7.0-cp313-cp313t-win_amd64.whl", hash = "sha256:3da4fb467498df97e986af166b12d01f05d2e04f978a9c1c680ea1988e0bc4b6", size = 53104, upload-time = "2025-10-06T14:50:48.851Z" }, + { url = "https://files.pythonhosted.org/packages/cc/28/04baeaf0428d95bb7a7bea0e691ba2f31394338ba424fb0679a9ed0f4c09/multidict-6.7.0-cp313-cp313t-win_arm64.whl", hash = "sha256:b4121773c49a0776461f4a904cdf6264c88e42218aaa8407e803ca8025872792", size = 45503, upload-time = "2025-10-06T14:50:50.16Z" }, + { url = "https://files.pythonhosted.org/packages/e2/b1/3da6934455dd4b261d4c72f897e3a5728eba81db59959f3a639245891baa/multidict-6.7.0-cp314-cp314-macosx_10_13_universal2.whl", hash = "sha256:3bab1e4aff7adaa34410f93b1f8e57c4b36b9af0426a76003f441ee1d3c7e842", size = 75128, upload-time = "2025-10-06T14:50:51.92Z" }, + { url = "https://files.pythonhosted.org/packages/14/2c/f069cab5b51d175a1a2cb4ccdf7a2c2dabd58aa5bd933fa036a8d15e2404/multidict-6.7.0-cp314-cp314-macosx_10_13_x86_64.whl", hash = "sha256:b8512bac933afc3e45fb2b18da8e59b78d4f408399a960339598374d4ae3b56b", size = 44410, upload-time = "2025-10-06T14:50:53.275Z" }, + { url = "https://files.pythonhosted.org/packages/42/e2/64bb41266427af6642b6b128e8774ed84c11b80a90702c13ac0a86bb10cc/multidict-6.7.0-cp314-cp314-macosx_11_0_arm64.whl", hash = "sha256:79dcf9e477bc65414ebfea98ffd013cb39552b5ecd62908752e0e413d6d06e38", size = 43205, upload-time = "2025-10-06T14:50:54.911Z" }, + { url = "https://files.pythonhosted.org/packages/02/68/6b086fef8a3f1a8541b9236c594f0c9245617c29841f2e0395d979485cde/multidict-6.7.0-cp314-cp314-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:31bae522710064b5cbeddaf2e9f32b1abab70ac6ac91d42572502299e9953128", size = 245084, upload-time = "2025-10-06T14:50:56.369Z" }, + { url = "https://files.pythonhosted.org/packages/15/ee/f524093232007cd7a75c1d132df70f235cfd590a7c9eaccd7ff422ef4ae8/multidict-6.7.0-cp314-cp314-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:4a0df7ff02397bb63e2fd22af2c87dfa39e8c7f12947bc524dbdc528282c7e34", size = 252667, upload-time = "2025-10-06T14:50:57.991Z" }, + { url = "https://files.pythonhosted.org/packages/02/a5/eeb3f43ab45878f1895118c3ef157a480db58ede3f248e29b5354139c2c9/multidict-6.7.0-cp314-cp314-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:7a0222514e8e4c514660e182d5156a415c13ef0aabbd71682fc714e327b95e99", size = 233590, upload-time = "2025-10-06T14:50:59.589Z" }, + { url = "https://files.pythonhosted.org/packages/6a/1e/76d02f8270b97269d7e3dbd45644b1785bda457b474315f8cf999525a193/multidict-6.7.0-cp314-cp314-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:2397ab4daaf2698eb51a76721e98db21ce4f52339e535725de03ea962b5a3202", size = 264112, upload-time = "2025-10-06T14:51:01.183Z" }, + { url = "https://files.pythonhosted.org/packages/76/0b/c28a70ecb58963847c2a8efe334904cd254812b10e535aefb3bcce513918/multidict-6.7.0-cp314-cp314-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:8891681594162635948a636c9fe0ff21746aeb3dd5463f6e25d9bea3a8a39ca1", size = 261194, upload-time = "2025-10-06T14:51:02.794Z" }, + { url = "https://files.pythonhosted.org/packages/b4/63/2ab26e4209773223159b83aa32721b4021ffb08102f8ac7d689c943fded1/multidict-6.7.0-cp314-cp314-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:18706cc31dbf402a7945916dd5cddf160251b6dab8a2c5f3d6d5a55949f676b3", size = 248510, upload-time = "2025-10-06T14:51:04.724Z" }, + { url = "https://files.pythonhosted.org/packages/93/cd/06c1fa8282af1d1c46fd55c10a7930af652afdce43999501d4d68664170c/multidict-6.7.0-cp314-cp314-musllinux_1_2_aarch64.whl", hash = "sha256:f844a1bbf1d207dd311a56f383f7eda2d0e134921d45751842d8235e7778965d", size = 248395, upload-time = "2025-10-06T14:51:06.306Z" }, + { url = "https://files.pythonhosted.org/packages/99/ac/82cb419dd6b04ccf9e7e61befc00c77614fc8134362488b553402ecd55ce/multidict-6.7.0-cp314-cp314-musllinux_1_2_armv7l.whl", hash = "sha256:d4393e3581e84e5645506923816b9cc81f5609a778c7e7534054091acc64d1c6", size = 239520, upload-time = "2025-10-06T14:51:08.091Z" }, + { url = "https://files.pythonhosted.org/packages/fa/f3/a0f9bf09493421bd8716a362e0cd1d244f5a6550f5beffdd6b47e885b331/multidict-6.7.0-cp314-cp314-musllinux_1_2_i686.whl", hash = "sha256:fbd18dc82d7bf274b37aa48d664534330af744e03bccf696d6f4c6042e7d19e7", size = 245479, upload-time = "2025-10-06T14:51:10.365Z" }, + { url = "https://files.pythonhosted.org/packages/8d/01/476d38fc73a212843f43c852b0eee266b6971f0e28329c2184a8df90c376/multidict-6.7.0-cp314-cp314-musllinux_1_2_ppc64le.whl", hash = "sha256:b6234e14f9314731ec45c42fc4554b88133ad53a09092cc48a88e771c125dadb", size = 258903, upload-time = "2025-10-06T14:51:12.466Z" }, + { url = "https://files.pythonhosted.org/packages/49/6d/23faeb0868adba613b817d0e69c5f15531b24d462af8012c4f6de4fa8dc3/multidict-6.7.0-cp314-cp314-musllinux_1_2_s390x.whl", hash = "sha256:08d4379f9744d8f78d98c8673c06e202ffa88296f009c71bbafe8a6bf847d01f", size = 252333, upload-time = "2025-10-06T14:51:14.48Z" }, + { url = "https://files.pythonhosted.org/packages/1e/cc/48d02ac22b30fa247f7dad82866e4b1015431092f4ba6ebc7e77596e0b18/multidict-6.7.0-cp314-cp314-musllinux_1_2_x86_64.whl", hash = "sha256:9fe04da3f79387f450fd0061d4dd2e45a72749d31bf634aecc9e27f24fdc4b3f", size = 243411, upload-time = "2025-10-06T14:51:16.072Z" }, + { url = "https://files.pythonhosted.org/packages/4a/03/29a8bf5a18abf1fe34535c88adbdfa88c9fb869b5a3b120692c64abe8284/multidict-6.7.0-cp314-cp314-win32.whl", hash = "sha256:fbafe31d191dfa7c4c51f7a6149c9fb7e914dcf9ffead27dcfd9f1ae382b3885", size = 40940, upload-time = "2025-10-06T14:51:17.544Z" }, + { url = "https://files.pythonhosted.org/packages/82/16/7ed27b680791b939de138f906d5cf2b4657b0d45ca6f5dd6236fdddafb1a/multidict-6.7.0-cp314-cp314-win_amd64.whl", hash = "sha256:2f67396ec0310764b9222a1728ced1ab638f61aadc6226f17a71dd9324f9a99c", size = 45087, upload-time = "2025-10-06T14:51:18.875Z" }, + { url = "https://files.pythonhosted.org/packages/cd/3c/e3e62eb35a1950292fe39315d3c89941e30a9d07d5d2df42965ab041da43/multidict-6.7.0-cp314-cp314-win_arm64.whl", hash = "sha256:ba672b26069957ee369cfa7fc180dde1fc6f176eaf1e6beaf61fbebbd3d9c000", size = 42368, upload-time = "2025-10-06T14:51:20.225Z" }, + { url = "https://files.pythonhosted.org/packages/8b/40/cd499bd0dbc5f1136726db3153042a735fffd0d77268e2ee20d5f33c010f/multidict-6.7.0-cp314-cp314t-macosx_10_13_universal2.whl", hash = "sha256:c1dcc7524066fa918c6a27d61444d4ee7900ec635779058571f70d042d86ed63", size = 82326, upload-time = "2025-10-06T14:51:21.588Z" }, + { url = "https://files.pythonhosted.org/packages/13/8a/18e031eca251c8df76daf0288e6790561806e439f5ce99a170b4af30676b/multidict-6.7.0-cp314-cp314t-macosx_10_13_x86_64.whl", hash = "sha256:27e0b36c2d388dc7b6ced3406671b401e84ad7eb0656b8f3a2f46ed0ce483718", size = 48065, upload-time = "2025-10-06T14:51:22.93Z" }, + { url = "https://files.pythonhosted.org/packages/40/71/5e6701277470a87d234e433fb0a3a7deaf3bcd92566e421e7ae9776319de/multidict-6.7.0-cp314-cp314t-macosx_11_0_arm64.whl", hash = "sha256:2a7baa46a22e77f0988e3b23d4ede5513ebec1929e34ee9495be535662c0dfe2", size = 46475, upload-time = "2025-10-06T14:51:24.352Z" }, + { url = "https://files.pythonhosted.org/packages/fe/6a/bab00cbab6d9cfb57afe1663318f72ec28289ea03fd4e8236bb78429893a/multidict-6.7.0-cp314-cp314t-manylinux1_i686.manylinux_2_28_i686.manylinux_2_5_i686.whl", hash = "sha256:7bf77f54997a9166a2f5675d1201520586439424c2511723a7312bdb4bcc034e", size = 239324, upload-time = "2025-10-06T14:51:25.822Z" }, + { url = "https://files.pythonhosted.org/packages/2a/5f/8de95f629fc22a7769ade8b41028e3e5a822c1f8904f618d175945a81ad3/multidict-6.7.0-cp314-cp314t-manylinux2014_aarch64.manylinux_2_17_aarch64.manylinux_2_28_aarch64.whl", hash = "sha256:e011555abada53f1578d63389610ac8a5400fc70ce71156b0aa30d326f1a5064", size = 246877, upload-time = "2025-10-06T14:51:27.604Z" }, + { url = "https://files.pythonhosted.org/packages/23/b4/38881a960458f25b89e9f4a4fdcb02ac101cfa710190db6e5528841e67de/multidict-6.7.0-cp314-cp314t-manylinux2014_armv7l.manylinux_2_17_armv7l.manylinux_2_31_armv7l.whl", hash = "sha256:28b37063541b897fd6a318007373930a75ca6d6ac7c940dbe14731ffdd8d498e", size = 225824, upload-time = "2025-10-06T14:51:29.664Z" }, + { url = "https://files.pythonhosted.org/packages/1e/39/6566210c83f8a261575f18e7144736059f0c460b362e96e9cf797a24b8e7/multidict-6.7.0-cp314-cp314t-manylinux2014_ppc64le.manylinux_2_17_ppc64le.manylinux_2_28_ppc64le.whl", hash = "sha256:05047ada7a2fde2631a0ed706f1fd68b169a681dfe5e4cf0f8e4cb6618bbc2cd", size = 253558, upload-time = "2025-10-06T14:51:31.684Z" }, + { url = "https://files.pythonhosted.org/packages/00/a3/67f18315100f64c269f46e6c0319fa87ba68f0f64f2b8e7fd7c72b913a0b/multidict-6.7.0-cp314-cp314t-manylinux2014_s390x.manylinux_2_17_s390x.manylinux_2_28_s390x.whl", hash = "sha256:716133f7d1d946a4e1b91b1756b23c088881e70ff180c24e864c26192ad7534a", size = 252339, upload-time = "2025-10-06T14:51:33.699Z" }, + { url = "https://files.pythonhosted.org/packages/c8/2a/1cb77266afee2458d82f50da41beba02159b1d6b1f7973afc9a1cad1499b/multidict-6.7.0-cp314-cp314t-manylinux2014_x86_64.manylinux_2_17_x86_64.manylinux_2_28_x86_64.whl", hash = "sha256:d1bed1b467ef657f2a0ae62844a607909ef1c6889562de5e1d505f74457d0b96", size = 244895, upload-time = "2025-10-06T14:51:36.189Z" }, + { url = "https://files.pythonhosted.org/packages/dd/72/09fa7dd487f119b2eb9524946ddd36e2067c08510576d43ff68469563b3b/multidict-6.7.0-cp314-cp314t-musllinux_1_2_aarch64.whl", hash = "sha256:ca43bdfa5d37bd6aee89d85e1d0831fb86e25541be7e9d376ead1b28974f8e5e", size = 241862, upload-time = "2025-10-06T14:51:41.291Z" }, + { url = "https://files.pythonhosted.org/packages/65/92/bc1f8bd0853d8669300f732c801974dfc3702c3eeadae2f60cef54dc69d7/multidict-6.7.0-cp314-cp314t-musllinux_1_2_armv7l.whl", hash = "sha256:44b546bd3eb645fd26fb949e43c02a25a2e632e2ca21a35e2e132c8105dc8599", size = 232376, upload-time = "2025-10-06T14:51:43.55Z" }, + { url = "https://files.pythonhosted.org/packages/09/86/ac39399e5cb9d0c2ac8ef6e10a768e4d3bc933ac808d49c41f9dc23337eb/multidict-6.7.0-cp314-cp314t-musllinux_1_2_i686.whl", hash = "sha256:a6ef16328011d3f468e7ebc326f24c1445f001ca1dec335b2f8e66bed3006394", size = 240272, upload-time = "2025-10-06T14:51:45.265Z" }, + { url = "https://files.pythonhosted.org/packages/3d/b6/fed5ac6b8563ec72df6cb1ea8dac6d17f0a4a1f65045f66b6d3bf1497c02/multidict-6.7.0-cp314-cp314t-musllinux_1_2_ppc64le.whl", hash = "sha256:5aa873cbc8e593d361ae65c68f85faadd755c3295ea2c12040ee146802f23b38", size = 248774, upload-time = "2025-10-06T14:51:46.836Z" }, + { url = "https://files.pythonhosted.org/packages/6b/8d/b954d8c0dc132b68f760aefd45870978deec6818897389dace00fcde32ff/multidict-6.7.0-cp314-cp314t-musllinux_1_2_s390x.whl", hash = "sha256:3d7b6ccce016e29df4b7ca819659f516f0bc7a4b3efa3bb2012ba06431b044f9", size = 242731, upload-time = "2025-10-06T14:51:48.541Z" }, + { url = "https://files.pythonhosted.org/packages/16/9d/a2dac7009125d3540c2f54e194829ea18ac53716c61b655d8ed300120b0f/multidict-6.7.0-cp314-cp314t-musllinux_1_2_x86_64.whl", hash = "sha256:171b73bd4ee683d307599b66793ac80981b06f069b62eea1c9e29c9241aa66b0", size = 240193, upload-time = "2025-10-06T14:51:50.355Z" }, + { url = "https://files.pythonhosted.org/packages/39/ca/c05f144128ea232ae2178b008d5011d4e2cea86e4ee8c85c2631b1b94802/multidict-6.7.0-cp314-cp314t-win32.whl", hash = "sha256:b2d7f80c4e1fd010b07cb26820aae86b7e73b681ee4889684fb8d2d4537aab13", size = 48023, upload-time = "2025-10-06T14:51:51.883Z" }, + { url = "https://files.pythonhosted.org/packages/ba/8f/0a60e501584145588be1af5cc829265701ba3c35a64aec8e07cbb71d39bb/multidict-6.7.0-cp314-cp314t-win_amd64.whl", hash = "sha256:09929cab6fcb68122776d575e03c6cc64ee0b8fca48d17e135474b042ce515cd", size = 53507, upload-time = "2025-10-06T14:51:53.672Z" }, + { url = "https://files.pythonhosted.org/packages/7f/ae/3148b988a9c6239903e786eac19c889fab607c31d6efa7fb2147e5680f23/multidict-6.7.0-cp314-cp314t-win_arm64.whl", hash = "sha256:cc41db090ed742f32bd2d2c721861725e6109681eddf835d0a82bd3a5c382827", size = 44804, upload-time = "2025-10-06T14:51:55.415Z" }, + { url = "https://files.pythonhosted.org/packages/b7/da/7d22601b625e241d4f23ef1ebff8acfc60da633c9e7e7922e24d10f592b3/multidict-6.7.0-py3-none-any.whl", hash = "sha256:394fc5c42a333c9ffc3e421a4c85e08580d990e08b99f6bf35b4132114c5dcb3", size = 12317, upload-time = "2025-10-06T14:52:29.272Z" }, ] [[package]] @@ -2320,14 +2392,15 @@ wheels = [ [[package]] name = "pytest-asyncio" -version = "0.24.0" +version = "1.3.0" source = { registry = "https://pypi.org/simple" } dependencies = [ { name = "pytest" }, + { name = "typing-extensions", marker = "python_full_version < '3.13'" }, ] -sdist = { url = "https://files.pythonhosted.org/packages/52/6d/c6cf50ce320cf8611df7a1254d86233b3df7cc07f9b5f5cbcb82e08aa534/pytest_asyncio-0.24.0.tar.gz", hash = "sha256:d081d828e576d85f875399194281e92bf8a68d60d72d1a2faf2feddb6c46b276", size = 49855, upload-time = "2024-08-22T08:03:18.145Z" } +sdist = { url = "https://files.pythonhosted.org/packages/90/2c/8af215c0f776415f3590cac4f9086ccefd6fd463befeae41cd4d3f193e5a/pytest_asyncio-1.3.0.tar.gz", hash = "sha256:d7f52f36d231b80ee124cd216ffb19369aa168fc10095013c6b014a34d3ee9e5", size = 50087, upload-time = "2025-11-10T16:07:47.256Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/96/31/6607dab48616902f76885dfcf62c08d929796fc3b2d2318faf9fd54dbed9/pytest_asyncio-0.24.0-py3-none-any.whl", hash = "sha256:a811296ed596b69bf0b6f3dc40f83bcaf341b155a269052d82efa2b25ac7037b", size = 18024, upload-time = "2024-08-22T08:03:15.536Z" }, + { url = "https://files.pythonhosted.org/packages/e5/35/f8b19922b6a25bc0880171a2f1a003eaeb93657475193ab516fd87cac9da/pytest_asyncio-1.3.0-py3-none-any.whl", hash = "sha256:611e26147c7f77640e6d0a92a38ed17c3e9848063698d5c93d5aa7aa11cebff5", size = 15075, upload-time = "2025-11-10T16:07:45.537Z" }, ] [[package]] @@ -2467,11 +2540,11 @@ wheels = [ [[package]] name = "redis" -version = "5.2.1" +version = "7.1.0" source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/47/da/d283a37303a995cd36f8b92db85135153dc4f7a8e4441aa827721b442cfb/redis-5.2.1.tar.gz", hash = "sha256:16f2e22dff21d5125e8481515e386711a34cbec50f0e44413dd7d9c060a54e0f", size = 4608355, upload-time = "2024-12-06T09:50:41.956Z" } +sdist = { url = "https://files.pythonhosted.org/packages/43/c8/983d5c6579a411d8a99bc5823cc5712768859b5ce2c8afe1a65b37832c81/redis-7.1.0.tar.gz", hash = "sha256:b1cc3cfa5a2cb9c2ab3ba700864fb0ad75617b41f01352ce5779dabf6d5f9c3c", size = 4796669, upload-time = "2025-11-19T15:54:39.961Z" } wheels = [ - { url = "https://files.pythonhosted.org/packages/3c/5f/fa26b9b2672cbe30e07d9a5bdf39cf16e3b80b42916757c5f92bca88e4ba/redis-5.2.1-py3-none-any.whl", hash = "sha256:ee7e1056b9aea0f04c6c2ed59452947f34c4940ee025f5dd83e6a6418b6989e4", size = 261502, upload-time = "2024-12-06T09:50:39.656Z" }, + { url = "https://files.pythonhosted.org/packages/89/f0/8956f8a86b20d7bb9d6ac0187cf4cd54d8065bc9a1a09eb8011d4d326596/redis-7.1.0-py3-none-any.whl", hash = "sha256:23c52b208f92b56103e17c5d06bdc1a6c2c0b3106583985a76a18f83b265de2b", size = 354159, upload-time = "2025-11-19T15:54:38.064Z" }, ] [[package]] @@ -2579,27 +2652,28 @@ wheels = [ [[package]] name = "ruff" -version = "0.12.7" -source = { registry = "https://pypi.org/simple" } -sdist = { url = "https://files.pythonhosted.org/packages/a1/81/0bd3594fa0f690466e41bd033bdcdf86cba8288345ac77ad4afbe5ec743a/ruff-0.12.7.tar.gz", hash = "sha256:1fc3193f238bc2d7968772c82831a4ff69252f673be371fb49663f0068b7ec71", size = 5197814, upload-time = "2025-07-29T22:32:35.877Z" } -wheels = [ - { url = "https://files.pythonhosted.org/packages/e1/d2/6cb35e9c85e7a91e8d22ab32ae07ac39cc34a71f1009a6f9e4a2a019e602/ruff-0.12.7-py3-none-linux_armv6l.whl", hash = "sha256:76e4f31529899b8c434c3c1dede98c4483b89590e15fb49f2d46183801565303", size = 11852189, upload-time = "2025-07-29T22:31:41.281Z" }, - { url = "https://files.pythonhosted.org/packages/63/5b/a4136b9921aa84638f1a6be7fb086f8cad0fde538ba76bda3682f2599a2f/ruff-0.12.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:789b7a03e72507c54fb3ba6209e4bb36517b90f1a3569ea17084e3fd295500fb", size = 12519389, upload-time = "2025-07-29T22:31:54.265Z" }, - { url = "https://files.pythonhosted.org/packages/a8/c9/3e24a8472484269b6b1821794141f879c54645a111ded4b6f58f9ab0705f/ruff-0.12.7-py3-none-macosx_11_0_arm64.whl", hash = "sha256:2e1c2a3b8626339bb6369116e7030a4cf194ea48f49b64bb505732a7fce4f4e3", size = 11743384, upload-time = "2025-07-29T22:31:59.575Z" }, - { url = "https://files.pythonhosted.org/packages/26/7c/458dd25deeb3452c43eaee853c0b17a1e84169f8021a26d500ead77964fd/ruff-0.12.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32dec41817623d388e645612ec70d5757a6d9c035f3744a52c7b195a57e03860", size = 11943759, upload-time = "2025-07-29T22:32:01.95Z" }, - { url = "https://files.pythonhosted.org/packages/7f/8b/658798472ef260ca050e400ab96ef7e85c366c39cf3dfbef4d0a46a528b6/ruff-0.12.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:47ef751f722053a5df5fa48d412dbb54d41ab9b17875c6840a58ec63ff0c247c", size = 11654028, upload-time = "2025-07-29T22:32:04.367Z" }, - { url = "https://files.pythonhosted.org/packages/a8/86/9c2336f13b2a3326d06d39178fd3448dcc7025f82514d1b15816fe42bfe8/ruff-0.12.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a828a5fc25a3efd3e1ff7b241fd392686c9386f20e5ac90aa9234a5faa12c423", size = 13225209, upload-time = "2025-07-29T22:32:06.952Z" }, - { url = "https://files.pythonhosted.org/packages/76/69/df73f65f53d6c463b19b6b312fd2391dc36425d926ec237a7ed028a90fc1/ruff-0.12.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:5726f59b171111fa6a69d82aef48f00b56598b03a22f0f4170664ff4d8298efb", size = 14182353, upload-time = "2025-07-29T22:32:10.053Z" }, - { url = "https://files.pythonhosted.org/packages/58/1e/de6cda406d99fea84b66811c189b5ea139814b98125b052424b55d28a41c/ruff-0.12.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:74e6f5c04c4dd4aba223f4fe6e7104f79e0eebf7d307e4f9b18c18362124bccd", size = 13631555, upload-time = "2025-07-29T22:32:12.644Z" }, - { url = "https://files.pythonhosted.org/packages/6f/ae/625d46d5164a6cc9261945a5e89df24457dc8262539ace3ac36c40f0b51e/ruff-0.12.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d0bfe4e77fba61bf2ccadf8cf005d6133e3ce08793bbe870dd1c734f2699a3e", size = 12667556, upload-time = "2025-07-29T22:32:15.312Z" }, - { url = "https://files.pythonhosted.org/packages/55/bf/9cb1ea5e3066779e42ade8d0cd3d3b0582a5720a814ae1586f85014656b6/ruff-0.12.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:06bfb01e1623bf7f59ea749a841da56f8f653d641bfd046edee32ede7ff6c606", size = 12939784, upload-time = "2025-07-29T22:32:17.69Z" }, - { url = "https://files.pythonhosted.org/packages/55/7f/7ead2663be5627c04be83754c4f3096603bf5e99ed856c7cd29618c691bd/ruff-0.12.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e41df94a957d50083fd09b916d6e89e497246698c3f3d5c681c8b3e7b9bb4ac8", size = 11771356, upload-time = "2025-07-29T22:32:20.134Z" }, - { url = "https://files.pythonhosted.org/packages/17/40/a95352ea16edf78cd3a938085dccc55df692a4d8ba1b3af7accbe2c806b0/ruff-0.12.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:4000623300563c709458d0ce170c3d0d788c23a058912f28bbadc6f905d67afa", size = 11612124, upload-time = "2025-07-29T22:32:22.645Z" }, - { url = "https://files.pythonhosted.org/packages/4d/74/633b04871c669e23b8917877e812376827c06df866e1677f15abfadc95cb/ruff-0.12.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:69ffe0e5f9b2cf2b8e289a3f8945b402a1b19eff24ec389f45f23c42a3dd6fb5", size = 12479945, upload-time = "2025-07-29T22:32:24.765Z" }, - { url = "https://files.pythonhosted.org/packages/be/34/c3ef2d7799c9778b835a76189c6f53c179d3bdebc8c65288c29032e03613/ruff-0.12.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:a07a5c8ffa2611a52732bdc67bf88e243abd84fe2d7f6daef3826b59abbfeda4", size = 12998677, upload-time = "2025-07-29T22:32:27.022Z" }, - { url = "https://files.pythonhosted.org/packages/77/ab/aca2e756ad7b09b3d662a41773f3edcbd262872a4fc81f920dc1ffa44541/ruff-0.12.7-py3-none-win32.whl", hash = "sha256:c928f1b2ec59fb77dfdf70e0419408898b63998789cc98197e15f560b9e77f77", size = 11756687, upload-time = "2025-07-29T22:32:29.381Z" }, - { url = "https://files.pythonhosted.org/packages/b4/71/26d45a5042bc71db22ddd8252ca9d01e9ca454f230e2996bb04f16d72799/ruff-0.12.7-py3-none-win_amd64.whl", hash = "sha256:9c18f3d707ee9edf89da76131956aba1270c6348bfee8f6c647de841eac7194f", size = 12912365, upload-time = "2025-07-29T22:32:31.517Z" }, - { url = "https://files.pythonhosted.org/packages/4c/9b/0b8aa09817b63e78d94b4977f18b1fcaead3165a5ee49251c5d5c245bb2d/ruff-0.12.7-py3-none-win_arm64.whl", hash = "sha256:dfce05101dbd11833a0776716d5d1578641b7fddb537fe7fa956ab85d1769b69", size = 11982083, upload-time = "2025-07-29T22:32:33.881Z" }, +version = "0.14.9" +source = { registry = "https://pypi.org/simple" } +sdist = { url = "https://files.pythonhosted.org/packages/f6/1b/ab712a9d5044435be8e9a2beb17cbfa4c241aa9b5e4413febac2a8b79ef2/ruff-0.14.9.tar.gz", hash = "sha256:35f85b25dd586381c0cc053f48826109384c81c00ad7ef1bd977bfcc28119d5b", size = 5809165, upload-time = "2025-12-11T21:39:47.381Z" } +wheels = [ + { url = "https://files.pythonhosted.org/packages/b8/1c/d1b1bba22cffec02351c78ab9ed4f7d7391876e12720298448b29b7229c1/ruff-0.14.9-py3-none-linux_armv6l.whl", hash = "sha256:f1ec5de1ce150ca6e43691f4a9ef5c04574ad9ca35c8b3b0e18877314aba7e75", size = 13576541, upload-time = "2025-12-11T21:39:14.806Z" }, + { url = "https://files.pythonhosted.org/packages/94/ab/ffe580e6ea1fca67f6337b0af59fc7e683344a43642d2d55d251ff83ceae/ruff-0.14.9-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:ed9d7417a299fc6030b4f26333bf1117ed82a61ea91238558c0268c14e00d0c2", size = 13779363, upload-time = "2025-12-11T21:39:20.29Z" }, + { url = "https://files.pythonhosted.org/packages/7d/f8/2be49047f929d6965401855461e697ab185e1a6a683d914c5c19c7962d9e/ruff-0.14.9-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d5dc3473c3f0e4a1008d0ef1d75cee24a48e254c8bed3a7afdd2b4392657ed2c", size = 12925292, upload-time = "2025-12-11T21:39:38.757Z" }, + { url = "https://files.pythonhosted.org/packages/9e/e9/08840ff5127916bb989c86f18924fd568938b06f58b60e206176f327c0fe/ruff-0.14.9-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:84bf7c698fc8f3cb8278830fb6b5a47f9bcc1ed8cb4f689b9dd02698fa840697", size = 13362894, upload-time = "2025-12-11T21:39:02.524Z" }, + { url = "https://files.pythonhosted.org/packages/31/1c/5b4e8e7750613ef43390bb58658eaf1d862c0cc3352d139cd718a2cea164/ruff-0.14.9-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:aa733093d1f9d88a5d98988d8834ef5d6f9828d03743bf5e338bf980a19fce27", size = 13311482, upload-time = "2025-12-11T21:39:17.51Z" }, + { url = "https://files.pythonhosted.org/packages/5b/3a/459dce7a8cb35ba1ea3e9c88f19077667a7977234f3b5ab197fad240b404/ruff-0.14.9-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a1cfb04eda979b20c8c19550c8b5f498df64ff8da151283311ce3199e8b3648", size = 14016100, upload-time = "2025-12-11T21:39:41.948Z" }, + { url = "https://files.pythonhosted.org/packages/a6/31/f064f4ec32524f9956a0890fc6a944e5cf06c63c554e39957d208c0ffc45/ruff-0.14.9-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:1e5cb521e5ccf0008bd74d5595a4580313844a42b9103b7388eca5a12c970743", size = 15477729, upload-time = "2025-12-11T21:39:23.279Z" }, + { url = "https://files.pythonhosted.org/packages/7a/6d/f364252aad36ccd443494bc5f02e41bf677f964b58902a17c0b16c53d890/ruff-0.14.9-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cd429a8926be6bba4befa8cdcf3f4dd2591c413ea5066b1e99155ed245ae42bb", size = 15122386, upload-time = "2025-12-11T21:39:33.125Z" }, + { url = "https://files.pythonhosted.org/packages/20/02/e848787912d16209aba2799a4d5a1775660b6a3d0ab3944a4ccc13e64a02/ruff-0.14.9-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ab208c1b7a492e37caeaf290b1378148f75e13c2225af5d44628b95fd7834273", size = 14497124, upload-time = "2025-12-11T21:38:59.33Z" }, + { url = "https://files.pythonhosted.org/packages/f3/51/0489a6a5595b7760b5dbac0dd82852b510326e7d88d51dbffcd2e07e3ff3/ruff-0.14.9-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:72034534e5b11e8a593f517b2f2f2b273eb68a30978c6a2d40473ad0aaa4cb4a", size = 14195343, upload-time = "2025-12-11T21:39:44.866Z" }, + { url = "https://files.pythonhosted.org/packages/f6/53/3bb8d2fa73e4c2f80acc65213ee0830fa0c49c6479313f7a68a00f39e208/ruff-0.14.9-py3-none-manylinux_2_31_riscv64.whl", hash = "sha256:712ff04f44663f1b90a1195f51525836e3413c8a773574a7b7775554269c30ed", size = 14346425, upload-time = "2025-12-11T21:39:05.927Z" }, + { url = "https://files.pythonhosted.org/packages/ad/04/bdb1d0ab876372da3e983896481760867fc84f969c5c09d428e8f01b557f/ruff-0.14.9-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:a111fee1db6f1d5d5810245295527cda1d367c5aa8f42e0fca9a78ede9b4498b", size = 13258768, upload-time = "2025-12-11T21:39:08.691Z" }, + { url = "https://files.pythonhosted.org/packages/40/d9/8bf8e1e41a311afd2abc8ad12be1b6c6c8b925506d9069b67bb5e9a04af3/ruff-0.14.9-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:8769efc71558fecc25eb295ddec7d1030d41a51e9dcf127cbd63ec517f22d567", size = 13326939, upload-time = "2025-12-11T21:39:53.842Z" }, + { url = "https://files.pythonhosted.org/packages/f4/56/a213fa9edb6dd849f1cfbc236206ead10913693c72a67fb7ddc1833bf95d/ruff-0.14.9-py3-none-musllinux_1_2_i686.whl", hash = "sha256:347e3bf16197e8a2de17940cd75fd6491e25c0aa7edf7d61aa03f146a1aa885a", size = 13578888, upload-time = "2025-12-11T21:39:35.988Z" }, + { url = "https://files.pythonhosted.org/packages/33/09/6a4a67ffa4abae6bf44c972a4521337ffce9cbc7808faadede754ef7a79c/ruff-0.14.9-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:7715d14e5bccf5b660f54516558aa94781d3eb0838f8e706fb60e3ff6eff03a8", size = 14314473, upload-time = "2025-12-11T21:39:50.78Z" }, + { url = "https://files.pythonhosted.org/packages/12/0d/15cc82da5d83f27a3c6b04f3a232d61bc8c50d38a6cd8da79228e5f8b8d6/ruff-0.14.9-py3-none-win32.whl", hash = "sha256:df0937f30aaabe83da172adaf8937003ff28172f59ca9f17883b4213783df197", size = 13202651, upload-time = "2025-12-11T21:39:26.628Z" }, + { url = "https://files.pythonhosted.org/packages/32/f7/c78b060388eefe0304d9d42e68fab8cffd049128ec466456cef9b8d4f06f/ruff-0.14.9-py3-none-win_amd64.whl", hash = "sha256:c0b53a10e61df15a42ed711ec0bda0c582039cf6c754c49c020084c55b5b0bc2", size = 14702079, upload-time = "2025-12-11T21:39:11.954Z" }, + { url = "https://files.pythonhosted.org/packages/26/09/7a9520315decd2334afa65ed258fed438f070e31f05a2e43dd480a5e5911/ruff-0.14.9-py3-none-win_arm64.whl", hash = "sha256:8e821c366517a074046d92f0e9213ed1c13dbc5b37a7fc20b07f79b64d62cc84", size = 13744730, upload-time = "2025-12-11T21:39:29.659Z" }, ] [[package]] diff --git a/cert-generator/Dockerfile b/cert-generator/Dockerfile index 9d885ac4..6dc068ab 100644 --- a/cert-generator/Dockerfile +++ b/cert-generator/Dockerfile @@ -1,4 +1,10 @@ -FROM alpine:3.17 +FROM alpine:3.23 + +# Pin versions for reproducible builds +# kubectl: Use supported version (N-2 policy: 1.35, 1.34, 1.33 as of Dec 2025) +# mkcert: Latest stable release +ARG KUBECTL_VERSION=v1.33.6 +ARG MKCERT_VERSION=v1.4.4 # Install required packages and tools for all architectures RUN apk add --no-cache wget ca-certificates openssl curl dos2unix netcat-openbsd && \ @@ -11,12 +17,11 @@ RUN apk add --no-cache wget ca-certificates openssl curl dos2unix netcat-openbsd armv7l) KUBECTL_ARCH=arm; MKCERT_ARCH=arm ;; \ *) echo "Unsupported architecture: $ARCH" && exit 1 ;; \ esac && \ - # Install kubectl - curl -LO "https://dl.k8s.io/release/$(curl -L -s https://dl.k8s.io/release/stable.txt)/bin/linux/${KUBECTL_ARCH}/kubectl" && \ - chmod +x kubectl && \ - mv kubectl /usr/local/bin/ && \ + # Install kubectl (pinned version for reproducibility) + curl -fsSL "https://dl.k8s.io/release/${KUBECTL_VERSION}/bin/linux/${KUBECTL_ARCH}/kubectl" -o /usr/local/bin/kubectl && \ + chmod +x /usr/local/bin/kubectl && \ # Install mkcert - wget -q "https://github.com/FiloSottile/mkcert/releases/download/v1.4.4/mkcert-v1.4.4-linux-${MKCERT_ARCH}" -O /usr/local/bin/mkcert && \ + wget -q "https://github.com/FiloSottile/mkcert/releases/download/${MKCERT_VERSION}/mkcert-${MKCERT_VERSION}-linux-${MKCERT_ARCH}" -O /usr/local/bin/mkcert && \ chmod +x /usr/local/bin/mkcert # Create shared directory for root CA diff --git a/deploy.sh b/deploy.sh index 23a4e0d1..cdf500dd 100755 --- a/deploy.sh +++ b/deploy.sh @@ -14,6 +14,8 @@ # ./deploy.sh test # Run full test suite locally # ./deploy.sh logs [service] # View logs (dev mode) # ./deploy.sh status # Show status of running services +# ./deploy.sh openapi [path] # Generate OpenAPI spec from backend +# ./deploy.sh types # Generate TypeScript types for frontend # # ============================================================================= @@ -60,6 +62,8 @@ show_help() { echo " test Run full test suite with docker-compose" echo " logs [service] View logs (defaults to all services)" echo " status Show status of running services" + echo " openapi [path] Generate OpenAPI spec (default: docs/reference/openapi.json)" + echo " types Generate TypeScript types for frontend from OpenAPI spec" echo " help Show this help message" echo "" echo "Prod options:" @@ -331,6 +335,48 @@ deploy_helm() { fi } +# ============================================================================= +# OPENAPI SPEC GENERATION +# ============================================================================= +cmd_openapi() { + print_header "Generating OpenAPI Spec" + + local OUTPUT="${1:-docs/reference/openapi.json}" + + cd backend + print_info "Extracting schema from FastAPI app..." + + uv run python -c " +import json +from app.main import app +schema = app.openapi() +print(json.dumps(schema, indent=2)) +" > "../$OUTPUT" + + cd .. + print_success "OpenAPI spec written to $OUTPUT" +} + +# ============================================================================= +# TYPESCRIPT API CLIENT GENERATION +# ============================================================================= +cmd_types() { + print_header "Generating TypeScript API Client" + + # Ensure OpenAPI spec exists + if [[ ! -f "docs/reference/openapi.json" ]]; then + print_info "OpenAPI spec not found, generating first..." + cmd_openapi + fi + + cd frontend + print_info "Generating typed API client from OpenAPI spec..." + npm run generate:api + cd .. + + print_success "Typed API client generated in frontend/src/lib/api/" +} + # ============================================================================= # MAIN # ============================================================================= @@ -357,6 +403,12 @@ case "${1:-help}" in shift cmd_prod "$@" ;; + openapi) + cmd_openapi "$2" + ;; + types) + cmd_types + ;; help|--help|-h) show_help ;; diff --git a/docs/architecture/frontend-build.md b/docs/architecture/frontend-build.md new file mode 100644 index 00000000..8322a440 --- /dev/null +++ b/docs/architecture/frontend-build.md @@ -0,0 +1,376 @@ +# Frontend build system + +This document explains how the frontend codebase is built, what libraries are involved, and how different parts connect at compile time and runtime. It's written for developers who need to modify the build pipeline or understand how the frontend works. + +## Overview + +The frontend is a Svelte 5 single-page application bundled with Rollup. It uses TypeScript for type safety, Tailwind CSS v4 for styling, and a generated SDK for type-safe API calls. The build outputs static files to `public/build/` which are served by nginx in production or by a custom HTTPS dev server during development. + +For details on the Svelte 5 runes API and migration patterns, see [Svelte 5 Migration](svelte5-migration.md). + +```mermaid +graph LR + subgraph "Source" + Main["src/main.ts"] + Svelte["*.svelte"] + TS["*.ts"] + CSS["app.css"] + end + + subgraph "Generated" + SDK["src/lib/api/*"] + end + + subgraph "Build" + Rollup["Rollup"] + PostCSS["PostCSS"] + TWv4["Tailwind v4"] + end + + subgraph "Output" + JS["public/build/*.js"] + Styles["public/build/bundle.css"] + end + + Main --> Rollup + Svelte --> Rollup + TS --> Rollup + CSS --> PostCSS + PostCSS --> TWv4 + TWv4 --> Styles + SDK --> Rollup + Rollup --> JS +``` + +## Rollup configuration + +The `rollup.config.js` file configures the entire build pipeline. It produces ES modules with code splitting, enabling parallel loading of vendor code and application code. + +### Entry point + +The build starts from `src/main.ts`, which imports the API client setup, mounts the Svelte `App` component using Svelte 5's `mount()` function, and imports global CSS: + +```typescript +import { mount } from 'svelte'; +import './lib/api/setup'; +import App from './App.svelte'; +import './app.css'; + +const app = mount(App, { + target: document.body, +}); +``` + +### Code splitting + +Rollup splits the bundle into chunks to improve load performance. The `manualChunks` configuration separates large dependencies: + +| Chunk | Contents | +|-------|----------| +| `vendor` | Svelte, @mateothegreat/svelte5-router | +| `codemirror` | All CodeMirror packages for the editor | +| Application chunks | Route components and shared code | + +This means users don't re-download vendor code when application code changes, and the editor chunk only loads when needed. + +### Plugins + +The plugin pipeline processes files in order: + +1. **replace** — Substitutes `process.env.VITE_BACKEND_URL` with an empty string, allowing relative API paths +2. **svelte** — Compiles `.svelte` files with TypeScript preprocessing via `svelte-preprocess`, with `runes: true` enabled for Svelte 5 +3. **postcss** — Processes CSS through PostCSS, extracting styles to `bundle.css` +4. **typescript** — Compiles TypeScript files with source maps +5. **json** — Allows importing JSON files +6. **resolve** — Resolves `node_modules` imports for browser usage, preferring ES modules +7. **commonjs** — Converts CommonJS modules to ES modules +8. **terser** (production only) — Minifies JavaScript, removes console logs, runs two compression passes + +### Development server + +In development mode (`npm run dev`), Rollup watches for changes and a custom HTTPS server starts automatically. The server handles two responsibilities: + +1. **Static file serving** — Serves files from `public/`, falling back to `index.html` for SPA routing +2. **API proxying** — Forwards `/api/*` requests to the backend container over HTTPS + +The proxy uses a custom `https.Agent` that trusts the local CA certificate at `/shared_ca/mkcert-ca.pem`, allowing secure communication with the backend during development. The server listens on port 5001. + +## TypeScript configuration + +The `tsconfig.json` configures TypeScript compilation: + +- Target: ES2020 with ESNext modules +- Strict mode enabled +- Module resolution set to bundler mode for Rollup compatibility +- Svelte component types enabled via `svelte-preprocess` + +TypeScript catches type errors during development and the build fails if any exist, preventing broken code from reaching production. + +## API SDK generation + +The frontend uses a generated SDK for type-safe API calls instead of manual fetch requests. This SDK is created from the backend's OpenAPI specification using `@hey-api/openapi-ts`. + +### Generation pipeline + +```mermaid +graph LR + OpenAPI["docs/reference/openapi.json"] --> Generator["@hey-api/openapi-ts"] + Generator --> Types["types.gen.ts"] + Generator --> SDK["sdk.gen.ts"] + Generator --> Client["client.gen.ts"] +``` + +Run `npm run generate:api` to regenerate the SDK. The configuration in `openapi-ts.config.ts` specifies: + +- Input: `../docs/reference/openapi.json` (the backend's OpenAPI spec) +- Output: `src/lib/api/` with Prettier formatting +- Plugins: TypeScript types, SDK functions, and fetch client + +### Generated files + +| File | Purpose | +|------|---------| +| `types.gen.ts` | TypeScript interfaces for all request/response models | +| `sdk.gen.ts` | Function for each API endpoint, fully typed | +| `client.gen.ts` | HTTP client with interceptor support | +| `index.ts` | Re-exports types and SDK functions | +| `setup.ts` | Manual file that configures the client (not generated) | + +### Client configuration + +The `setup.ts` file configures the generated client: + +```typescript +client.setConfig({ + baseUrl: '', // Relative URLs, proxied in dev + credentials: 'include', // Send cookies for auth +}); + +client.interceptors.request.use((request) => { + const token = get(csrfToken); + if (token && ['POST', 'PUT', 'DELETE', 'PATCH'].includes(request.method)) { + request.headers.set('X-CSRF-Token', token); + } + return request; +}); +``` + +The interceptor automatically adds CSRF tokens to mutating requests, pulling the token from the auth store. This happens transparently for all SDK calls. + +### Usage pattern + +Components import SDK functions and types directly: + +```typescript +import { + getNotificationsApiV1NotificationsGet, + type NotificationResponse, +} from '../lib/api'; + +const { data, error } = await getNotificationsApiV1NotificationsGet({ + query: { limit: 20 } +}); +``` + +The SDK returns `{ data, error }` tuples, making error handling explicit without try/catch boilerplate. + +## Tailwind CSS v4 + +The frontend uses Tailwind CSS v4 with the new CSS-first configuration. Unlike v3, there's no `tailwind.config.js` — all configuration lives in CSS. + +### PostCSS integration + +PostCSS processes CSS through `@tailwindcss/postcss`: + +```javascript +// postcss.config.cjs +module.exports = { + plugins: { + "@tailwindcss/postcss": {}, + }, +} +``` + +### CSS configuration + +The `src/app.css` file contains all Tailwind configuration using v4's new at-rules: + +```css +/* Import Tailwind */ +@import "tailwindcss"; + +/* Forms plugin */ +@plugin "@tailwindcss/forms" { + strategy: class; +} + +/* Class-based dark mode */ +@variant dark (&:where(.dark, .dark *)); + +/* Custom theme tokens */ +@theme { + --color-primary: #3b82f6; + --color-bg-default: #f8fafc; + --font-sans: 'Inter', ui-sans-serif, system-ui; + /* ... */ +} + +/* Custom utilities */ +@utility animate-fadeIn { + animation: fadeIn 0.3s ease-in-out; +} +``` + +### Theme structure + +The theme defines semantic color tokens for both light and dark modes: + +| Token | Light | Dark | +|-------|-------|------| +| `bg-default` | `#f8fafc` | `#0f172a` | +| `fg-default` | `#1e293b` | `#e2e8f0` | +| `border-default` | `#e2e8f0` | `#334155` | + +Components use these tokens (e.g., `bg-bg-default dark:bg-dark-bg-default`) for consistent theming. The `@variant dark` rule enables the `.dark` class on `` to trigger dark mode. + +### Layer organization + +Styles are organized into Tailwind layers: + +- **base** — Element defaults, form styles, scrollbars, CodeMirror overrides +- **components** — Reusable patterns like `.btn`, `.card`, `.form-input-standard` + +## Svelte stores and runes + +The frontend uses a hybrid approach to state management: + +**Svelte stores** (`src/stores/`) handle global, shared state: + +| Store | Purpose | +|-------|---------| +| `auth.ts` | Authentication state, login/logout, CSRF token | +| `theme.ts` | Theme preference (light/dark/auto) with localStorage persistence | +| `toastStore.ts` | Toast notifications queue | +| `notificationStore.ts` | Server notifications with pagination | + +Stores use the generated SDK for API calls and persist state to localStorage where appropriate. The auth store exposes a `csrfToken` store that the API client interceptor reads for request signing. + +**Svelte 5 runes** (`$state`, `$derived`, `$effect`) handle component-local state: + +```svelte + + +{#if $isAuthenticated} + Items: {itemCount} +{/if} +``` + +For detailed patterns and migration guidance, see [Svelte 5 Migration](svelte5-migration.md). + +## Build commands + +| Command | Purpose | +|---------|---------| +| `npm run dev` | Start Rollup in watch mode with HTTPS dev server | +| `npm run build` | Production build with minification | +| `npm run generate:api` | Regenerate SDK from OpenAPI spec | + +## File structure + +``` +frontend/ +├── public/ +│ ├── index.html # HTML shell +│ └── build/ # Rollup output +├── src/ +│ ├── main.ts # Entry point +│ ├── App.svelte # Root component with routing +│ ├── app.css # Tailwind config and global styles +│ ├── components/ # Reusable components +│ ├── routes/ # Page components +│ ├── stores/ # Svelte stores +│ ├── lib/ +│ │ ├── api/ # Generated SDK + setup +│ │ ├── auth-init.ts # Auth verification on load +│ │ ├── settings-cache.ts +│ │ └── user-settings.ts +│ └── styles/ # Additional CSS modules +├── rollup.config.js # Build configuration +├── postcss.config.cjs # PostCSS plugins +├── tsconfig.json # TypeScript config +└── openapi-ts.config.ts # SDK generator config +``` + +## Local development + +Start the development stack: + +```bash +# From project root +docker compose up -d + +# In frontend directory +npm install +npm run dev +``` + +The dev server runs at `https://localhost:5001`. API requests proxy to the backend container. Changes to `.svelte`, `.ts`, and `.css` files trigger automatic rebuilds. + +### Regenerating the API client + +When backend endpoints change: + +1. Update the backend and restart it +2. Fetch the new OpenAPI spec (the docs workflow does this automatically) +3. Run `npm run generate:api` +4. Fix any TypeScript errors from changed types + +### Adding new routes + +1. Create a component in `src/routes/` +2. Add a `` entry in `App.svelte` +3. Use SDK functions for API calls +4. Use semantic color tokens for styling + +## Production build + +The production build runs `npm run build`, which: + +1. Compiles TypeScript with source maps +2. Processes Svelte components in production mode (no dev warnings) +3. Extracts and minifies CSS +4. Splits code into chunks +5. Minifies JavaScript with Terser (removes console.log) +6. Outputs to `public/build/` + +The Docker build copies `public/` to nginx, which serves static files and proxies `/api/` to the backend. + +## Troubleshooting + +### TypeScript errors after SDK regeneration + +If the backend changed response types, update components to match. The SDK provides exact types — check `types.gen.ts` for the new structure. + +### Styles not applying + +Ensure the class exists in Tailwind's default utilities or is defined in `app.css`. Check for typos in semantic token names (e.g., `bg-default` vs `bg-bg-default`). + +### Dev server certificate errors + +The dev server requires certificates at `./certs/server.key` and `./certs/server.crt`, and the CA at `/shared_ca/mkcert-ca.pem`. Run the cert-generator container first via Docker Compose. + +### API calls failing in development + +Verify the backend is running and healthy. The dev server proxies to `https://backend:443` — check Docker networking if the container can't resolve the hostname. diff --git a/docs/architecture/svelte5-migration.md b/docs/architecture/svelte5-migration.md new file mode 100644 index 00000000..684821de --- /dev/null +++ b/docs/architecture/svelte5-migration.md @@ -0,0 +1,684 @@ +# Svelte 5 migration + +This document explains the migration from Svelte 4 to Svelte 5, covering the new runes API, reactivity model, and +practical patterns used throughout the frontend. It serves as both a reference for understanding the current codebase +and a guide for future development. + +## Why Svelte 5 + +Svelte 5 introduces **runes** — a new reactivity system that replaces Svelte 4's implicit reactivity with explicit +declarations. The key benefits: + +| Svelte 4 | Svelte 5 | +|---------------------------------------------------------------------|------------------------------------------------------------------| +| `let count = 0` was implicitly reactive only at component top-level | `let count = $state(0)` is explicitly reactive anywhere | +| Reactivity couldn't be refactored into external files | Runes work in `.svelte.ts` files, enabling shared reactive logic | +| `$:` reactive statements mixed derivations and side effects | `$derived` and `$effect` separate concerns | +| Slots for component composition | Snippets provide more flexible composition | + +The migration also updated the router from `svelte-routing` to `@mateothegreat/svelte5-router`, which is designed for +Svelte 5's component model. + +## Runes overview + +Runes are compiler directives that look like function calls but are processed at compile time. They're available in +`.svelte` files and `.svelte.ts` files without imports. + +### $state + +Creates reactive state that triggers UI updates when modified: + +```svelte + + +{count} +``` + +**When to use `$state`:** + +- Variables displayed in the template that can change +- Variables controlling conditional rendering (`{#if loading}`) +- Arrays and objects that will be mutated +- Any state that should trigger re-renders + +**When NOT to use `$state`:** + +- DOM element references (`bind:this`) +- Cleanup functions and subscriptions +- Constants that never change +- Helper variables used only inside functions + +```svelte + +``` + +### $derived + +Creates computed values that automatically update when dependencies change: + +```svelte + +``` + +Use `$derived` for any value computed from reactive state. Use `$derived.by` when the computation needs multiple +statements. + +### $effect + +Runs side effects when dependencies change: + +```svelte + +``` + +!!! warning "Use $effect sparingly" +Most reactive needs are better served by `$derived`. Use `$effect` only for: + + - DOM manipulation outside Svelte's control + - External library integration + - Subscriptions and event listeners + - Logging and debugging + +### $props + +Declares component props with destructuring: + +```svelte + +``` + +## Event handlers + +Svelte 5 uses standard DOM event attributes instead of the `on:` directive: + +```svelte + +Click +Submit + + + +Click + { e.preventDefault(); submit(); }}>Submit + { e.preventDefault(); handleSubmit(); }}> +``` + +### Event modifier migration + +| Svelte 4 | Svelte 5 | +|-----------------------------|-----------------------------------------------------------------------| +| `on:click\|preventDefault` | `onclick={(e) => { e.preventDefault(); handler(); }}` | +| `on:click\|stopPropagation` | `onclick={(e) => { e.stopPropagation(); handler(); }}` | +| `on:keydown\|self` | `onkeydown={(e) => { if (e.target === e.currentTarget) handler(); }}` | + +All standard DOM events follow this pattern: `on:eventname` becomes `oneventname`. + +## Snippets (replacing slots) + +Snippets replace slots for component composition: + +```svelte + + + Title + Content goes here + + + + + + + +``` + +```svelte + + + {#snippet header()} + Title + {/snippet} + Content goes here + + + + + + + {#if header} + {@render header()} + {/if} + {@render children?.()} + +``` + +For simple cases with just a default slot: + +```svelte + + + +{#if authenticated} + {@render children?.()} +{/if} +``` + +## Component instantiation + +The `new Component()` syntax is replaced with `mount()`: + +```typescript +// Svelte 4: main.ts +import App from './App.svelte'; + +const app = new App({ + target: document.body, +}); + +// Svelte 5: main.ts +import {mount} from 'svelte'; +import App from './App.svelte'; + +const app = mount(App, { + target: document.body, +}); +``` + +## Router migration + +The frontend uses `@mateothegreat/svelte5-router` instead of `svelte-routing`: + +### API changes + +| svelte-routing | svelte5-router | +|---------------------------------------|---------------------------------------| +| `navigate('/path')` | `goto('/path')` | +| `` | `` | +| `` | `` | + +### Route configuration + +```svelte + + + + + + + + + + + + +``` + +### Programmatic navigation + +```svelte + +``` + +### Link styling with route action + +```svelte + + +Settings +Logout +``` + +## Stores compatibility + +Svelte stores (`writable`, `derived`, `readable`) work unchanged in Svelte 5. The `$store` auto-subscription syntax +continues to work: + +```svelte + + +{#if $isAuthenticated} + Welcome, {$username} +{/if} + + theme.set('dark')}> + Current: {$theme} + +``` + +!!! note "When to use stores vs runes" +- **Stores**: Shared state across components, persisted state, complex async state +- **Runes ($state)**: Component-local state, simple reactive values + + The existing stores (`auth.ts`, `theme.ts`, `toastStore.ts`) remain as stores because they manage global, shared state. + +## Build configuration + +### rollup.config.js + +The Svelte plugin requires the `runes: true` compiler option: + +```javascript +import svelte from 'rollup-plugin-svelte'; +import sveltePreprocess from 'svelte-preprocess'; + +export default { + plugins: [ + svelte({ + preprocess: sveltePreprocess({postcss: true}), + compilerOptions: { + dev: !production, + runes: true, // Enable runes mode + }, + }), + // ... other plugins + ], +}; +``` + +### package.json dependencies + +```json +{ + "dependencies": { + "svelte": "^5.46.0", + "@mateothegreat/svelte5-router": "^2.16.19" + }, + "devDependencies": { + "svelte-preprocess": "^6.0.3" + } +} +``` + +## Migration patterns + +### Pattern 1: Simple reactive variable + +```svelte + + + + + +``` + +### Pattern 2: Reactive statement with side effect + +```svelte + + + + + +``` + +### Pattern 3: Form with loading state + +```svelte + + + + + + + + + { e.preventDefault(); handleSubmit(); }}> +``` + +### Pattern 4: Component with props and children + +```svelte + + + + + + + + + +``` + +### Pattern 5: Cleanup with subscriptions + +```svelte + + + + + +``` + +## Common pitfalls + +### Destructuring reactive values + +Destructuring breaks reactivity: + +```svelte + +``` + +### Missing $state on mutable variables + +Variables that are reassigned AND displayed in the template need `$state`: + +```svelte + + + count++}>{count} +``` + +### Using $effect for derivations + +```svelte + +``` + +### Self-closing non-void elements + +HTML elements like ``, ``, `` cannot be self-closing: + +```svelte + + + + + + + +``` + +## File-by-file changes + +### Critical files + +| File | Changes | +|-------------------------|----------------------------------------| +| `main.ts` | `new App()` → `mount(App, { target })` | +| `App.svelte` | Router imports, `$derived` for theme | +| `ProtectedRoute.svelte` | `$props`, snippet children, `goto()` | +| `AdminLayout.svelte` | `$props`, snippet children | + +### Components with $state + +| File | State variables | +|-----------------------------|----------------------------------------------------------| +| `Header.svelte` | `isMenuActive`, `isMobile`, `showUserDropdown` | +| `Editor.svelte` | `executing`, `result`, `showLimits`, `showOptions`, etc. | +| `ToastContainer.svelte` | `toastList` | +| `NotificationCenter.svelte` | `showDropdown`, `loading`, `notifications` | +| `Spinner.svelte` | None (uses `$derived` for `sizeClass`) | + +### Components with event syntax updates + +All components using `on:click`, `on:submit`, `on:change`, etc. were updated to `onclick`, `onsubmit`, `onchange`. This +includes all form components, buttons, and interactive elements. + +## Verification + +After migration, verify the build succeeds without warnings: + +```bash +cd frontend +npm run build +``` + +Expected output shows only Svelte internal circular dependency notes (normal for Svelte 5): + +``` +src/main.ts → public/build... +(!) Circular dependencies +node_modules/svelte/src/internal/... +...and 34 more +created public/build in 12.5s +``` + +Test the application: + +- [ ] All routes navigate correctly +- [ ] Authentication flow works (login/logout) +- [ ] Protected routes redirect properly +- [ ] Theme switching works +- [ ] Notifications display and update +- [ ] Toast messages appear +- [ ] Editor loads and executes code +- [ ] Admin pages function correctly + +## References + +- [Svelte 5 Documentation](https://svelte.dev/docs/svelte) +- [Svelte 5 Migration Guide](https://svelte.dev/docs/svelte/v5-migration-guide) +- [$state Rune](https://svelte.dev/docs/svelte/$state) +- [$derived Rune](https://svelte.dev/docs/svelte/$derived) +- [$effect Rune](https://svelte.dev/docs/svelte/$effect) +- [svelte5-router](https://github.com/mateothegreat/svelte5-router) diff --git a/docs/reference/openapi.json b/docs/reference/openapi.json new file mode 100644 index 00000000..2e243585 --- /dev/null +++ b/docs/reference/openapi.json @@ -0,0 +1,8935 @@ +{ + "openapi": "3.1.0", + "info": { + "title": "integr8scode", + "version": "0.1.0" + }, + "paths": { + "/api/v1/auth/login": { + "post": { + "tags": [ + "authentication" + ], + "summary": "Login", + "operationId": "login_api_v1_auth_login_post", + "requestBody": { + "content": { + "application/x-www-form-urlencoded": { + "schema": { + "$ref": "#/components/schemas/Body_login_api_v1_auth_login_post" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/LoginResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/auth/register": { + "post": { + "tags": [ + "authentication" + ], + "summary": "Register", + "operationId": "register_api_v1_auth_register_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserCreate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/auth/me": { + "get": { + "tags": [ + "authentication" + ], + "summary": "Get Current User Profile", + "operationId": "get_current_user_profile_api_v1_auth_me_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserResponse" + } + } + } + } + } + } + }, + "/api/v1/auth/verify-token": { + "get": { + "tags": [ + "authentication" + ], + "summary": "Verify Token", + "operationId": "verify_token_api_v1_auth_verify_token_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/TokenValidationResponse" + } + } + } + } + } + } + }, + "/api/v1/auth/logout": { + "post": { + "tags": [ + "authentication" + ], + "summary": "Logout", + "operationId": "logout_api_v1_auth_logout_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageResponse" + } + } + } + } + } + } + }, + "/api/v1/execute": { + "post": { + "summary": "Create Execution", + "operationId": "create_execution_api_v1_execute_post", + "parameters": [ + { + "name": "Idempotency-Key", + "in": "header", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Idempotency-Key" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecutionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecutionResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/result/{execution_id}": { + "get": { + "summary": "Get Result", + "operationId": "get_result_api_v1_result__execution_id__get", + "parameters": [ + { + "name": "execution_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Execution Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecutionResult" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/{execution_id}/cancel": { + "post": { + "summary": "Cancel Execution", + "operationId": "cancel_execution_api_v1__execution_id__cancel_post", + "parameters": [ + { + "name": "execution_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Execution Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CancelExecutionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CancelResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/{execution_id}/retry": { + "post": { + "summary": "Retry Execution", + "description": "Retry a failed or completed execution.", + "operationId": "retry_execution_api_v1__execution_id__retry_post", + "parameters": [ + { + "name": "execution_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Execution Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RetryExecutionRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecutionResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/executions/{execution_id}/events": { + "get": { + "summary": "Get Execution Events", + "description": "Get all events for an execution.", + "operationId": "get_execution_events_api_v1_executions__execution_id__events_get", + "parameters": [ + { + "name": "execution_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Execution Id" + } + }, + { + "name": "event_types", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Comma-separated event types to filter", + "title": "Event Types" + }, + "description": "Comma-separated event types to filter" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "minimum": 1, + "default": 100, + "title": "Limit" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/ExecutionEventResponse" + }, + "title": "Response Get Execution Events Api V1 Executions Execution Id Events Get" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/user/executions": { + "get": { + "summary": "Get User Executions", + "description": "Get executions for the current user.", + "operationId": "get_user_executions_api_v1_user_executions_get", + "parameters": [ + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/ExecutionStatus" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "name": "lang", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Lang" + } + }, + { + "name": "start_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Time" + } + }, + { + "name": "end_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Time" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 200, + "minimum": 1, + "default": 50, + "title": "Limit" + } + }, + { + "name": "skip", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Skip" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExecutionListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/example-scripts": { + "get": { + "summary": "Get Example Scripts", + "operationId": "get_example_scripts_api_v1_example_scripts_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ExampleScripts" + } + } + } + } + } + } + }, + "/api/v1/k8s-limits": { + "get": { + "summary": "Get K8S Resource Limits", + "operationId": "get_k8s_resource_limits_api_v1_k8s_limits_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ResourceLimits" + } + } + } + } + } + } + }, + "/api/v1/{execution_id}": { + "delete": { + "summary": "Delete Execution", + "description": "Delete an execution and its associated data (admin only).", + "operationId": "delete_execution_api_v1__execution_id__delete", + "parameters": [ + { + "name": "execution_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Execution Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/scripts": { + "get": { + "summary": "List Saved Scripts", + "operationId": "list_saved_scripts_api_v1_scripts_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/SavedScriptResponse" + }, + "type": "array", + "title": "Response List Saved Scripts Api V1 Scripts Get" + } + } + } + } + } + }, + "post": { + "summary": "Create Saved Script", + "operationId": "create_saved_script_api_v1_scripts_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SavedScriptCreateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SavedScriptResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/scripts/{script_id}": { + "get": { + "summary": "Get Saved Script", + "operationId": "get_saved_script_api_v1_scripts__script_id__get", + "parameters": [ + { + "name": "script_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Script Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SavedScriptResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "put": { + "summary": "Update Saved Script", + "operationId": "update_saved_script_api_v1_scripts__script_id__put", + "parameters": [ + { + "name": "script_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Script Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SavedScriptCreateRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SavedScriptResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "summary": "Delete Saved Script", + "operationId": "delete_saved_script_api_v1_scripts__script_id__delete", + "parameters": [ + { + "name": "script_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Script Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/replay/sessions": { + "post": { + "tags": [ + "Event Replay" + ], + "summary": "Create Replay Session", + "operationId": "create_replay_session_api_v1_replay_sessions_post", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplayRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplayResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "get": { + "tags": [ + "Event Replay" + ], + "summary": "List Replay Sessions", + "operationId": "list_replay_sessions_api_v1_replay_sessions_get", + "parameters": [ + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/ReplayStatus" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "minimum": 1, + "default": 100, + "title": "Limit" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "array", + "items": { + "$ref": "#/components/schemas/SessionSummary" + }, + "title": "Response List Replay Sessions Api V1 Replay Sessions Get" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/replay/sessions/{session_id}/start": { + "post": { + "tags": [ + "Event Replay" + ], + "summary": "Start Replay Session", + "operationId": "start_replay_session_api_v1_replay_sessions__session_id__start_post", + "parameters": [ + { + "name": "session_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Session Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplayResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/replay/sessions/{session_id}/pause": { + "post": { + "tags": [ + "Event Replay" + ], + "summary": "Pause Replay Session", + "operationId": "pause_replay_session_api_v1_replay_sessions__session_id__pause_post", + "parameters": [ + { + "name": "session_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Session Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplayResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/replay/sessions/{session_id}/resume": { + "post": { + "tags": [ + "Event Replay" + ], + "summary": "Resume Replay Session", + "operationId": "resume_replay_session_api_v1_replay_sessions__session_id__resume_post", + "parameters": [ + { + "name": "session_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Session Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplayResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/replay/sessions/{session_id}/cancel": { + "post": { + "tags": [ + "Event Replay" + ], + "summary": "Cancel Replay Session", + "operationId": "cancel_replay_session_api_v1_replay_sessions__session_id__cancel_post", + "parameters": [ + { + "name": "session_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Session Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplayResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/replay/sessions/{session_id}": { + "get": { + "tags": [ + "Event Replay" + ], + "summary": "Get Replay Session", + "operationId": "get_replay_session_api_v1_replay_sessions__session_id__get", + "parameters": [ + { + "name": "session_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Session Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplaySession" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/replay/cleanup": { + "post": { + "tags": [ + "Event Replay" + ], + "summary": "Cleanup Old Sessions", + "operationId": "cleanup_old_sessions_api_v1_replay_cleanup_post", + "parameters": [ + { + "name": "older_than_hours", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 1, + "default": 24, + "title": "Older Than Hours" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/CleanupResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/health/live": { + "get": { + "tags": [ + "Health" + ], + "summary": "Liveness", + "description": "Basic liveness probe. Does not touch external deps.", + "operationId": "liveness_api_v1_health_live_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Response Liveness Api V1 Health Live Get" + } + } + } + } + } + } + }, + "/api/v1/health/ready": { + "get": { + "tags": [ + "Health" + ], + "summary": "Readiness", + "description": "Simple readiness probe. Extend with dependency checks if needed.", + "operationId": "readiness_api_v1_health_ready_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Response Readiness Api V1 Health Ready Get" + } + } + } + } + } + } + }, + "/api/v1/dlq/stats": { + "get": { + "tags": [ + "Dead Letter Queue" + ], + "summary": "Get Dlq Statistics", + "operationId": "get_dlq_statistics_api_v1_dlq_stats_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DLQStats" + } + } + } + } + } + } + }, + "/api/v1/dlq/messages": { + "get": { + "tags": [ + "Dead Letter Queue" + ], + "summary": "Get Dlq Messages", + "operationId": "get_dlq_messages_api_v1_dlq_messages_get", + "parameters": [ + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/DLQMessageStatus" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "name": "topic", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Topic" + } + }, + { + "name": "event_type", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Event Type" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "minimum": 1, + "default": 50, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Offset" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DLQMessagesResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/dlq/messages/{event_id}": { + "get": { + "tags": [ + "Dead Letter Queue" + ], + "summary": "Get Dlq Message", + "operationId": "get_dlq_message_api_v1_dlq_messages__event_id__get", + "parameters": [ + { + "name": "event_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Event Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DLQMessageDetail" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "Dead Letter Queue" + ], + "summary": "Discard Dlq Message", + "operationId": "discard_dlq_message_api_v1_dlq_messages__event_id__delete", + "parameters": [ + { + "name": "event_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Event Id" + } + }, + { + "name": "reason", + "in": "query", + "required": true, + "schema": { + "type": "string", + "description": "Reason for discarding", + "title": "Reason" + }, + "description": "Reason for discarding" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/dlq/retry": { + "post": { + "tags": [ + "Dead Letter Queue" + ], + "summary": "Retry Dlq Messages", + "operationId": "retry_dlq_messages_api_v1_dlq_retry_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ManualRetryRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DLQBatchRetryResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/dlq/retry-policy": { + "post": { + "tags": [ + "Dead Letter Queue" + ], + "summary": "Set Retry Policy", + "operationId": "set_retry_policy_api_v1_dlq_retry_policy_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RetryPolicyRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/dlq/topics": { + "get": { + "tags": [ + "Dead Letter Queue" + ], + "summary": "Get Dlq Topics", + "operationId": "get_dlq_topics_api_v1_dlq_topics_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "$ref": "#/components/schemas/DLQTopicSummaryResponse" + }, + "type": "array", + "title": "Response Get Dlq Topics Api V1 Dlq Topics Get" + } + } + } + } + } + } + }, + "/api/v1/events/notifications/stream": { + "get": { + "tags": [ + "sse" + ], + "summary": "Notification Stream", + "description": "Stream notifications for authenticated user.", + "operationId": "notification_stream_api_v1_events_notifications_stream_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + } + } + } + }, + "/api/v1/events/executions/{execution_id}": { + "get": { + "tags": [ + "sse" + ], + "summary": "Execution Events", + "description": "Stream events for specific execution.", + "operationId": "execution_events_api_v1_events_executions__execution_id__get", + "parameters": [ + { + "name": "execution_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Execution Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/health": { + "get": { + "tags": [ + "sse" + ], + "summary": "Sse Health", + "description": "Get SSE service health status.", + "operationId": "sse_health_api_v1_events_health_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SSEHealthResponse" + } + } + } + } + } + } + }, + "/api/v1/events/executions/{execution_id}/events": { + "get": { + "tags": [ + "events" + ], + "summary": "Get Execution Events", + "operationId": "get_execution_events_api_v1_events_executions__execution_id__events_get", + "parameters": [ + { + "name": "execution_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Execution Id" + } + }, + { + "name": "include_system_events", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Include system-generated events", + "default": false, + "title": "Include System Events" + }, + "description": "Include system-generated events" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/user": { + "get": { + "tags": [ + "events" + ], + "summary": "Get User Events", + "description": "Get events for the current user", + "operationId": "get_user_events_api_v1_events_user_get", + "parameters": [ + { + "name": "event_types", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "title": "Event Types" + } + }, + { + "name": "start_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Time" + } + }, + { + "name": "end_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Time" + } + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "minimum": 1, + "default": 100, + "title": "Limit" + } + }, + { + "name": "skip", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Skip" + } + }, + { + "name": "sort_order", + "in": "query", + "required": false, + "schema": { + "$ref": "#/components/schemas/SortOrder", + "default": "desc" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/query": { + "post": { + "tags": [ + "events" + ], + "summary": "Query Events", + "operationId": "query_events_api_v1_events_query_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventFilterRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/correlation/{correlation_id}": { + "get": { + "tags": [ + "events" + ], + "summary": "Get Events By Correlation", + "operationId": "get_events_by_correlation_api_v1_events_correlation__correlation_id__get", + "parameters": [ + { + "name": "correlation_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Correlation Id" + } + }, + { + "name": "include_all_users", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Include events from all users (admin only)", + "default": false, + "title": "Include All Users" + }, + "description": "Include events from all users (admin only)" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "minimum": 1, + "default": 100, + "title": "Limit" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/current-request": { + "get": { + "tags": [ + "events" + ], + "summary": "Get Current Request Events", + "operationId": "get_current_request_events_api_v1_events_current_request_get", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "minimum": 1, + "default": 100, + "title": "Limit" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/statistics": { + "get": { + "tags": [ + "events" + ], + "summary": "Get Event Statistics", + "operationId": "get_event_statistics_api_v1_events_statistics_get", + "parameters": [ + { + "name": "start_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Start time for statistics (defaults to 24 hours ago)", + "title": "Start Time" + }, + "description": "Start time for statistics (defaults to 24 hours ago)" + }, + { + "name": "end_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "End time for statistics (defaults to now)", + "title": "End Time" + }, + "description": "End time for statistics (defaults to now)" + }, + { + "name": "include_all_users", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Include stats from all users (admin only)", + "default": false, + "title": "Include All Users" + }, + "description": "Include stats from all users (admin only)" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventStatistics" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/{event_id}": { + "get": { + "tags": [ + "events" + ], + "summary": "Get Event", + "description": "Get a specific event by ID", + "operationId": "get_event_api_v1_events__event_id__get", + "parameters": [ + { + "name": "event_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Event Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "events" + ], + "summary": "Delete Event", + "operationId": "delete_event_api_v1_events__event_id__delete", + "parameters": [ + { + "name": "event_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Event Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteEventResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/publish": { + "post": { + "tags": [ + "events" + ], + "summary": "Publish Custom Event", + "operationId": "publish_custom_event_api_v1_events_publish_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublishEventRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PublishEventResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/aggregate": { + "post": { + "tags": [ + "events" + ], + "summary": "Aggregate Events", + "operationId": "aggregate_events_api_v1_events_aggregate_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventAggregationRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Response Aggregate Events Api V1 Events Aggregate Post" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/events/types/list": { + "get": { + "tags": [ + "events" + ], + "summary": "List Event Types", + "operationId": "list_event_types_api_v1_events_types_list_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Response List Event Types Api V1 Events Types List Get" + } + } + } + } + } + } + }, + "/api/v1/events/replay/{aggregate_id}": { + "post": { + "tags": [ + "events" + ], + "summary": "Replay Aggregate Events", + "operationId": "replay_aggregate_events_api_v1_events_replay__aggregate_id__post", + "parameters": [ + { + "name": "aggregate_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Aggregate Id" + } + }, + { + "name": "target_service", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Service to replay events to", + "title": "Target Service" + }, + "description": "Service to replay events to" + }, + { + "name": "dry_run", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "If true, only show what would be replayed", + "default": true, + "title": "Dry Run" + }, + "description": "If true, only show what would be replayed" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ReplayAggregateResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/events/browse": { + "post": { + "tags": [ + "admin-events" + ], + "summary": "Browse Events", + "operationId": "browse_events_api_v1_admin_events_browse_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventBrowseRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventBrowseResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/events/stats": { + "get": { + "tags": [ + "admin-events" + ], + "summary": "Get Event Stats", + "operationId": "get_event_stats_api_v1_admin_events_stats_get", + "parameters": [ + { + "name": "hours", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 168, + "default": 24, + "title": "Hours" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventStatsResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/events/{event_id}": { + "get": { + "tags": [ + "admin-events" + ], + "summary": "Get Event Detail", + "operationId": "get_event_detail_api_v1_admin_events__event_id__get", + "parameters": [ + { + "name": "event_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Event Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventDetailResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "admin-events" + ], + "summary": "Delete Event", + "operationId": "delete_event_api_v1_admin_events__event_id__delete", + "parameters": [ + { + "name": "event_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Event Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventDeleteResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/events/replay": { + "post": { + "tags": [ + "admin-events" + ], + "summary": "Replay Events", + "operationId": "replay_events_api_v1_admin_events_replay_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventReplayRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventReplayResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/events/replay/{session_id}/status": { + "get": { + "tags": [ + "admin-events" + ], + "summary": "Get Replay Status", + "operationId": "get_replay_status_api_v1_admin_events_replay__session_id__status_get", + "parameters": [ + { + "name": "session_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Session Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EventReplayStatusResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/events/export/csv": { + "get": { + "tags": [ + "admin-events" + ], + "summary": "Export Events Csv", + "operationId": "export_events_csv_api_v1_admin_events_export_csv_get", + "parameters": [ + { + "name": "event_types", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/components/schemas/EventType" + } + }, + { + "type": "null" + } + ], + "description": "Event types (repeat param for multiple)", + "title": "Event Types" + }, + "description": "Event types (repeat param for multiple)" + }, + { + "name": "start_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Start time", + "title": "Start Time" + }, + "description": "Start time" + }, + { + "name": "end_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "End time", + "title": "End Time" + }, + "description": "End time" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 50000, + "default": 10000, + "title": "Limit" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/events/export/json": { + "get": { + "tags": [ + "admin-events" + ], + "summary": "Export Events Json", + "description": "Export events as JSON with comprehensive filtering.", + "operationId": "export_events_json_api_v1_admin_events_export_json_get", + "parameters": [ + { + "name": "event_types", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "$ref": "#/components/schemas/EventType" + } + }, + { + "type": "null" + } + ], + "description": "Event types (repeat param for multiple)", + "title": "Event Types" + }, + "description": "Event types (repeat param for multiple)" + }, + { + "name": "aggregate_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Aggregate ID filter", + "title": "Aggregate Id" + }, + "description": "Aggregate ID filter" + }, + { + "name": "correlation_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Correlation ID filter", + "title": "Correlation Id" + }, + "description": "Correlation ID filter" + }, + { + "name": "user_id", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "User ID filter", + "title": "User Id" + }, + "description": "User ID filter" + }, + { + "name": "service_name", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Service name filter", + "title": "Service Name" + }, + "description": "Service name filter" + }, + { + "name": "start_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "Start time", + "title": "Start Time" + }, + "description": "Start time" + }, + { + "name": "end_time", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "description": "End time", + "title": "End Time" + }, + "description": "End time" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 50000, + "default": 10000, + "title": "Limit" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": {} + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/settings/": { + "get": { + "tags": [ + "admin", + "settings" + ], + "summary": "Get System Settings", + "operationId": "get_system_settings_api_v1_admin_settings__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SystemSettings" + } + } + } + } + } + }, + "put": { + "tags": [ + "admin", + "settings" + ], + "summary": "Update System Settings", + "operationId": "update_system_settings_api_v1_admin_settings__put", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SystemSettings" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SystemSettings" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/settings/reset": { + "post": { + "tags": [ + "admin", + "settings" + ], + "summary": "Reset System Settings", + "operationId": "reset_system_settings_api_v1_admin_settings_reset_post", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SystemSettings" + } + } + } + } + } + } + }, + "/api/v1/admin/users/": { + "get": { + "tags": [ + "admin", + "users" + ], + "summary": "List Users", + "operationId": "list_users_api_v1_admin_users__get", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "default": 100, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Offset" + } + }, + { + "name": "search", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search" + } + }, + { + "name": "role", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/UserRole" + }, + { + "type": "null" + } + ], + "title": "Role" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "post": { + "tags": [ + "admin", + "users" + ], + "summary": "Create User", + "description": "Create a new user (admin only).", + "operationId": "create_user_api_v1_admin_users__post", + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserCreate" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/users/{user_id}": { + "get": { + "tags": [ + "admin", + "users" + ], + "summary": "Get User", + "operationId": "get_user_api_v1_admin_users__user_id__get", + "parameters": [ + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "User Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "put": { + "tags": [ + "admin", + "users" + ], + "summary": "Update User", + "operationId": "update_user_api_v1_admin_users__user_id__put", + "parameters": [ + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "User Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "delete": { + "tags": [ + "admin", + "users" + ], + "summary": "Delete User", + "operationId": "delete_user_api_v1_admin_users__user_id__delete", + "parameters": [ + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "User Id" + } + }, + { + "name": "cascade", + "in": "query", + "required": false, + "schema": { + "type": "boolean", + "description": "Cascade delete user's data", + "default": true, + "title": "Cascade" + }, + "description": "Cascade delete user's data" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Response Delete User Api V1 Admin Users User Id Delete" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/users/{user_id}/overview": { + "get": { + "tags": [ + "admin", + "users" + ], + "summary": "Get User Overview", + "operationId": "get_user_overview_api_v1_admin_users__user_id__overview_get", + "parameters": [ + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "User Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AdminUserOverview" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/users/{user_id}/reset-password": { + "post": { + "tags": [ + "admin", + "users" + ], + "summary": "Reset User Password", + "operationId": "reset_user_password_api_v1_admin_users__user_id__reset_password_post", + "parameters": [ + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "User Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/PasswordResetRequest" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/users/{user_id}/rate-limits": { + "get": { + "tags": [ + "admin", + "users" + ], + "summary": "Get User Rate Limits", + "operationId": "get_user_rate_limits_api_v1_admin_users__user_id__rate_limits_get", + "parameters": [ + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "User Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Response Get User Rate Limits Api V1 Admin Users User Id Rate Limits Get" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + }, + "put": { + "tags": [ + "admin", + "users" + ], + "summary": "Update User Rate Limits", + "operationId": "update_user_rate_limits_api_v1_admin_users__user_id__rate_limits_put", + "parameters": [ + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "User Id" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserRateLimit" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Response Update User Rate Limits Api V1 Admin Users User Id Rate Limits Put" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/admin/users/{user_id}/rate-limits/reset": { + "post": { + "tags": [ + "admin", + "users" + ], + "summary": "Reset User Rate Limits", + "operationId": "reset_user_rate_limits_api_v1_admin_users__user_id__rate_limits_reset_post", + "parameters": [ + { + "name": "user_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "User Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/MessageResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/user/settings/": { + "get": { + "tags": [ + "user-settings" + ], + "summary": "Get User Settings", + "operationId": "get_user_settings_api_v1_user_settings__get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettings" + } + } + } + } + } + }, + "put": { + "tags": [ + "user-settings" + ], + "summary": "Update User Settings", + "operationId": "update_user_settings_api_v1_user_settings__put", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettingsUpdate" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettings" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/user/settings/theme": { + "put": { + "tags": [ + "user-settings" + ], + "summary": "Update Theme", + "operationId": "update_theme_api_v1_user_settings_theme_put", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/ThemeUpdateRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettings" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/user/settings/notifications": { + "put": { + "tags": [ + "user-settings" + ], + "summary": "Update Notification Settings", + "operationId": "update_notification_settings_api_v1_user_settings_notifications_put", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotificationSettings" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettings" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/user/settings/editor": { + "put": { + "tags": [ + "user-settings" + ], + "summary": "Update Editor Settings", + "operationId": "update_editor_settings_api_v1_user_settings_editor_put", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/EditorSettings" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettings" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/user/settings/history": { + "get": { + "tags": [ + "user-settings" + ], + "summary": "Get Settings History", + "operationId": "get_settings_history_api_v1_user_settings_history_get", + "parameters": [ + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "default": 50, + "title": "Limit" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SettingsHistoryResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/user/settings/restore": { + "post": { + "tags": [ + "user-settings" + ], + "summary": "Restore Settings", + "operationId": "restore_settings_api_v1_user_settings_restore_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/RestoreSettingsRequest" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettings" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/user/settings/custom/{key}": { + "put": { + "tags": [ + "user-settings" + ], + "summary": "Update Custom Setting", + "operationId": "update_custom_setting_api_v1_user_settings_custom__key__put", + "parameters": [ + { + "name": "key", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Key" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "type": "object", + "title": "Value" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UserSettings" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/notifications": { + "get": { + "tags": [ + "notifications" + ], + "summary": "Get Notifications", + "operationId": "get_notifications_api_v1_notifications_get", + "parameters": [ + { + "name": "status", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/NotificationStatus" + }, + { + "type": "null" + } + ], + "title": "Status" + } + }, + { + "name": "include_tags", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Only notifications with any of these tags", + "title": "Include Tags" + }, + "description": "Only notifications with any of these tags" + }, + { + "name": "exclude_tags", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "array", + "items": { + "type": "string" + } + }, + { + "type": "null" + } + ], + "description": "Exclude notifications with any of these tags", + "title": "Exclude Tags" + }, + "description": "Exclude notifications with any of these tags" + }, + { + "name": "tag_prefix", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "description": "Only notifications having a tag starting with this prefix", + "title": "Tag Prefix" + }, + "description": "Only notifications having a tag starting with this prefix" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 100, + "minimum": 1, + "default": 50, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Offset" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotificationListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/notifications/{notification_id}/read": { + "put": { + "tags": [ + "notifications" + ], + "summary": "Mark Notification Read", + "operationId": "mark_notification_read_api_v1_notifications__notification_id__read_put", + "parameters": [ + { + "name": "notification_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Notification Id" + } + } + ], + "responses": { + "204": { + "description": "Successful Response" + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/notifications/mark-all-read": { + "post": { + "tags": [ + "notifications" + ], + "summary": "Mark All Read", + "operationId": "mark_all_read_api_v1_notifications_mark_all_read_post", + "responses": { + "204": { + "description": "Successful Response" + } + } + } + }, + "/api/v1/notifications/subscriptions": { + "get": { + "tags": [ + "notifications" + ], + "summary": "Get Subscriptions", + "operationId": "get_subscriptions_api_v1_notifications_subscriptions_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionsResponse" + } + } + } + } + } + } + }, + "/api/v1/notifications/subscriptions/{channel}": { + "put": { + "tags": [ + "notifications" + ], + "summary": "Update Subscription", + "operationId": "update_subscription_api_v1_notifications_subscriptions__channel__put", + "parameters": [ + { + "name": "channel", + "in": "path", + "required": true, + "schema": { + "$ref": "#/components/schemas/NotificationChannel" + } + } + ], + "requestBody": { + "required": true, + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SubscriptionUpdate" + } + } + } + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/NotificationSubscription" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/notifications/unread-count": { + "get": { + "tags": [ + "notifications" + ], + "summary": "Get Unread Count", + "operationId": "get_unread_count_api_v1_notifications_unread_count_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/UnreadCountResponse" + } + } + } + } + } + } + }, + "/api/v1/notifications/{notification_id}": { + "delete": { + "tags": [ + "notifications" + ], + "summary": "Delete Notification", + "operationId": "delete_notification_api_v1_notifications__notification_id__delete", + "parameters": [ + { + "name": "notification_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Notification Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/DeleteNotificationResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/sagas/{saga_id}": { + "get": { + "tags": [ + "sagas" + ], + "summary": "Get Saga Status", + "description": "Get saga status by ID.\n\nArgs:\n saga_id: The saga identifier\n request: FastAPI request object\n saga_service: Saga service from DI\n auth_service: Auth service from DI\n \nReturns:\n Saga status response\n \nRaises:\n HTTPException: 404 if saga not found, 403 if access denied", + "operationId": "get_saga_status_api_v1_sagas__saga_id__get", + "parameters": [ + { + "name": "saga_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Saga Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SagaStatusResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/sagas/execution/{execution_id}": { + "get": { + "tags": [ + "sagas" + ], + "summary": "Get Execution Sagas", + "description": "Get all sagas for an execution.\n\nArgs:\n execution_id: The execution identifier\n request: FastAPI request object\n saga_service: Saga service from DI\n auth_service: Auth service from DI\n state: Optional state filter\n \nReturns:\n List of sagas for the execution\n \nRaises:\n HTTPException: 403 if access denied", + "operationId": "get_execution_sagas_api_v1_sagas_execution__execution_id__get", + "parameters": [ + { + "name": "execution_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Execution Id" + } + }, + { + "name": "state", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/SagaState" + }, + { + "type": "null" + } + ], + "description": "Filter by saga state", + "title": "State" + }, + "description": "Filter by saga state" + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SagaListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/sagas/": { + "get": { + "tags": [ + "sagas" + ], + "summary": "List Sagas", + "description": "List sagas accessible by the current user.\n\nArgs:\n request: FastAPI request object\n saga_service: Saga service from DI\n auth_service: Auth service from DI\n state: Optional state filter\n limit: Maximum number of results\n offset: Number of results to skip\n \nReturns:\n Paginated list of sagas", + "operationId": "list_sagas_api_v1_sagas__get", + "parameters": [ + { + "name": "state", + "in": "query", + "required": false, + "schema": { + "anyOf": [ + { + "$ref": "#/components/schemas/SagaState" + }, + { + "type": "null" + } + ], + "description": "Filter by saga state", + "title": "State" + }, + "description": "Filter by saga state" + }, + { + "name": "limit", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "maximum": 1000, + "minimum": 1, + "default": 100, + "title": "Limit" + } + }, + { + "name": "offset", + "in": "query", + "required": false, + "schema": { + "type": "integer", + "minimum": 0, + "default": 0, + "title": "Offset" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SagaListResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/sagas/{saga_id}/cancel": { + "post": { + "tags": [ + "sagas" + ], + "summary": "Cancel Saga", + "description": "Cancel a running saga.\n\nArgs:\n saga_id: The saga identifier\n request: FastAPI request object\n saga_service: Saga service from DI\n auth_service: Auth service from DI\n \nReturns:\n Cancellation response with success status\n \nRaises:\n HTTPException: 404 if not found, 403 if denied, 400 if invalid state", + "operationId": "cancel_saga_api_v1_sagas__saga_id__cancel_post", + "parameters": [ + { + "name": "saga_id", + "in": "path", + "required": true, + "schema": { + "type": "string", + "title": "Saga Id" + } + } + ], + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/SagaCancellationResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/alerts/grafana": { + "post": { + "tags": [ + "alerts" + ], + "summary": "Receive Grafana Alerts", + "operationId": "receive_grafana_alerts_api_v1_alerts_grafana_post", + "requestBody": { + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/GrafanaWebhook" + } + } + }, + "required": true + }, + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/AlertResponse" + } + } + } + }, + "422": { + "description": "Validation Error", + "content": { + "application/json": { + "schema": { + "$ref": "#/components/schemas/HTTPValidationError" + } + } + } + } + } + } + }, + "/api/v1/alerts/grafana/test": { + "get": { + "tags": [ + "alerts" + ], + "summary": "Test Grafana Alert Endpoint", + "operationId": "test_grafana_alert_endpoint_api_v1_alerts_grafana_test_get", + "responses": { + "200": { + "description": "Successful Response", + "content": { + "application/json": { + "schema": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Response Test Grafana Alert Endpoint Api V1 Alerts Grafana Test Get" + } + } + } + } + } + } + } + }, + "components": { + "schemas": { + "AdminUserOverview": { + "properties": { + "user": { + "$ref": "#/components/schemas/UserResponse" + }, + "stats": { + "$ref": "#/components/schemas/EventStatistics" + }, + "derived_counts": { + "$ref": "#/components/schemas/DerivedCounts" + }, + "rate_limit_summary": { + "$ref": "#/components/schemas/RateLimitSummary" + }, + "recent_events": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Recent Events", + "default": [] + } + }, + "type": "object", + "required": [ + "user", + "stats", + "derived_counts", + "rate_limit_summary" + ], + "title": "AdminUserOverview" + }, + "AlertResponse": { + "properties": { + "message": { + "type": "string", + "title": "Message" + }, + "alerts_received": { + "type": "integer", + "title": "Alerts Received" + }, + "alerts_processed": { + "type": "integer", + "title": "Alerts Processed" + }, + "errors": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Errors" + } + }, + "type": "object", + "required": [ + "message", + "alerts_received", + "alerts_processed" + ], + "title": "AlertResponse" + }, + "Body_login_api_v1_auth_login_post": { + "properties": { + "grant_type": { + "anyOf": [ + { + "type": "string", + "pattern": "^password$" + }, + { + "type": "null" + } + ], + "title": "Grant Type" + }, + "username": { + "type": "string", + "title": "Username" + }, + "password": { + "type": "string", + "format": "password", + "title": "Password" + }, + "scope": { + "type": "string", + "title": "Scope", + "default": "" + }, + "client_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Client Id" + }, + "client_secret": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "format": "password", + "title": "Client Secret" + } + }, + "type": "object", + "required": [ + "username", + "password" + ], + "title": "Body_login_api_v1_auth_login_post" + }, + "CancelExecutionRequest": { + "properties": { + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reason", + "description": "Reason for cancellation" + } + }, + "type": "object", + "title": "CancelExecutionRequest", + "description": "Model for cancelling an execution." + }, + "CancelResponse": { + "properties": { + "execution_id": { + "type": "string", + "title": "Execution Id" + }, + "status": { + "type": "string", + "title": "Status" + }, + "message": { + "type": "string", + "title": "Message" + }, + "event_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Event Id", + "description": "Event ID for the cancellation event, if published" + } + }, + "type": "object", + "required": [ + "execution_id", + "status", + "message" + ], + "title": "CancelResponse", + "description": "Model for execution cancellation response." + }, + "CleanupResponse": { + "properties": { + "removed_sessions": { + "type": "integer", + "title": "Removed Sessions" + }, + "message": { + "type": "string", + "title": "Message" + } + }, + "type": "object", + "required": [ + "removed_sessions", + "message" + ], + "title": "CleanupResponse", + "description": "Response schema for cleanup operations" + }, + "DLQBatchRetryResponse": { + "properties": { + "total": { + "type": "integer", + "title": "Total" + }, + "successful": { + "type": "integer", + "title": "Successful" + }, + "failed": { + "type": "integer", + "title": "Failed" + }, + "details": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Details" + } + }, + "type": "object", + "required": [ + "total", + "successful", + "failed", + "details" + ], + "title": "DLQBatchRetryResponse", + "description": "Response model for batch retry operation." + }, + "DLQMessageDetail": { + "properties": { + "event_id": { + "type": "string", + "title": "Event Id" + }, + "event": { + "type": "object", + "title": "Event" + }, + "event_type": { + "type": "string", + "title": "Event Type" + }, + "original_topic": { + "type": "string", + "title": "Original Topic" + }, + "error": { + "type": "string", + "title": "Error" + }, + "retry_count": { + "type": "integer", + "title": "Retry Count" + }, + "failed_at": { + "type": "string", + "format": "date-time", + "title": "Failed At" + }, + "status": { + "$ref": "#/components/schemas/DLQMessageStatus" + }, + "created_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Created At" + }, + "last_updated": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Updated" + }, + "next_retry_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Next Retry At" + }, + "retried_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Retried At" + }, + "discarded_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Discarded At" + }, + "discard_reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Discard Reason" + }, + "producer_id": { + "type": "string", + "title": "Producer Id" + }, + "dlq_offset": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Dlq Offset" + }, + "dlq_partition": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Dlq Partition" + }, + "last_error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Last Error" + } + }, + "type": "object", + "required": [ + "event_id", + "event", + "event_type", + "original_topic", + "error", + "retry_count", + "failed_at", + "status", + "producer_id" + ], + "title": "DLQMessageDetail", + "description": "Detailed DLQ message response." + }, + "DLQMessageResponse": { + "properties": { + "event_id": { + "type": "string", + "title": "Event Id" + }, + "event_type": { + "type": "string", + "title": "Event Type" + }, + "original_topic": { + "type": "string", + "title": "Original Topic" + }, + "error": { + "type": "string", + "title": "Error" + }, + "retry_count": { + "type": "integer", + "title": "Retry Count" + }, + "failed_at": { + "type": "string", + "format": "date-time", + "title": "Failed At" + }, + "status": { + "$ref": "#/components/schemas/DLQMessageStatus" + }, + "age_seconds": { + "type": "number", + "title": "Age Seconds" + }, + "details": { + "type": "object", + "title": "Details" + } + }, + "type": "object", + "required": [ + "event_id", + "event_type", + "original_topic", + "error", + "retry_count", + "failed_at", + "status", + "age_seconds", + "details" + ], + "title": "DLQMessageResponse", + "description": "Response model for a DLQ message." + }, + "DLQMessageStatus": { + "type": "string", + "enum": [ + "pending", + "scheduled", + "retried", + "discarded" + ], + "title": "DLQMessageStatus", + "description": "Status of a message in the Dead Letter Queue." + }, + "DLQMessagesResponse": { + "properties": { + "messages": { + "items": { + "$ref": "#/components/schemas/DLQMessageResponse" + }, + "type": "array", + "title": "Messages" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "offset": { + "type": "integer", + "title": "Offset" + }, + "limit": { + "type": "integer", + "title": "Limit" + } + }, + "type": "object", + "required": [ + "messages", + "total", + "offset", + "limit" + ], + "title": "DLQMessagesResponse", + "description": "Response model for listing DLQ messages." + }, + "DLQStats": { + "properties": { + "by_status": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "By Status" + }, + "by_topic": { + "items": { + "type": "object" + }, + "type": "array", + "title": "By Topic" + }, + "by_event_type": { + "items": { + "type": "object" + }, + "type": "array", + "title": "By Event Type" + }, + "age_stats": { + "type": "object", + "title": "Age Stats" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + } + }, + "type": "object", + "required": [ + "by_status", + "by_topic", + "by_event_type", + "age_stats", + "timestamp" + ], + "title": "DLQStats", + "description": "Statistics for the Dead Letter Queue." + }, + "DLQTopicSummaryResponse": { + "properties": { + "topic": { + "type": "string", + "title": "Topic" + }, + "total_messages": { + "type": "integer", + "title": "Total Messages" + }, + "status_breakdown": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Status Breakdown" + }, + "oldest_message": { + "type": "string", + "format": "date-time", + "title": "Oldest Message" + }, + "newest_message": { + "type": "string", + "format": "date-time", + "title": "Newest Message" + }, + "avg_retry_count": { + "type": "number", + "title": "Avg Retry Count" + }, + "max_retry_count": { + "type": "integer", + "title": "Max Retry Count" + } + }, + "type": "object", + "required": [ + "topic", + "total_messages", + "status_breakdown", + "oldest_message", + "newest_message", + "avg_retry_count", + "max_retry_count" + ], + "title": "DLQTopicSummaryResponse", + "description": "Response model for topic summary." + }, + "DeleteEventResponse": { + "properties": { + "message": { + "type": "string", + "title": "Message" + }, + "event_id": { + "type": "string", + "title": "Event Id" + }, + "deleted_at": { + "type": "string", + "format": "date-time", + "title": "Deleted At" + } + }, + "type": "object", + "required": [ + "message", + "event_id", + "deleted_at" + ], + "title": "DeleteEventResponse", + "description": "Response model for deleting events" + }, + "DeleteNotificationResponse": { + "properties": { + "message": { + "type": "string", + "title": "Message" + } + }, + "type": "object", + "required": [ + "message" + ], + "title": "DeleteNotificationResponse", + "description": "Response schema for notification deletion" + }, + "DeleteResponse": { + "properties": { + "message": { + "type": "string", + "title": "Message" + }, + "execution_id": { + "type": "string", + "title": "Execution Id" + } + }, + "type": "object", + "required": [ + "message", + "execution_id" + ], + "title": "DeleteResponse", + "description": "Model for execution deletion response." + }, + "DerivedCounts": { + "properties": { + "succeeded": { + "type": "integer", + "title": "Succeeded", + "default": 0 + }, + "failed": { + "type": "integer", + "title": "Failed", + "default": 0 + }, + "timeout": { + "type": "integer", + "title": "Timeout", + "default": 0 + }, + "cancelled": { + "type": "integer", + "title": "Cancelled", + "default": 0 + }, + "terminal_total": { + "type": "integer", + "title": "Terminal Total", + "default": 0 + } + }, + "type": "object", + "title": "DerivedCounts" + }, + "EditorSettings": { + "properties": { + "theme": { + "type": "string", + "title": "Theme", + "default": "one-dark" + }, + "font_size": { + "type": "integer", + "title": "Font Size", + "default": 14 + }, + "tab_size": { + "type": "integer", + "title": "Tab Size", + "default": 4 + }, + "use_tabs": { + "type": "boolean", + "title": "Use Tabs", + "default": false + }, + "word_wrap": { + "type": "boolean", + "title": "Word Wrap", + "default": true + }, + "show_line_numbers": { + "type": "boolean", + "title": "Show Line Numbers", + "default": true + }, + "font_family": { + "type": "string", + "title": "Font Family", + "default": "Monaco, Consolas, 'Courier New', monospace" + }, + "auto_complete": { + "type": "boolean", + "title": "Auto Complete", + "default": true + }, + "bracket_matching": { + "type": "boolean", + "title": "Bracket Matching", + "default": true + }, + "highlight_active_line": { + "type": "boolean", + "title": "Highlight Active Line", + "default": true + }, + "default_language": { + "type": "string", + "title": "Default Language", + "default": "python" + } + }, + "type": "object", + "title": "EditorSettings", + "description": "Code editor preferences" + }, + "EndpointGroup": { + "type": "string", + "enum": [ + "execution", + "admin", + "sse", + "websocket", + "auth", + "public", + "api" + ], + "title": "EndpointGroup" + }, + "ErrorType": { + "type": "string", + "enum": [ + "script_error", + "system_error", + "success" + ], + "title": "ErrorType", + "description": "Classification of error types in execution platform." + }, + "EventAggregationRequest": { + "properties": { + "pipeline": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Pipeline", + "description": "MongoDB aggregation pipeline" + }, + "limit": { + "type": "integer", + "maximum": 1000.0, + "minimum": 1.0, + "title": "Limit", + "default": 100 + } + }, + "type": "object", + "required": [ + "pipeline" + ], + "title": "EventAggregationRequest", + "description": "Request model for event aggregation queries." + }, + "EventBrowseRequest": { + "properties": { + "filters": { + "$ref": "#/components/schemas/EventFilter" + }, + "skip": { + "type": "integer", + "title": "Skip", + "default": 0 + }, + "limit": { + "type": "integer", + "maximum": 500.0, + "title": "Limit", + "default": 50 + }, + "sort_by": { + "type": "string", + "title": "Sort By", + "default": "timestamp" + }, + "sort_order": { + "type": "integer", + "title": "Sort Order", + "default": -1 + } + }, + "type": "object", + "required": [ + "filters" + ], + "title": "EventBrowseRequest", + "description": "Request model for browsing events" + }, + "EventBrowseResponse": { + "properties": { + "events": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Events" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "skip": { + "type": "integer", + "title": "Skip" + }, + "limit": { + "type": "integer", + "title": "Limit" + } + }, + "type": "object", + "required": [ + "events", + "total", + "skip", + "limit" + ], + "title": "EventBrowseResponse", + "description": "Response model for browsing events" + }, + "EventDeleteResponse": { + "properties": { + "message": { + "type": "string", + "title": "Message" + }, + "event_id": { + "type": "string", + "title": "Event Id" + } + }, + "type": "object", + "required": [ + "message", + "event_id" + ], + "title": "EventDeleteResponse", + "description": "Response model for event deletion" + }, + "EventDetailResponse": { + "properties": { + "event": { + "type": "object", + "title": "Event" + }, + "related_events": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Related Events" + }, + "timeline": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Timeline" + } + }, + "type": "object", + "required": [ + "event", + "related_events", + "timeline" + ], + "title": "EventDetailResponse", + "description": "Response model for event detail" + }, + "EventFilter": { + "properties": { + "event_types": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/EventType" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Event Types" + }, + "aggregate_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Aggregate Id" + }, + "correlation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Correlation Id" + }, + "user_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Id" + }, + "start_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Time" + }, + "end_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Time" + }, + "service_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Service Name" + }, + "search_text": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Search Text" + } + }, + "type": "object", + "title": "EventFilter", + "description": "Filter criteria for browsing events" + }, + "EventFilterRequest": { + "properties": { + "event_types": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/EventType" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Event Types", + "description": "Filter by event types" + }, + "aggregate_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Aggregate Id", + "description": "Filter by aggregate ID" + }, + "correlation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Correlation Id", + "description": "Filter by correlation ID" + }, + "user_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Id", + "description": "Filter by user ID (admin only)" + }, + "service_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Service Name", + "description": "Filter by service name" + }, + "start_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Time", + "description": "Filter events after this time" + }, + "end_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Time", + "description": "Filter events before this time" + }, + "text_search": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Text Search", + "description": "Full-text search in event data" + }, + "sort_by": { + "type": "string", + "title": "Sort By", + "description": "Field to sort by", + "default": "timestamp" + }, + "sort_order": { + "$ref": "#/components/schemas/SortOrder", + "description": "Sort order", + "default": "desc" + }, + "limit": { + "type": "integer", + "maximum": 1000.0, + "minimum": 1.0, + "title": "Limit", + "description": "Maximum events to return", + "default": 100 + }, + "skip": { + "type": "integer", + "minimum": 0.0, + "title": "Skip", + "description": "Number of events to skip", + "default": 0 + } + }, + "type": "object", + "title": "EventFilterRequest", + "description": "Request model for filtering events." + }, + "EventListResponse": { + "properties": { + "events": { + "items": { + "$ref": "#/components/schemas/EventResponse" + }, + "type": "array", + "title": "Events" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "limit": { + "type": "integer", + "title": "Limit" + }, + "skip": { + "type": "integer", + "title": "Skip" + }, + "has_more": { + "type": "boolean", + "title": "Has More" + } + }, + "type": "object", + "required": [ + "events", + "total", + "limit", + "skip", + "has_more" + ], + "title": "EventListResponse" + }, + "EventReplayRequest": { + "properties": { + "event_ids": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Event Ids" + }, + "correlation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Correlation Id" + }, + "aggregate_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Aggregate Id" + }, + "start_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Time" + }, + "end_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Time" + }, + "target_service": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target Service" + }, + "dry_run": { + "type": "boolean", + "title": "Dry Run", + "default": true + } + }, + "type": "object", + "title": "EventReplayRequest", + "description": "Request model for replaying events" + }, + "EventReplayResponse": { + "properties": { + "dry_run": { + "type": "boolean", + "title": "Dry Run" + }, + "total_events": { + "type": "integer", + "title": "Total Events" + }, + "replay_correlation_id": { + "type": "string", + "title": "Replay Correlation Id" + }, + "session_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Session Id" + }, + "status": { + "type": "string", + "title": "Status" + }, + "events_preview": { + "anyOf": [ + { + "items": { + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Events Preview" + } + }, + "type": "object", + "required": [ + "dry_run", + "total_events", + "replay_correlation_id", + "status" + ], + "title": "EventReplayResponse", + "description": "Response model for event replay" + }, + "EventReplayStatusResponse": { + "properties": { + "session_id": { + "type": "string", + "title": "Session Id" + }, + "status": { + "type": "string", + "title": "Status" + }, + "total_events": { + "type": "integer", + "title": "Total Events" + }, + "replayed_events": { + "type": "integer", + "title": "Replayed Events" + }, + "failed_events": { + "type": "integer", + "title": "Failed Events" + }, + "skipped_events": { + "type": "integer", + "title": "Skipped Events" + }, + "correlation_id": { + "type": "string", + "title": "Correlation Id" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "started_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Started At" + }, + "completed_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "error": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error" + }, + "progress_percentage": { + "type": "number", + "title": "Progress Percentage" + }, + "estimated_completion": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Estimated Completion" + }, + "execution_results": { + "anyOf": [ + { + "items": { + "type": "object" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Execution Results" + } + }, + "type": "object", + "required": [ + "session_id", + "status", + "total_events", + "replayed_events", + "failed_events", + "skipped_events", + "correlation_id", + "created_at", + "progress_percentage" + ], + "title": "EventReplayStatusResponse", + "description": "Response model for replay status" + }, + "EventResponse": { + "properties": { + "event_id": { + "type": "string", + "title": "Event Id" + }, + "event_type": { + "$ref": "#/components/schemas/EventType" + }, + "event_version": { + "type": "string", + "title": "Event Version" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + }, + "aggregate_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Aggregate Id" + }, + "correlation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Correlation Id" + }, + "causation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Causation Id" + }, + "metadata": { + "type": "object", + "title": "Metadata" + }, + "payload": { + "type": "object", + "title": "Payload" + }, + "stored_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Stored At" + } + }, + "type": "object", + "required": [ + "event_id", + "event_type", + "event_version", + "timestamp", + "metadata", + "payload" + ], + "title": "EventResponse" + }, + "EventStatistics": { + "properties": { + "total_events": { + "type": "integer", + "title": "Total Events" + }, + "events_by_type": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Events By Type" + }, + "events_by_service": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Events By Service" + }, + "events_by_hour": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Events By Hour" + }, + "start_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Time" + }, + "end_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Time" + } + }, + "type": "object", + "required": [ + "total_events", + "events_by_type", + "events_by_service", + "events_by_hour" + ], + "title": "EventStatistics", + "description": "Event statistics response.", + "example": { + "events_by_hour": [ + { + "count": 85, + "hour": "2024-01-20 10:00" + }, + { + "count": 92, + "hour": "2024-01-20 11:00" + } + ], + "events_by_service": { + "api-gateway": 523, + "execution-service": 1020 + }, + "events_by_type": { + "execution_completed": 498, + "execution_requested": 523, + "pod_created": 522 + }, + "total_events": 1543 + } + }, + "EventStatsResponse": { + "properties": { + "total_events": { + "type": "integer", + "title": "Total Events" + }, + "events_by_type": { + "additionalProperties": { + "type": "integer" + }, + "type": "object", + "title": "Events By Type" + }, + "events_by_hour": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Events By Hour" + }, + "top_users": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Top Users" + }, + "error_rate": { + "type": "number", + "title": "Error Rate" + }, + "avg_processing_time": { + "type": "number", + "title": "Avg Processing Time" + } + }, + "type": "object", + "required": [ + "total_events", + "events_by_type", + "events_by_hour", + "top_users", + "error_rate", + "avg_processing_time" + ], + "title": "EventStatsResponse", + "description": "Response model for event statistics" + }, + "EventType": { + "type": "string", + "enum": [ + "execution_requested", + "execution_accepted", + "execution_queued", + "execution_started", + "execution_running", + "execution_completed", + "execution_failed", + "execution_timeout", + "execution_cancelled", + "pod_created", + "pod_scheduled", + "pod_running", + "pod_succeeded", + "pod_failed", + "pod_terminated", + "pod_deleted", + "user_registered", + "user_login", + "user_logged_in", + "user_logged_out", + "user_updated", + "user_deleted", + "user_settings_updated", + "user_theme_changed", + "user_notification_settings_updated", + "user_editor_settings_updated", + "notification_created", + "notification_sent", + "notification_delivered", + "notification_failed", + "notification_read", + "notification_clicked", + "notification_preferences_updated", + "script_saved", + "script_deleted", + "script_shared", + "security_violation", + "rate_limit_exceeded", + "auth_failed", + "resource_limit_exceeded", + "quota_exceeded", + "system_error", + "service_unhealthy", + "service_recovered", + "result_stored", + "result_failed", + "saga_started", + "saga_completed", + "saga_failed", + "saga_cancelled", + "saga_compensating", + "saga_compensated", + "create_pod_command", + "delete_pod_command", + "allocate_resources_command", + "release_resources_command" + ], + "title": "EventType", + "description": "Event types used throughout the system." + }, + "ExampleScripts": { + "properties": { + "scripts": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Scripts" + } + }, + "type": "object", + "required": [ + "scripts" + ], + "title": "ExampleScripts", + "description": "Model for example scripts." + }, + "ExecutionEventResponse": { + "properties": { + "event_id": { + "type": "string", + "title": "Event Id" + }, + "event_type": { + "type": "string", + "title": "Event Type" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + }, + "payload": { + "type": "object", + "title": "Payload" + } + }, + "type": "object", + "required": [ + "event_id", + "event_type", + "timestamp", + "payload" + ], + "title": "ExecutionEventResponse", + "description": "Model for execution event response." + }, + "ExecutionLimitsSchema": { + "properties": { + "max_timeout_seconds": { + "type": "integer", + "maximum": 3600.0, + "minimum": 10.0, + "title": "Max Timeout Seconds", + "description": "Maximum execution timeout", + "default": 300 + }, + "max_memory_mb": { + "type": "integer", + "maximum": 4096.0, + "minimum": 128.0, + "title": "Max Memory Mb", + "description": "Maximum memory in MB", + "default": 512 + }, + "max_cpu_cores": { + "type": "integer", + "maximum": 8.0, + "minimum": 1.0, + "title": "Max Cpu Cores", + "description": "Maximum CPU cores", + "default": 2 + }, + "max_concurrent_executions": { + "type": "integer", + "maximum": 100.0, + "minimum": 1.0, + "title": "Max Concurrent Executions", + "description": "Maximum concurrent executions", + "default": 10 + } + }, + "type": "object", + "title": "ExecutionLimitsSchema", + "description": "Execution resource limits schema." + }, + "ExecutionListResponse": { + "properties": { + "executions": { + "items": { + "$ref": "#/components/schemas/ExecutionResult" + }, + "type": "array", + "title": "Executions" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "limit": { + "type": "integer", + "title": "Limit" + }, + "skip": { + "type": "integer", + "title": "Skip" + }, + "has_more": { + "type": "boolean", + "title": "Has More" + } + }, + "type": "object", + "required": [ + "executions", + "total", + "limit", + "skip", + "has_more" + ], + "title": "ExecutionListResponse", + "description": "Model for paginated execution list." + }, + "ExecutionRequest": { + "properties": { + "script": { + "type": "string", + "maxLength": 50000, + "title": "Script", + "description": "Script content (max 50,000 characters)" + }, + "lang": { + "type": "string", + "title": "Lang", + "description": "Language name", + "default": "python" + }, + "lang_version": { + "type": "string", + "title": "Lang Version", + "description": "Language version to use for execution", + "default": "3.11" + } + }, + "type": "object", + "required": [ + "script" + ], + "title": "ExecutionRequest", + "description": "Model for execution request." + }, + "ExecutionResponse": { + "properties": { + "execution_id": { + "type": "string", + "title": "Execution Id" + }, + "status": { + "$ref": "#/components/schemas/ExecutionStatus" + } + }, + "type": "object", + "required": [ + "execution_id", + "status" + ], + "title": "ExecutionResponse", + "description": "Model for execution response." + }, + "ExecutionResult": { + "properties": { + "execution_id": { + "type": "string", + "title": "Execution Id" + }, + "status": { + "$ref": "#/components/schemas/ExecutionStatus" + }, + "stdout": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Stdout" + }, + "stderr": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Stderr" + }, + "lang": { + "type": "string", + "title": "Lang" + }, + "lang_version": { + "type": "string", + "title": "Lang Version" + }, + "resource_usage": { + "anyOf": [ + { + "$ref": "#/components/schemas/ResourceUsage" + }, + { + "type": "null" + } + ] + }, + "exit_code": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Exit Code" + }, + "error_type": { + "anyOf": [ + { + "$ref": "#/components/schemas/ErrorType" + }, + { + "type": "null" + } + ] + } + }, + "type": "object", + "required": [ + "execution_id", + "status", + "lang", + "lang_version" + ], + "title": "ExecutionResult", + "description": "Model for execution result." + }, + "ExecutionStatus": { + "type": "string", + "enum": [ + "queued", + "scheduled", + "running", + "completed", + "failed", + "timeout", + "cancelled", + "error" + ], + "title": "ExecutionStatus", + "description": "Status of an execution." + }, + "GrafanaAlertItem": { + "properties": { + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "labels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Labels" + }, + "annotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Annotations" + }, + "valueString": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Valuestring" + } + }, + "type": "object", + "title": "GrafanaAlertItem" + }, + "GrafanaWebhook": { + "properties": { + "status": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Status" + }, + "receiver": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Receiver" + }, + "alerts": { + "items": { + "$ref": "#/components/schemas/GrafanaAlertItem" + }, + "type": "array", + "title": "Alerts" + }, + "groupLabels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Grouplabels" + }, + "commonLabels": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Commonlabels" + }, + "commonAnnotations": { + "additionalProperties": { + "type": "string" + }, + "type": "object", + "title": "Commonannotations" + } + }, + "type": "object", + "title": "GrafanaWebhook" + }, + "HTTPValidationError": { + "properties": { + "detail": { + "items": { + "$ref": "#/components/schemas/ValidationError" + }, + "type": "array", + "title": "Detail" + } + }, + "type": "object", + "title": "HTTPValidationError" + }, + "LoginResponse": { + "properties": { + "message": { + "type": "string", + "title": "Message" + }, + "username": { + "type": "string", + "title": "Username" + }, + "role": { + "type": "string", + "title": "Role" + }, + "csrf_token": { + "type": "string", + "title": "Csrf Token" + } + }, + "type": "object", + "required": [ + "message", + "username", + "role", + "csrf_token" + ], + "title": "LoginResponse", + "description": "Response model for successful login" + }, + "ManualRetryRequest": { + "properties": { + "event_ids": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Event Ids" + } + }, + "type": "object", + "required": [ + "event_ids" + ], + "title": "ManualRetryRequest", + "description": "Request model for manual retry of messages." + }, + "MessageResponse": { + "properties": { + "message": { + "type": "string", + "title": "Message" + } + }, + "type": "object", + "required": [ + "message" + ], + "title": "MessageResponse", + "description": "Generic message response" + }, + "MonitoringSettingsSchema": { + "properties": { + "metrics_retention_days": { + "type": "integer", + "maximum": 90.0, + "minimum": 7.0, + "title": "Metrics Retention Days", + "description": "Metrics retention in days", + "default": 30 + }, + "log_level": { + "type": "string", + "pattern": "^(DEBUG|INFO|WARNING|ERROR|CRITICAL)$", + "title": "Log Level", + "description": "Log level", + "default": "INFO" + }, + "enable_tracing": { + "type": "boolean", + "title": "Enable Tracing", + "description": "Enable distributed tracing", + "default": true + }, + "sampling_rate": { + "type": "number", + "maximum": 1.0, + "minimum": 0.0, + "title": "Sampling Rate", + "description": "Trace sampling rate", + "default": 0.1 + } + }, + "type": "object", + "title": "MonitoringSettingsSchema", + "description": "Monitoring and observability schema." + }, + "NotificationChannel": { + "type": "string", + "enum": [ + "in_app", + "webhook", + "slack" + ], + "title": "NotificationChannel", + "description": "Notification delivery channels." + }, + "NotificationListResponse": { + "properties": { + "notifications": { + "items": { + "$ref": "#/components/schemas/NotificationResponse" + }, + "type": "array", + "title": "Notifications" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "unread_count": { + "type": "integer", + "title": "Unread Count" + } + }, + "type": "object", + "required": [ + "notifications", + "total", + "unread_count" + ], + "title": "NotificationListResponse", + "description": "Response schema for notification list endpoints" + }, + "NotificationResponse": { + "properties": { + "notification_id": { + "type": "string", + "title": "Notification Id" + }, + "channel": { + "$ref": "#/components/schemas/NotificationChannel" + }, + "status": { + "$ref": "#/components/schemas/NotificationStatus" + }, + "subject": { + "type": "string", + "title": "Subject" + }, + "body": { + "type": "string", + "title": "Body" + }, + "action_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Action Url" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "read_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Read At" + }, + "severity": { + "$ref": "#/components/schemas/NotificationSeverity" + }, + "tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Tags" + } + }, + "type": "object", + "required": [ + "notification_id", + "channel", + "status", + "subject", + "body", + "action_url", + "created_at", + "read_at", + "severity", + "tags" + ], + "title": "NotificationResponse", + "description": "Response schema for notification endpoints" + }, + "NotificationSettings": { + "properties": { + "execution_completed": { + "type": "boolean", + "title": "Execution Completed", + "default": true + }, + "execution_failed": { + "type": "boolean", + "title": "Execution Failed", + "default": true + }, + "system_updates": { + "type": "boolean", + "title": "System Updates", + "default": true + }, + "security_alerts": { + "type": "boolean", + "title": "Security Alerts", + "default": true + }, + "channels": { + "items": { + "$ref": "#/components/schemas/NotificationChannel" + }, + "type": "array", + "title": "Channels", + "default": [ + "in_app" + ] + } + }, + "type": "object", + "title": "NotificationSettings", + "description": "User notification preferences" + }, + "NotificationSeverity": { + "type": "string", + "enum": [ + "low", + "medium", + "high", + "urgent" + ], + "title": "NotificationSeverity", + "description": "Notification severity levels." + }, + "NotificationStatus": { + "type": "string", + "enum": [ + "pending", + "queued", + "sending", + "delivered", + "failed", + "skipped", + "read", + "clicked" + ], + "title": "NotificationStatus", + "description": "Notification delivery status." + }, + "NotificationSubscription": { + "properties": { + "user_id": { + "type": "string", + "title": "User Id" + }, + "channel": { + "$ref": "#/components/schemas/NotificationChannel" + }, + "severities": { + "items": { + "$ref": "#/components/schemas/NotificationSeverity" + }, + "type": "array", + "title": "Severities" + }, + "include_tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Include Tags" + }, + "exclude_tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Exclude Tags" + }, + "enabled": { + "type": "boolean", + "title": "Enabled", + "default": true + }, + "webhook_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Webhook Url" + }, + "slack_webhook": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Slack Webhook" + }, + "quiet_hours_enabled": { + "type": "boolean", + "title": "Quiet Hours Enabled", + "default": false + }, + "quiet_hours_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Quiet Hours Start" + }, + "quiet_hours_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Quiet Hours End" + }, + "timezone": { + "type": "string", + "title": "Timezone", + "default": "UTC" + }, + "batch_interval_minutes": { + "type": "integer", + "title": "Batch Interval Minutes", + "default": 60 + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At" + } + }, + "type": "object", + "required": [ + "user_id", + "channel" + ], + "title": "NotificationSubscription", + "description": "User subscription preferences for notifications" + }, + "PasswordResetRequest": { + "properties": { + "new_password": { + "type": "string", + "minLength": 8, + "title": "New Password", + "description": "New password for the user" + } + }, + "type": "object", + "required": [ + "new_password" + ], + "title": "PasswordResetRequest", + "description": "Request model for password reset" + }, + "PublishEventRequest": { + "properties": { + "event_type": { + "$ref": "#/components/schemas/EventType", + "description": "Type of event to publish" + }, + "payload": { + "type": "object", + "title": "Payload", + "description": "Event payload data" + }, + "aggregate_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Aggregate Id", + "description": "Aggregate root ID" + }, + "correlation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Correlation Id", + "description": "Correlation ID" + }, + "causation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Causation Id", + "description": "ID of causing event" + }, + "metadata": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Metadata", + "description": "Additional metadata" + } + }, + "type": "object", + "required": [ + "event_type", + "payload" + ], + "title": "PublishEventRequest", + "description": "Request model for publishing events." + }, + "PublishEventResponse": { + "properties": { + "event_id": { + "type": "string", + "title": "Event Id" + }, + "status": { + "type": "string", + "title": "Status" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + } + }, + "type": "object", + "required": [ + "event_id", + "status", + "timestamp" + ], + "title": "PublishEventResponse", + "description": "Response model for publishing events" + }, + "RateLimitAlgorithm": { + "type": "string", + "enum": [ + "sliding_window", + "token_bucket", + "fixed_window", + "leaky_bucket" + ], + "title": "RateLimitAlgorithm" + }, + "RateLimitRule": { + "properties": { + "endpoint_pattern": { + "type": "string", + "title": "Endpoint Pattern" + }, + "group": { + "$ref": "#/components/schemas/EndpointGroup" + }, + "requests": { + "type": "integer", + "title": "Requests" + }, + "window_seconds": { + "type": "integer", + "title": "Window Seconds" + }, + "burst_multiplier": { + "type": "number", + "title": "Burst Multiplier", + "default": 1.5 + }, + "algorithm": { + "$ref": "#/components/schemas/RateLimitAlgorithm", + "default": "sliding_window" + }, + "priority": { + "type": "integer", + "title": "Priority", + "default": 0 + }, + "enabled": { + "type": "boolean", + "title": "Enabled", + "default": true + }, + "compiled_pattern": { + "anyOf": [ + { + "type": "string", + "format": "regex" + }, + { + "type": "null" + } + ], + "title": "Compiled Pattern" + } + }, + "type": "object", + "required": [ + "endpoint_pattern", + "group", + "requests", + "window_seconds" + ], + "title": "RateLimitRule" + }, + "RateLimitSummary": { + "properties": { + "bypass_rate_limit": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Bypass Rate Limit" + }, + "global_multiplier": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Global Multiplier" + }, + "has_custom_limits": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Has Custom Limits" + } + }, + "type": "object", + "title": "RateLimitSummary" + }, + "ReplayAggregateResponse": { + "properties": { + "dry_run": { + "type": "boolean", + "title": "Dry Run" + }, + "aggregate_id": { + "type": "string", + "title": "Aggregate Id" + }, + "event_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Event Count" + }, + "event_types": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Event Types" + }, + "start_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Time" + }, + "end_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Time" + }, + "replayed_count": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Replayed Count" + }, + "replay_correlation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Replay Correlation Id" + } + }, + "type": "object", + "required": [ + "dry_run", + "aggregate_id" + ], + "title": "ReplayAggregateResponse", + "description": "Response model for replaying aggregate events" + }, + "ReplayConfigSchema": { + "properties": { + "replay_type": { + "$ref": "#/components/schemas/ReplayType" + }, + "target": { + "$ref": "#/components/schemas/ReplayTarget", + "default": "kafka" + }, + "filter": { + "$ref": "#/components/schemas/ReplayFilterSchema" + }, + "speed_multiplier": { + "type": "number", + "maximum": 100.0, + "minimum": 0.1, + "title": "Speed Multiplier", + "default": 1.0 + }, + "preserve_timestamps": { + "type": "boolean", + "title": "Preserve Timestamps", + "default": false + }, + "batch_size": { + "type": "integer", + "maximum": 1000.0, + "minimum": 1.0, + "title": "Batch Size", + "default": 100 + }, + "max_events": { + "anyOf": [ + { + "type": "integer", + "minimum": 1.0 + }, + { + "type": "null" + } + ], + "title": "Max Events" + }, + "target_topics": { + "anyOf": [ + { + "additionalProperties": { + "type": "string" + }, + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Target Topics" + }, + "target_file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target File Path" + }, + "skip_errors": { + "type": "boolean", + "title": "Skip Errors", + "default": true + }, + "retry_failed": { + "type": "boolean", + "title": "Retry Failed", + "default": false + }, + "retry_attempts": { + "type": "integer", + "title": "Retry Attempts", + "default": 3 + }, + "enable_progress_tracking": { + "type": "boolean", + "title": "Enable Progress Tracking", + "default": true + } + }, + "type": "object", + "required": [ + "replay_type", + "filter" + ], + "title": "ReplayConfigSchema" + }, + "ReplayFilterSchema": { + "properties": { + "execution_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Execution Id" + }, + "event_types": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Event Types" + }, + "start_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Time" + }, + "end_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Time" + }, + "user_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Id" + }, + "service_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Service Name" + }, + "custom_query": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Custom Query" + }, + "exclude_event_types": { + "anyOf": [ + { + "items": { + "type": "string" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Exclude Event Types" + } + }, + "type": "object", + "title": "ReplayFilterSchema" + }, + "ReplayRequest": { + "properties": { + "replay_type": { + "$ref": "#/components/schemas/ReplayType" + }, + "target": { + "$ref": "#/components/schemas/ReplayTarget", + "default": "kafka" + }, + "execution_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Execution Id" + }, + "event_types": { + "anyOf": [ + { + "items": { + "$ref": "#/components/schemas/EventType" + }, + "type": "array" + }, + { + "type": "null" + } + ], + "title": "Event Types" + }, + "start_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Start Time" + }, + "end_time": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "End Time" + }, + "user_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "User Id" + }, + "service_name": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Service Name" + }, + "speed_multiplier": { + "type": "number", + "maximum": 100.0, + "minimum": 0.1, + "title": "Speed Multiplier", + "default": 1.0 + }, + "preserve_timestamps": { + "type": "boolean", + "title": "Preserve Timestamps", + "default": false + }, + "batch_size": { + "type": "integer", + "maximum": 1000.0, + "minimum": 1.0, + "title": "Batch Size", + "default": 100 + }, + "max_events": { + "anyOf": [ + { + "type": "integer", + "minimum": 1.0 + }, + { + "type": "null" + } + ], + "title": "Max Events" + }, + "skip_errors": { + "type": "boolean", + "title": "Skip Errors", + "default": true + }, + "target_file_path": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Target File Path" + } + }, + "type": "object", + "required": [ + "replay_type" + ], + "title": "ReplayRequest", + "description": "Request schema for creating replay sessions" + }, + "ReplayResponse": { + "properties": { + "session_id": { + "type": "string", + "title": "Session Id" + }, + "status": { + "$ref": "#/components/schemas/ReplayStatus" + }, + "message": { + "type": "string", + "title": "Message" + } + }, + "type": "object", + "required": [ + "session_id", + "status", + "message" + ], + "title": "ReplayResponse", + "description": "Response schema for replay operations" + }, + "ReplaySession": { + "properties": { + "session_id": { + "type": "string", + "title": "Session Id" + }, + "config": { + "$ref": "#/components/schemas/ReplayConfigSchema" + }, + "status": { + "$ref": "#/components/schemas/ReplayStatus", + "default": "created" + }, + "total_events": { + "type": "integer", + "title": "Total Events", + "default": 0 + }, + "replayed_events": { + "type": "integer", + "title": "Replayed Events", + "default": 0 + }, + "failed_events": { + "type": "integer", + "title": "Failed Events", + "default": 0 + }, + "skipped_events": { + "type": "integer", + "title": "Skipped Events", + "default": 0 + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "started_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Started At" + }, + "completed_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "last_event_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Last Event At" + }, + "errors": { + "items": { + "type": "object" + }, + "type": "array", + "title": "Errors" + } + }, + "type": "object", + "required": [ + "config" + ], + "title": "ReplaySession" + }, + "ReplayStatus": { + "type": "string", + "enum": [ + "scheduled", + "created", + "running", + "paused", + "completed", + "failed", + "cancelled" + ], + "title": "ReplayStatus" + }, + "ReplayTarget": { + "type": "string", + "enum": [ + "kafka", + "callback", + "file", + "test" + ], + "title": "ReplayTarget" + }, + "ReplayType": { + "type": "string", + "enum": [ + "execution", + "time_range", + "event_type", + "query", + "recovery" + ], + "title": "ReplayType" + }, + "ResourceLimits": { + "properties": { + "cpu_limit": { + "type": "string", + "title": "Cpu Limit" + }, + "memory_limit": { + "type": "string", + "title": "Memory Limit" + }, + "cpu_request": { + "type": "string", + "title": "Cpu Request" + }, + "memory_request": { + "type": "string", + "title": "Memory Request" + }, + "execution_timeout": { + "type": "integer", + "title": "Execution Timeout" + }, + "supported_runtimes": { + "additionalProperties": { + "items": { + "type": "string" + }, + "type": "array" + }, + "type": "object", + "title": "Supported Runtimes" + } + }, + "type": "object", + "required": [ + "cpu_limit", + "memory_limit", + "cpu_request", + "memory_request", + "execution_timeout", + "supported_runtimes" + ], + "title": "ResourceLimits", + "description": "Model for resource limits configuration." + }, + "ResourceUsage": { + "properties": { + "execution_time_wall_seconds": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Execution Time Wall Seconds", + "description": "Wall clock execution time in seconds" + }, + "cpu_time_jiffies": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Cpu Time Jiffies", + "description": "CPU time in jiffies (multiply by 10 for milliseconds)" + }, + "clk_tck_hertz": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Clk Tck Hertz", + "description": "Clock ticks per second (usually 100)" + }, + "peak_memory_kb": { + "anyOf": [ + { + "type": "integer" + }, + { + "type": "null" + } + ], + "title": "Peak Memory Kb", + "description": "Peak memory usage in KB" + } + }, + "type": "object", + "title": "ResourceUsage", + "description": "Model for execution resource usage." + }, + "RestoreSettingsRequest": { + "properties": { + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reason" + } + }, + "type": "object", + "required": [ + "timestamp" + ], + "title": "RestoreSettingsRequest", + "description": "Request model for restoring settings" + }, + "RetryExecutionRequest": { + "properties": { + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reason", + "description": "Reason for retry" + }, + "preserve_output": { + "type": "boolean", + "title": "Preserve Output", + "description": "Keep output from previous attempt", + "default": false + } + }, + "type": "object", + "title": "RetryExecutionRequest", + "description": "Model for retrying an execution." + }, + "RetryPolicyRequest": { + "properties": { + "topic": { + "type": "string", + "title": "Topic" + }, + "strategy": { + "$ref": "#/components/schemas/RetryStrategy" + }, + "max_retries": { + "type": "integer", + "title": "Max Retries", + "default": 5 + }, + "base_delay_seconds": { + "type": "number", + "title": "Base Delay Seconds", + "default": 60.0 + }, + "max_delay_seconds": { + "type": "number", + "title": "Max Delay Seconds", + "default": 3600.0 + }, + "retry_multiplier": { + "type": "number", + "title": "Retry Multiplier", + "default": 2.0 + } + }, + "type": "object", + "required": [ + "topic", + "strategy" + ], + "title": "RetryPolicyRequest", + "description": "Request model for setting a retry policy." + }, + "RetryStrategy": { + "type": "string", + "enum": [ + "immediate", + "exponential_backoff", + "fixed_interval", + "scheduled", + "manual" + ], + "title": "RetryStrategy", + "description": "Retry strategies for DLQ messages." + }, + "SSEHealthResponse": { + "properties": { + "status": { + "type": "string", + "title": "Status", + "description": "Health status: healthy or draining" + }, + "kafka_enabled": { + "type": "boolean", + "title": "Kafka Enabled", + "description": "Whether Kafka features are enabled", + "default": true + }, + "active_connections": { + "type": "integer", + "title": "Active Connections", + "description": "Total number of active SSE connections" + }, + "active_executions": { + "type": "integer", + "title": "Active Executions", + "description": "Number of executions being monitored" + }, + "active_consumers": { + "type": "integer", + "title": "Active Consumers", + "description": "Number of active Kafka consumers" + }, + "max_connections_per_user": { + "type": "integer", + "title": "Max Connections Per User", + "description": "Maximum connections allowed per user" + }, + "shutdown": { + "type": "object", + "title": "Shutdown", + "description": "Shutdown status information" + }, + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp", + "description": "Health check timestamp" + } + }, + "type": "object", + "required": [ + "status", + "active_connections", + "active_executions", + "active_consumers", + "max_connections_per_user", + "shutdown", + "timestamp" + ], + "title": "SSEHealthResponse", + "description": "Response model for SSE health check." + }, + "SagaCancellationResponse": { + "properties": { + "success": { + "type": "boolean", + "title": "Success" + }, + "message": { + "type": "string", + "title": "Message" + }, + "saga_id": { + "type": "string", + "title": "Saga Id" + } + }, + "type": "object", + "required": [ + "success", + "message", + "saga_id" + ], + "title": "SagaCancellationResponse", + "description": "Response schema for saga cancellation" + }, + "SagaListResponse": { + "properties": { + "sagas": { + "items": { + "$ref": "#/components/schemas/SagaStatusResponse" + }, + "type": "array", + "title": "Sagas" + }, + "total": { + "type": "integer", + "title": "Total" + } + }, + "type": "object", + "required": [ + "sagas", + "total" + ], + "title": "SagaListResponse", + "description": "Response schema for saga list" + }, + "SagaState": { + "type": "string", + "enum": [ + "created", + "running", + "compensating", + "completed", + "failed", + "timeout", + "cancelled" + ], + "title": "SagaState", + "description": "Saga execution states." + }, + "SagaStatusResponse": { + "properties": { + "saga_id": { + "type": "string", + "title": "Saga Id" + }, + "saga_name": { + "type": "string", + "title": "Saga Name" + }, + "execution_id": { + "type": "string", + "title": "Execution Id" + }, + "state": { + "$ref": "#/components/schemas/SagaState" + }, + "current_step": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Current Step" + }, + "completed_steps": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Completed Steps" + }, + "compensated_steps": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Compensated Steps" + }, + "error_message": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Error Message" + }, + "created_at": { + "type": "string", + "title": "Created At" + }, + "updated_at": { + "type": "string", + "title": "Updated At" + }, + "completed_at": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "retry_count": { + "type": "integer", + "title": "Retry Count" + } + }, + "type": "object", + "required": [ + "saga_id", + "saga_name", + "execution_id", + "state", + "current_step", + "completed_steps", + "compensated_steps", + "error_message", + "created_at", + "updated_at", + "completed_at", + "retry_count" + ], + "title": "SagaStatusResponse", + "description": "Response schema for saga status" + }, + "SavedScriptCreateRequest": { + "properties": { + "name": { + "type": "string", + "title": "Name" + }, + "script": { + "type": "string", + "title": "Script" + }, + "lang": { + "type": "string", + "title": "Lang", + "default": "python" + }, + "lang_version": { + "type": "string", + "title": "Lang Version", + "default": "3.11" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + } + }, + "type": "object", + "required": [ + "name", + "script" + ], + "title": "SavedScriptCreateRequest" + }, + "SavedScriptResponse": { + "properties": { + "script_id": { + "type": "string", + "title": "Script Id" + }, + "name": { + "type": "string", + "title": "Name" + }, + "script": { + "type": "string", + "title": "Script" + }, + "lang": { + "type": "string", + "title": "Lang" + }, + "lang_version": { + "type": "string", + "title": "Lang Version" + }, + "description": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Description" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At" + } + }, + "type": "object", + "required": [ + "script_id", + "name", + "script", + "lang", + "lang_version", + "created_at", + "updated_at" + ], + "title": "SavedScriptResponse" + }, + "SecuritySettingsSchema": { + "properties": { + "password_min_length": { + "type": "integer", + "maximum": 32.0, + "minimum": 6.0, + "title": "Password Min Length", + "description": "Minimum password length", + "default": 8 + }, + "session_timeout_minutes": { + "type": "integer", + "maximum": 1440.0, + "minimum": 5.0, + "title": "Session Timeout Minutes", + "description": "Session timeout in minutes", + "default": 60 + }, + "max_login_attempts": { + "type": "integer", + "maximum": 10.0, + "minimum": 3.0, + "title": "Max Login Attempts", + "description": "Maximum login attempts", + "default": 5 + }, + "lockout_duration_minutes": { + "type": "integer", + "maximum": 60.0, + "minimum": 5.0, + "title": "Lockout Duration Minutes", + "description": "Account lockout duration", + "default": 15 + } + }, + "type": "object", + "title": "SecuritySettingsSchema", + "description": "Security configuration schema." + }, + "SessionSummary": { + "properties": { + "session_id": { + "type": "string", + "title": "Session Id" + }, + "replay_type": { + "$ref": "#/components/schemas/ReplayType" + }, + "target": { + "$ref": "#/components/schemas/ReplayTarget" + }, + "status": { + "$ref": "#/components/schemas/ReplayStatus" + }, + "total_events": { + "type": "integer", + "title": "Total Events" + }, + "replayed_events": { + "type": "integer", + "title": "Replayed Events" + }, + "failed_events": { + "type": "integer", + "title": "Failed Events" + }, + "skipped_events": { + "type": "integer", + "title": "Skipped Events" + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "started_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Started At" + }, + "completed_at": { + "anyOf": [ + { + "type": "string", + "format": "date-time" + }, + { + "type": "null" + } + ], + "title": "Completed At" + }, + "duration_seconds": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Duration Seconds" + }, + "throughput_events_per_second": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Throughput Events Per Second" + } + }, + "type": "object", + "required": [ + "session_id", + "replay_type", + "target", + "status", + "total_events", + "replayed_events", + "failed_events", + "skipped_events", + "created_at", + "started_at", + "completed_at" + ], + "title": "SessionSummary", + "description": "Summary information for replay sessions" + }, + "SettingsHistoryEntry": { + "properties": { + "timestamp": { + "type": "string", + "format": "date-time", + "title": "Timestamp" + }, + "event_type": { + "type": "string", + "title": "Event Type" + }, + "field": { + "type": "string", + "title": "Field" + }, + "old_value": { + "title": "Old Value" + }, + "new_value": { + "title": "New Value" + }, + "reason": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Reason" + }, + "correlation_id": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Correlation Id" + } + }, + "type": "object", + "required": [ + "timestamp", + "event_type", + "field", + "old_value", + "new_value" + ], + "title": "SettingsHistoryEntry", + "description": "Single entry in settings history" + }, + "SettingsHistoryResponse": { + "properties": { + "history": { + "items": { + "$ref": "#/components/schemas/SettingsHistoryEntry" + }, + "type": "array", + "title": "History" + }, + "total": { + "type": "integer", + "title": "Total" + } + }, + "type": "object", + "required": [ + "history", + "total" + ], + "title": "SettingsHistoryResponse", + "description": "Response model for settings history" + }, + "SortOrder": { + "type": "string", + "enum": [ + "asc", + "desc" + ], + "title": "SortOrder", + "description": "Sort order for queries." + }, + "SubscriptionUpdate": { + "properties": { + "enabled": { + "type": "boolean", + "title": "Enabled" + }, + "severities": { + "items": { + "$ref": "#/components/schemas/NotificationSeverity" + }, + "type": "array", + "title": "Severities" + }, + "include_tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Include Tags" + }, + "exclude_tags": { + "items": { + "type": "string" + }, + "type": "array", + "title": "Exclude Tags" + }, + "webhook_url": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Webhook Url" + }, + "slack_webhook": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Slack Webhook" + }, + "quiet_hours_enabled": { + "type": "boolean", + "title": "Quiet Hours Enabled", + "default": false + }, + "quiet_hours_start": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Quiet Hours Start" + }, + "quiet_hours_end": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Quiet Hours End" + }, + "timezone": { + "type": "string", + "title": "Timezone", + "default": "UTC" + }, + "batch_interval_minutes": { + "type": "integer", + "title": "Batch Interval Minutes", + "default": 60 + } + }, + "type": "object", + "required": [ + "enabled" + ], + "title": "SubscriptionUpdate", + "description": "Request schema for updating notification subscriptions" + }, + "SubscriptionsResponse": { + "properties": { + "subscriptions": { + "items": { + "$ref": "#/components/schemas/NotificationSubscription" + }, + "type": "array", + "title": "Subscriptions" + } + }, + "type": "object", + "required": [ + "subscriptions" + ], + "title": "SubscriptionsResponse", + "description": "Response schema for user subscriptions" + }, + "SystemSettings": { + "properties": { + "execution_limits": { + "$ref": "#/components/schemas/ExecutionLimitsSchema" + }, + "security_settings": { + "$ref": "#/components/schemas/SecuritySettingsSchema" + }, + "monitoring_settings": { + "$ref": "#/components/schemas/MonitoringSettingsSchema" + } + }, + "type": "object", + "title": "SystemSettings", + "description": "System-wide settings model." + }, + "Theme": { + "type": "string", + "enum": [ + "light", + "dark", + "auto" + ], + "title": "Theme", + "description": "Available UI themes." + }, + "ThemeUpdateRequest": { + "properties": { + "theme": { + "$ref": "#/components/schemas/Theme" + } + }, + "type": "object", + "required": [ + "theme" + ], + "title": "ThemeUpdateRequest", + "description": "Request model for theme update" + }, + "TokenValidationResponse": { + "properties": { + "valid": { + "type": "boolean", + "title": "Valid" + }, + "username": { + "type": "string", + "title": "Username" + }, + "role": { + "type": "string", + "title": "Role" + }, + "csrf_token": { + "type": "string", + "title": "Csrf Token" + } + }, + "type": "object", + "required": [ + "valid", + "username", + "role", + "csrf_token" + ], + "title": "TokenValidationResponse", + "description": "Response model for token validation" + }, + "UnreadCountResponse": { + "properties": { + "unread_count": { + "type": "integer", + "title": "Unread Count" + } + }, + "type": "object", + "required": [ + "unread_count" + ], + "title": "UnreadCountResponse", + "description": "Response schema for unread notification count" + }, + "UserCreate": { + "properties": { + "username": { + "type": "string", + "title": "Username" + }, + "email": { + "type": "string", + "format": "email", + "title": "Email" + }, + "role": { + "$ref": "#/components/schemas/UserRole", + "default": "user" + }, + "is_active": { + "type": "boolean", + "title": "Is Active", + "default": true + }, + "password": { + "type": "string", + "minLength": 8, + "title": "Password" + } + }, + "type": "object", + "required": [ + "username", + "email", + "password" + ], + "title": "UserCreate", + "description": "Model for creating a new user" + }, + "UserListResponse": { + "properties": { + "users": { + "items": { + "$ref": "#/components/schemas/UserResponse" + }, + "type": "array", + "title": "Users" + }, + "total": { + "type": "integer", + "title": "Total" + }, + "offset": { + "type": "integer", + "title": "Offset" + }, + "limit": { + "type": "integer", + "title": "Limit" + } + }, + "type": "object", + "required": [ + "users", + "total", + "offset", + "limit" + ], + "title": "UserListResponse", + "description": "Response model for listing users" + }, + "UserRateLimit": { + "properties": { + "user_id": { + "type": "string", + "title": "User Id" + }, + "rules": { + "items": { + "$ref": "#/components/schemas/RateLimitRule" + }, + "type": "array", + "title": "Rules" + }, + "global_multiplier": { + "type": "number", + "title": "Global Multiplier", + "default": 1.0 + }, + "bypass_rate_limit": { + "type": "boolean", + "title": "Bypass Rate Limit", + "default": false + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At" + }, + "notes": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Notes" + } + }, + "type": "object", + "required": [ + "user_id" + ], + "title": "UserRateLimit" + }, + "UserResponse": { + "properties": { + "username": { + "type": "string", + "title": "Username" + }, + "email": { + "type": "string", + "format": "email", + "title": "Email" + }, + "role": { + "$ref": "#/components/schemas/UserRole", + "default": "user" + }, + "is_active": { + "type": "boolean", + "title": "Is Active", + "default": true + }, + "user_id": { + "type": "string", + "title": "User Id" + }, + "is_superuser": { + "type": "boolean", + "title": "Is Superuser", + "default": false + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At" + }, + "bypass_rate_limit": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Bypass Rate Limit" + }, + "global_multiplier": { + "anyOf": [ + { + "type": "number" + }, + { + "type": "null" + } + ], + "title": "Global Multiplier" + }, + "has_custom_limits": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Has Custom Limits" + } + }, + "type": "object", + "required": [ + "username", + "email", + "user_id", + "created_at", + "updated_at" + ], + "title": "UserResponse", + "description": "User model for API responses (without password)" + }, + "UserRole": { + "type": "string", + "enum": [ + "user", + "admin", + "moderator" + ], + "title": "UserRole", + "description": "User roles in the system." + }, + "UserSettings": { + "properties": { + "user_id": { + "type": "string", + "title": "User Id" + }, + "theme": { + "$ref": "#/components/schemas/Theme", + "default": "auto" + }, + "timezone": { + "type": "string", + "title": "Timezone", + "default": "UTC" + }, + "date_format": { + "type": "string", + "title": "Date Format", + "default": "YYYY-MM-DD" + }, + "time_format": { + "type": "string", + "title": "Time Format", + "default": "24h" + }, + "notifications": { + "$ref": "#/components/schemas/NotificationSettings" + }, + "editor": { + "$ref": "#/components/schemas/EditorSettings" + }, + "custom_settings": { + "type": "object", + "title": "Custom Settings" + }, + "version": { + "type": "integer", + "title": "Version", + "default": 1 + }, + "created_at": { + "type": "string", + "format": "date-time", + "title": "Created At" + }, + "updated_at": { + "type": "string", + "format": "date-time", + "title": "Updated At" + } + }, + "type": "object", + "required": [ + "user_id" + ], + "title": "UserSettings", + "description": "Complete user settings model" + }, + "UserSettingsUpdate": { + "properties": { + "theme": { + "anyOf": [ + { + "$ref": "#/components/schemas/Theme" + }, + { + "type": "null" + } + ] + }, + "timezone": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Timezone" + }, + "date_format": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Date Format" + }, + "time_format": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Time Format" + }, + "notifications": { + "anyOf": [ + { + "$ref": "#/components/schemas/NotificationSettings" + }, + { + "type": "null" + } + ] + }, + "editor": { + "anyOf": [ + { + "$ref": "#/components/schemas/EditorSettings" + }, + { + "type": "null" + } + ] + }, + "custom_settings": { + "anyOf": [ + { + "type": "object" + }, + { + "type": "null" + } + ], + "title": "Custom Settings" + } + }, + "type": "object", + "title": "UserSettingsUpdate", + "description": "Partial update model for user settings" + }, + "UserUpdate": { + "properties": { + "username": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "null" + } + ], + "title": "Username" + }, + "email": { + "anyOf": [ + { + "type": "string", + "format": "email" + }, + { + "type": "null" + } + ], + "title": "Email" + }, + "role": { + "anyOf": [ + { + "$ref": "#/components/schemas/UserRole" + }, + { + "type": "null" + } + ] + }, + "is_active": { + "anyOf": [ + { + "type": "boolean" + }, + { + "type": "null" + } + ], + "title": "Is Active" + }, + "password": { + "anyOf": [ + { + "type": "string", + "minLength": 8 + }, + { + "type": "null" + } + ], + "title": "Password" + } + }, + "type": "object", + "title": "UserUpdate", + "description": "Model for updating a user" + }, + "ValidationError": { + "properties": { + "loc": { + "items": { + "anyOf": [ + { + "type": "string" + }, + { + "type": "integer" + } + ] + }, + "type": "array", + "title": "Location" + }, + "msg": { + "type": "string", + "title": "Message" + }, + "type": { + "type": "string", + "title": "Error Type" + } + }, + "type": "object", + "required": [ + "loc", + "msg", + "type" + ], + "title": "ValidationError" + } + } + } +} diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 51dd3682..94b3912d 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,4 +1,4 @@ -FROM node:20 +FROM node:22 WORKDIR /app diff --git a/frontend/Dockerfile.prod b/frontend/Dockerfile.prod index c5e21136..58c0d2f8 100644 --- a/frontend/Dockerfile.prod +++ b/frontend/Dockerfile.prod @@ -1,5 +1,5 @@ # Build stage -FROM node:20-alpine AS builder +FROM node:22-alpine AS builder WORKDIR /app diff --git a/frontend/openapi-ts.config.ts b/frontend/openapi-ts.config.ts new file mode 100644 index 00000000..7251f44b --- /dev/null +++ b/frontend/openapi-ts.config.ts @@ -0,0 +1,14 @@ +import { defineConfig } from '@hey-api/openapi-ts'; + +export default defineConfig({ + input: '../docs/reference/openapi.json', + output: { + path: 'src/lib/api', + format: 'prettier', + }, + plugins: [ + '@hey-api/typescript', + '@hey-api/sdk', + '@hey-api/client-fetch', + ], +}); diff --git a/frontend/package-lock.json b/frontend/package-lock.json new file mode 100644 index 00000000..ea1d447e --- /dev/null +++ b/frontend/package-lock.json @@ -0,0 +1,4765 @@ +{ + "name": "svelte-app", + "version": "1.0.0", + "lockfileVersion": 3, + "requires": true, + "packages": { + "": { + "name": "svelte-app", + "version": "1.0.0", + "dependencies": { + "@babel/runtime": "^7.27.6", + "@codemirror/autocomplete": "^6.17.0", + "@codemirror/commands": "^6.7.0", + "@codemirror/lang-python": "^6.1.6", + "@codemirror/language": "^6.10.2", + "@codemirror/state": "^6.4.1", + "@codemirror/theme-one-dark": "^6.1.2", + "@codemirror/view": "^6.34.1", + "@mateothegreat/svelte5-router": "^2.16.19", + "@rollup/plugin-commonjs": "^24.0.0", + "@rollup/plugin-json": "^6.1.0", + "@rollup/plugin-node-resolve": "^15.0.0", + "@rollup/plugin-replace": "^6.0.1", + "@rollup/plugin-terser": "^0.4.4", + "@uiw/codemirror-theme-bbedit": "^4.21.25", + "@uiw/codemirror-theme-dracula": "^4.24.2", + "@uiw/codemirror-theme-github": "^4.23.13", + "@uiw/codemirror-theme-monokai": "^4.24.2", + "@uiw/codemirror-theme-vscode": "^4.24.2", + "ansi-to-html": "^0.7.2", + "codemirror": "^6.0.1", + "dompurify": "^3.2.0", + "dotenv": "^17.2.3", + "postcss": "^8.4.47", + "rollup": "^3.15.0", + "rollup-plugin-css-only": "^4.3.0", + "rollup-plugin-livereload": "^2.0.0", + "rollup-plugin-postcss": "^4.0.2", + "rollup-plugin-svelte": "^7.2.2", + "sirv-cli": "^3.0.1", + "svelte": "^5.46.0", + "svelte-preprocess": "^6.0.3" + }, + "devDependencies": { + "@babel/runtime": "^7.24.7", + "@hey-api/openapi-ts": "0.89.1", + "@rollup/plugin-typescript": "^12.1.2", + "@tailwindcss/forms": "^0.5.11", + "@tailwindcss/postcss": "^4.1.13", + "express": "^5.2.1", + "http-proxy": "^1.18.1", + "rollup-plugin-serve": "^1.1.1", + "tailwindcss": "^4.1.13", + "tslib": "^2.8.1", + "typescript": "^5.7.2" + } + }, + "node_modules/@alloc/quick-lru": { + "version": "5.2.0", + "resolved": "https://registry.npmjs.org/@alloc/quick-lru/-/quick-lru-5.2.0.tgz", + "integrity": "sha512-UrcABB+4bUrFABwbluTIBErXwvbsU/V7TZWfmbgJfbkwiBuziS9gxdODUyuiecfdGQ85jglMW6juS3+z5TsKLw==", + "dev": true, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/@babel/runtime": { + "version": "7.28.4", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.28.4.tgz", + "integrity": "sha512-Q/N6JNWvIvPnLDvjlE1OUBLPQHH6l3CltCEsHIujp45zQUSSh8K+gHnaEX45yAT1nyngnINhvWtzN+Nb9D8RAQ==", + "dev": true, + "engines": { + "node": ">=6.9.0" + } + }, + "node_modules/@codemirror/autocomplete": { + "version": "6.20.0", + "resolved": "https://registry.npmjs.org/@codemirror/autocomplete/-/autocomplete-6.20.0.tgz", + "integrity": "sha512-bOwvTOIJcG5FVo5gUUupiwYh8MioPLQ4UcqbcRf7UQ98X90tCa9E1kZ3Z7tqwpZxYyOvh1YTYbmZE9RTfTp5hg==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.17.0", + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@codemirror/commands": { + "version": "6.10.1", + "resolved": "https://registry.npmjs.org/@codemirror/commands/-/commands-6.10.1.tgz", + "integrity": "sha512-uWDWFypNdQmz2y1LaNJzK7fL7TYKLeUAU0npEC685OKTF3KcQ2Vu3klIM78D7I6wGhktme0lh3CuQLv0ZCrD9Q==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.4.0", + "@codemirror/view": "^6.27.0", + "@lezer/common": "^1.1.0" + } + }, + "node_modules/@codemirror/lang-python": { + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/@codemirror/lang-python/-/lang-python-6.2.1.tgz", + "integrity": "sha512-IRjC8RUBhn9mGR9ywecNhB51yePWCGgvHfY1lWN/Mrp3cKuHr0isDKia+9HnvhiWNnMpbGhWrkhuWOc09exRyw==", + "dependencies": { + "@codemirror/autocomplete": "^6.3.2", + "@codemirror/language": "^6.8.0", + "@codemirror/state": "^6.0.0", + "@lezer/common": "^1.2.1", + "@lezer/python": "^1.1.4" + } + }, + "node_modules/@codemirror/language": { + "version": "6.11.3", + "resolved": "https://registry.npmjs.org/@codemirror/language/-/language-6.11.3.tgz", + "integrity": "sha512-9HBM2XnwDj7fnu0551HkGdrUrrqmYq/WC5iv6nbY2WdicXdGbhR/gfbZOH73Aqj4351alY1+aoG9rCNfiwS1RA==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.23.0", + "@lezer/common": "^1.1.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0", + "style-mod": "^4.0.0" + } + }, + "node_modules/@codemirror/lint": { + "version": "6.9.2", + "resolved": "https://registry.npmjs.org/@codemirror/lint/-/lint-6.9.2.tgz", + "integrity": "sha512-sv3DylBiIyi+xKwRCJAAsBZZZWo82shJ/RTMymLabAdtbkV5cSKwWDeCgtUq3v8flTaXS2y1kKkICuRYtUswyQ==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.35.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/search": { + "version": "6.5.11", + "resolved": "https://registry.npmjs.org/@codemirror/search/-/search-6.5.11.tgz", + "integrity": "sha512-KmWepDE6jUdL6n8cAAqIpRmLPBZ5ZKnicE8oGU/s3QrAVID+0VhLFrzUucVKHG5035/BSykhExDL/Xm7dHthiA==", + "dependencies": { + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "crelt": "^1.0.5" + } + }, + "node_modules/@codemirror/state": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/@codemirror/state/-/state-6.5.2.tgz", + "integrity": "sha512-FVqsPqtPWKVVL3dPSxy8wEF/ymIEuVzF1PK3VbUgrxXpJUSHQWWZz4JMToquRxnkw+36LTamCZG2iua2Ptq0fA==", + "dependencies": { + "@marijn/find-cluster-break": "^1.0.0" + } + }, + "node_modules/@codemirror/theme-one-dark": { + "version": "6.1.3", + "resolved": "https://registry.npmjs.org/@codemirror/theme-one-dark/-/theme-one-dark-6.1.3.tgz", + "integrity": "sha512-NzBdIvEJmx6fjeremiGp3t/okrLPYT0d9orIc7AFun8oZcRk58aejkqhv6spnz4MLAevrKNPMQYXEWMg4s+sKA==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0", + "@lezer/highlight": "^1.0.0" + } + }, + "node_modules/@codemirror/view": { + "version": "6.39.4", + "resolved": "https://registry.npmjs.org/@codemirror/view/-/view-6.39.4.tgz", + "integrity": "sha512-xMF6OfEAUVY5Waega4juo1QGACfNkNF+aJLqpd8oUJz96ms2zbfQ9Gh35/tI3y8akEV31FruKfj7hBnIU/nkqA==", + "dependencies": { + "@codemirror/state": "^6.5.0", + "crelt": "^1.0.6", + "style-mod": "^4.1.0", + "w3c-keyname": "^2.2.4" + } + }, + "node_modules/@hey-api/codegen-core": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/@hey-api/codegen-core/-/codegen-core-0.4.0.tgz", + "integrity": "sha512-o8rBbEXEUhEPzrHbqImYjwIHm4Oj0r1RPS+5cp8Z66kPO7SEN7PYUgK7XpmSxoy9LPMNK1M5qmCO4cGGwT+ELQ==", + "dev": true, + "dependencies": { + "ansi-colors": "4.1.3", + "color-support": "1.1.3" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/hey-api" + }, + "peerDependencies": { + "typescript": ">=5.5.3" + } + }, + "node_modules/@hey-api/json-schema-ref-parser": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/@hey-api/json-schema-ref-parser/-/json-schema-ref-parser-1.2.2.tgz", + "integrity": "sha512-oS+5yAdwnK20lSeFO1d53Ku+yaGCsY8PcrmSq2GtSs3bsBfRnHAbpPKSVzQcaxAOrzj5NB+f34WhZglVrNayBA==", + "dev": true, + "dependencies": { + "@jsdevtools/ono": "^7.1.3", + "@types/json-schema": "^7.0.15", + "js-yaml": "^4.1.1", + "lodash": "^4.17.21" + }, + "engines": { + "node": ">= 16" + }, + "funding": { + "url": "https://github.com/sponsors/hey-api" + } + }, + "node_modules/@hey-api/openapi-ts": { + "version": "0.89.1", + "resolved": "https://registry.npmjs.org/@hey-api/openapi-ts/-/openapi-ts-0.89.1.tgz", + "integrity": "sha512-1iG8e0hLIiaImFJdqXBNh9yu5B6oYUicrS/x/MwyWGuGH1A2D8DSjMKHbIfU6PIg4HH0rjZlRt2FoxDlBEGMRg==", + "dev": true, + "dependencies": { + "@hey-api/codegen-core": "^0.4.0", + "@hey-api/json-schema-ref-parser": "1.2.2", + "ansi-colors": "4.1.3", + "c12": "3.3.2", + "color-support": "1.1.3", + "commander": "14.0.2", + "open": "11.0.0", + "semver": "7.7.3" + }, + "bin": { + "openapi-ts": "bin/run.js" + }, + "engines": { + "node": ">=20.19.0" + }, + "funding": { + "url": "https://github.com/sponsors/hey-api" + }, + "peerDependencies": { + "typescript": ">=5.5.3" + } + }, + "node_modules/@hey-api/openapi-ts/node_modules/commander": { + "version": "14.0.2", + "resolved": "https://registry.npmjs.org/commander/-/commander-14.0.2.tgz", + "integrity": "sha512-TywoWNNRbhoD0BXs1P3ZEScW8W5iKrnbithIl0YH+uCmBd0QpPOA8yc82DS3BIE5Ma6FnBVUsJ7wVUDz4dvOWQ==", + "dev": true, + "engines": { + "node": ">=20" + } + }, + "node_modules/@isaacs/fs-minipass": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/@isaacs/fs-minipass/-/fs-minipass-4.0.1.tgz", + "integrity": "sha512-wgm9Ehl2jpeqP3zw/7mo3kRHFp5MEDhqAdwy1fTGkHAwnkGOVsgpvQhL8B5n1qlb01jV3n/bI0ZfZp5lWA1k4w==", + "dev": true, + "dependencies": { + "minipass": "^7.0.4" + }, + "engines": { + "node": ">=18.0.0" + } + }, + "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==", + "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==", + "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==", + "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==", + "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==" + }, + "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==", + "dependencies": { + "@jridgewell/resolve-uri": "^3.1.0", + "@jridgewell/sourcemap-codec": "^1.4.14" + } + }, + "node_modules/@jsdevtools/ono": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/@jsdevtools/ono/-/ono-7.1.3.tgz", + "integrity": "sha512-4JQNk+3mVzK3xh2rqd6RB4J46qUR19azEHBneZyTZM+c456qOrbbM/5xcR8huNCCcbVt7+UmizG6GuUvPvKUYg==", + "dev": true + }, + "node_modules/@lezer/common": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/@lezer/common/-/common-1.4.0.tgz", + "integrity": "sha512-DVeMRoGrgn/k45oQNu189BoW4SZwgZFzJ1+1TV5j2NJ/KFC83oa/enRqZSGshyeMk5cPWMhsKs9nx+8o0unwGg==" + }, + "node_modules/@lezer/highlight": { + "version": "1.2.3", + "resolved": "https://registry.npmjs.org/@lezer/highlight/-/highlight-1.2.3.tgz", + "integrity": "sha512-qXdH7UqTvGfdVBINrgKhDsVTJTxactNNxLk7+UMwZhU13lMHaOBlJe9Vqp907ya56Y3+ed2tlqzys7jDkTmW0g==", + "dependencies": { + "@lezer/common": "^1.3.0" + } + }, + "node_modules/@lezer/lr": { + "version": "1.4.5", + "resolved": "https://registry.npmjs.org/@lezer/lr/-/lr-1.4.5.tgz", + "integrity": "sha512-/YTRKP5yPPSo1xImYQk7AZZMAgap0kegzqCSYHjAL9x1AZ0ZQW+IpcEzMKagCsbTsLnVeWkxYrCNeXG8xEPrjg==", + "dependencies": { + "@lezer/common": "^1.0.0" + } + }, + "node_modules/@lezer/python": { + "version": "1.1.18", + "resolved": "https://registry.npmjs.org/@lezer/python/-/python-1.1.18.tgz", + "integrity": "sha512-31FiUrU7z9+d/ElGQLJFXl+dKOdx0jALlP3KEOsGTex8mvj+SoE1FgItcHWK/axkxCHGUSpqIHt6JAWfWu9Rhg==", + "dependencies": { + "@lezer/common": "^1.2.0", + "@lezer/highlight": "^1.0.0", + "@lezer/lr": "^1.0.0" + } + }, + "node_modules/@marijn/find-cluster-break": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/@marijn/find-cluster-break/-/find-cluster-break-1.0.2.tgz", + "integrity": "sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==" + }, + "node_modules/@mateothegreat/svelte5-router": { + "version": "2.16.19", + "resolved": "https://registry.npmjs.org/@mateothegreat/svelte5-router/-/svelte5-router-2.16.19.tgz", + "integrity": "sha512-SNkR15x3b0HLNM33BORKF9U6elHHWZxg42yikNUKW1YNjkYRBLBgDkVSJTqRIC6aE8Wt4vqmKKmHzQTK2EKiqA==", + "peerDependencies": { + "svelte": "^5.0.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==" + }, + "node_modules/@rollup/plugin-commonjs": { + "version": "24.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-commonjs/-/plugin-commonjs-24.1.0.tgz", + "integrity": "sha512-eSL45hjhCWI0jCCXcNtLVqM5N1JlBGvlFfY0m6oOYnLCJ6N0qEXoZql4sY2MOUArzhH4SA/qBpTxvvZp2Sc+DQ==", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "commondir": "^1.0.1", + "estree-walker": "^2.0.2", + "glob": "^8.0.3", + "is-reference": "1.2.1", + "magic-string": "^0.27.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.68.0||^3.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-json": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-json/-/plugin-json-6.1.0.tgz", + "integrity": "sha512-EGI2te5ENk1coGeADSIwZ7G2Q8CJS2sF120T7jLw4xFw9n7wIOXHo+kIYRAoVpJAN+kmqZSoO3Fp4JtoNF4ReA==", + "dependencies": { + "@rollup/pluginutils": "^5.1.0" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-node-resolve": { + "version": "15.3.1", + "resolved": "https://registry.npmjs.org/@rollup/plugin-node-resolve/-/plugin-node-resolve-15.3.1.tgz", + "integrity": "sha512-tgg6b91pAybXHJQMAAwW9VuWBO6Thi+q7BCNARLwSqlmsHz0XYURtGvh/AuwSADXSI4h/2uHbs7s4FzlZDGSGA==", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "@types/resolve": "1.20.2", + "deepmerge": "^4.2.2", + "is-module": "^1.0.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.78.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-replace": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/@rollup/plugin-replace/-/plugin-replace-6.0.3.tgz", + "integrity": "sha512-J4RZarRvQAm5IF0/LwUUg+obsm+xZhYnbMXmXROyoSE1ATJe3oXSb9L5MMppdxP2ylNSjv6zFBwKYjcKMucVfA==", + "dependencies": { + "@rollup/pluginutils": "^5.0.1", + "magic-string": "^0.30.3" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-replace/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==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/@rollup/plugin-terser": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/@rollup/plugin-terser/-/plugin-terser-0.4.4.tgz", + "integrity": "sha512-XHeJC5Bgvs8LfukDwWZp7yeqin6ns8RTl2B9avbejt6tZqsqvVoWI7ZTQrcNsfKEDWBTnTxM8nMDkO2IFFbd0A==", + "dependencies": { + "serialize-javascript": "^6.0.1", + "smob": "^1.0.0", + "terser": "^5.17.4" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@rollup/plugin-typescript": { + "version": "12.3.0", + "resolved": "https://registry.npmjs.org/@rollup/plugin-typescript/-/plugin-typescript-12.3.0.tgz", + "integrity": "sha512-7DP0/p7y3t67+NabT9f8oTBFE6gGkto4SA6Np2oudYmZE/m1dt8RB0SjL1msMxFpLo631qjRCcBlAbq1ml/Big==", + "dev": true, + "dependencies": { + "@rollup/pluginutils": "^5.1.0", + "resolve": "^1.22.1" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^2.14.0||^3.0.0||^4.0.0", + "tslib": "*", + "typescript": ">=3.7.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + }, + "tslib": { + "optional": true + } + } + }, + "node_modules/@rollup/pluginutils": { + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-5.3.0.tgz", + "integrity": "sha512-5EdhGZtnu3V88ces7s53hhfK5KSASnJZv8Lulpc04cWO3REESroJXg73DFsOmgbU2BhwV0E20bu2IDZb3VKW4Q==", + "dependencies": { + "@types/estree": "^1.0.0", + "estree-walker": "^2.0.2", + "picomatch": "^4.0.2" + }, + "engines": { + "node": ">=14.0.0" + }, + "peerDependencies": { + "rollup": "^1.20.0||^2.0.0||^3.0.0||^4.0.0" + }, + "peerDependenciesMeta": { + "rollup": { + "optional": true + } + } + }, + "node_modules/@sveltejs/acorn-typescript": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@sveltejs/acorn-typescript/-/acorn-typescript-1.0.8.tgz", + "integrity": "sha512-esgN+54+q0NjB0Y/4BomT9samII7jGwNy/2a3wNZbT2A2RpmXsXwUt24LvLhx6jUq2gVk4cWEvcRO6MFQbOfNA==", + "peerDependencies": { + "acorn": "^8.9.0" + } + }, + "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==", + "dev": true, + "dependencies": { + "mini-svg-data-uri": "^1.2.3" + }, + "peerDependencies": { + "tailwindcss": ">=3.0.0 || >= 3.0.0-alpha.1 || >= 4.0.0-alpha.20 || >= 4.0.0-beta.1" + } + }, + "node_modules/@tailwindcss/node": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/node/-/node-4.1.13.tgz", + "integrity": "sha512-eq3ouolC1oEFOAvOMOBAmfCIqZBJuvWvvYWh5h5iOYfe1HFC6+GZ6EIL0JdM3/niGRJmnrOc+8gl9/HGUaaptw==", + "dev": true, + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "enhanced-resolve": "^5.18.3", + "jiti": "^2.5.1", + "lightningcss": "1.30.1", + "magic-string": "^0.30.18", + "source-map-js": "^1.2.1", + "tailwindcss": "4.1.13" + } + }, + "node_modules/@tailwindcss/node/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, + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/@tailwindcss/oxide": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide/-/oxide-4.1.13.tgz", + "integrity": "sha512-CPgsM1IpGRa880sMbYmG1s4xhAy3xEt1QULgTJGQmZUeNgXFR7s1YxYygmJyBGtou4SyEosGAGEeYqY7R53bIA==", + "dev": true, + "hasInstallScript": true, + "dependencies": { + "detect-libc": "^2.0.4", + "tar": "^7.4.3" + }, + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "@tailwindcss/oxide-android-arm64": "4.1.13", + "@tailwindcss/oxide-darwin-arm64": "4.1.13", + "@tailwindcss/oxide-darwin-x64": "4.1.13", + "@tailwindcss/oxide-freebsd-x64": "4.1.13", + "@tailwindcss/oxide-linux-arm-gnueabihf": "4.1.13", + "@tailwindcss/oxide-linux-arm64-gnu": "4.1.13", + "@tailwindcss/oxide-linux-arm64-musl": "4.1.13", + "@tailwindcss/oxide-linux-x64-gnu": "4.1.13", + "@tailwindcss/oxide-linux-x64-musl": "4.1.13", + "@tailwindcss/oxide-wasm32-wasi": "4.1.13", + "@tailwindcss/oxide-win32-arm64-msvc": "4.1.13", + "@tailwindcss/oxide-win32-x64-msvc": "4.1.13" + } + }, + "node_modules/@tailwindcss/oxide-android-arm64": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-android-arm64/-/oxide-android-arm64-4.1.13.tgz", + "integrity": "sha512-BrpTrVYyejbgGo57yc8ieE+D6VT9GOgnNdmh5Sac6+t0m+v+sKQevpFVpwX3pBrM2qKrQwJ0c5eDbtjouY/+ew==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-arm64": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-arm64/-/oxide-darwin-arm64-4.1.13.tgz", + "integrity": "sha512-YP+Jksc4U0KHcu76UhRDHq9bx4qtBftp9ShK/7UGfq0wpaP96YVnnjFnj3ZFrUAjc5iECzODl/Ts0AN7ZPOANQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-darwin-x64": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-darwin-x64/-/oxide-darwin-x64-4.1.13.tgz", + "integrity": "sha512-aAJ3bbwrn/PQHDxCto9sxwQfT30PzyYJFG0u/BWZGeVXi5Hx6uuUOQEI2Fa43qvmUjTRQNZnGqe9t0Zntexeuw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-freebsd-x64": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-freebsd-x64/-/oxide-freebsd-x64-4.1.13.tgz", + "integrity": "sha512-Wt8KvASHwSXhKE/dJLCCWcTSVmBj3xhVhp/aF3RpAhGeZ3sVo7+NTfgiN8Vey/Fi8prRClDs6/f0KXPDTZE6nQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm-gnueabihf": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm-gnueabihf/-/oxide-linux-arm-gnueabihf-4.1.13.tgz", + "integrity": "sha512-mbVbcAsW3Gkm2MGwA93eLtWrwajz91aXZCNSkGTx/R5eb6KpKD5q8Ueckkh9YNboU8RH7jiv+ol/I7ZyQ9H7Bw==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-gnu": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-gnu/-/oxide-linux-arm64-gnu-4.1.13.tgz", + "integrity": "sha512-wdtfkmpXiwej/yoAkrCP2DNzRXCALq9NVLgLELgLim1QpSfhQM5+ZxQQF8fkOiEpuNoKLp4nKZ6RC4kmeFH0HQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-arm64-musl": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-arm64-musl/-/oxide-linux-arm64-musl-4.1.13.tgz", + "integrity": "sha512-hZQrmtLdhyqzXHB7mkXfq0IYbxegaqTmfa1p9MBj72WPoDD3oNOh1Lnxf6xZLY9C3OV6qiCYkO1i/LrzEdW2mg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-gnu": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-gnu/-/oxide-linux-x64-gnu-4.1.13.tgz", + "integrity": "sha512-uaZTYWxSXyMWDJZNY1Ul7XkJTCBRFZ5Fo6wtjrgBKzZLoJNrG+WderJwAjPzuNZOnmdrVg260DKwXCFtJ/hWRQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-linux-x64-musl": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-linux-x64-musl/-/oxide-linux-x64-musl-4.1.13.tgz", + "integrity": "sha512-oXiPj5mi4Hdn50v5RdnuuIms0PVPI/EG4fxAfFiIKQh5TgQgX7oSuDWntHW7WNIi/yVLAiS+CRGW4RkoGSSgVQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-wasm32-wasi": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-wasm32-wasi/-/oxide-wasm32-wasi-4.1.13.tgz", + "integrity": "sha512-+LC2nNtPovtrDwBc/nqnIKYh/W2+R69FA0hgoeOn64BdCX522u19ryLh3Vf3F8W49XBcMIxSe665kwy21FkhvA==", + "bundleDependencies": [ + "@napi-rs/wasm-runtime", + "@emnapi/core", + "@emnapi/runtime", + "@tybys/wasm-util", + "@emnapi/wasi-threads", + "tslib" + ], + "cpu": [ + "wasm32" + ], + "dev": true, + "optional": true, + "dependencies": { + "@emnapi/core": "^1.4.5", + "@emnapi/runtime": "^1.4.5", + "@emnapi/wasi-threads": "^1.0.4", + "@napi-rs/wasm-runtime": "^0.2.12", + "@tybys/wasm-util": "^0.10.0", + "tslib": "^2.8.0" + }, + "engines": { + "node": ">=14.0.0" + } + }, + "node_modules/@tailwindcss/oxide-win32-arm64-msvc": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-arm64-msvc/-/oxide-win32-arm64-msvc-4.1.13.tgz", + "integrity": "sha512-dziTNeQXtoQ2KBXmrjCxsuPk3F3CQ/yb7ZNZNA+UkNTeiTGgfeh+gH5Pi7mRncVgcPD2xgHvkFCh/MhZWSgyQg==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/oxide-win32-x64-msvc": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/oxide-win32-x64-msvc/-/oxide-win32-x64-msvc-4.1.13.tgz", + "integrity": "sha512-3+LKesjXydTkHk5zXX01b5KMzLV1xl2mcktBJkje7rhFUpUlYJy7IMOLqjIRQncLTa1WZZiFY/foAeB5nmaiTw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/@tailwindcss/postcss": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/@tailwindcss/postcss/-/postcss-4.1.13.tgz", + "integrity": "sha512-HLgx6YSFKJT7rJqh9oJs/TkBFhxuMOfUKSBEPYwV+t78POOBsdQ7crhZLzwcH3T0UyUuOzU/GK5pk5eKr3wCiQ==", + "dev": true, + "dependencies": { + "@alloc/quick-lru": "^5.2.0", + "@tailwindcss/node": "4.1.13", + "@tailwindcss/oxide": "4.1.13", + "postcss": "^8.4.41", + "tailwindcss": "4.1.13" + } + }, + "node_modules/@trysound/sax": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/@trysound/sax/-/sax-0.2.0.tgz", + "integrity": "sha512-L7z9BgrNEcYyUYtF+HaEfiS5ebkh9jXqbszz7pC0hRBPaatV0XjSD3+eHrpqFemQfgwiFF0QPIarnIihIDn7OA==", + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/@types/estree": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/@types/estree/-/estree-1.0.8.tgz", + "integrity": "sha512-dWHzHa2WqEXI/O1E9OjrocMTKJl2mSrEolh1Iomrv6U+JuNwaHXsXx9bLu5gG7BUWFIN0skIQJQ/L1rIex4X6w==" + }, + "node_modules/@types/json-schema": { + "version": "7.0.15", + "resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz", + "integrity": "sha512-5+fP8P8MFNC+AyZCDxrB2pkZFPGzqQWUzpSeuuVLvm8VMcorNYavBqoFcxK8bQz4Qsbn4oUEEem4wDLfcysGHA==", + "dev": true + }, + "node_modules/@types/resolve": { + "version": "1.20.2", + "resolved": "https://registry.npmjs.org/@types/resolve/-/resolve-1.20.2.tgz", + "integrity": "sha512-60BCwRFOZCQhDncwQdxxeOEEkbc5dIMccYLwbxsS4TUNeVECQ/pBJ0j09mrHOl/JJvpRPGwO9SvE4nR2Nb/a4Q==" + }, + "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==", + "optional": true + }, + "node_modules/@uiw/codemirror-theme-bbedit": { + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-bbedit/-/codemirror-theme-bbedit-4.25.4.tgz", + "integrity": "sha512-Rq6rlv/Jr9G/PNSRAIfLl7OUyZAOVdVwkHTQP8YJVCj7JGylv/+7CflET6CPJXCZmrv4ZvPZmjS53c1+Pz5I6w==", + "dependencies": { + "@uiw/codemirror-themes": "4.25.4" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/@uiw/codemirror-theme-dracula": { + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-dracula/-/codemirror-theme-dracula-4.25.4.tgz", + "integrity": "sha512-ejmDA9cXVLWDJGlgxCjz4vVMn2fnFexMX3QxoH8d/pbunIFy//lyqmEO6zzKC9+ltc0PaKvZYYx668qqip/pDA==", + "dependencies": { + "@uiw/codemirror-themes": "4.25.4" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/@uiw/codemirror-theme-github": { + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-github/-/codemirror-theme-github-4.25.4.tgz", + "integrity": "sha512-M5zRT2vIpNsuKN0Lz+DwLnmhHW8Eddp1M9zC0hm3V+bvffmaSn/pUDey1eqGIv5xNNmjhqvDAz0a90xLYCzvSw==", + "dependencies": { + "@uiw/codemirror-themes": "4.25.4" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/@uiw/codemirror-theme-monokai": { + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-monokai/-/codemirror-theme-monokai-4.25.4.tgz", + "integrity": "sha512-XUMC1valIiyYTXQ9GwlohBQ2OtwygFZ/gIu1qODzCZ5r6Hi2m1MpdpjtYXnUhDa0sqD2TmUGaCGSFyInv9dl2g==", + "dependencies": { + "@uiw/codemirror-themes": "4.25.4" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/@uiw/codemirror-theme-vscode": { + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-theme-vscode/-/codemirror-theme-vscode-4.25.4.tgz", + "integrity": "sha512-9ob5EtLqrXBFl8uf4eFRkXjyjfyfBRVsJdt7xbc33f+2/I29/2v2nEdU/xw40+dhloxF/h1Ry281f8wAs97MWQ==", + "dependencies": { + "@uiw/codemirror-themes": "4.25.4" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + } + }, + "node_modules/@uiw/codemirror-themes": { + "version": "4.25.4", + "resolved": "https://registry.npmjs.org/@uiw/codemirror-themes/-/codemirror-themes-4.25.4.tgz", + "integrity": "sha512-2SLktItgcZC4p0+PfFusEbAHwbuAWe3bOOntCevVgHtrWGtGZX3IPv2k8IKZMgOXtAHyGKpJvT9/nspPn/uCQg==", + "dependencies": { + "@codemirror/language": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.0.0" + }, + "funding": { + "url": "https://jaywcjlove.github.io/#/sponsor" + }, + "peerDependencies": { + "@codemirror/language": ">=6.0.0", + "@codemirror/state": ">=6.0.0", + "@codemirror/view": ">=6.0.0" + } + }, + "node_modules/accepts": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-2.0.0.tgz", + "integrity": "sha512-5cvg6CtKwfgdmVqY1WIiXKc3Q1bkRqGLi+2W/6ao+6Y7gu/RCwRuAhGEzh5B4KlszSuTLgZYuqFqo5bImjNKng==", + "dev": true, + "dependencies": { + "mime-types": "^3.0.0", + "negotiator": "^1.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/acorn": { + "version": "8.15.0", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", + "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", + "bin": { + "acorn": "bin/acorn" + }, + "engines": { + "node": ">=0.4.0" + } + }, + "node_modules/ansi-colors": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/ansi-colors/-/ansi-colors-4.1.3.tgz", + "integrity": "sha512-/6w/C21Pm1A7aZitlI5Ni/2J6FFQN8i1Cvz3kHABAAbw93v/NlvKdVOqz7CCWz/3iv/JplRSEEZ83XION15ovw==", + "dev": true, + "engines": { + "node": ">=6" + } + }, + "node_modules/ansi-styles": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz", + "integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==", + "dependencies": { + "color-convert": "^2.0.1" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/chalk/ansi-styles?sponsor=1" + } + }, + "node_modules/ansi-to-html": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/ansi-to-html/-/ansi-to-html-0.7.2.tgz", + "integrity": "sha512-v6MqmEpNlxF+POuyhKkidusCHWWkaLcGRURzivcU3I9tv7k4JVhFcnukrM5Rlk2rUywdZuzYAZ+kbZqWCnfN3g==", + "dependencies": { + "entities": "^2.2.0" + }, + "bin": { + "ansi-to-html": "bin/ansi-to-html" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/anymatch": { + "version": "3.1.3", + "resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz", + "integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==", + "dependencies": { + "normalize-path": "^3.0.0", + "picomatch": "^2.0.4" + }, + "engines": { + "node": ">= 8" + } + }, + "node_modules/anymatch/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/argparse": { + "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 + }, + "node_modules/aria-query": { + "version": "5.3.2", + "resolved": "https://registry.npmjs.org/aria-query/-/aria-query-5.3.2.tgz", + "integrity": "sha512-COROpnaoap1E2F000S62r6A60uHZnmlvomhfyT2DlTcrY1OrBKn2UhH7qn5wTC9zMvD0AY7csdPSNwKP+7WiQw==", + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/axobject-query": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/axobject-query/-/axobject-query-4.1.0.tgz", + "integrity": "sha512-qIj0G9wZbMGNLjLmg1PT6v2mE9AH2zlnADJD/2tC6E00hgmhUOfEB6greHPAfLRSufHqROIUTkw6E+M3lH0PTQ==", + "engines": { + "node": ">= 0.4" + } + }, + "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==" + }, + "node_modules/baseline-browser-mapping": { + "version": "2.9.10", + "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.10.tgz", + "integrity": "sha512-2VIKvDx8Z1a9rTB2eCkdPE5nSe28XnA+qivGnWHoB40hMMt/h1hSz0960Zqsn6ZyxWXUie0EBdElKv8may20AA==", + "bin": { + "baseline-browser-mapping": "dist/cli.js" + } + }, + "node_modules/binary-extensions": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/binary-extensions/-/binary-extensions-2.3.0.tgz", + "integrity": "sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/body-parser": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-2.2.1.tgz", + "integrity": "sha512-nfDwkulwiZYQIGwxdy0RUmowMhKcFVcYXUU7m4QlKYim1rUtg83xm2yjZ40QjDuc291AJjjeSc9b++AWHSgSHw==", + "dev": true, + "dependencies": { + "bytes": "^3.1.2", + "content-type": "^1.0.5", + "debug": "^4.4.3", + "http-errors": "^2.0.0", + "iconv-lite": "^0.7.0", + "on-finished": "^2.4.1", + "qs": "^6.14.0", + "raw-body": "^3.0.1", + "type-is": "^2.0.1" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/boolbase": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/boolbase/-/boolbase-1.0.0.tgz", + "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" + }, + "node_modules/brace-expansion": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.2.tgz", + "integrity": "sha512-Jt0vHyM+jmUBqojB7E1NIYadt0vI0Qxjxd2TErW94wDz+E2LAm5vKMXXwg6ZZBTHPuUlDgQHKXvjGBdfcF1ZDQ==", + "dependencies": { + "balanced-match": "^1.0.0" + } + }, + "node_modules/braces": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", + "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", + "dependencies": { + "fill-range": "^7.1.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/browserslist": { + "version": "4.28.1", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", + "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/browserslist" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "baseline-browser-mapping": "^2.9.0", + "caniuse-lite": "^1.0.30001759", + "electron-to-chromium": "^1.5.263", + "node-releases": "^2.0.27", + "update-browserslist-db": "^1.2.0" + }, + "bin": { + "browserslist": "cli.js" + }, + "engines": { + "node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7" + } + }, + "node_modules/buffer-from": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/buffer-from/-/buffer-from-1.1.2.tgz", + "integrity": "sha512-E+XQCRwSbaaiChtv6k6Dwgc+bx+Bs6vuKJHHl5kox/BaKbhiXzqQOwK4cO22yElGp2OCmjwVhT3HmxgyPGnJfQ==" + }, + "node_modules/bundle-name": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/bundle-name/-/bundle-name-4.1.0.tgz", + "integrity": "sha512-tjwM5exMg6BGRI+kNmTntNsvdZS1X8BFYS6tnJ2hdH0kVxM6/eVZ2xy+FqStSWvYmtfFMDLIxurorHwDKfDz5Q==", + "dev": true, + "dependencies": { + "run-applescript": "^7.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/bytes": { + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.1.2.tgz", + "integrity": "sha512-/Nf7TyzTx6S3yRJObOAV7956r8cr2+Oj8AC5dt8wSP3BQAoeX58NoHyCU8P8zGkNXStjTSi6fzO6F0pBdcYbEg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/c12": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/c12/-/c12-3.3.2.tgz", + "integrity": "sha512-QkikB2X5voO1okL3QsES0N690Sn/K9WokXqUsDQsWy5SnYb+psYQFGA10iy1bZHj3fjISKsI67Q90gruvWWM3A==", + "dev": true, + "dependencies": { + "chokidar": "^4.0.3", + "confbox": "^0.2.2", + "defu": "^6.1.4", + "dotenv": "^17.2.3", + "exsolve": "^1.0.8", + "giget": "^2.0.0", + "jiti": "^2.6.1", + "ohash": "^2.0.11", + "pathe": "^2.0.3", + "perfect-debounce": "^2.0.0", + "pkg-types": "^2.3.0", + "rc9": "^2.1.2" + }, + "peerDependencies": { + "magicast": "*" + }, + "peerDependenciesMeta": { + "magicast": { + "optional": true + } + } + }, + "node_modules/c12/node_modules/chokidar": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-4.0.3.tgz", + "integrity": "sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==", + "dev": true, + "dependencies": { + "readdirp": "^4.0.1" + }, + "engines": { + "node": ">= 14.16.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/c12/node_modules/readdirp": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-4.1.2.tgz", + "integrity": "sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==", + "dev": true, + "engines": { + "node": ">= 14.18.0" + }, + "funding": { + "type": "individual", + "url": "https://paulmillr.com/funding/" + } + }, + "node_modules/call-bind-apply-helpers": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/call-bind-apply-helpers/-/call-bind-apply-helpers-1.0.2.tgz", + "integrity": "sha512-Sp1ablJ0ivDkSzjcaJdxEunN5/XvksFJ2sMBFfq6x0ryhQV/2b/KwFe21cMpmHtPOSij8K99/wSfoEuTObmuMQ==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/call-bound": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/call-bound/-/call-bound-1.0.4.tgz", + "integrity": "sha512-+ys997U96po4Kx/ABpBCqhA9EuxJaQWDQg7295H4hBphv3IZg0boBKuwYpt4YXp6MZ5AmZQnU/tyMTlRpaSejg==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "get-intrinsic": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/caniuse-api": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/caniuse-api/-/caniuse-api-3.0.0.tgz", + "integrity": "sha512-bsTwuIg/BZZK/vreVTYYbSWoe2F+71P7K5QGEX+pT250DZbfU1MQ5prOKpPR+LL6uWKK3KMwMCAS74QB3Um1uw==", + "dependencies": { + "browserslist": "^4.0.0", + "caniuse-lite": "^1.0.0", + "lodash.memoize": "^4.1.2", + "lodash.uniq": "^4.5.0" + } + }, + "node_modules/caniuse-lite": { + "version": "1.0.30001760", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001760.tgz", + "integrity": "sha512-7AAMPcueWELt1p3mi13HR/LHH0TJLT11cnwDJEs3xA4+CK/PLKeO9Kl1oru24htkyUKtkGCvAx4ohB0Ttry8Dw==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/browserslist" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/caniuse-lite" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ] + }, + "node_modules/chalk": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz", + "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==", + "dependencies": { + "ansi-styles": "^4.1.0", + "supports-color": "^7.1.0" + }, + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/chalk/chalk?sponsor=1" + } + }, + "node_modules/chokidar": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/chokidar/-/chokidar-3.6.0.tgz", + "integrity": "sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==", + "dependencies": { + "anymatch": "~3.1.2", + "braces": "~3.0.2", + "glob-parent": "~5.1.2", + "is-binary-path": "~2.1.0", + "is-glob": "~4.0.1", + "normalize-path": "~3.0.0", + "readdirp": "~3.6.0" + }, + "engines": { + "node": ">= 8.10.0" + }, + "funding": { + "url": "https://paulmillr.com/funding/" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/chownr": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-3.0.0.tgz", + "integrity": "sha512-+IxzY9BZOQd/XuYPRmrvEVjF/nqj5kgT4kEq7VofrDoM1MxoRjEWkrCC3EtLi59TVawxTAn+orJwFQcrqEN1+g==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/citty": { + "version": "0.1.6", + "resolved": "https://registry.npmjs.org/citty/-/citty-0.1.6.tgz", + "integrity": "sha512-tskPPKEs8D2KPafUypv2gxwJP8h/OaJmC82QQGGDQcHvXX43xF2VDACcJVmZ0EuSxkpO9Kc4MlrA3q0+FG58AQ==", + "dev": true, + "dependencies": { + "consola": "^3.2.3" + } + }, + "node_modules/clsx": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/clsx/-/clsx-2.1.1.tgz", + "integrity": "sha512-eYm0QWBtUrBWZWG0d386OGAw16Z995PiOVo2B7bjWSbHedGl5e0ZWaq65kOGgUSNesEIDkB9ISbTg/JK9dhCZA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/codemirror": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/codemirror/-/codemirror-6.0.2.tgz", + "integrity": "sha512-VhydHotNW5w1UGK0Qj96BwSk/Zqbp9WbnyK2W/eVMv4QyF41INRGpjUhFJY7/uDNuudSc33a/PKr4iDqRduvHw==", + "dependencies": { + "@codemirror/autocomplete": "^6.0.0", + "@codemirror/commands": "^6.0.0", + "@codemirror/language": "^6.0.0", + "@codemirror/lint": "^6.0.0", + "@codemirror/search": "^6.0.0", + "@codemirror/state": "^6.0.0", + "@codemirror/view": "^6.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==", + "dependencies": { + "color-name": "~1.1.4" + }, + "engines": { + "node": ">=7.0.0" + } + }, + "node_modules/color-name": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz", + "integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==" + }, + "node_modules/color-support": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-support/-/color-support-1.1.3.tgz", + "integrity": "sha512-qiBjkpbMLO/HL68y+lh4q0/O1MZFj2RX6X/KmMa3+gJD3z+WwI1ZzDHysvqHGS3mP6mznPckpXmw1nI9cJjyRg==", + "dev": true, + "bin": { + "color-support": "bin.js" + } + }, + "node_modules/colord": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/colord/-/colord-2.9.3.tgz", + "integrity": "sha512-jeC1axXpnb0/2nn/Y1LPuLdgXBLH7aDcHu4KEKfqw3CUhX7ZpfBSlPKyqXE6btIgEzfWtrX3/tyBCaCvXvMkOw==" + }, + "node_modules/commander": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-7.2.0.tgz", + "integrity": "sha512-QrWXB+ZQSVPmIWIhtEO9H+gwHaMGYiF5ChvoJ+K9ZGHG/sVsa6yiesAD1GC/x46sET00Xlwo1u49RVVVzvcSkw==", + "engines": { + "node": ">= 10" + } + }, + "node_modules/commondir": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/commondir/-/commondir-1.0.1.tgz", + "integrity": "sha512-W9pAhw0ja1Edb5GVdIF1mjZw/ASI0AlShXM83UUGe2DVr5TdAPEA1OA8m/g8zWp9x6On7gqufY+FatDbC3MDQg==" + }, + "node_modules/concat-with-sourcemaps": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/concat-with-sourcemaps/-/concat-with-sourcemaps-1.1.0.tgz", + "integrity": "sha512-4gEjHJFT9e+2W/77h/DS5SGUgwDaOwprX8L/gl5+3ixnzkVJJsZWDSelmN3Oilw3LNDZjZV0yqH1hLG3k6nghg==", + "dependencies": { + "source-map": "^0.6.1" + } + }, + "node_modules/confbox": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/confbox/-/confbox-0.2.2.tgz", + "integrity": "sha512-1NB+BKqhtNipMsov4xI/NnhCKp9XG9NamYp5PVm9klAT0fsrNPjaFICsCFhNhwZJKNh7zB/3q8qXz0E9oaMNtQ==", + "dev": true + }, + "node_modules/consola": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/consola/-/consola-3.4.2.tgz", + "integrity": "sha512-5IKcdX0nnYavi6G7TtOhwkYzyjfJlatbjMjuLSfE2kYT5pMDOilZ4OvMhi637CcDICTmz3wARPoyhqyX1Y+XvA==", + "dev": true, + "engines": { + "node": "^14.18.0 || >=16.10.0" + } + }, + "node_modules/console-clear": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/console-clear/-/console-clear-1.1.1.tgz", + "integrity": "sha512-pMD+MVR538ipqkG5JXeOEbKWS5um1H4LUUccUQG68qpeqBYbzYy79Gh55jkd2TtPdRfUaLWdv6LPP//5Zt0aPQ==", + "engines": { + "node": ">=4" + } + }, + "node_modules/content-disposition": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-1.0.1.tgz", + "integrity": "sha512-oIXISMynqSqm241k6kcQ5UwttDILMK4BiurCfGEREw6+X9jkkpEe5T9FZaApyLGGOnFuyMWZpdolTXMtvEJ08Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/content-type": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.5.tgz", + "integrity": "sha512-nTjqfcBFEipKdXCv4YDQWCfmcLZKm81ldF0pAopTvyrFGVbcR6P/VAAd5G7N+0tTr8QqiU0tFadD6FK4NtJwOA==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie": { + "version": "0.7.2", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.7.2.tgz", + "integrity": "sha512-yki5XnKuf750l50uGTllt6kKILY4nQ1eNIQatoXEByZ5dWgnKqbnqmTrBE5B4N7lrMJKQ2ytWMiTO2o0v6Ew/w==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/cookie-signature": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.2.2.tgz", + "integrity": "sha512-D76uU73ulSXrD1UXF4KE2TMxVVwhsnCgfAyTg9k8P6KGZjlXKrOLe4dJQKI3Bxi5wjesZoFXJWElNWBjPZMbhg==", + "dev": true, + "engines": { + "node": ">=6.6.0" + } + }, + "node_modules/crelt": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/crelt/-/crelt-1.0.6.tgz", + "integrity": "sha512-VQ2MBenTq1fWZUH9DJNGti7kKv6EeAuYr3cLwxUWhIu1baTaXh4Ib5W2CqHVqib4/MqbYGJqiL3Zb8GJZr3l4g==" + }, + "node_modules/css-declaration-sorter": { + "version": "6.4.1", + "resolved": "https://registry.npmjs.org/css-declaration-sorter/-/css-declaration-sorter-6.4.1.tgz", + "integrity": "sha512-rtdthzxKuyq6IzqX6jEcIzQF/YqccluefyCYheovBOLhFT/drQA9zj/UbRAa9J7C0o6EG6u3E6g+vKkay7/k3g==", + "engines": { + "node": "^10 || ^12 || >=14" + }, + "peerDependencies": { + "postcss": "^8.0.9" + } + }, + "node_modules/css-select": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/css-select/-/css-select-4.3.0.tgz", + "integrity": "sha512-wPpOYtnsVontu2mODhA19JrqWxNsfdatRKd64kmpRbQgh1KtItko5sTnEpPdpSaJszTOhEMlF/RPz28qj4HqhQ==", + "dependencies": { + "boolbase": "^1.0.0", + "css-what": "^6.0.1", + "domhandler": "^4.3.1", + "domutils": "^2.8.0", + "nth-check": "^2.0.1" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/css-what": { + "version": "6.2.2", + "resolved": "https://registry.npmjs.org/css-what/-/css-what-6.2.2.tgz", + "integrity": "sha512-u/O3vwbptzhMs3L1fQE82ZSLHQQfto5gyZzwteVIEyeaY5Fc7R4dapF/BvRoSYFeqfBk4m0V1Vafq5Pjv25wvA==", + "engines": { + "node": ">= 6" + }, + "funding": { + "url": "https://github.com/sponsors/fb55" + } + }, + "node_modules/cssesc": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/cssesc/-/cssesc-3.0.0.tgz", + "integrity": "sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==", + "bin": { + "cssesc": "bin/cssesc" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/cssnano": { + "version": "5.1.15", + "resolved": "https://registry.npmjs.org/cssnano/-/cssnano-5.1.15.tgz", + "integrity": "sha512-j+BKgDcLDQA+eDifLx0EO4XSA56b7uut3BQFH+wbSaSTuGLuiyTa/wbRYthUXX8LC9mLg+WWKe8h+qJuwTAbHw==", + "dependencies": { + "cssnano-preset-default": "^5.2.14", + "lilconfig": "^2.0.3", + "yaml": "^1.10.2" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/cssnano" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-preset-default": { + "version": "5.2.14", + "resolved": "https://registry.npmjs.org/cssnano-preset-default/-/cssnano-preset-default-5.2.14.tgz", + "integrity": "sha512-t0SFesj/ZV2OTylqQVOrFgEh5uanxbO6ZAdeCrNsUQ6fVuXwYTxJPNAGvGTxHbD68ldIJNec7PyYZDBrfDQ+6A==", + "dependencies": { + "css-declaration-sorter": "^6.3.1", + "cssnano-utils": "^3.1.0", + "postcss-calc": "^8.2.3", + "postcss-colormin": "^5.3.1", + "postcss-convert-values": "^5.1.3", + "postcss-discard-comments": "^5.1.2", + "postcss-discard-duplicates": "^5.1.0", + "postcss-discard-empty": "^5.1.1", + "postcss-discard-overridden": "^5.1.0", + "postcss-merge-longhand": "^5.1.7", + "postcss-merge-rules": "^5.1.4", + "postcss-minify-font-values": "^5.1.0", + "postcss-minify-gradients": "^5.1.1", + "postcss-minify-params": "^5.1.4", + "postcss-minify-selectors": "^5.2.1", + "postcss-normalize-charset": "^5.1.0", + "postcss-normalize-display-values": "^5.1.0", + "postcss-normalize-positions": "^5.1.1", + "postcss-normalize-repeat-style": "^5.1.1", + "postcss-normalize-string": "^5.1.0", + "postcss-normalize-timing-functions": "^5.1.0", + "postcss-normalize-unicode": "^5.1.1", + "postcss-normalize-url": "^5.1.0", + "postcss-normalize-whitespace": "^5.1.1", + "postcss-ordered-values": "^5.1.3", + "postcss-reduce-initial": "^5.1.2", + "postcss-reduce-transforms": "^5.1.0", + "postcss-svgo": "^5.1.0", + "postcss-unique-selectors": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/cssnano-utils": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/cssnano-utils/-/cssnano-utils-3.1.0.tgz", + "integrity": "sha512-JQNR19/YZhz4psLX/rQ9M83e3z2Wf/HdJbryzte4a3NSuafyp9w/I4U+hx5C2S9g41qlstH7DEWnZaaj83OuEA==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/csso": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/csso/-/csso-4.2.0.tgz", + "integrity": "sha512-wvlcdIbf6pwKEk7vHj8/Bkc0B4ylXZruLvOgs9doS5eOsOpuodOV2zJChSpkp+pRpYQLQMeF04nr3Z68Sta9jA==", + "dependencies": { + "css-tree": "^1.1.2" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/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==", + "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==" + }, + "node_modules/debug": { + "version": "4.4.3", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", + "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", + "dev": true, + "dependencies": { + "ms": "^2.1.3" + }, + "engines": { + "node": ">=6.0" + }, + "peerDependenciesMeta": { + "supports-color": { + "optional": true + } + } + }, + "node_modules/deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/default-browser": { + "version": "5.4.0", + "resolved": "https://registry.npmjs.org/default-browser/-/default-browser-5.4.0.tgz", + "integrity": "sha512-XDuvSq38Hr1MdN47EDvYtx3U0MTqpCEn+F6ft8z2vYDzMrvQhVp0ui9oQdqW3MvK3vqUETglt1tVGgjLuJ5izg==", + "dev": true, + "dependencies": { + "bundle-name": "^4.1.0", + "default-browser-id": "^5.0.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/default-browser-id": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/default-browser-id/-/default-browser-id-5.0.1.tgz", + "integrity": "sha512-x1VCxdX4t+8wVfd1so/9w+vQ4vx7lKd2Qp5tDRutErwmR85OgmfX7RlLRMWafRMY7hbEiXIbudNrjOAPa/hL8Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/define-lazy-prop": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/define-lazy-prop/-/define-lazy-prop-3.0.0.tgz", + "integrity": "sha512-N+MeXYoqr3pOgn8xfyRPREN7gHakLYjhsHhWGT3fWAiL4IkAt0iDw14QiiEm2bE30c5XX5q0FtAA3CK5f9/BUg==", + "dev": true, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/defu": { + "version": "6.1.4", + "resolved": "https://registry.npmjs.org/defu/-/defu-6.1.4.tgz", + "integrity": "sha512-mEQCMmwJu317oSz8CwdIOdwf3xMif1ttiM8LTufzc3g6kR+9Pe236twL8j3IYT1F7GfRgGcW6MWxzZjLIkuHIg==", + "dev": true + }, + "node_modules/depd": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/depd/-/depd-2.0.0.tgz", + "integrity": "sha512-g7nH6P6dyDioJogAAGprGpCtVImJhpPk/roCzdb3fIh61/s/nPsfR6onyMwkCAR/OlC3yBC0lESvUoQEAssIrw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/destr": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/destr/-/destr-2.0.5.tgz", + "integrity": "sha512-ugFTXCtDZunbzasqBxrK93Ik/DRYsO6S/fedkWEMKqt04xZ4csmnmwGDBAb07QWNaGMAmnTIemsYZCksjATwsA==", + "dev": true + }, + "node_modules/detect-libc": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-2.1.2.tgz", + "integrity": "sha512-Btj2BOOO83o3WyH59e8MgXsxEQVcarkUOpEYrubB0urwnN10yQ364rsiByU11nZlqWYZm05i/of7io4mzihBtQ==", + "dev": true, + "engines": { + "node": ">=8" + } + }, + "node_modules/devalue": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/devalue/-/devalue-5.6.1.tgz", + "integrity": "sha512-jDwizj+IlEZBunHcOuuFVBnIMPAEHvTsJj0BcIp94xYguLRVBcXO853px/MyIJvbVzWdsGvrRweIUWJw8hBP7A==" + }, + "node_modules/dom-serializer": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/dom-serializer/-/dom-serializer-1.4.1.tgz", + "integrity": "sha512-VHwB3KfrcOOkelEG2ZOfxqLZdfkil8PtJi4P8N2MMXucZq2yLp75ClViUlOVwyoHEDjYU433Aq+5zWP61+RGag==", + "dependencies": { + "domelementtype": "^2.0.1", + "domhandler": "^4.2.0", + "entities": "^2.0.0" + }, + "funding": { + "url": "https://github.com/cheeriojs/dom-serializer?sponsor=1" + } + }, + "node_modules/domelementtype": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/domelementtype/-/domelementtype-2.3.0.tgz", + "integrity": "sha512-OLETBj6w0OsagBwdXnPdN0cnMfF9opN69co+7ZrbfPGrdpPVNBUj02spi6B1N7wChLQiPn4CSH/zJvXw56gmHw==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/fb55" + } + ] + }, + "node_modules/domhandler": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/domhandler/-/domhandler-4.3.1.tgz", + "integrity": "sha512-GrwoxYN+uWlzO8uhUXRl0P+kHE4GtVPfYzVLcUxPL7KNdHKj66vvlhiweIHqYYXWlw+T8iLMp42Lm67ghw4WMQ==", + "dependencies": { + "domelementtype": "^2.2.0" + }, + "engines": { + "node": ">= 4" + }, + "funding": { + "url": "https://github.com/fb55/domhandler?sponsor=1" + } + }, + "node_modules/dompurify": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.3.1.tgz", + "integrity": "sha512-qkdCKzLNtrgPFP1Vo+98FRzJnBRGe4ffyCea9IwHB1fyxPOeNTHpLKYGd4Uk9xvNoH0ZoOjwZxNptyMwqrId1Q==", + "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==", + "dependencies": { + "dom-serializer": "^1.0.1", + "domelementtype": "^2.2.0", + "domhandler": "^4.2.0" + }, + "funding": { + "url": "https://github.com/fb55/domutils?sponsor=1" + } + }, + "node_modules/dotenv": { + "version": "17.2.3", + "resolved": "https://registry.npmjs.org/dotenv/-/dotenv-17.2.3.tgz", + "integrity": "sha512-JVUnt+DUIzu87TABbhPmNfVdBDt18BLOWjMUFJMSi/Qqg7NTYtabbvSNJGOJ7afbRuv9D/lngizHtP7QyLQ+9w==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://dotenvx.com" + } + }, + "node_modules/dunder-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz", + "integrity": "sha512-KIN/nDJBQRcXw0MLVhZE9iQHmG68qAVIBg9CqmUYjmQIhgij9U5MFvrqkUL5FbtyyzZuOeOt0zdeRe4UY7ct+A==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.1", + "es-errors": "^1.3.0", + "gopd": "^1.2.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha512-WMwm9LhRUo+WUaRN+vRuETqG89IgZphVSNkdFgeb6sS/E4OrDIN7t48CAewSHXc6C8lefD8KKfr5vY61brQlow==", + "dev": true + }, + "node_modules/electron-to-chromium": { + "version": "1.5.267", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.267.tgz", + "integrity": "sha512-0Drusm6MVRXSOJpGbaSVgcQsuB4hEkMpHXaVstcPmhu5LIedxs1xNK/nIxmQIU/RPC0+1/o0AVZfBTkTNJOdUw==" + }, + "node_modules/encodeurl": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-2.0.0.tgz", + "integrity": "sha512-Q0n9HRi4m6JuGIV1eFlmvJB7ZEVxu93IrMyiMsGC0lrMJMWzRgx6WGquyfQgZVb31vhGgXnfmPNNXmxnOkRBrg==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/enhanced-resolve": { + "version": "5.18.4", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.18.4.tgz", + "integrity": "sha512-LgQMM4WXU3QI+SYgEc2liRgznaD5ojbmY3sb8LxyguVkIg5FxdpTkvk72te2R38/TGKxH634oLxXRGY6d7AP+Q==", + "dev": true, + "dependencies": { + "graceful-fs": "^4.2.4", + "tapable": "^2.2.0" + }, + "engines": { + "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==", + "funding": { + "url": "https://github.com/fb55/entities?sponsor=1" + } + }, + "node_modules/es-define-property": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/es-define-property/-/es-define-property-1.0.1.tgz", + "integrity": "sha512-e3nRfgfUZ4rNGL232gUgX06QNyyez04KdjFrF+LTRoOXmrOgFKDg4BCdsjW8EnT69eqdYGmRpJwiPVYNrCaW3g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-errors": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/es-errors/-/es-errors-1.3.0.tgz", + "integrity": "sha512-Zf5H2Kxt2xjTvbJvP2ZWLEICxA6j+hAmMzIlypy4xcBg1vKVnx89Wy0GbS+kf5cwCVFFzdCFh2XSCFNULS6csw==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/es-object-atoms": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/es-object-atoms/-/es-object-atoms-1.1.1.tgz", + "integrity": "sha512-FGgH2h8zKNim9ljj7dankFPcICIK9Cp5bm+c2gQSYePhpaG5+esrLODihIorn+Pe6FGJzWhXQotPv73jTaldXA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/escalade": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", + "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", + "engines": { + "node": ">=6" + } + }, + "node_modules/escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha512-NiSupZ4OeuGwr68lGIeym/ksIZMJodUGOSCZ/FSnTxcrekbvqrgdUxlJOMpijaKZVjAJrWrGs/6Jy8OMuyj9ow==", + "dev": true + }, + "node_modules/esm-env": { + "version": "1.2.2", + "resolved": "https://registry.npmjs.org/esm-env/-/esm-env-1.2.2.tgz", + "integrity": "sha512-Epxrv+Nr/CaL4ZcFGPJIYLWFom+YeV1DqMLHJoEd9SYRxNbaFruBwfEX/kkHUJf55j2+TUbmDcmuilbP1TmXHA==" + }, + "node_modules/esrap": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/esrap/-/esrap-2.2.1.tgz", + "integrity": "sha512-GiYWG34AN/4CUyaWAgunGt0Rxvr1PTMlGC0vvEov/uOQYWne2bpN03Um+k8jT+q3op33mKouP2zeJ6OlM+qeUg==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.15" + } + }, + "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==" + }, + "node_modules/etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha512-aIL5Fx7mawVa300al2BnEE4iNvo1qETxLrPI/o05L7z6go7fCw1J6EQmbK4FmJ2AS7kgVF/KEZWufBfdClMcPg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/eventemitter3": { + "version": "4.0.7", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-4.0.7.tgz", + "integrity": "sha512-8guHBZCwKnFhYdHr2ysuRWErTwhoN2X8XELRlrRwpmfeY2jjuUN4taQMsULKUVo1K4DvZl+0pgfyoysHxvmvEw==" + }, + "node_modules/express": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/express/-/express-5.2.1.tgz", + "integrity": "sha512-hIS4idWWai69NezIdRt2xFVofaF4j+6INOpJlVOLDO8zXGpUVEVzIYk12UUi2JzjEzWL3IOAxcTubgz9Po0yXw==", + "dev": true, + "dependencies": { + "accepts": "^2.0.0", + "body-parser": "^2.2.1", + "content-disposition": "^1.0.0", + "content-type": "^1.0.5", + "cookie": "^0.7.1", + "cookie-signature": "^1.2.1", + "debug": "^4.4.0", + "depd": "^2.0.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "finalhandler": "^2.1.0", + "fresh": "^2.0.0", + "http-errors": "^2.0.0", + "merge-descriptors": "^2.0.0", + "mime-types": "^3.0.0", + "on-finished": "^2.4.1", + "once": "^1.4.0", + "parseurl": "^1.3.3", + "proxy-addr": "^2.0.7", + "qs": "^6.14.0", + "range-parser": "^1.2.1", + "router": "^2.2.0", + "send": "^1.1.0", + "serve-static": "^2.2.0", + "statuses": "^2.0.1", + "type-is": "^2.0.1", + "vary": "^1.1.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/exsolve": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/exsolve/-/exsolve-1.0.8.tgz", + "integrity": "sha512-LmDxfWXwcTArk8fUEnOfSZpHOJ6zOMUJKOtFLFqJLoKJetuQG874Uc7/Kki7zFLzYybmZhp1M7+98pfMqeX8yA==", + "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==", + "dependencies": { + "to-regex-range": "^5.0.1" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/finalhandler": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/finalhandler/-/finalhandler-2.1.1.tgz", + "integrity": "sha512-S8KoZgRZN+a5rNwqTxlZZePjT/4cnm0ROV70LedRHZ0p8u9fRID0hJUZQpkKLzro8LfmC8sx23bY6tVNxv8pQA==", + "dev": true, + "dependencies": { + "debug": "^4.4.0", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "on-finished": "^2.4.1", + "parseurl": "^1.3.3", + "statuses": "^2.0.1" + }, + "engines": { + "node": ">= 18.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/follow-redirects": { + "version": "1.15.11", + "resolved": "https://registry.npmjs.org/follow-redirects/-/follow-redirects-1.15.11.tgz", + "integrity": "sha512-deG2P0JfjrTxl50XGCDyfI97ZGVCxIpfKYmfyrQ54n5FO/0gfIES8C/Psl6kWVDolizcaaxZJnTS0QSMxvnsBQ==", + "dev": true, + "funding": [ + { + "type": "individual", + "url": "https://github.com/sponsors/RubenVerborgh" + } + ], + "engines": { + "node": ">=4.0" + }, + "peerDependenciesMeta": { + "debug": { + "optional": true + } + } + }, + "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/fresh": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-2.0.0.tgz", + "integrity": "sha512-Rx/WycZ60HOaqLKAi6cHRKKI7zxWbJ31MhntmtwMoaTeF7XFH9hhBp8vITaMidfljRQ6eYWCKkaTK+ykVJHP2A==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==" + }, + "node_modules/fsevents": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.3.tgz", + "integrity": "sha512-5xoDfX+fL7faATnagmWPpbFtwh/R77WmMMqqHGS65C3vvB0YHrgF+B1YmZ3441tMj5n63k0212XNoJwzlhffQw==", + "hasInstallScript": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": "^8.16.0 || ^10.6.0 || >=11.0.0" + } + }, + "node_modules/function-bind": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/function-bind/-/function-bind-1.1.2.tgz", + "integrity": "sha512-7XHNxH7qX9xG5mIwxkhumTox/MIRNcOgDrxWsMt2pAr23WHp6MrRlN7FBSFpCpr+oVO0F744iUgR82nJMfG2SA==", + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/generic-names": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/generic-names/-/generic-names-4.0.0.tgz", + "integrity": "sha512-ySFolZQfw9FoDb3ed9d80Cm9f0+r7qj+HJkWjeD9RBfpxEVTlVhol+gvaQB/78WbwYfbnNh8nWHHBSlg072y6A==", + "dependencies": { + "loader-utils": "^3.2.0" + } + }, + "node_modules/get-intrinsic": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/get-intrinsic/-/get-intrinsic-1.3.0.tgz", + "integrity": "sha512-9fSjSaos/fRIVIp+xSJlE6lfwhES7LNtKaCBIamHsjr2na1BiABJPo0mOjjz8GJDURarmCPGqaiVg5mfjb98CQ==", + "dev": true, + "dependencies": { + "call-bind-apply-helpers": "^1.0.2", + "es-define-property": "^1.0.1", + "es-errors": "^1.3.0", + "es-object-atoms": "^1.1.1", + "function-bind": "^1.1.2", + "get-proto": "^1.0.1", + "gopd": "^1.2.0", + "has-symbols": "^1.1.0", + "hasown": "^2.0.2", + "math-intrinsics": "^1.1.0" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/get-port": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/get-port/-/get-port-5.1.1.tgz", + "integrity": "sha512-g/Q1aTSDOxFpchXC4i8ZWvxA1lnPqx/JHqcpIw0/LX9T8x/GBbi6YnlN5nhaKIFkT8oFsscUKgDJYxfwfS6QsQ==", + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/get-proto": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/get-proto/-/get-proto-1.0.1.tgz", + "integrity": "sha512-sTSfBjoXBp89JvIKIefqw7U2CCebsc74kiY6awiGogKtoSGbgjYE/G/+l9sF3MWFPNc9IcoOC4ODfKHfxFmp0g==", + "dev": true, + "dependencies": { + "dunder-proto": "^1.0.1", + "es-object-atoms": "^1.0.0" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/giget": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/giget/-/giget-2.0.0.tgz", + "integrity": "sha512-L5bGsVkxJbJgdnwyuheIunkGatUF/zssUoxxjACCseZYAVbaqdh9Tsmmlkl8vYan09H7sbvKt4pS8GqKLBrEzA==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.0", + "defu": "^6.1.4", + "node-fetch-native": "^1.6.6", + "nypm": "^0.6.0", + "pathe": "^2.0.3" + }, + "bin": { + "giget": "dist/cli.mjs" + } + }, + "node_modules/glob": { + "version": "8.1.0", + "resolved": "https://registry.npmjs.org/glob/-/glob-8.1.0.tgz", + "integrity": "sha512-r8hpEjiQEYlF2QU0df3dS+nxxSIreXQS1qRhMJM0Q5NDdR386C7jb7Hwwod8Fgiuex+k0GFjgft18yvxm5XoCQ==", + "deprecated": "Glob versions prior to v9 are no longer supported", + "dependencies": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^5.0.1", + "once": "^1.3.0" + }, + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/isaacs" + } + }, + "node_modules/glob-parent": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz", + "integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==", + "dependencies": { + "is-glob": "^4.0.1" + }, + "engines": { + "node": ">= 6" + } + }, + "node_modules/gopd": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/gopd/-/gopd-1.2.0.tgz", + "integrity": "sha512-ZUKRh6/kUFoAiTAtTYPZJ3hw9wNxx+BIBOijnlG9PnrJsCcSjs1wyyD6vJpaYtgnzDrKYRSqf3OO6Rfa93xsRg==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/graceful-fs": { + "version": "4.2.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.2.11.tgz", + "integrity": "sha512-RbJ5/jmFcNNCcDV5o9eTnBLJ/HszWV0P73bc+Ff4nS/rJj+YaS6IGyiOL0VoBYX+l1Wrl3k63h/KrH+nhJ0XvQ==", + "dev": true + }, + "node_modules/has-flag": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz", + "integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==", + "engines": { + "node": ">=8" + } + }, + "node_modules/has-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/has-symbols/-/has-symbols-1.1.0.tgz", + "integrity": "sha512-1cDNdwJ2Jaohmb3sg4OmKaMBwuC48sYni5HUw2DvsC8LjGTLK9h+eb1X6RyuOHe4hT0ULCW68iomhjUoKUqlPQ==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/hasown": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/hasown/-/hasown-2.0.2.tgz", + "integrity": "sha512-0hJU9SCPvmMzIBdZFqNPXWa6dqh7WdH0cII9y+CyS8rG3nL48Bclra9HmKhVVUHyPWNH5Y7xDwAB7bfgSjkUMQ==", + "dependencies": { + "function-bind": "^1.1.2" + }, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/http-errors": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-2.0.1.tgz", + "integrity": "sha512-4FbRdAX+bSdmo4AUFuS0WNiPz8NgFt+r8ThgNWmlrjQjt1Q7ZR9+zTlce2859x4KSXrwIsaeTqDoKQmtP8pLmQ==", + "dev": true, + "dependencies": { + "depd": "~2.0.0", + "inherits": "~2.0.4", + "setprototypeof": "~1.2.0", + "statuses": "~2.0.2", + "toidentifier": "~1.0.1" + }, + "engines": { + "node": ">= 0.8" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/http-proxy": { + "version": "1.18.1", + "resolved": "https://registry.npmjs.org/http-proxy/-/http-proxy-1.18.1.tgz", + "integrity": "sha512-7mz/721AbnJwIVbnaSv1Cz3Am0ZLT/UBwkC92VlxhXv/k/BBQfM2fXElQNC27BVGr0uwUpplYPQM9LnaBMR5NQ==", + "dev": true, + "dependencies": { + "eventemitter3": "^4.0.0", + "follow-redirects": "^1.0.0", + "requires-port": "^1.0.0" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/iconv-lite": { + "version": "0.7.1", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.7.1.tgz", + "integrity": "sha512-2Tth85cXwGFHfvRgZWszZSvdo+0Xsqmw8k8ZwxScfcBneNUraK+dxRxRm24nszx80Y0TVio8kKLt5sLE7ZCLlw==", + "dev": true, + "dependencies": { + "safer-buffer": ">= 2.1.2 < 3.0.0" + }, + "engines": { + "node": ">=0.10.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/icss-replace-symbols": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/icss-replace-symbols/-/icss-replace-symbols-1.1.0.tgz", + "integrity": "sha512-chIaY3Vh2mh2Q3RGXttaDIzeiPvaVXJ+C4DAh/w3c37SKZ/U6PGMmuicR2EQQp9bKG8zLMCl7I+PtIoOOPp8Gg==" + }, + "node_modules/icss-utils": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz", + "integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "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==", + "dependencies": { + "import-from": "^3.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "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==", + "dependencies": { + "resolve-from": "^5.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==", + "deprecated": "This module is not supported, and leaks memory. Do not use it. Check out lru-cache if you want a good and tested way to coalesce async requests by a key value, which is much more comprehensive and powerful.", + "dependencies": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "node_modules/inherits": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.4.tgz", + "integrity": "sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==" + }, + "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-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==", + "dependencies": { + "binary-extensions": "^2.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-core-module": { + "version": "2.16.1", + "resolved": "https://registry.npmjs.org/is-core-module/-/is-core-module-2.16.1.tgz", + "integrity": "sha512-UfoeMA6fIJ8wTYFEUjelnaGI67v6+N7qXJEvQuIGa99l4xsCruSYOVSQ0uPANn4dAzm8lkYPaKLrrijLq7x23w==", + "dependencies": { + "hasown": "^2.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/is-docker": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-docker/-/is-docker-3.0.0.tgz", + "integrity": "sha512-eljcgEDlEns/7AXFosB5K/2nCM4P7FQPkGc/DWLy5rmFEWvZayGrik1d9/QIY5nJ4f9YsVvBkA6kJpHn9rISdQ==", + "dev": true, + "bin": { + "is-docker": "cli.js" + }, + "engines": { + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-extglob": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", + "integrity": "sha512-SbKbANkN603Vi4jEZv49LeVJMn4yGwsbzZworEoyEiutsN3nJYdbO36zfhGJ6QEDpOZIFkDtnq5JRxmvl3jsoQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-glob": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/is-glob/-/is-glob-4.0.3.tgz", + "integrity": "sha512-xelSayHH36ZgE7ZWhli7pW34hNbNl8Ojv5KVmkJD4hBdD3th8Tfk9vYasLM+mXWOZhFkgZfxhLSnrwRr4elSSg==", + "dependencies": { + "is-extglob": "^2.1.1" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-in-ssh": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-in-ssh/-/is-in-ssh-1.0.0.tgz", + "integrity": "sha512-jYa6Q9rH90kR1vKB6NM7qqd1mge3Fx4Dhw5TVlK1MUBqhEOuCagrEHMevNuCcbECmXZ0ThXkRm+Ymr51HwEPAw==", + "dev": true, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-inside-container": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-inside-container/-/is-inside-container-1.0.0.tgz", + "integrity": "sha512-KIYLCCJghfHZxqjYBE7rEy0OBuTd5xCHS7tHVgvCLkx7StIoaxwNW3hCALgEUjFfeRk+MG/Qxmp/vtETEF3tRA==", + "dev": true, + "dependencies": { + "is-docker": "^3.0.0" + }, + "bin": { + "is-inside-container": "cli.js" + }, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/is-module": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-module/-/is-module-1.0.0.tgz", + "integrity": "sha512-51ypPSPCoTEIN9dy5Oy+h4pShgJmPCygKfyRCISBI+JoWT/2oJvK8QPxmwv7b/p239jXrm9M1mlQbyKJ5A152g==" + }, + "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==", + "engines": { + "node": ">=0.12.0" + } + }, + "node_modules/is-promise": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-4.0.0.tgz", + "integrity": "sha512-hvpoI6korhJMnej285dSg6nu1+e6uxs7zG3BYAm5byqDsgJNWwxzM6z6iZiAgQR4TJ30JmBTOwqZUw3WlyH3AQ==", + "dev": true + }, + "node_modules/is-reference": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-1.2.1.tgz", + "integrity": "sha512-U82MsXXiFIrjCK4otLT+o2NA2Cd2g5MLoOVXUZjIOhLurrRxpEXzI8O0KZHr3IjLvlAH1kTPYSuqer5T9ZVBKQ==", + "dependencies": { + "@types/estree": "*" + } + }, + "node_modules/is-wsl": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/is-wsl/-/is-wsl-3.1.0.tgz", + "integrity": "sha512-UcVfVfaK4Sc4m7X3dUSoHoozQGBEFeDC+zVo06t98xe8CzHSZZBekNXH+tu0NalHolcJ/QAGqS46Hef7QXBIMw==", + "dev": true, + "dependencies": { + "is-inside-container": "^1.0.0" + }, + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/jiti": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/jiti/-/jiti-2.6.1.tgz", + "integrity": "sha512-ekilCSN1jwRvIbgeg/57YFh8qQDNbwDb9xT/qu2DAHbFFZUicIl4ygVaAvzveMhMVr3LnpSKTNnwt8PoOfmKhQ==", + "dev": true, + "bin": { + "jiti": "lib/jiti-cli.mjs" + } + }, + "node_modules/js-yaml": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-4.1.1.tgz", + "integrity": "sha512-qQKT4zQxXl8lLwBtHMWwaTcGfFOZviOJet3Oy/xmGk2gZH677CJM9EvtfdSkgWcATZhj/55JZ0rmy3myCT5lsA==", + "dev": true, + "dependencies": { + "argparse": "^2.0.1" + }, + "bin": { + "js-yaml": "bin/js-yaml.js" + } + }, + "node_modules/kleur": { + "version": "4.1.5", + "resolved": "https://registry.npmjs.org/kleur/-/kleur-4.1.5.tgz", + "integrity": "sha512-o+NO+8WrRiQEE4/7nwRJhN1HWpVmJm511pBHUxPLtp0BUISzlBplORYSmTclCnJvQq2tKu/sgl3xVpkc7ZWuQQ==", + "engines": { + "node": ">=6" + } + }, + "node_modules/lightningcss": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss/-/lightningcss-1.30.1.tgz", + "integrity": "sha512-xi6IyHML+c9+Q3W0S4fCQJOym42pyurFiJUHEcEyHS0CeKzia4yZDEsLlqOFykxOdHpNy0NmvVO31vcSqAxJCg==", + "dev": true, + "dependencies": { + "detect-libc": "^2.0.3" + }, + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + }, + "optionalDependencies": { + "lightningcss-darwin-arm64": "1.30.1", + "lightningcss-darwin-x64": "1.30.1", + "lightningcss-freebsd-x64": "1.30.1", + "lightningcss-linux-arm-gnueabihf": "1.30.1", + "lightningcss-linux-arm64-gnu": "1.30.1", + "lightningcss-linux-arm64-musl": "1.30.1", + "lightningcss-linux-x64-gnu": "1.30.1", + "lightningcss-linux-x64-musl": "1.30.1", + "lightningcss-win32-arm64-msvc": "1.30.1", + "lightningcss-win32-x64-msvc": "1.30.1" + } + }, + "node_modules/lightningcss-darwin-arm64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-arm64/-/lightningcss-darwin-arm64-1.30.1.tgz", + "integrity": "sha512-c8JK7hyE65X1MHMN+Viq9n11RRC7hgin3HhYKhrMyaXflk5GVplZ60IxyoVtzILeKr+xAJwg6zK6sjTBJ0FKYQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-darwin-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-darwin-x64/-/lightningcss-darwin-x64-1.30.1.tgz", + "integrity": "sha512-k1EvjakfumAQoTfcXUcHQZhSpLlkAuEkdMBsI/ivWw9hL+7FtilQc0Cy3hrx0AAQrVtQAbMI7YjCgYgvn37PzA==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "darwin" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-freebsd-x64": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-freebsd-x64/-/lightningcss-freebsd-x64-1.30.1.tgz", + "integrity": "sha512-kmW6UGCGg2PcyUE59K5r0kWfKPAVy4SltVeut+umLCFoJ53RdCUWxcRDzO1eTaxf/7Q2H7LTquFHPL5R+Gjyig==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "freebsd" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm-gnueabihf": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm-gnueabihf/-/lightningcss-linux-arm-gnueabihf-1.30.1.tgz", + "integrity": "sha512-MjxUShl1v8pit+6D/zSPq9S9dQ2NPFSQwGvxBCYaBYLPlCWuPh9/t1MRS8iUaR8i+a6w7aps+B4N0S1TYP/R+Q==", + "cpu": [ + "arm" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-gnu/-/lightningcss-linux-arm64-gnu-1.30.1.tgz", + "integrity": "sha512-gB72maP8rmrKsnKYy8XUuXi/4OctJiuQjcuqWNlJQ6jZiWqtPvqFziskH3hnajfvKB27ynbVCucKSm2rkQp4Bw==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-arm64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-arm64-musl/-/lightningcss-linux-arm64-musl-1.30.1.tgz", + "integrity": "sha512-jmUQVx4331m6LIX+0wUhBbmMX7TCfjF5FoOH6SD1CttzuYlGNVpA7QnrmLxrsub43ClTINfGSYyHe2HWeLl5CQ==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-gnu": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-gnu/-/lightningcss-linux-x64-gnu-1.30.1.tgz", + "integrity": "sha512-piWx3z4wN8J8z3+O5kO74+yr6ze/dKmPnI7vLqfSqI8bccaTGY5xiSGVIJBDd5K5BHlvVLpUB3S2YCfelyJ1bw==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-linux-x64-musl": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-linux-x64-musl/-/lightningcss-linux-x64-musl-1.30.1.tgz", + "integrity": "sha512-rRomAK7eIkL+tHY0YPxbc5Dra2gXlI63HL+v1Pdi1a3sC+tJTcFrHX+E86sulgAXeI7rSzDYhPSeHHjqFhqfeQ==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-arm64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-arm64-msvc/-/lightningcss-win32-arm64-msvc-1.30.1.tgz", + "integrity": "sha512-mSL4rqPi4iXq5YVqzSsJgMVFENoa4nGTT/GjO2c0Yl9OuQfPsIfncvLrEW6RbbB24WtZ3xP/2CCmI3tNkNV4oA==", + "cpu": [ + "arm64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lightningcss-win32-x64-msvc": { + "version": "1.30.1", + "resolved": "https://registry.npmjs.org/lightningcss-win32-x64-msvc/-/lightningcss-win32-x64-msvc-1.30.1.tgz", + "integrity": "sha512-PVqXh48wh4T53F/1CCu8PIPCxLzWyCnn/9T5W1Jpmdy5h9Cwd+0YQS6/LwhHXSafuc61/xg9Lv5OrCby6a++jg==", + "cpu": [ + "x64" + ], + "dev": true, + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 12.0.0" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/parcel" + } + }, + "node_modules/lilconfig": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-2.1.0.tgz", + "integrity": "sha512-utWOt/GHzuUxnLKxB6dk81RoOeoNeHgbrXiuGk4yyF5qlRz+iIVWu56E2fqGHFrXz0QNUhLB/8nKqvRH66JKGQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/livereload": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/livereload/-/livereload-0.9.3.tgz", + "integrity": "sha512-q7Z71n3i4X0R9xthAryBdNGVGAO2R5X+/xXpmKeuPMrteg+W2U8VusTKV3YiJbXZwKsOlFlHe+go6uSNjfxrZw==", + "dependencies": { + "chokidar": "^3.5.0", + "livereload-js": "^3.3.1", + "opts": ">= 1.2.0", + "ws": "^7.4.3" + }, + "bin": { + "livereload": "bin/livereload.js" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/livereload-js": { + "version": "3.4.1", + "resolved": "https://registry.npmjs.org/livereload-js/-/livereload-js-3.4.1.tgz", + "integrity": "sha512-5MP0uUeVCec89ZbNOT/i97Mc+q3SxXmiUGhRFOTmhrGPn//uWVQdCvcLJDy64MSBR5MidFdOR7B9viumoavy6g==" + }, + "node_modules/loader-utils": { + "version": "3.3.1", + "resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-3.3.1.tgz", + "integrity": "sha512-FMJTLMXfCLMLfJxcX9PFqX5qD88Z5MRGaZCVzfuqeZSPsyiBzs+pahDQjbIWz2QIzPZz0NX9Zy4FX3lmK6YHIg==", + "engines": { + "node": ">= 12.13.0" + } + }, + "node_modules/local-access": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/local-access/-/local-access-1.1.0.tgz", + "integrity": "sha512-XfegD5pyTAfb+GY6chk283Ox5z8WexG56OvM06RWLpAc/UHozO8X6xAxEkIitZOtsSMM1Yr3DkHgW5W+onLhCw==", + "engines": { + "node": ">=6" + } + }, + "node_modules/locate-character": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/locate-character/-/locate-character-3.0.0.tgz", + "integrity": "sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==" + }, + "node_modules/lodash": { + "version": "4.17.21", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz", + "integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==", + "dev": true + }, + "node_modules/lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha512-TwuEnCnxbc3rAvhf/LbG7tJUDzhqXyFnv3dtzLOPgCG/hODL7WFnsbwktkD7yUV0RrreP/l1PALq/YSg6VvjlA==" + }, + "node_modules/lodash.memoize": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/lodash.memoize/-/lodash.memoize-4.1.2.tgz", + "integrity": "sha512-t7j+NzmgnQzTAYXcsHYLgimltOV1MXHtlOWf6GjL9Kj8GK5FInw5JotxvbOs+IvV1/Dzo04/fCGfLVs7aXb4Ag==" + }, + "node_modules/lodash.uniq": { + "version": "4.5.0", + "resolved": "https://registry.npmjs.org/lodash.uniq/-/lodash.uniq-4.5.0.tgz", + "integrity": "sha512-xfBaXQd9ryd9dlSDvnvI0lvxfLJlYAZzXomUYzLKtUeOQvOP5piqAWuGtrhWeqaXK9hhoM/iyJc5AV+XfsX3HQ==" + }, + "node_modules/magic-string": { + "version": "0.27.0", + "resolved": "https://registry.npmjs.org/magic-string/-/magic-string-0.27.0.tgz", + "integrity": "sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.4.13" + }, + "engines": { + "node": ">=12" + } + }, + "node_modules/math-intrinsics": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/math-intrinsics/-/math-intrinsics-1.1.0.tgz", + "integrity": "sha512-/IXtbwEk5HTPyEwyKX6hGkYXxM9nbj64B+ilVJnC/R6B0pH5G4V3b0pVbL7DBj4tkhBAppbQUlf6F6Xl9LHu1g==", + "dev": true, + "engines": { + "node": ">= 0.4" + } + }, + "node_modules/media-typer": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-1.1.0.tgz", + "integrity": "sha512-aisnrDP4GNe06UcKFnV5bfMNPBUw4jsLGaWwWfnH3v02GnBuXX2MCVn5RbrWo0j3pczUilYblq7fQ7Nw2t5XKw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/merge-descriptors": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-2.0.0.tgz", + "integrity": "sha512-Snk314V5ayFLhp3fkUREub6WtjBfPdCPY1Ln8/8munuLuiYhsABgBVWsozAG+MWMbVEvcdcpbi9R7ww22l9Q3g==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/mime": { + "version": "2.6.0", + "resolved": "https://registry.npmjs.org/mime/-/mime-2.6.0.tgz", + "integrity": "sha512-USPkMeET31rOMiarsBNIHZKLGgvKc/LrjofAnBlOttf5ajRvqiRA8QsenbcooctK6d6Ts6aqZXBA+XbkKthiQg==", + "dev": true, + "bin": { + "mime": "cli.js" + }, + "engines": { + "node": ">=4.0.0" + } + }, + "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==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/mime-types": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-3.0.2.tgz", + "integrity": "sha512-Lbgzdk0h4juoQ9fCKXW4by0UJqj+nOOrI9MJ1sSj4nI8aI2eo1qmvQEie4VD1glsS250n15LsWsYtCugiStS5A==", + "dev": true, + "dependencies": { + "mime-db": "^1.54.0" + }, + "engines": { + "node": ">=18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/mini-svg-data-uri": { + "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==", + "dev": true, + "bin": { + "mini-svg-data-uri": "cli.js" + } + }, + "node_modules/minimatch": { + "version": "5.1.6", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-5.1.6.tgz", + "integrity": "sha512-lKwV/1brpG6mBUFHtb7NUmtABCb2WZZmm2wNiOA5hAb8VdCS4B3dtMWyvcoViccwAW/COERjXLt0zP1zXUN26g==", + "dependencies": { + "brace-expansion": "^2.0.1" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/minipass": { + "version": "7.1.2", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-7.1.2.tgz", + "integrity": "sha512-qOOzS1cBTWYF4BH8fVePDBOO9iptMnGUEZwNc/cMWnTV2nVLZ7VoNWEPHkYczZA0pdoA7dl6e7FL659nX9S2aw==", + "dev": true, + "engines": { + "node": ">=16 || 14 >=14.17" + } + }, + "node_modules/minizlib": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-3.1.0.tgz", + "integrity": "sha512-KZxYo1BUkWD2TVFLr0MQoM8vUUigWD3LlD83a/75BqC+4qE0Hb1Vo5v1FgcfaNXvfXzr+5EhQ6ing/CaBijTlw==", + "dev": true, + "dependencies": { + "minipass": "^7.1.2" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/mri": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", + "integrity": "sha512-tzzskb3bG8LvYGFF/mDTpq3jpI6Q9wc3LEmBaghu+DdCssd1FakN7Bc0hVNmEyGq1bq3RgfkCb3cmQLpNPOroA==", + "engines": { + "node": ">=4" + } + }, + "node_modules/mrmime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/mrmime/-/mrmime-2.0.1.tgz", + "integrity": "sha512-Y3wQdFg2Va6etvQ5I82yUhGdsKrcYox6p7FfL1LbK2J4V01F9TGlepTIhnK24t7koZibmg82KGglhA1XK5IsLQ==", + "engines": { + "node": ">=10" + } + }, + "node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", + "dev": true + }, + "node_modules/nanoid": { + "version": "3.3.11", + "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.11.tgz", + "integrity": "sha512-N8SpfPUnUp1bK+PMYW8qSWdl9U+wwNWI4QKxOYDy9JAro3WMX7p2OeVRF9v+347pnakNevPmiHhNmZ2HbFA76w==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "bin": { + "nanoid": "bin/nanoid.cjs" + }, + "engines": { + "node": "^10 || ^12 || ^13.7 || ^14 || >=15.0.1" + } + }, + "node_modules/negotiator": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-1.0.0.tgz", + "integrity": "sha512-8Ofs/AUQh8MaEcrlq5xOX0CQ9ypTF5dl78mjlMNfOK08fzpgTHQRQPBxcPlEtIw0yRpws+Zo/3r+5WRby7u3Gg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/node-fetch-native": { + "version": "1.6.7", + "resolved": "https://registry.npmjs.org/node-fetch-native/-/node-fetch-native-1.6.7.tgz", + "integrity": "sha512-g9yhqoedzIUm0nTnTqAQvueMPVOuIY16bqgAJJC8XOOubYFNwz6IER9qs0Gq2Xd0+CecCKFjtdDTMA4u4xG06Q==", + "dev": true + }, + "node_modules/node-releases": { + "version": "2.0.27", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", + "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==" + }, + "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==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/normalize-url": { + "version": "6.1.0", + "resolved": "https://registry.npmjs.org/normalize-url/-/normalize-url-6.1.0.tgz", + "integrity": "sha512-DlL+XwOy3NxAQ8xuC0okPgK46iuVNAK01YN7RueYBqqFeGsBjV9XmCAzAdgt+667bCl5kPh9EqKKDwnaPG1I7A==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/nth-check": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/nth-check/-/nth-check-2.1.1.tgz", + "integrity": "sha512-lqjrjmaOoAnWfMmBPL+XNnynZh2+swxiX3WUE0s4yEHI6m+AwrK2UZOimIRl3X/4QctVqS8AiZjFqyOGrMXb/w==", + "dependencies": { + "boolbase": "^1.0.0" + }, + "funding": { + "url": "https://github.com/fb55/nth-check?sponsor=1" + } + }, + "node_modules/nypm": { + "version": "0.6.2", + "resolved": "https://registry.npmjs.org/nypm/-/nypm-0.6.2.tgz", + "integrity": "sha512-7eM+hpOtrKrBDCh7Ypu2lJ9Z7PNZBdi/8AT3AX8xoCj43BBVHD0hPSTEvMtkMpfs8FCqBGhxB+uToIQimA111g==", + "dev": true, + "dependencies": { + "citty": "^0.1.6", + "consola": "^3.4.2", + "pathe": "^2.0.3", + "pkg-types": "^2.3.0", + "tinyexec": "^1.0.1" + }, + "bin": { + "nypm": "dist/cli.mjs" + }, + "engines": { + "node": "^14.16.0 || >=16.10.0" + } + }, + "node_modules/object-inspect": { + "version": "1.13.4", + "resolved": "https://registry.npmjs.org/object-inspect/-/object-inspect-1.13.4.tgz", + "integrity": "sha512-W67iLl4J2EXEGTbfeHCffrjDfitvLANg0UlX3wFUUSTx92KXRFegMHUVgSqE+wvhAbi4WqjGg9czysTV2Epbew==", + "dev": true, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/ohash": { + "version": "2.0.11", + "resolved": "https://registry.npmjs.org/ohash/-/ohash-2.0.11.tgz", + "integrity": "sha512-RdR9FQrFwNBNXAr4GixM8YaRZRJ5PUWbKYbE5eOsrwAjJW0q2REGcf79oYPsLyskQCZG1PLN+S/K1V00joZAoQ==", + "dev": true + }, + "node_modules/on-finished": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.4.1.tgz", + "integrity": "sha512-oVlzkg3ENAhCk2zdv7IJwd/QUD4z2RxRwpkcGY8psCVcCYZNq4wYnVWALHM+brtuJjePWiYF/ClmuDr8Ch5+kg==", + "dev": true, + "dependencies": { + "ee-first": "1.1.1" + }, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha512-lNaJgI+2Q5URQBkccEKHTQOPaXdUxnZZElQTZY0MFUAuaEqe1E+Nyvgdz/aIyNi6Z9MzO5dv1H8n58/GELp3+w==", + "dependencies": { + "wrappy": "1" + } + }, + "node_modules/open": { + "version": "11.0.0", + "resolved": "https://registry.npmjs.org/open/-/open-11.0.0.tgz", + "integrity": "sha512-smsWv2LzFjP03xmvFoJ331ss6h+jixfA4UUV/Bsiyuu4YJPfN+FIQGOIiv4w9/+MoHkfkJ22UIaQWRVFRfH6Vw==", + "dev": true, + "dependencies": { + "default-browser": "^5.4.0", + "define-lazy-prop": "^3.0.0", + "is-in-ssh": "^1.0.0", + "is-inside-container": "^1.0.0", + "powershell-utils": "^0.1.0", + "wsl-utils": "^0.3.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/opener": { + "version": "1.5.2", + "resolved": "https://registry.npmjs.org/opener/-/opener-1.5.2.tgz", + "integrity": "sha512-ur5UIdyw5Y7yEj9wLzhqXiy6GZ3Mwx0yGI+5sMn2r0N0v3cKJvUmFH5yPP+WXh9e0xfyzyJX95D8l088DNFj7A==", + "dev": true, + "bin": { + "opener": "bin/opener-bin.js" + } + }, + "node_modules/opts": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/opts/-/opts-2.0.2.tgz", + "integrity": "sha512-k41FwbcLnlgnFh69f4qdUfvDQ+5vaSDnVPFI/y5XuhKRq97EnVVneO9F1ESVCdiVu4fCS2L8usX3mU331hB7pg==" + }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "engines": { + "node": ">=4" + } + }, + "node_modules/p-queue": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/p-queue/-/p-queue-6.6.2.tgz", + "integrity": "sha512-RwFpb72c/BhQLEXIZ5K2e+AhgNVmIejGlTgiB9MzZ0e93GRvqZ7uSi0dvRF7/XIXDeNkra2fNHBxTyPDGySpjQ==", + "dependencies": { + "eventemitter3": "^4.0.4", + "p-timeout": "^3.2.0" + }, + "engines": { + "node": ">=8" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/p-timeout": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/p-timeout/-/p-timeout-3.2.0.tgz", + "integrity": "sha512-rhIwUycgwwKcP9yTOOFK/AKsAopjjCakVqLHePO3CC6Mir1Z99xT+R63jZxAT5lFZLa2inS5h+ZS2GvR99/FBg==", + "dependencies": { + "p-finally": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/parseurl": { + "version": "1.3.3", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.3.tgz", + "integrity": "sha512-CiyeOxFT/JZyN5m0z9PfXw4SCBJ6Sygz1Dpl0wqjlhDEGGBP1GnsUVEL0p63hoG1fcj3fHynXi9NYO4nWOL+qQ==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/path-parse": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.7.tgz", + "integrity": "sha512-LDJzPVEEEPR+y48z93A0Ed0yXb8pAByGWo/k5YYdYgpY2/2EsOsksJrq7lOHxryrVOn1ejG6oAp8ahvOIQD8sw==" + }, + "node_modules/path-to-regexp": { + "version": "8.3.0", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-8.3.0.tgz", + "integrity": "sha512-7jdwVIRtsP8MYpdXSwOS0YdD0Du+qOoF/AEPIt88PcCFrZCzx41oxku1jD88hZBwbNUIEfpqvuhjFaMAqMTWnA==", + "dev": true, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/pathe": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/pathe/-/pathe-2.0.3.tgz", + "integrity": "sha512-WUjGcAqP1gQacoQe+OBJsFA7Ld4DyXuUIjZ5cc75cLHvJ7dtNsTugphxIADwspS+AraAUePCKrSVtPLFj/F88w==", + "dev": true + }, + "node_modules/perfect-debounce": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/perfect-debounce/-/perfect-debounce-2.0.0.tgz", + "integrity": "sha512-fkEH/OBiKrqqI/yIgjR92lMfs2K8105zt/VT6+7eTjNwisrsh47CeIED9z58zI7DfKdH3uHAn25ziRZn3kgAow==", + "dev": true + }, + "node_modules/picocolors": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", + "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==" + }, + "node_modules/picomatch": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-4.0.3.tgz", + "integrity": "sha512-5gTmgEY/sqK6gFXLIsQNH19lWb4ebPDLA4SdLP7dsWkIXHWlG66oPuVvXSGFPppYZz8ZDZq0dYYrbHfBCVUb1Q==", + "engines": { + "node": ">=12" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/pify": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-5.0.0.tgz", + "integrity": "sha512-eW/gHNMlxdSP6dmG6uJip6FXN0EQBwm2clYYd8Wul42Cwu/DK8HEftzsapcNdYe2MfLiIwZqsDk2RDEsTE79hA==", + "engines": { + "node": ">=10" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/pkg-types": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pkg-types/-/pkg-types-2.3.0.tgz", + "integrity": "sha512-SIqCzDRg0s9npO5XQ3tNZioRY1uK06lA41ynBC1YmFTmnY6FjUjVt6s4LoADmwoig1qqD0oK8h1p/8mlMx8Oig==", + "dev": true, + "dependencies": { + "confbox": "^0.2.2", + "exsolve": "^1.0.7", + "pathe": "^2.0.3" + } + }, + "node_modules/postcss": { + "version": "8.5.6", + "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.5.6.tgz", + "integrity": "sha512-3Ybi1tAuwAP9s0r1UQ2J4n5Y0G05bJkpUIO0/bI9MhwmD70S5aTWbXGBwxHrelT+XM1k6dM0pk+SwNkpTRN7Pg==", + "funding": [ + { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + { + "type": "tidelift", + "url": "https://tidelift.com/funding/github/npm/postcss" + }, + { + "type": "github", + "url": "https://github.com/sponsors/ai" + } + ], + "dependencies": { + "nanoid": "^3.3.11", + "picocolors": "^1.1.1", + "source-map-js": "^1.2.1" + }, + "engines": { + "node": "^10 || ^12 || >=14" + } + }, + "node_modules/postcss-calc": { + "version": "8.2.4", + "resolved": "https://registry.npmjs.org/postcss-calc/-/postcss-calc-8.2.4.tgz", + "integrity": "sha512-SmWMSJmB8MRnnULldx0lQIyhSNvuDl9HfrZkaqqE/WHAhToYsAvDq+yAsA/kIyINDszOp3Rh0GFoNuH5Ypsm3Q==", + "dependencies": { + "postcss-selector-parser": "^6.0.9", + "postcss-value-parser": "^4.2.0" + }, + "peerDependencies": { + "postcss": "^8.2.2" + } + }, + "node_modules/postcss-colormin": { + "version": "5.3.1", + "resolved": "https://registry.npmjs.org/postcss-colormin/-/postcss-colormin-5.3.1.tgz", + "integrity": "sha512-UsWQG0AqTFQmpBegeLLc1+c3jIqBNB0zlDGRWR+dQ3pRKJL1oeMzyqmH3o2PIfn9MBdNrVPWhDbT769LxCTLJQ==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "colord": "^2.9.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-convert-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-convert-values/-/postcss-convert-values-5.1.3.tgz", + "integrity": "sha512-82pC1xkJZtcJEfiLw6UXnXVXScgtBrjlO5CBmuDQc+dlb88ZYheFsjTn40+zBVi3DkfF7iezO0nJUPLcJK3pvA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-comments": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-discard-comments/-/postcss-discard-comments-5.1.2.tgz", + "integrity": "sha512-+L8208OVbHVF2UQf1iDmRcbdjJkuBF6IS29yBDSiWUIzpYaAhtNl6JYnYm12FnkeCwQqF5LeklOu6rAqgfBZqQ==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-duplicates": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-duplicates/-/postcss-discard-duplicates-5.1.0.tgz", + "integrity": "sha512-zmX3IoSI2aoenxHV6C7plngHWWhUOV3sP1T8y2ifzxzbtnuhk1EdPwm0S1bIUNaJ2eNbWeGLEwzw8huPD67aQw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-empty": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-discard-empty/-/postcss-discard-empty-5.1.1.tgz", + "integrity": "sha512-zPz4WljiSuLWsI0ir4Mcnr4qQQ5e1Ukc3i7UfE2XcrwKK2LIPIqE5jxMRxO6GbI3cv//ztXDsXwEWT3BHOGh3A==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-discard-overridden": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-discard-overridden/-/postcss-discard-overridden-5.1.0.tgz", + "integrity": "sha512-21nOL7RqWR1kasIVdKs8HNqQJhFxLsyRfAnUDm4Fe4t4mCWL9OJiHvlHPjcd8zc5Myu89b/7wZDnOSjFgeWRtw==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-load-config": { + "version": "3.1.4", + "resolved": "https://registry.npmjs.org/postcss-load-config/-/postcss-load-config-3.1.4.tgz", + "integrity": "sha512-6DiM4E7v4coTE4uzA8U//WhtPwyhiim3eyjEMFCnUpzbrkK9wJHgKDT2mR+HbtSrd/NubVaYTOpSpjUl8NQeRg==", + "dependencies": { + "lilconfig": "^2.0.5", + "yaml": "^1.10.2" + }, + "engines": { + "node": ">= 10" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/postcss/" + }, + "peerDependencies": { + "postcss": ">=8.0.9", + "ts-node": ">=9.0.0" + }, + "peerDependenciesMeta": { + "postcss": { + "optional": true + }, + "ts-node": { + "optional": true + } + } + }, + "node_modules/postcss-merge-longhand": { + "version": "5.1.7", + "resolved": "https://registry.npmjs.org/postcss-merge-longhand/-/postcss-merge-longhand-5.1.7.tgz", + "integrity": "sha512-YCI9gZB+PLNskrK0BB3/2OzPnGhPkBEwmwhfYk1ilBHYVAZB7/tkTHFBAnCrvBBOmeYyMYw3DMjT55SyxMBzjQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "stylehacks": "^5.1.1" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-merge-rules": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-merge-rules/-/postcss-merge-rules-5.1.4.tgz", + "integrity": "sha512-0R2IuYpgU93y9lhVbO/OylTtKMVcHb67zjWIfCiKR9rWL3GUk1677LAqD/BcHizukdZEjT8Ru3oHRoAYoJy44g==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0", + "cssnano-utils": "^3.1.0", + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-font-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-minify-font-values/-/postcss-minify-font-values-5.1.0.tgz", + "integrity": "sha512-el3mYTgx13ZAPPirSVsHqFzl+BBBDrXvbySvPGFnQcTI4iNslrPaFq4muTkLZmKlGk4gyFAYUBMH30+HurREyA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-gradients": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-minify-gradients/-/postcss-minify-gradients-5.1.1.tgz", + "integrity": "sha512-VGvXMTpCEo4qHTNSa9A0a3D+dxGFZCYwR6Jokk+/3oB6flu2/PnPXAh2x7x52EkY5xlIHLm+Le8tJxe/7TNhzw==", + "dependencies": { + "colord": "^2.9.1", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-params": { + "version": "5.1.4", + "resolved": "https://registry.npmjs.org/postcss-minify-params/-/postcss-minify-params-5.1.4.tgz", + "integrity": "sha512-+mePA3MgdmVmv6g+30rn57USjOGSAyuxUmkfiWpzalZ8aiBkdPYjXWtHuwJGm1v5Ojy0Z0LaSYhHaLJQB0P8Jw==", + "dependencies": { + "browserslist": "^4.21.4", + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-minify-selectors": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/postcss-minify-selectors/-/postcss-minify-selectors-5.2.1.tgz", + "integrity": "sha512-nPJu7OjZJTsVUmPdm2TcaiohIwxP+v8ha9NehQ2ye9szv4orirRU3SDdtUmKH+10nzn0bAyOXZ0UEr7OpvLehg==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-modules": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.3.1.tgz", + "integrity": "sha512-ItUhSUxBBdNamkT3KzIZwYNNRFKmkJrofvC2nWab3CPKhYBQ1f27XXh1PAPE27Psx58jeelPsxWB/+og+KEH0Q==", + "dependencies": { + "generic-names": "^4.0.0", + "icss-replace-symbols": "^1.1.0", + "lodash.camelcase": "^4.3.0", + "postcss-modules-extract-imports": "^3.0.0", + "postcss-modules-local-by-default": "^4.0.0", + "postcss-modules-scope": "^3.0.0", + "postcss-modules-values": "^4.0.0", + "string-hash": "^1.1.1" + }, + "peerDependencies": { + "postcss": "^8.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==", + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "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==", + "dependencies": { + "icss-utils": "^5.0.0", + "postcss-selector-parser": "^7.0.0", + "postcss-value-parser": "^4.1.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "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==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "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==", + "dependencies": { + "postcss-selector-parser": "^7.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "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==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-modules-values": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz", + "integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==", + "dependencies": { + "icss-utils": "^5.0.0" + }, + "engines": { + "node": "^10 || ^12 || >= 14" + }, + "peerDependencies": { + "postcss": "^8.1.0" + } + }, + "node_modules/postcss-normalize-charset": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-charset/-/postcss-normalize-charset-5.1.0.tgz", + "integrity": "sha512-mSgUJ+pd/ldRGVx26p2wz9dNZ7ji6Pn8VWBajMXFf8jk7vUoSrZ2lt/wZR7DtlZYKesmZI680qjr2CeFF2fbUg==", + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-display-values": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-display-values/-/postcss-normalize-display-values-5.1.0.tgz", + "integrity": "sha512-WP4KIM4o2dazQXWmFaqMmcvsKmhdINFblgSeRgn8BJ6vxaMyaJkwAzpPpuvSIoG/rmX3M+IrRZEz2H0glrQNEA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-positions": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-positions/-/postcss-normalize-positions-5.1.1.tgz", + "integrity": "sha512-6UpCb0G4eofTCQLFVuI3EVNZzBNPiIKcA1AKVka+31fTVySphr3VUgAIULBhxZkKgwLImhzMR2Bw1ORK+37INg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-repeat-style": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-repeat-style/-/postcss-normalize-repeat-style-5.1.1.tgz", + "integrity": "sha512-mFpLspGWkQtBcWIRFLmewo8aC3ImN2i/J3v8YCFUwDnPu3Xz4rLohDO26lGjwNsQxB3YF0KKRwspGzE2JEuS0g==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-string": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-string/-/postcss-normalize-string-5.1.0.tgz", + "integrity": "sha512-oYiIJOf4T9T1N4i+abeIc7Vgm/xPCGih4bZz5Nm0/ARVJ7K6xrDlLwvwqOydvyL3RHNf8qZk6vo3aatiw/go3w==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-timing-functions": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-timing-functions/-/postcss-normalize-timing-functions-5.1.0.tgz", + "integrity": "sha512-DOEkzJ4SAXv5xkHl0Wa9cZLF3WCBhF3o1SKVxKQAa+0pYKlueTpCgvkFAHfk+Y64ezX9+nITGrDZeVGgITJXjg==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-unicode": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-unicode/-/postcss-normalize-unicode-5.1.1.tgz", + "integrity": "sha512-qnCL5jzkNUmKVhZoENp1mJiGNPcsJCs1aaRmURmeJGES23Z/ajaln+EPTD+rBeNkSryI+2WTdW+lwcVdOikrpA==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-url": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-normalize-url/-/postcss-normalize-url-5.1.0.tgz", + "integrity": "sha512-5upGeDO+PVthOxSmds43ZeMeZfKH+/DKgGRD7TElkkyS46JXAUhMzIKiCa7BabPeIy3AQcTkXwVVN7DbqsiCew==", + "dependencies": { + "normalize-url": "^6.0.1", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-normalize-whitespace": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-normalize-whitespace/-/postcss-normalize-whitespace-5.1.1.tgz", + "integrity": "sha512-83ZJ4t3NUDETIHTa3uEg6asWjSBYL5EdkVB0sDncx9ERzOKBVJIUeDO9RyA9Zwtig8El1d79HBp0JEi8wvGQnA==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-ordered-values": { + "version": "5.1.3", + "resolved": "https://registry.npmjs.org/postcss-ordered-values/-/postcss-ordered-values-5.1.3.tgz", + "integrity": "sha512-9UO79VUhPwEkzbb3RNpqqghc6lcYej1aveQteWY+4POIwlqkYE21HKWaLDF6lWNuqCobEAyTovVhtI32Rbv2RQ==", + "dependencies": { + "cssnano-utils": "^3.1.0", + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-initial": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/postcss-reduce-initial/-/postcss-reduce-initial-5.1.2.tgz", + "integrity": "sha512-dE/y2XRaqAi6OvjzD22pjTUQ8eOfc6m/natGHgKFBK9DxFmIm69YmaRVQrGgFlEfc1HePIurY0TmDeROK05rIg==", + "dependencies": { + "browserslist": "^4.21.4", + "caniuse-api": "^3.0.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-reduce-transforms": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-reduce-transforms/-/postcss-reduce-transforms-5.1.0.tgz", + "integrity": "sha512-2fbdbmgir5AvpW9RLtdONx1QoYG2/EtqpNQbFASDlixBbAYuTcJ0dECwlqNqH7VbaUnEnh8SrxOe2sRIn24XyQ==", + "dependencies": { + "postcss-value-parser": "^4.2.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-selector-parser": { + "version": "6.1.2", + "resolved": "https://registry.npmjs.org/postcss-selector-parser/-/postcss-selector-parser-6.1.2.tgz", + "integrity": "sha512-Q8qQfPiZ+THO/3ZrOrO0cJJKfpYCagtMUkXbnEfmgUjwXg6z/WBeOyS9APBBPCTSiDV+s4SwQGu8yFsiMRIudg==", + "dependencies": { + "cssesc": "^3.0.0", + "util-deprecate": "^1.0.2" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/postcss-svgo": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/postcss-svgo/-/postcss-svgo-5.1.0.tgz", + "integrity": "sha512-D75KsH1zm5ZrHyxPakAxJWtkyXew5qwS70v56exwvw542d9CRtTo78K0WeFxZB4G7JXKKMbEZtZayTGdIky/eA==", + "dependencies": { + "postcss-value-parser": "^4.2.0", + "svgo": "^2.7.0" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-unique-selectors": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/postcss-unique-selectors/-/postcss-unique-selectors-5.1.1.tgz", + "integrity": "sha512-5JiODlELrz8L2HwxfPnhOWZYWDxVHWL83ufOv84NrcgipI7TaeRsatAhK4Tr2/ZiYldpK/wBvw5BD3qfaK96GA==", + "dependencies": { + "postcss-selector-parser": "^6.0.5" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/postcss-value-parser": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/postcss-value-parser/-/postcss-value-parser-4.2.0.tgz", + "integrity": "sha512-1NNCs6uurfkVbeXG4S8JFT9t19m45ICnif8zWLd5oPSZ50QnwMfK+H3jv408d4jw/7Bttv5axS5IiHoLaVNHeQ==" + }, + "node_modules/powershell-utils": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/powershell-utils/-/powershell-utils-0.1.0.tgz", + "integrity": "sha512-dM0jVuXJPsDN6DvRpea484tCUaMiXWjuCn++HGTqUWzGDjv5tZkEZldAJ/UMlqRYGFrD/etByo4/xOuC/snX2A==", + "dev": true, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/promise.series": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/promise.series/-/promise.series-0.2.0.tgz", + "integrity": "sha512-VWQJyU2bcDTgZw8kpfBpB/ejZASlCrzwz5f2hjb/zlujOEB4oeiAhHygAWq8ubsX2GVkD4kCU5V2dwOTaCY5EQ==", + "engines": { + "node": ">=0.12" + } + }, + "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/qs": { + "version": "6.14.0", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.0.tgz", + "integrity": "sha512-YWWTjgABSKcvs/nWBi9PycY/JiPJqOD4JA6o9Sej2AtvSGarXxKC3OQSk4pAarbdQlKAh5D4FCQkJNkW+GAn3w==", + "dev": true, + "dependencies": { + "side-channel": "^1.1.0" + }, + "engines": { + "node": ">=0.6" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/randombytes": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/randombytes/-/randombytes-2.1.0.tgz", + "integrity": "sha512-vYl3iOX+4CKUWuxGi9Ukhie6fsqXqS9FE2Zaic4tNFD2N2QQaXOMFbuKK4QmDHC0JO6B1Zp41J0LpT0oR68amQ==", + "dependencies": { + "safe-buffer": "^5.1.0" + } + }, + "node_modules/range-parser": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.1.tgz", + "integrity": "sha512-Hrgsx+orqoygnmhFbKaHE6c296J+HTAQXoxEF6gNupROmmGJRoyzfG3ccAveqCBrwr/2yxQ5BVd/GTl5agOwSg==", + "dev": true, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/raw-body": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-3.0.2.tgz", + "integrity": "sha512-K5zQjDllxWkf7Z5xJdV0/B0WTNqx6vxG70zJE4N0kBs4LovmEYWJzQGxC9bS9RAKu3bgM40lrd5zoLJ12MQ5BA==", + "dev": true, + "dependencies": { + "bytes": "~3.1.2", + "http-errors": "~2.0.1", + "iconv-lite": "~0.7.0", + "unpipe": "~1.0.0" + }, + "engines": { + "node": ">= 0.10" + } + }, + "node_modules/rc9": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/rc9/-/rc9-2.1.2.tgz", + "integrity": "sha512-btXCnMmRIBINM2LDZoEmOogIZU7Qe7zn4BpomSKZ/ykbLObuBdvG+mFq11DL6fjH1DRwHhrlgtYWG96bJiC7Cg==", + "dev": true, + "dependencies": { + "defu": "^6.1.4", + "destr": "^2.0.3" + } + }, + "node_modules/readdirp": { + "version": "3.6.0", + "resolved": "https://registry.npmjs.org/readdirp/-/readdirp-3.6.0.tgz", + "integrity": "sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==", + "dependencies": { + "picomatch": "^2.2.1" + }, + "engines": { + "node": ">=8.10.0" + } + }, + "node_modules/readdirp/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/requires-port": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/requires-port/-/requires-port-1.0.0.tgz", + "integrity": "sha512-KigOCHcocU3XODJxsu8i/j8T9tzT4adHiecwORRQ0ZZFcp7ahwXuRU1m+yuO90C5ZUyGeGfocHDI14M3L3yDAQ==", + "dev": true + }, + "node_modules/resolve": { + "version": "1.22.11", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.22.11.tgz", + "integrity": "sha512-RfqAvLnMl313r7c9oclB1HhUEAezcpLjz95wFH4LVuhk9JF/r22qmVP9AMmOU4vMX7Q8pN8jwNg/CSpdFnMjTQ==", + "dependencies": { + "is-core-module": "^2.16.1", + "path-parse": "^1.0.7", + "supports-preserve-symlinks-flag": "^1.0.0" + }, + "bin": { + "resolve": "bin/resolve" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "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==", + "engines": { + "node": ">=8" + } + }, + "node_modules/resolve.exports": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/resolve.exports/-/resolve.exports-2.0.3.tgz", + "integrity": "sha512-OcXjMsGdhL4XnbShKpAcSqPMzQoYkYyhbEaeSko47MjRP9NfEQMhZkXL1DoFlt9LWQn4YttrdnV6X2OiyzBi+A==", + "engines": { + "node": ">=10" + } + }, + "node_modules/rollup": { + "version": "3.29.5", + "resolved": "https://registry.npmjs.org/rollup/-/rollup-3.29.5.tgz", + "integrity": "sha512-GVsDdsbJzzy4S/v3dqWPJ7EfvZJfCHiDqe80IyrF59LYuP+e6U1LJoUqeuqRbwAWoMNoXivMNeNAOf5E22VA1w==", + "bin": { + "rollup": "dist/bin/rollup" + }, + "engines": { + "node": ">=14.18.0", + "npm": ">=8.0.0" + }, + "optionalDependencies": { + "fsevents": "~2.3.2" + } + }, + "node_modules/rollup-plugin-css-only": { + "version": "4.5.5", + "resolved": "https://registry.npmjs.org/rollup-plugin-css-only/-/rollup-plugin-css-only-4.5.5.tgz", + "integrity": "sha512-O2m2Sj8qsAtjUVqZyGTDXJypaOFFNV4knz8OlS6wJBws6XEICIiLsXmI56SbQEmWDqYU5TgRgWmslGj4THofJQ==", + "dependencies": { + "@rollup/pluginutils": "5" + }, + "engines": { + "node": ">=14" + }, + "peerDependencies": { + "rollup": "<5" + } + }, + "node_modules/rollup-plugin-livereload": { + "version": "2.0.5", + "resolved": "https://registry.npmjs.org/rollup-plugin-livereload/-/rollup-plugin-livereload-2.0.5.tgz", + "integrity": "sha512-vqQZ/UQowTW7VoiKEM5ouNW90wE5/GZLfdWuR0ELxyKOJUIaj+uismPZZaICU4DnWPVjnpCDDxEqwU7pcKY/PA==", + "dependencies": { + "livereload": "^0.9.1" + }, + "engines": { + "node": ">=8.3" + } + }, + "node_modules/rollup-plugin-postcss": { + "version": "4.0.2", + "resolved": "https://registry.npmjs.org/rollup-plugin-postcss/-/rollup-plugin-postcss-4.0.2.tgz", + "integrity": "sha512-05EaY6zvZdmvPUDi3uCcAQoESDcYnv8ogJJQRp6V5kZ6J6P7uAVJlrTZcaaA20wTH527YTnKfkAoPxWI/jPp4w==", + "dependencies": { + "chalk": "^4.1.0", + "concat-with-sourcemaps": "^1.1.0", + "cssnano": "^5.0.1", + "import-cwd": "^3.0.0", + "p-queue": "^6.6.2", + "pify": "^5.0.0", + "postcss-load-config": "^3.0.0", + "postcss-modules": "^4.0.0", + "promise.series": "^0.2.0", + "resolve": "^1.19.0", + "rollup-pluginutils": "^2.8.2", + "safe-identifier": "^0.4.2", + "style-inject": "^0.3.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "postcss": "8.x" + } + }, + "node_modules/rollup-plugin-serve": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/rollup-plugin-serve/-/rollup-plugin-serve-1.1.1.tgz", + "integrity": "sha512-H0VarZRtFR0lfiiC9/P8jzCDvtFf1liOX4oSdIeeYqUCKrmFA7vNiQ0rg2D+TuoP7leaa/LBR8XBts5viF6lnw==", + "dev": true, + "dependencies": { + "mime": "^2", + "opener": "1" + } + }, + "node_modules/rollup-plugin-svelte": { + "version": "7.2.3", + "resolved": "https://registry.npmjs.org/rollup-plugin-svelte/-/rollup-plugin-svelte-7.2.3.tgz", + "integrity": "sha512-LlniP+h00DfM+E4eav/Kk8uGjgPUjGIBfrAS/IxQvsuFdqSM0Y2sXf31AdxuIGSW9GsmocDqOfaxR5QNno/Tgw==", + "dependencies": { + "@rollup/pluginutils": "^4.1.0", + "resolve.exports": "^2.0.0" + }, + "engines": { + "node": ">=10" + }, + "peerDependencies": { + "rollup": ">=2.0.0", + "svelte": ">=3.5.0" + } + }, + "node_modules/rollup-plugin-svelte/node_modules/@rollup/pluginutils": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/@rollup/pluginutils/-/pluginutils-4.2.1.tgz", + "integrity": "sha512-iKnFXr7NkdZAIHiIWE+BX5ULi/ucVFYWD6TbAV+rZctiRTY2PL6tsIKhoIOaoskiWAkgu+VsbXgUVDNLHf+InQ==", + "dependencies": { + "estree-walker": "^2.0.1", + "picomatch": "^2.2.2" + }, + "engines": { + "node": ">= 8.0.0" + } + }, + "node_modules/rollup-plugin-svelte/node_modules/picomatch": { + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", + "engines": { + "node": ">=8.6" + }, + "funding": { + "url": "https://github.com/sponsors/jonschlinkert" + } + }, + "node_modules/rollup-pluginutils": { + "version": "2.8.2", + "resolved": "https://registry.npmjs.org/rollup-pluginutils/-/rollup-pluginutils-2.8.2.tgz", + "integrity": "sha512-EEp9NhnUkwY8aif6bxgovPHMoMoNr2FulJziTndpt5H9RdwC47GSGuII9XxpSdzVGM0GWrNPHV6ie1LTNJPaLQ==", + "dependencies": { + "estree-walker": "^0.6.1" + } + }, + "node_modules/rollup-pluginutils/node_modules/estree-walker": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/estree-walker/-/estree-walker-0.6.1.tgz", + "integrity": "sha512-SqmZANLWS0mnatqbSfRP5g8OXZC12Fgg1IwNtLsyHDzJizORW4khDfjPqJZsemPWBB2uqykUah5YpQ6epsqC/w==" + }, + "node_modules/router": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/router/-/router-2.2.0.tgz", + "integrity": "sha512-nLTrUKm2UyiL7rlhapu/Zl45FwNgkZGaCpZbIHajDYgwlJCOzLSk+cIPAnsEqV955GjILJnKbdQC1nVPz+gAYQ==", + "dev": true, + "dependencies": { + "debug": "^4.4.0", + "depd": "^2.0.0", + "is-promise": "^4.0.0", + "parseurl": "^1.3.3", + "path-to-regexp": "^8.0.0" + }, + "engines": { + "node": ">= 18" + } + }, + "node_modules/run-applescript": { + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/run-applescript/-/run-applescript-7.1.0.tgz", + "integrity": "sha512-DPe5pVFaAsinSaV6QjQ6gdiedWDcRCbUuiQfQa2wmWV7+xC9bGulGI8+TdRmoFkAPaBXk8CrAbnlY2ISniJ47Q==", + "dev": true, + "engines": { + "node": ">=18" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/sade": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/sade/-/sade-1.8.1.tgz", + "integrity": "sha512-xal3CZX1Xlo/k4ApwCFrHVACi9fBqJ7V+mwhBsuf/1IOKbBy098Fex+Wa/5QMubw09pSZ/u8EY8PWgevJsXp1A==", + "dependencies": { + "mri": "^1.1.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/safe-buffer": { + "version": "5.2.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.2.1.tgz", + "integrity": "sha512-rp3So07KcdmmKbGvgaNxQSJr7bGVSVk5S9Eq1F+ppbRo70+YeaDxkw5Dd8NPN+GD6bjnYm2VuPuCXmpuYvmCXQ==", + "funding": [ + { + "type": "github", + "url": "https://github.com/sponsors/feross" + }, + { + "type": "patreon", + "url": "https://www.patreon.com/feross" + }, + { + "type": "consulting", + "url": "https://feross.org/support" + } + ] + }, + "node_modules/safe-identifier": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/safe-identifier/-/safe-identifier-0.4.2.tgz", + "integrity": "sha512-6pNbSMW6OhAi9j+N8V+U715yBQsaWJ7eyEUaOrawX+isg5ZxhUlV1NipNtgaKHmFGiABwt+ZF04Ii+3Xjkg+8w==" + }, + "node_modules/safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==", + "dev": true + }, + "node_modules/semiver": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/semiver/-/semiver-1.1.0.tgz", + "integrity": "sha512-QNI2ChmuioGC1/xjyYwyZYADILWyW6AmS1UH6gDj/SFUUUS4MBAWs/7mxnkRPc/F4iHezDP+O8t0dO8WHiEOdg==", + "engines": { + "node": ">=6" + } + }, + "node_modules/semver": { + "version": "7.7.3", + "resolved": "https://registry.npmjs.org/semver/-/semver-7.7.3.tgz", + "integrity": "sha512-SdsKMrI9TdgjdweUSR9MweHA4EJ8YxHn8DFaDisvhVlUOe4BF1tLD7GAj0lIqWVl+dPb/rExr0Btby5loQm20Q==", + "dev": true, + "bin": { + "semver": "bin/semver.js" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/send": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/send/-/send-1.2.1.tgz", + "integrity": "sha512-1gnZf7DFcoIcajTjTwjwuDjzuz4PPcY2StKPlsGAQ1+YH20IRVrBaXSWmdjowTJ6u8Rc01PoYOGHXfP1mYcZNQ==", + "dev": true, + "dependencies": { + "debug": "^4.4.3", + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "etag": "^1.8.1", + "fresh": "^2.0.0", + "http-errors": "^2.0.1", + "mime-types": "^3.0.2", + "ms": "^2.1.3", + "on-finished": "^2.4.1", + "range-parser": "^1.2.1", + "statuses": "^2.0.2" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/serialize-javascript": { + "version": "6.0.2", + "resolved": "https://registry.npmjs.org/serialize-javascript/-/serialize-javascript-6.0.2.tgz", + "integrity": "sha512-Saa1xPByTTq2gdeFZYLLo+RFE35NHZkAbqZeWNd3BpzppeVisAqpDjcp8dyf6uIvEqJRd46jemmyA4iFIeVk8g==", + "dependencies": { + "randombytes": "^2.1.0" + } + }, + "node_modules/serve-static": { + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-2.2.1.tgz", + "integrity": "sha512-xRXBn0pPqQTVQiC8wyQrKs2MOlX24zQ0POGaj0kultvoOCstBQM5yvOhAVSUwOMjQtTvsPWoNCHfPGwaaQJhTw==", + "dev": true, + "dependencies": { + "encodeurl": "^2.0.0", + "escape-html": "^1.0.3", + "parseurl": "^1.3.3", + "send": "^1.2.0" + }, + "engines": { + "node": ">= 18" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/express" + } + }, + "node_modules/setprototypeof": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.2.0.tgz", + "integrity": "sha512-E5LDX7Wrp85Kil5bhZv46j8jOeboKq5JMmYM3gVGdGH8xFpPWXUMsNrlODCrkoxMEeNi/XZIwuRvY4XNwYMJpw==", + "dev": true + }, + "node_modules/side-channel": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/side-channel/-/side-channel-1.1.0.tgz", + "integrity": "sha512-ZX99e6tRweoUXqR+VBrslhda51Nh5MTQwou5tnUDgbtyM0dBgmhEDtWGP/xbKn6hqfPRHujUNwz5fy/wbbhnpw==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3", + "side-channel-list": "^1.0.0", + "side-channel-map": "^1.0.1", + "side-channel-weakmap": "^1.0.2" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-list": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/side-channel-list/-/side-channel-list-1.0.0.tgz", + "integrity": "sha512-FCLHtRD/gnpCiCHEiJLOwdmFP+wzCmDEkc9y7NsYxeF4u7Btsn1ZuwgwJGxImImHicJArLP4R0yX4c2KCrMrTA==", + "dev": true, + "dependencies": { + "es-errors": "^1.3.0", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-map": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/side-channel-map/-/side-channel-map-1.0.1.tgz", + "integrity": "sha512-VCjCNfgMsby3tTdo02nbjtM/ewra6jPHmpThenkTYh8pG9ucZ/1P8So4u4FGBek/BjpOVsDCMoLA/iuBKIFXRA==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/side-channel-weakmap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/side-channel-weakmap/-/side-channel-weakmap-1.0.2.tgz", + "integrity": "sha512-WPS/HvHQTYnHisLo9McqBHOJk2FkHO/tlpvldyrnem4aeQp4hai3gythswg6p01oSoTl58rcpiFAjF2br2Ak2A==", + "dev": true, + "dependencies": { + "call-bound": "^1.0.2", + "es-errors": "^1.3.0", + "get-intrinsic": "^1.2.5", + "object-inspect": "^1.13.3", + "side-channel-map": "^1.0.1" + }, + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/sirv": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/sirv/-/sirv-3.0.2.tgz", + "integrity": "sha512-2wcC/oGxHis/BoHkkPwldgiPSYcpZK3JU28WoMVv55yHJgcZ8rlXvuG9iZggz+sU1d4bRgIGASwyWqjxu3FM0g==", + "dependencies": { + "@polka/url": "^1.0.0-next.24", + "mrmime": "^2.0.0", + "totalist": "^3.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/sirv-cli": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/sirv-cli/-/sirv-cli-3.0.1.tgz", + "integrity": "sha512-ICXaF2u6IQhLZ0EXF6nqUF4YODfSQSt+mGykt4qqO5rY+oIiwdg7B8w2PVDBJlQulaS2a3J8666CUoDoAuCGvg==", + "dependencies": { + "console-clear": "^1.1.0", + "get-port": "^5.1.1", + "kleur": "^4.1.4", + "local-access": "^1.0.1", + "sade": "^1.6.0", + "semiver": "^1.0.0", + "sirv": "^3.0.0", + "tinydate": "^1.0.0" + }, + "bin": { + "sirv": "bin.js" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/smob": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/smob/-/smob-1.5.0.tgz", + "integrity": "sha512-g6T+p7QO8npa+/hNx9ohv1E5pVCmWrVCUzUXJyLdMmftX6ER0oiWY/w9knEonLpnOp6b6FenKnMfR8gqwWdwig==" + }, + "node_modules/source-map": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz", + "integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-js": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.2.1.tgz", + "integrity": "sha512-UXWMKhLOwVKb728IUtQPXxfYU+usdybtUrK/8uGE8CQMvrhOpwvzDBwj0QhSL7MQc7vIsISBG8VQ8+IDQxpfQA==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/source-map-support": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/source-map-support/-/source-map-support-0.5.21.tgz", + "integrity": "sha512-uBHU3L3czsIyYXKX88fdrGovxdSCoTGDRZ6SYXtSRxLZUzHg5P/66Ht6uoUlHu9EZod+inXhKo3qQgwXUT/y1w==", + "dependencies": { + "buffer-from": "^1.0.0", + "source-map": "^0.6.0" + } + }, + "node_modules/stable": { + "version": "0.1.8", + "resolved": "https://registry.npmjs.org/stable/-/stable-0.1.8.tgz", + "integrity": "sha512-ji9qxRnOVfcuLDySj9qzhGSEFVobyt1kIOSkj1qZzYLzq7Tos/oUUWvotUPQLlrsidqsK6tBH89Bc9kL5zHA6w==", + "deprecated": "Modern JS already guarantees Array#sort() is a stable sort, so this library is deprecated. See the compatibility table on MDN: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort#browser_compatibility" + }, + "node_modules/statuses": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-2.0.2.tgz", + "integrity": "sha512-DvEy55V3DB7uknRo+4iOGT5fP1slR8wQohVdknigZPMpMstaKJQWhwiYBACJE3Ul2pTnATihhBYnRhZQHGBiRw==", + "dev": true, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/string-hash": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/string-hash/-/string-hash-1.1.3.tgz", + "integrity": "sha512-kJUvRUFK49aub+a7T1nNE66EJbZBMnBgoC1UbCZ5n6bsZKBRga4KgBRTMn/pFkeCZSYtNeSyMxPDM0AXWELk2A==" + }, + "node_modules/style-inject": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/style-inject/-/style-inject-0.3.0.tgz", + "integrity": "sha512-IezA2qp+vcdlhJaVm5SOdPPTUu0FCEqfNSli2vRuSIBbu5Nq5UvygTk/VzeCqfLz2Atj3dVII5QBKGZRZ0edzw==" + }, + "node_modules/style-mod": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/style-mod/-/style-mod-4.1.3.tgz", + "integrity": "sha512-i/n8VsZydrugj3Iuzll8+x/00GH2vnYsk1eomD8QiRrSAeW6ItbCQDtfXCeJHd0iwiNagqjQkvpvREEPtW3IoQ==" + }, + "node_modules/stylehacks": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/stylehacks/-/stylehacks-5.1.1.tgz", + "integrity": "sha512-sBpcd5Hx7G6seo7b1LkpttvTz7ikD0LlH5RmdcBNb6fFR0Fl7LQwHDFr300q4cwUqi+IYrFGmsIHieMBfnN/Bw==", + "dependencies": { + "browserslist": "^4.21.4", + "postcss-selector-parser": "^6.0.4" + }, + "engines": { + "node": "^10 || ^12 || >=14.0" + }, + "peerDependencies": { + "postcss": "^8.2.15" + } + }, + "node_modules/supports-color": { + "version": "7.2.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz", + "integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==", + "dependencies": { + "has-flag": "^4.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/supports-preserve-symlinks-flag": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/supports-preserve-symlinks-flag/-/supports-preserve-symlinks-flag-1.0.0.tgz", + "integrity": "sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==", + "engines": { + "node": ">= 0.4" + }, + "funding": { + "url": "https://github.com/sponsors/ljharb" + } + }, + "node_modules/svelte": { + "version": "5.46.0", + "resolved": "https://registry.npmjs.org/svelte/-/svelte-5.46.0.tgz", + "integrity": "sha512-ZhLtvroYxUxr+HQJfMZEDRsGsmU46x12RvAv/zi9584f5KOX7bUrEbhPJ7cKFmUvZTJXi/CFZUYwDC6M1FigPw==", + "dependencies": { + "@jridgewell/remapping": "^2.3.4", + "@jridgewell/sourcemap-codec": "^1.5.0", + "@sveltejs/acorn-typescript": "^1.0.5", + "@types/estree": "^1.0.5", + "acorn": "^8.12.1", + "aria-query": "^5.3.1", + "axobject-query": "^4.1.0", + "clsx": "^2.1.1", + "devalue": "^5.5.0", + "esm-env": "^1.2.1", + "esrap": "^2.2.1", + "is-reference": "^3.0.3", + "locate-character": "^3.0.0", + "magic-string": "^0.30.11", + "zimmerframe": "^1.1.2" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/svelte-preprocess": { + "version": "6.0.3", + "resolved": "https://registry.npmjs.org/svelte-preprocess/-/svelte-preprocess-6.0.3.tgz", + "integrity": "sha512-PLG2k05qHdhmRG7zR/dyo5qKvakhm8IJ+hD2eFRQmMLHp7X3eJnjeupUtvuRpbNiF31RjVw45W+abDwHEmP5OA==", + "hasInstallScript": true, + "engines": { + "node": ">= 18.0.0" + }, + "peerDependencies": { + "@babel/core": "^7.10.2", + "coffeescript": "^2.5.1", + "less": "^3.11.3 || ^4.0.0", + "postcss": "^7 || ^8", + "postcss-load-config": ">=3", + "pug": "^3.0.0", + "sass": "^1.26.8", + "stylus": ">=0.55", + "sugarss": "^2.0.0 || ^3.0.0 || ^4.0.0", + "svelte": "^4.0.0 || ^5.0.0-next.100 || ^5.0.0", + "typescript": "^5.0.0" + }, + "peerDependenciesMeta": { + "@babel/core": { + "optional": true + }, + "coffeescript": { + "optional": true + }, + "less": { + "optional": true + }, + "postcss": { + "optional": true + }, + "postcss-load-config": { + "optional": true + }, + "pug": { + "optional": true + }, + "sass": { + "optional": true + }, + "stylus": { + "optional": true + }, + "sugarss": { + "optional": true + }, + "typescript": { + "optional": true + } + } + }, + "node_modules/svelte/node_modules/is-reference": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/is-reference/-/is-reference-3.0.3.tgz", + "integrity": "sha512-ixkJoqQvAP88E6wLydLGGqCJsrFUnqoH6HnaczB8XmDH1oaWU+xxdptvikTgaEhtZ53Ky6YXiBuUI2WXLMCwjw==", + "dependencies": { + "@types/estree": "^1.0.6" + } + }, + "node_modules/svelte/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==", + "dependencies": { + "@jridgewell/sourcemap-codec": "^1.5.5" + } + }, + "node_modules/svgo": { + "version": "2.8.0", + "resolved": "https://registry.npmjs.org/svgo/-/svgo-2.8.0.tgz", + "integrity": "sha512-+N/Q9kV1+F+UeWYoSiULYo4xYSDQlTgb+ayMobAXPwMnLvop7oxKMo9OzIrX5x3eS4L4f2UHhc9axXwY8DpChg==", + "dependencies": { + "@trysound/sax": "0.2.0", + "commander": "^7.2.0", + "css-select": "^4.1.3", + "css-tree": "^1.1.3", + "csso": "^4.2.0", + "picocolors": "^1.0.0", + "stable": "^0.1.8" + }, + "bin": { + "svgo": "bin/svgo" + }, + "engines": { + "node": ">=10.13.0" + } + }, + "node_modules/svgo/node_modules/css-tree": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/css-tree/-/css-tree-1.1.3.tgz", + "integrity": "sha512-tRpdppF7TRazZrjJ6v3stzv93qxRcSsFmW6cX0Zm2NVKpxE1WV1HblnghVv9TreireHkqI/VDEsfolRF1p6y7Q==", + "dependencies": { + "mdn-data": "2.0.14", + "source-map": "^0.6.1" + }, + "engines": { + "node": ">=8.0.0" + } + }, + "node_modules/svgo/node_modules/mdn-data": { + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/mdn-data/-/mdn-data-2.0.14.tgz", + "integrity": "sha512-dn6wd0uw5GsdswPFfsgMp5NSB0/aDe6fK94YJV/AJDYXL6HVLWBsxeq7js7Ad+mU2K9LAlwpk6kN2D5mwCPVow==" + }, + "node_modules/tailwindcss": { + "version": "4.1.13", + "resolved": "https://registry.npmjs.org/tailwindcss/-/tailwindcss-4.1.13.tgz", + "integrity": "sha512-i+zidfmTqtwquj4hMEwdjshYYgMbOrPzb9a0M3ZgNa0JMoZeFC6bxZvO8yr8ozS6ix2SDz0+mvryPeBs2TFE+w==", + "dev": true + }, + "node_modules/tapable": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", + "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", + "dev": true, + "engines": { + "node": ">=6" + }, + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/webpack" + } + }, + "node_modules/tar": { + "version": "7.5.2", + "resolved": "https://registry.npmjs.org/tar/-/tar-7.5.2.tgz", + "integrity": "sha512-7NyxrTE4Anh8km8iEy7o0QYPs+0JKBTj5ZaqHg6B39erLg0qYXN3BijtShwbsNSvQ+LN75+KV+C4QR/f6Gwnpg==", + "dev": true, + "dependencies": { + "@isaacs/fs-minipass": "^4.0.0", + "chownr": "^3.0.0", + "minipass": "^7.1.2", + "minizlib": "^3.1.0", + "yallist": "^5.0.0" + }, + "engines": { + "node": ">=18" + } + }, + "node_modules/terser": { + "version": "5.44.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.44.1.tgz", + "integrity": "sha512-t/R3R/n0MSwnnazuPpPNVO60LX0SKL45pyl9YlvxIdkH0Of7D5qM2EVe+yASRIlY5pZ73nclYJfNANGWPwFDZw==", + "dependencies": { + "@jridgewell/source-map": "^0.3.3", + "acorn": "^8.15.0", + "commander": "^2.20.0", + "source-map-support": "~0.5.20" + }, + "bin": { + "terser": "bin/terser" + }, + "engines": { + "node": ">=10" + } + }, + "node_modules/terser/node_modules/commander": { + "version": "2.20.3", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", + "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==" + }, + "node_modules/tinydate": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/tinydate/-/tinydate-1.3.0.tgz", + "integrity": "sha512-7cR8rLy2QhYHpsBDBVYnnWXm8uRTr38RoZakFSW7Bs7PzfMPNZthuMLkwqZv7MTu8lhQ91cOFYS5a7iFj2oR3w==", + "engines": { + "node": ">=4" + } + }, + "node_modules/tinyexec": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/tinyexec/-/tinyexec-1.0.2.tgz", + "integrity": "sha512-W/KYk+NFhkmsYpuHq5JykngiOCnxeVL8v8dFnqxSD8qEEdRfXk1SDM6JzNqcERbcGYj9tMrDQBYV9cjgnunFIg==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "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==", + "dependencies": { + "is-number": "^7.0.0" + }, + "engines": { + "node": ">=8.0" + } + }, + "node_modules/toidentifier": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toidentifier/-/toidentifier-1.0.1.tgz", + "integrity": "sha512-o5sSPKEkg/DIQNmH43V0/uerLrpzVedkUh8tGNvaeXpfpuwjKenlSox/2O/BTlZUtEe+JG7s5YhEz608PlAHRA==", + "dev": true, + "engines": { + "node": ">=0.6" + } + }, + "node_modules/totalist": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/totalist/-/totalist-3.0.1.tgz", + "integrity": "sha512-sf4i37nQ2LBx4m3wB74y+ubopq6W/dIzXg0FDGjsYnZHVa1Da8FH853wlL2gtUhg+xJXjfk3kUZS3BRoQeoQBQ==", + "engines": { + "node": ">=6" + } + }, + "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==", + "dev": true + }, + "node_modules/type-is": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-2.0.1.tgz", + "integrity": "sha512-OZs6gsjF4vMp32qrCbiVSkrFmXtG/AZhY3t0iAMrMBiAZyV9oALtXO8hsrHbMXF9x6L3grlFuwW2oAz7cav+Gw==", + "dev": true, + "dependencies": { + "content-type": "^1.0.5", + "media-typer": "^1.1.0", + "mime-types": "^3.0.0" + }, + "engines": { + "node": ">= 0.6" + } + }, + "node_modules/typescript": { + "version": "5.9.3", + "resolved": "https://registry.npmjs.org/typescript/-/typescript-5.9.3.tgz", + "integrity": "sha512-jl1vZzPDinLr9eUt3J/t7V6FgNEw9QjvBPdysz9KfQDD41fQrC2Y4vKQdiaUpFT4bXlb1RHhLpp8wtm6M5TgSw==", + "devOptional": true, + "bin": { + "tsc": "bin/tsc", + "tsserver": "bin/tsserver" + }, + "engines": { + "node": ">=14.17" + } + }, + "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, + "engines": { + "node": ">= 0.8" + } + }, + "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" + } + ], + "dependencies": { + "escalade": "^3.2.0", + "picocolors": "^1.1.1" + }, + "bin": { + "update-browserslist-db": "cli.js" + }, + "peerDependencies": { + "browserslist": ">= 4.21.0" + } + }, + "node_modules/util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==" + }, + "node_modules/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, + "engines": { + "node": ">= 0.8" + } + }, + "node_modules/w3c-keyname": { + "version": "2.2.8", + "resolved": "https://registry.npmjs.org/w3c-keyname/-/w3c-keyname-2.2.8.tgz", + "integrity": "sha512-dpojBhNsCNN7T82Tm7k26A6G9ML3NkhDsnw9n/eoxSRlVBB4CEtIQ/KTCLI2Fwf3ataSXRhYFkQi3SlnFwPvPQ==" + }, + "node_modules/wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ==" + }, + "node_modules/ws": { + "version": "7.5.10", + "resolved": "https://registry.npmjs.org/ws/-/ws-7.5.10.tgz", + "integrity": "sha512-+dbF1tHwZpXcbOJdVOkzLDxZP1ailvSxM6ZweXTegylPny803bFhA+vqBYw4s31NSAk4S2Qz+AKXK9a4wkdjcQ==", + "engines": { + "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/wsl-utils": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/wsl-utils/-/wsl-utils-0.3.0.tgz", + "integrity": "sha512-3sFIGLiaDP7rTO4xh3g+b3AzhYDIUGGywE/WsmqzJWDxus5aJXVnPTNC/6L+r2WzrwXqVOdD262OaO+cEyPMSQ==", + "dev": true, + "dependencies": { + "is-wsl": "^3.1.0", + "powershell-utils": "^0.1.0" + }, + "engines": { + "node": ">=20" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, + "node_modules/yallist": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-5.0.0.tgz", + "integrity": "sha512-YgvUTfwqyc7UXVMrB+SImsVYSmTS8X/tSrtdNZMImM+n7+QTriRXyXim0mBrTXNeqzVF0KWGgHPeiyViFFrNDw==", + "dev": true, + "engines": { + "node": ">=18" + } + }, + "node_modules/yaml": { + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", + "engines": { + "node": ">= 6" + } + }, + "node_modules/zimmerframe": { + "version": "1.1.4", + "resolved": "https://registry.npmjs.org/zimmerframe/-/zimmerframe-1.1.4.tgz", + "integrity": "sha512-B58NGBEoc8Y9MWWCQGl/gq9xBCe4IiKM0a2x7GZdQKOW5Exr8S1W24J6OgM1njK8xCRGvAJIL/MxXHf6SkmQKQ==" + } + } +} diff --git a/frontend/package.json b/frontend/package.json index ecdfe6fc..f73adc4d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -6,7 +6,8 @@ "scripts": { "build": "npx rollup -c", "dev": "npx rollup -c -w", - "start": "sirv public --single --no-clear --dev --host" + "start": "sirv public --single --no-clear --dev --host", + "generate:api": "openapi-ts" }, "dependencies": { "@babel/runtime": "^7.27.6", @@ -17,7 +18,6 @@ "@codemirror/state": "^6.4.1", "@codemirror/theme-one-dark": "^6.1.2", "@codemirror/view": "^6.34.1", - "@macfja/svelte-persistent-store": "^2.4.1", "@rollup/plugin-commonjs": "^24.0.0", "@rollup/plugin-json": "^6.1.0", "@rollup/plugin-node-resolve": "^15.0.0", @@ -29,29 +29,31 @@ "@uiw/codemirror-theme-monokai": "^4.24.2", "@uiw/codemirror-theme-vscode": "^4.24.2", "ansi-to-html": "^0.7.2", - "autoprefixer": "^10.4.20", - "axios": "^1.7.7", "codemirror": "^6.0.1", "dompurify": "^3.2.0", - "dotenv": "^16.4.5", - "exponential-backoff": "^3.1.2", + "dotenv": "^17.2.3", "postcss": "^8.4.47", "rollup": "^3.15.0", "rollup-plugin-css-only": "^4.3.0", "rollup-plugin-livereload": "^2.0.0", "rollup-plugin-postcss": "^4.0.2", "rollup-plugin-svelte": "^7.2.2", - "sirv-cli": "^2.0.0", - "svelte": "^4.2.19", + "sirv-cli": "^3.0.1", + "svelte": "^5.46.0", "svelte-preprocess": "^6.0.3", - "svelte-routing": "^2.13.0", - "tailwindcss": "^3.4.13" + "@mateothegreat/svelte5-router": "^2.16.19" }, "devDependencies": { "@babel/runtime": "^7.24.7", - "@tailwindcss/forms": "^0.5.7", - "express": "^4.21.1", + "@rollup/plugin-typescript": "^12.1.2", + "@tailwindcss/forms": "^0.5.11", + "@tailwindcss/postcss": "^4.1.13", + "express": "^5.2.1", "http-proxy": "^1.18.1", - "rollup-plugin-serve": "^1.1.1" + "@hey-api/openapi-ts": "0.89.1", + "rollup-plugin-serve": "^1.1.1", + "tailwindcss": "^4.1.13", + "tslib": "^2.8.1", + "typescript": "^5.7.2" } } diff --git a/frontend/postcss.config.cjs b/frontend/postcss.config.cjs index 96bb01e7..78286dd6 100644 --- a/frontend/postcss.config.cjs +++ b/frontend/postcss.config.cjs @@ -1,6 +1,5 @@ module.exports = { plugins: { - tailwindcss: {}, - autoprefixer: {}, + "@tailwindcss/postcss": {}, }, } \ No newline at end of file diff --git a/frontend/rollup.config.js b/frontend/rollup.config.js index 55bf04e8..4a19f998 100644 --- a/frontend/rollup.config.js +++ b/frontend/rollup.config.js @@ -5,6 +5,7 @@ import terser from '@rollup/plugin-terser'; import postcss from 'rollup-plugin-postcss'; import sveltePreprocess from 'svelte-preprocess'; import replace from '@rollup/plugin-replace'; +import typescript from '@rollup/plugin-typescript'; import dotenv from 'dotenv'; import fs from 'fs'; import https from 'https'; @@ -112,7 +113,7 @@ function startServer() { } export default { - input: 'src/main.js', + input: 'src/main.ts', output: { sourcemap: true, format: 'es', @@ -121,8 +122,7 @@ export default { manualChunks: { 'vendor': [ 'svelte', - 'svelte-routing', - 'axios' + '@mateothegreat/svelte5-router' ], 'codemirror': [ '@codemirror/state', @@ -148,12 +148,19 @@ export default { }), svelte({ preprocess: sveltePreprocess({ postcss: true }), - compilerOptions: { dev: !production } + compilerOptions: { + dev: !production, + runes: true + } }), postcss({ extract: 'bundle.css', minimize: production, }), + typescript({ + sourceMap: true, + inlineSources: !production + }), json(), resolve({ browser: true, @@ -175,7 +182,7 @@ export default { module: true, compress: { passes: 2, - pure_funcs: ['console.log'] + drop_console: true }, format: { comments: false diff --git a/frontend/scripts/setupTypeScript.js b/frontend/scripts/setupTypeScript.js deleted file mode 100644 index 4385f655..00000000 --- a/frontend/scripts/setupTypeScript.js +++ /dev/null @@ -1,134 +0,0 @@ -// @ts-check - -/** This script modifies the project to support TS code in .svelte files like: - - - - As well as validating the code for CI. - */ - -/** To work on this script: - rm -rf test-template template && git clone sveltejs/template test-template && node scripts/setupTypeScript.js test-template -*/ - -import fs from "fs" -import path from "path" -import { argv } from "process" -import url from 'url'; - -const __filename = url.fileURLToPath(import.meta.url); -const __dirname = url.fileURLToPath(new URL('.', import.meta.url)); -const projectRoot = argv[2] || path.join(__dirname, "..") - -// Add deps to pkg.json -const packageJSON = JSON.parse(fs.readFileSync(path.join(projectRoot, "package.json"), "utf8")) -packageJSON.devDependencies = Object.assign(packageJSON.devDependencies, { - "svelte-check": "^3.0.0", - "svelte-preprocess": "^5.0.0", - "@rollup/plugin-typescript": "^11.0.0", - "typescript": "^4.9.0", - "tslib": "^2.5.0", - "@tsconfig/svelte": "^3.0.0" -}) - -// Add script for checking -packageJSON.scripts = Object.assign(packageJSON.scripts, { - "check": "svelte-check" -}) - -// Write the package JSON -fs.writeFileSync(path.join(projectRoot, "package.json"), JSON.stringify(packageJSON, null, " ")) - -// mv src/main.js to main.ts - note, we need to edit rollup.config.js for this too -const beforeMainJSPath = path.join(projectRoot, "src", "main.js") -const afterMainTSPath = path.join(projectRoot, "src", "main.ts") -fs.renameSync(beforeMainJSPath, afterMainTSPath) - -// Switch the app.svelte file to use TS -const appSveltePath = path.join(projectRoot, "src", "App.svelte") -let appFile = fs.readFileSync(appSveltePath, "utf8") -appFile = appFile.replace(" -{#if !authInitialized} - - - -{:else} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + +{#snippet layoutWrapper(content: Snippet, isProtected: boolean = false, isFullWidth: boolean = false)} + {#if isProtected} + + + + + + + {@render content()} + - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + - - - - - + + {:else} - - - + + + {@render content()} - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + {/if} +{/snippet} + + +{#snippet homeSnippet()} + {@render layoutWrapper(homeContent, false)} +{/snippet} + +{#snippet homeContent()} + +{/snippet} + +{#snippet loginSnippet()} + {@render layoutWrapper(loginContent, false)} +{/snippet} + +{#snippet loginContent()} + +{/snippet} + +{#snippet registerSnippet()} + {@render layoutWrapper(registerContent, false)} +{/snippet} + +{#snippet registerContent()} + +{/snippet} + +{#snippet privacySnippet()} + {@render layoutWrapper(privacyContent, false)} +{/snippet} + +{#snippet privacyContent()} + +{/snippet} + + +{#snippet editorSnippet()} + {@render layoutWrapper(editorContent, true)} +{/snippet} + +{#snippet editorContent()} + +{/snippet} + +{#snippet settingsSnippet()} + {@render layoutWrapper(settingsContent, true)} +{/snippet} + +{#snippet settingsContent()} + +{/snippet} + +{#snippet notificationsSnippet()} + {@render layoutWrapper(notificationsContent, true)} +{/snippet} + +{#snippet notificationsContent()} + +{/snippet} + + +{#snippet adminEventsSnippet()} + {@render layoutWrapper(adminEventsContent, true, true)} +{/snippet} + +{#snippet adminEventsContent()} + +{/snippet} + +{#snippet adminSagasSnippet()} + {@render layoutWrapper(adminSagasContent, true, true)} +{/snippet} + +{#snippet adminSagasContent()} + +{/snippet} + +{#snippet adminUsersSnippet()} + {@render layoutWrapper(adminUsersContent, true, true)} +{/snippet} + +{#snippet adminUsersContent()} + +{/snippet} + +{#snippet adminSettingsSnippet()} + {@render layoutWrapper(adminSettingsContent, true, true)} +{/snippet} + +{#snippet adminSettingsContent()} + +{/snippet} + +{#if !authInitialized} + + + +{:else} + {/if} \ No newline at end of file + diff --git a/frontend/src/app.css b/frontend/src/app.css index 6567ec9b..34dc3d44 100644 --- a/frontend/src/app.css +++ b/frontend/src/app.css @@ -1,42 +1,89 @@ /* Import Google Fonts */ @import url('https://fonts.googleapis.com/css2?family=Fira+Code:wght@400;500&family=Inter:wght@400;500;600;700&display=swap'); -@tailwind base; -@tailwind components; -@tailwind utilities; +/* Tailwind CSS v4 */ +@import "tailwindcss"; -/* Import component styles */ +/* Import component and page styles (after tailwindcss, before other directives) */ @import './styles/components.css'; +@import './styles/pages.css'; -@layer utilities { - /* Animation utilities for consistent transitions */ - .animate-fadeIn { - animation: fadeIn 0.3s ease-in-out; - } - - .animate-flyIn { - animation: flyIn 0.3s ease-out; - } - - @keyframes fadeIn { - from { - opacity: 0; - } - to { - opacity: 1; - } - } - - @keyframes flyIn { - from { - opacity: 0; - transform: translateY(10px); - } - to { - opacity: 1; - transform: translateY(0); - } - } +/* Forms plugin */ +@plugin "@tailwindcss/forms" { + strategy: class; +} + +/* Dark mode variant (class-based) */ +@variant dark (&:where(.dark, .dark *)); + +/* Theme configuration */ +@theme { + /* Primary - Blue */ + --color-primary-light: #60a5fa; + --color-primary: #3b82f6; + --color-primary-dark: #2563eb; + + /* Secondary - Teal */ + --color-secondary-light: #5eead4; + --color-secondary: #14b8a6; + --color-secondary-dark: #0f766e; + + /* Semantic Colors - Light */ + --color-bg-default: #f8fafc; + --color-bg-alt: #ffffff; + --color-bg-sidebar: #f1f5f9; + --color-fg-default: #1e293b; + --color-fg-muted: #64748b; + --color-fg-subtle: #94a3b8; + --color-border-default: #e2e8f0; + --color-border-input: #cbd5e1; + --color-focus-ring: #93c5fd; + + /* Semantic Colors - Dark */ + --color-dark-bg-default: #0f172a; + --color-dark-bg-alt: #1e293b; + --color-dark-bg-sidebar: #020617; + --color-dark-fg-default: #e2e8f0; + --color-dark-fg-muted: #94a3b8; + --color-dark-fg-subtle: #64748b; + --color-dark-border-default: #334155; + --color-dark-border-input: #475569; + --color-dark-focus-ring: #3b82f6; + + --color-code-bg: #0f172a; + + /* Font Families */ + --font-sans: 'Inter', ui-sans-serif, system-ui, -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, 'Helvetica Neue', Arial, 'Noto Sans', sans-serif; + --font-mono: 'Fira Code', ui-monospace, SFMono-Regular, Menlo, Monaco, Consolas, 'Liberation Mono', 'Courier New', monospace; + + /* Custom Shadow */ + --shadow-input-focus: 0 0 0 3px var(--tw-shadow-color); + + /* Custom Timing Function */ + --ease-out-expo: cubic-bezier(0.16, 1, 0.3, 1); + + /* Animations */ + --animate-fadeIn: fadeIn 0.3s ease-out; + --animate-flyIn: flyIn 0.3s var(--ease-out-expo); +} + +@keyframes fadeIn { + from { opacity: 0; } + to { opacity: 1; } +} + +@keyframes flyIn { + from { opacity: 0; transform: translateY(10px); } + to { opacity: 1; transform: translateY(0); } +} + +/* Custom utilities */ +@utility animate-fadeIn { + animation: var(--animate-fadeIn); +} + +@utility animate-flyIn { + animation: var(--animate-flyIn); } @layer base { @@ -53,7 +100,7 @@ [type='search'], textarea, select { - @apply form-input border-border-input dark:border-dark-border-input bg-bg-alt dark:bg-dark-bg-alt dark:text-dark-fg-default focus:border-primary dark:focus:border-primary focus:ring focus:ring-focus-ring dark:focus:ring-dark-focus-ring focus:ring-opacity-50 rounded-md shadow-sm text-sm; + @apply form-input border-border-input dark:border-dark-border-input bg-bg-alt dark:bg-dark-bg-alt dark:text-dark-fg-default focus:border-primary dark:focus:border-primary focus:ring-3 focus:ring-focus-ring/50 dark:focus:ring-dark-focus-ring/50 rounded-md shadow-xs text-sm; } [type='text']:disabled, [type='email']:disabled, @@ -93,11 +140,11 @@ /* CodeMirror Base Overrides */ .cm-editor { - @apply !font-mono text-sm border border-border-default dark:border-dark-border-default rounded-lg; + @apply font-mono! text-sm border border-border-default dark:border-dark-border-default rounded-lg; height: 100% !important; /* Force height */ } .cm-scroller { - @apply !font-mono; + @apply font-mono!; } /* oneDark Theme specific overrides for better integration */ .cm-theme-onedark .cm-gutters { @@ -125,7 +172,7 @@ @layer components { /* Reusable Button Styles */ .btn { - @apply inline-flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-sm focus:outline-none focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-dark-bg-default transition-all duration-150 ease-in-out disabled:opacity-60 disabled:cursor-not-allowed; + @apply inline-flex items-center justify-center px-4 py-2 border border-transparent text-sm font-medium rounded-md shadow-xs focus:outline-hidden focus:ring-2 focus:ring-offset-2 dark:focus:ring-offset-dark-bg-default transition-all duration-150 ease-in-out disabled:opacity-60 disabled:cursor-not-allowed; } .btn-sm { @apply px-3 py-1.5 text-xs rounded; /* Smaller padding/text/radius */ @@ -134,7 +181,7 @@ @apply px-2.5 py-1 text-xs rounded; } .btn-icon { - @apply !p-2; /* Specific padding for icon-only buttons */ + @apply p-2!; /* Specific padding for icon-only buttons */ } .btn-primary { @apply text-white bg-primary hover:bg-primary-dark focus:ring-primary; @@ -175,181 +222,286 @@ .input-group > :not(:first-child) { @apply rounded-l-none; } - + /* Stacked Input Group (for login/register forms) */ .input-group-stacked { - @apply rounded-md shadow-sm -space-y-px; + @apply rounded-md shadow-xs -space-y-px; } - + .input-group-stacked > div:first-child input { @apply rounded-t-md rounded-b-none; } - + .input-group-stacked > div:last-child input { @apply rounded-b-md rounded-t-none; } - + .input-group-stacked > div:not(:first-child):not(:last-child) input { @apply rounded-none; } - + .input-group-stacked input { - @apply appearance-none relative block w-full px-3 py-2 border + @apply appearance-none relative block w-full px-3 py-2 border border-neutral-300 dark:border-dark-border-input - placeholder-fg-subtle dark:placeholder-dark-fg-subtle - text-fg-default dark:text-dark-fg-default - focus:outline-none focus:ring-primary focus:border-primary focus:z-10 sm:text-sm; + placeholder-fg-subtle dark:placeholder-dark-fg-subtle + text-fg-default dark:text-dark-fg-default + focus:outline-hidden focus:ring-primary focus:border-primary focus:z-10 sm:text-sm; } - + /* Form Control Styles */ .form-control { @apply space-y-1; } - + .form-control label { @apply block text-sm font-medium text-fg-default dark:text-dark-fg-default; } - + /* Multi-select styles */ .form-select-standard[multiple] { @apply overflow-y-auto; } - + .form-select-standard[multiple] option { @apply px-2 py-1 hover:bg-neutral-100 dark:hover:bg-neutral-700; } - + .form-select-standard[multiple] option:checked { @apply bg-primary/20 dark:bg-primary/30 font-medium; } - + /* Standard Input Styles */ .form-input-standard { - @apply w-full px-3 py-1.5 text-sm border border-neutral-300 dark:border-dark-border-input - bg-white dark:bg-dark-bg-alt text-fg-default dark:text-dark-fg-default - rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary + @apply w-full px-3 py-1.5 text-sm border border-neutral-300 dark:border-dark-border-input + bg-white dark:bg-dark-bg-alt text-fg-default dark:text-dark-fg-default + rounded-md focus:outline-hidden focus:ring-2 focus:ring-primary focus:border-primary hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors; } - + .form-input-standard:disabled { @apply bg-neutral-100 dark:bg-neutral-700 opacity-70 cursor-not-allowed hover:bg-neutral-100 dark:hover:bg-neutral-700; } - + /* Number Input with Spinner Controls */ .form-input-number { - @apply form-input-standard; + @apply w-full px-3 py-1.5 text-sm border border-neutral-300 dark:border-dark-border-input + bg-white dark:bg-dark-bg-alt text-fg-default dark:text-dark-fg-default + rounded-md focus:outline-hidden focus:ring-2 focus:ring-primary focus:border-primary + hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors; } - + /* Textarea Styles */ .form-textarea { - @apply form-input-standard resize-y min-h-[80px]; + @apply w-full px-3 py-1.5 text-sm border border-neutral-300 dark:border-dark-border-input + bg-white dark:bg-dark-bg-alt text-fg-default dark:text-dark-fg-default + rounded-md focus:outline-hidden focus:ring-2 focus:ring-primary focus:border-primary + hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors resize-y min-h-[80px]; } - + /* Select/Dropdown Styles */ .form-select-standard { - @apply w-full px-3 py-1.5 text-sm border border-neutral-300 dark:border-dark-border-input - bg-white dark:bg-dark-bg-alt text-fg-default dark:text-dark-fg-default - rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary + @apply w-full px-3 py-1.5 text-sm border border-neutral-300 dark:border-dark-border-input + bg-white dark:bg-dark-bg-alt text-fg-default dark:text-dark-fg-default + rounded-md focus:outline-hidden focus:ring-2 focus:ring-primary focus:border-primary hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors pr-10 cursor-pointer; } - + /* Custom Dropdown Button */ .form-dropdown-button { @apply w-full flex items-center justify-between text-left - px-3 py-1.5 text-sm border border-neutral-300 dark:border-dark-border-input - bg-white dark:bg-dark-bg-alt text-fg-default dark:text-dark-fg-default - rounded-md focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary + px-3 py-1.5 text-sm border border-neutral-300 dark:border-dark-border-input + bg-white dark:bg-dark-bg-alt text-fg-default dark:text-dark-fg-default + rounded-md focus:outline-hidden focus:ring-2 focus:ring-primary focus:border-primary hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors cursor-pointer; } - + .form-dropdown-button svg { - @apply w-5 h-5 ml-2 flex-shrink-0 text-fg-muted dark:text-dark-fg-muted transform transition-transform; + @apply w-5 h-5 ml-2 shrink-0 text-fg-muted dark:text-dark-fg-muted transform transition-transform; } - + .form-dropdown-button[aria-expanded="true"] svg { @apply -rotate-180; } - + /* Dropdown Menu */ .form-dropdown-menu { - @apply absolute top-full mt-1 w-full bg-bg-alt dark:bg-dark-bg-alt - rounded-lg shadow-xl ring-1 ring-black ring-opacity-5 - dark:ring-white dark:ring-opacity-10 z-30; + @apply absolute top-full mt-1 w-full bg-bg-alt dark:bg-dark-bg-alt + rounded-lg shadow-xl ring-1 ring-black/5 + dark:ring-white/10 z-30; } - + .form-dropdown-menu ul { @apply py-1; } - + .form-dropdown-menu li button { - @apply w-full text-left px-3 py-2 text-sm hover:bg-neutral-100 + @apply w-full text-left px-3 py-2 text-sm hover:bg-neutral-100 dark:hover:bg-neutral-700/60 transition-colors duration-100 text-fg-default dark:text-dark-fg-default; } - + .form-dropdown-menu li button.selected { @apply text-primary dark:text-primary-light font-semibold; } - + /* Checkbox and Radio Styles */ .form-checkbox-standard, .form-radio-standard { @apply form-checkbox rounded text-primary focus:ring-primary focus:ring-2; } - + .form-radio-standard { @apply rounded-full; } - + /* Toggle/Switch Style */ .form-toggle { @apply relative inline-flex h-6 w-11 items-center rounded-full transition-colors - focus:outline-none focus:ring-2 focus:ring-primary focus:ring-offset-2 + focus:outline-hidden focus:ring-2 focus:ring-primary focus:ring-offset-2 dark:focus:ring-offset-dark-bg-default cursor-pointer; } - + .form-toggle.checked { @apply bg-primary; } - + .form-toggle:not(.checked) { @apply bg-neutral-200 dark:bg-neutral-600; } - + .form-toggle-handle { - @apply inline-block h-5 w-5 transform rounded-full bg-white transition-transform shadow-sm; + @apply inline-block h-5 w-5 transform rounded-full bg-white transition-transform shadow-xs; } - + .form-toggle.checked .form-toggle-handle { @apply translate-x-5; } - + .form-toggle:not(.checked) .form-toggle-handle { @apply translate-x-0; } - + /* Date Input Styles */ .form-input-date { - @apply form-input-standard; + @apply w-full px-3 py-1.5 text-sm border border-neutral-300 dark:border-dark-border-input + bg-white dark:bg-dark-bg-alt text-fg-default dark:text-dark-fg-default + rounded-md focus:outline-hidden focus:ring-2 focus:ring-primary focus:border-primary + hover:bg-neutral-50 dark:hover:bg-neutral-700 transition-colors; } - + /* Error State Styles */ .form-input-error { @apply border-red-500 dark:border-red-400 focus:ring-red-500 focus:border-red-500; } - + .form-error-message { @apply text-sm text-red-600 dark:text-red-400 mt-1; } - + /* Helper Text */ .form-helper-text { @apply text-sm text-fg-muted dark:text-dark-fg-muted mt-1; } - + /* Label with Required Indicator */ .form-label-required::after { content: " *"; @apply text-red-500; } -} \ No newline at end of file + + /* ========================================================================== + Editor Component Styles + ========================================================================== */ + + /* Bare input (no border/background) for inline editing */ + .form-input-bare { + @apply bg-transparent border-0 focus:ring-0 w-full text-sm font-medium + text-fg-default dark:text-dark-fg-default + placeholder-fg-muted dark:placeholder-dark-fg-muted; + } + + /* Output container for code execution results */ + .output-container { + @apply bg-bg-alt dark:bg-dark-bg-alt border border-border-default + dark:border-dark-border-default rounded-lg p-4 w-full + overflow-hidden shadow-xs; + } + + /* Preformatted output text */ + .output-pre { + @apply bg-bg-default dark:bg-dark-bg-default p-3 rounded border + border-border-default dark:border-dark-border-default text-xs + font-mono whitespace-pre-wrap break-words max-h-[40vh] overflow-auto; + padding-right: 3rem; /* Space for copy button */ + } + + /* Output scrollbar styling */ + .output-content, + .output-pre, + .custom-scrollbar { + scrollbar-width: thin; + scrollbar-color: #9ca3af #e5e7eb; /* neutral-400 neutral-200 */ + } + + .output-content::-webkit-scrollbar, + .output-pre::-webkit-scrollbar, + .custom-scrollbar::-webkit-scrollbar { + width: 6px; + height: 6px; + } + + .output-content::-webkit-scrollbar-track, + .output-pre::-webkit-scrollbar-track, + .custom-scrollbar::-webkit-scrollbar-track { + @apply bg-neutral-100 dark:bg-neutral-800 rounded; + margin-right: 2px; + } + + .output-content::-webkit-scrollbar-thumb, + .output-pre::-webkit-scrollbar-thumb, + .custom-scrollbar::-webkit-scrollbar-thumb { + @apply bg-neutral-300 dark:bg-neutral-600 rounded; + } + + .output-content::-webkit-scrollbar-thumb:hover, + .output-pre::-webkit-scrollbar-thumb:hover, + .custom-scrollbar::-webkit-scrollbar-thumb:hover { + @apply bg-neutral-400 dark:bg-neutral-500; + } + + /* Output section positioning */ + .output-section .relative { + overflow: visible; + } + + .output-section .group, + .relative .group { + z-index: 10; + } + + /* ========================================================================== + Prose/Typography Styles (Privacy, Terms, etc.) + ========================================================================== */ + + .prose-page h2 { + @apply mt-8 mb-4; + } + + .prose-page p { + @apply mb-4; + } + + .prose-page section { + @apply mb-6; + } + + /* ========================================================================== + Admin Component Styles + ========================================================================== */ + + /* Small input variant for admin tables */ + .input-sm { + @apply px-2 py-1 text-sm border border-gray-300 dark:border-gray-600 + rounded bg-white dark:bg-gray-700 text-fg-default dark:text-dark-fg-default; + } +} diff --git a/frontend/src/components/Footer.svelte b/frontend/src/components/Footer.svelte index 1b80de72..f71c0769 100644 --- a/frontend/src/components/Footer.svelte +++ b/frontend/src/components/Footer.svelte @@ -37,7 +37,7 @@ Tools & Info - Grafana - import { Link, navigate } from "svelte-routing"; - import { isAuthenticated, username, userRole, logout as authLogout, userEmail } from "../stores/auth.js"; - import { theme, toggleTheme } from "../stores/theme.js"; + - + - - + + Integr8sCode - + @@ -112,7 +105,7 @@ - + {#if $theme === 'light'} {@html sunIcon} {:else if $theme === 'dark'} @@ -127,8 +120,8 @@ - { e.stopPropagation(); showUserDropdown = !showUserDropdown; }} + { e.stopPropagation(); showUserDropdown = !showUserDropdown; }} class="flex items-center space-x-2 btn btn-ghost btn-sm" > @@ -141,12 +134,12 @@ {#if showUserDropdown} - - + {$username.charAt(0).toUpperCase()} @@ -167,24 +160,25 @@ {#if $userRole === 'admin'} { + onclick={() => { showUserDropdown = false; - navigate('/admin/events'); + goto('/admin/events'); }} class="btn btn-secondary-outline btn-sm flex-1" > Admin {/if} - showUserDropdown = false} + showUserDropdown = false} class="btn btn-secondary-outline btn-sm flex-1 text-center" > Settings - + Logout @@ -195,17 +189,17 @@ {/if} {:else} - + Login - - + + Register - + {/if} - + {@html isMenuActive ? closeIcon : menuIcon} @@ -231,23 +225,23 @@ {#if $userRole === 'admin'} - + {@html adminIcon} Admin Panel - + {/if} - + Settings - - + + {@html logoutIcon} Logout {:else} - + {@html loginIcon} Login - - + + {@html registerIcon} Register - + {/if} diff --git a/frontend/src/components/NotificationCenter.svelte b/frontend/src/components/NotificationCenter.svelte index 46b46ec1..5d5a64d5 100644 --- a/frontend/src/components/NotificationCenter.svelte +++ b/frontend/src/components/NotificationCenter.svelte @@ -1,23 +1,28 @@ - {#if !authReady} @@ -48,10 +58,10 @@ {:else if authorized} - + {@render children?.()} {:else} -{/if} \ No newline at end of file +{/if} diff --git a/frontend/src/components/Spinner.svelte b/frontend/src/components/Spinner.svelte index 84caefb9..81337b36 100644 --- a/frontend/src/components/Spinner.svelte +++ b/frontend/src/components/Spinner.svelte @@ -1,45 +1,47 @@ - - - - - \ No newline at end of file + diff --git a/frontend/src/components/Notifications.svelte b/frontend/src/components/ToastContainer.svelte similarity index 67% rename from frontend/src/components/Notifications.svelte rename to frontend/src/components/ToastContainer.svelte index 40458e9d..677f338f 100644 --- a/frontend/src/components/Notifications.svelte +++ b/frontend/src/components/ToastContainer.svelte @@ -1,6 +1,6 @@ - - - {#each $notifications as notification (notification.id)} + + {#each toastList as toast (toast.id)} 1 - Math.pow(1 - t, 3) }} out:fly={{ x: 100, opacity: 0, duration: 200, easing: (t) => t * t }} - on:mouseenter={() => clearTimer(notification)} - on:mouseleave={() => startTimer(notification)} + onmouseenter={() => clearTimer(toast)} + onmouseleave={() => startTimer(toast)} > - - {#if notification.type === 'success'} {@html checkCircleIcon} - {:else if notification.type === 'error'} {@html errorIcon} - {:else if notification.type === 'warning'} {@html warningIcon} + + {#if toast.type === 'success'} {@html checkCircleIcon} + {:else if toast.type === 'error'} {@html errorIcon} + {:else if toast.type === 'warning'} {@html warningIcon} {:else} {@html infoIcon} {/if} - {notification.message} + {toast.message} { clearTimer(notification); removeNotification(notification.id); }} - aria-label="Close notification" + class={getButtonClasses(toast.type)} + onclick={() => { clearTimer(toast); removeToast(toast.id); }} + aria-label="Close toast" > {@html closeIcon} - {#if notification.progress > 0} + {#if toast.progress > 0} {/if} @@ -148,7 +152,7 @@ diff --git a/frontend/src/routes/Home.svelte b/frontend/src/routes/Home.svelte index 87892189..dfc8dbe0 100644 --- a/frontend/src/routes/Home.svelte +++ b/frontend/src/routes/Home.svelte @@ -1,8 +1,8 @@ - @@ -247,7 +274,7 @@ {count} - + {@html info.icon} @@ -270,12 +297,13 @@ {#if autoRefresh} - Every: + Every: @@ -288,7 +316,7 @@ {/if} @@ -308,27 +336,29 @@ - Search + Search - + - State + State @@ -338,29 +368,30 @@ {/each} - + - Execution ID + Execution ID - Actions + Actions @@ -433,13 +464,13 @@ loadExecutionSagas(saga.execution_id)} + onclick={() => loadExecutionSagas(saga.execution_id)} class="flex-1 text-xs py-1.5 px-2 rounded border border-border-default dark:border-dark-border-default text-primary hover:bg-primary hover:text-white transition-colors" > Execution loadSagaDetails(saga.saga_id)} + onclick={() => loadSagaDetails(saga.saga_id)} class="flex-1 text-xs py-1.5 px-2 rounded bg-primary text-white hover:bg-primary-dark transition-colors" > View Details @@ -472,7 +503,7 @@ ID: {saga.saga_id.slice(0, 8)}... loadExecutionSagas(saga.execution_id)} + onclick={() => loadExecutionSagas(saga.execution_id)} class="text-xs text-primary hover:text-primary-dark" > Execution: {saga.execution_id.slice(0, 8)}... @@ -517,7 +548,7 @@ loadSagaDetails(saga.saga_id)} + onclick={() => loadSagaDetails(saga.saga_id)} class="text-primary hover:text-primary-dark" > View Details @@ -537,11 +568,12 @@ - Show: + Show: { currentPage = 1; loadSagas(); }} - class="px-3 py-1.5 pr-8 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-sm focus:outline-none focus:ring-2 focus:ring-blue-500 focus:border-blue-500 appearance-none cursor-pointer" + onchange={() => { currentPage = 1; loadSagas(); }} + class="px-3 py-1.5 pr-8 rounded-lg border border-gray-300 dark:border-gray-600 bg-white dark:bg-gray-800 text-gray-900 dark:text-gray-100 text-sm focus:outline-hidden focus:ring-2 focus:ring-blue-500 focus:border-blue-500 appearance-none cursor-pointer" style="background-image: url('data:image/svg+xml;utf8,'); background-repeat: no-repeat; background-position: right 0.5rem center; background-size: 16px;" > 10 @@ -557,7 +589,7 @@ { currentPage = 1; loadSagas(); }} + onclick={() => { currentPage = 1; loadSagas(); }} disabled={currentPage === 1} class="pagination-button" title="First page" @@ -569,7 +601,7 @@ { currentPage--; loadSagas(); }} + onclick={() => { currentPage--; loadSagas(); }} disabled={currentPage === 1} class="pagination-button" title="Previous page" @@ -588,7 +620,7 @@ { currentPage++; loadSagas(); }} + onclick={() => { currentPage++; loadSagas(); }} disabled={currentPage === totalPages} class="pagination-button" title="Next page" @@ -600,7 +632,7 @@ { currentPage = totalPages; loadSagas(); }} + onclick={() => { currentPage = totalPages; loadSagas(); }} disabled={currentPage === totalPages} class="pagination-button" title="Last page" @@ -627,12 +659,12 @@ {#if showDetailModal && selectedSaga} - + Saga Details showDetailModal = false} + onclick={() => showDetailModal = false} class="text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 text-2xl leading-none" > × @@ -657,7 +689,7 @@ Execution ID { + onclick={() => { showDetailModal = false; loadExecutionSagas(selectedSaga.execution_id); }} diff --git a/frontend/src/routes/admin/AdminSettings.svelte b/frontend/src/routes/admin/AdminSettings.svelte index aef30829..928f01fe 100644 --- a/frontend/src/routes/admin/AdminSettings.svelte +++ b/frontend/src/routes/admin/AdminSettings.svelte @@ -1,58 +1,74 @@ - @@ -488,7 +540,7 @@ @@ -498,7 +550,7 @@ @@ -520,10 +572,11 @@ - + Search - + - + Role - + All Roles User Admin - + - + Status - + All Status Active Disabled @@ -561,7 +614,7 @@ showAdvancedFilters = !showAdvancedFilters} + onclick={() => showAdvancedFilters = !showAdvancedFilters} class="btn btn-outline flex items-center gap-2 w-full sm:w-auto justify-center" > @@ -572,7 +625,7 @@ Rate Limit Filters - + Bypass Rate Limit - + All Yes (Bypassed) No (Limited) - + - + Custom Limits - + All Has Custom Default Only - + - + Global Multiplier - + All Custom (≠ 1.0) Default (= 1.0) @@ -670,7 +723,7 @@ openEditUserModal(user)} + onclick={() => openEditUserModal(user)} class="flex-1 btn btn-sm btn-outline flex items-center justify-center gap-1" > @@ -680,7 +733,7 @@ openRateLimitModal(user)} + onclick={() => openRateLimitModal(user)} class="flex-1 btn btn-sm btn-outline flex items-center justify-center gap-1" > @@ -690,7 +743,7 @@ { + onclick={() => { userToDelete = user; showDeleteModal = true; }} @@ -744,7 +797,7 @@ openEditUserModal(user)} + onclick={() => openEditUserModal(user)} class="text-green-600 hover:text-green-800 dark:text-green-400 dark:hover:text-green-300" title="Edit User" > @@ -754,7 +807,7 @@ openRateLimitModal(user)} + onclick={() => openRateLimitModal(user)} class="text-blue-600 hover:text-blue-800 dark:text-blue-400 dark:hover:text-blue-300" title="Manage Rate Limits" > @@ -763,7 +816,7 @@ { + onclick={() => { userToDelete = user; showDeleteModal = true; }} @@ -791,7 +844,7 @@ changePage(currentPage - 1)} + onclick={() => changePage(currentPage - 1)} disabled={currentPage === 1} class="px-3 py-1 rounded border border-border-default dark:border-dark-border-default hover:bg-gray-50 dark:hover:bg-gray-800 disabled:opacity-50 disabled:cursor-not-allowed @@ -807,7 +860,7 @@ changePage(currentPage + 1)} + onclick={() => changePage(currentPage + 1)} disabled={currentPage === totalPages} class="px-3 py-1 rounded border border-border-default dark:border-dark-border-default hover:bg-gray-50 dark:hover:bg-gray-800 disabled:opacity-50 disabled:cursor-not-allowed @@ -819,11 +872,12 @@ - Show: + Show: currentPage = 1} - class="text-sm px-2 py-1 rounded border border-border-default dark:border-dark-border-default + onchange={() => currentPage = 1} + class="text-sm px-2 py-1 rounded border border-border-default dark:border-dark-border-default bg-bg-default dark:bg-dark-bg-default text-fg-default dark:text-dark-fg-default" > 5 @@ -847,7 +901,7 @@ {#if showDeleteModal && userToDelete} - + Delete User @@ -880,7 +934,7 @@ { + onclick={() => { showDeleteModal = false; userToDelete = null; }} @@ -890,7 +944,7 @@ Cancel @@ -908,7 +962,7 @@ {#if showRateLimitModal && rateLimitUser} - + Rate Limits for {rateLimitUser.username} @@ -940,10 +994,11 @@ - + Global Multiplier - + Admin Notes + > @@ -976,7 +1032,7 @@ Endpoint Rate Limits addNewRule()} + onclick={() => addNewRule()} class="btn btn-sm btn-primary flex items-center gap-1" disabled={rateLimitConfig.bypass_rate_limit} > @@ -1039,7 +1095,7 @@ handleEndpointChange(rule)} + oninput={() => handleEndpointChange(rule)} placeholder="Endpoint pattern (e.g., /api/v1/auth/verify)" class="input input-sm w-full" disabled={rateLimitConfig.bypass_rate_limit} @@ -1108,7 +1164,7 @@ removeRule(index)} + onclick={() => removeRule(index)} class="text-red-600 hover:text-red-800 dark:text-red-400 dark:hover:text-red-300 p-1" disabled={rateLimitConfig.bypass_rate_limit} title="Remove rule" @@ -1133,7 +1189,7 @@ Current Usage Reset All Counters @@ -1160,7 +1216,7 @@ { + onclick={() => { showRateLimitModal = false; rateLimitUser = null; rateLimitConfig = null; @@ -1171,7 +1227,7 @@ Cancel @@ -1189,19 +1245,20 @@ {#if showUserModal} - + {editingUser ? 'Edit User' : 'Create New User'} - + { e.preventDefault(); saveUser(); }}> - + Username * - + - + Email - + - + Password {!editingUser ? '* ' : ''} {#if editingUser} (leave empty to keep current) {/if} - + - + Role - + User Admin @@ -1279,7 +1338,7 @@ showUserModal = false} + onclick={() => showUserModal = false} class="btn btn-outline" disabled={savingUser} > @@ -1302,22 +1361,4 @@ {/if} - - - + \ No newline at end of file diff --git a/frontend/src/stores/auth.js b/frontend/src/stores/auth.js deleted file mode 100644 index 9cf1ddab..00000000 --- a/frontend/src/stores/auth.js +++ /dev/null @@ -1,339 +0,0 @@ -import { writable, get } from 'svelte/store'; -import { backendUrl } from "../config.js"; -import { fetchWithRetry } from "../lib/fetch-utils.js"; -import { clearSettingsCache } from "../lib/auth-utils.js"; - -// Helper to get persisted auth state from localStorage -function getPersistedAuthState() { - if (typeof window === 'undefined') return null; - - try { - const authData = localStorage.getItem('authState'); - if (!authData) return null; - - const parsed = JSON.parse(authData); - // Check if auth data is still fresh (24 hours) - if (Date.now() - parsed.timestamp > 24 * 60 * 60 * 1000) { - localStorage.removeItem('authState'); - return null; - } - - return parsed; - } catch (e) { - console.error('Failed to parse persisted auth state:', e); - return null; - } -} - -// Initialize stores with persisted state or null (unknown state) -const persistedState = getPersistedAuthState(); -export const isAuthenticated = writable(persistedState ? persistedState.isAuthenticated : null); -export const username = writable(persistedState ? persistedState.username : null); -export const userId = writable(persistedState ? persistedState.userId : null); -export const userRole = writable(persistedState ? persistedState.userRole : null); -export const userEmail = writable(persistedState ? persistedState.userEmail : null); -export const csrfToken = writable(persistedState ? persistedState.csrfToken : null); - -// Helper to persist auth state to localStorage -function persistAuthState(authenticated, user, email, role, id, csrf) { - if (typeof window === 'undefined') return; - - try { - if (authenticated) { - const authData = { - isAuthenticated: authenticated, - username: user, - userId: id, - userRole: role, - userEmail: email, - csrfToken: csrf, - timestamp: Date.now() - }; - localStorage.setItem('authState', JSON.stringify(authData)); - } else { - localStorage.removeItem('authState'); - } - } catch (e) { - console.error('Failed to persist auth state:', e); - } -} - -// Cache for auth verification -let authCache = { - valid: null, - timestamp: 0 -}; -const AUTH_CACHE_DURATION = 30000; // 30 seconds - -// Deduplication for concurrent requests -let verifyAuthPromise = null; - -export async function login(usernameValue, password) { - try { - const formData = new URLSearchParams(); - formData.append('username', usernameValue); - formData.append('password', password); - - const response = await fetchWithRetry(`/api/v1/auth/login`, { - method: 'POST', - headers: { - 'Content-Type': 'application/x-www-form-urlencoded', - }, - body: formData - }, { - numOfAttempts: 3, - maxDelay: 5000 - }); - - if (!response.ok) { - const errorData = await response.json(); - throw new Error(errorData.detail || 'Login failed'); - } - - const data = await response.json(); - // Token is now stored in httpOnly cookie, just update auth state - isAuthenticated.set(true); - username.set(data.username || usernameValue); - userRole.set(data.role || 'user'); - csrfToken.set(data.csrf_token); - - // Clear detailed user info until fetched from /me endpoint - userId.set(null); - userEmail.set(null); - - // Persist minimal auth state to localStorage - persistAuthState( - true, - data.username || usernameValue, - null, // email will be fetched separately - data.role || 'user', - null, // user_id will be fetched separately - data.csrf_token - ); - - // Fetch detailed user profile after successful login - try { - await fetchUserProfile(); - } catch (e) { - console.warn('Failed to fetch user profile after login:', e); - // Continue anyway - basic auth is successful - } - - // Invalidate cache on login - authCache = { - valid: true, - timestamp: Date.now() - }; - - return true; - } catch (error) { - console.error("Login failed:", error); - throw error; - } -} - -export async function fetchUserProfile() { - try { - const response = await fetchWithRetry('/api/v1/auth/me', { - method: 'GET' - }, { - numOfAttempts: 2, - maxDelay: 3000 - }); - - if (!response.ok) { - throw new Error('Failed to fetch user profile'); - } - - const data = await response.json(); - - // Update stores with detailed user info - userId.set(data.user_id); - userEmail.set(data.email); - - // Update persisted state - const currentState = getPersistedAuthState(); - if (currentState) { - persistAuthState( - currentState.isAuthenticated, - currentState.username, - data.email, - currentState.userRole, - data.user_id, - currentState.csrfToken - ); - } - - return data; - } catch (error) { - console.error("Failed to fetch user profile:", error); - throw error; - } -} - -export async function logout() { - try { - const response = await fetchWithRetry('/api/v1/auth/logout', { - method: 'POST' - }, { - numOfAttempts: 2, - maxDelay: 3000 - }); - - // Clear auth state regardless of response (cookie might be expired) - isAuthenticated.set(false); - username.set(null); - userId.set(null); - userRole.set(null); - userEmail.set(null); - csrfToken.set(null); - - // Clear persisted auth state - persistAuthState(false); - - // Clear settings cache - clearSettingsCache(); - - // Invalidate cache on logout - authCache = { - valid: false, - timestamp: Date.now() - }; - - if (!response.ok) { - console.warn('Logout request failed, but cleared local auth state'); - } - } catch (error) { - console.error('Logout error:', error); - isAuthenticated.set(false); - username.set(null); - userId.set(null); - userRole.set(null); - userEmail.set(null); - csrfToken.set(null); - - // Clear persisted auth state - persistAuthState(false); - - // Clear settings cache - clearSettingsCache(); - } -} - -export async function verifyAuth(forceRefresh = false) { - // Return cached result if still valid - if (!forceRefresh && authCache.valid !== null && Date.now() - authCache.timestamp < AUTH_CACHE_DURATION) { - return authCache.valid; - } - - // If there's already a verification in progress, return the same promise - if (verifyAuthPromise) { - return verifyAuthPromise; - } - - // Create new verification promise - verifyAuthPromise = (async () => { - try { - console.log('[verifyAuth] Starting token verification...'); - const response = await fetchWithRetry('/api/v1/auth/verify-token', { - method: 'GET' - }, { - numOfAttempts: 1, // Don't retry for auth verification - maxDelay: 1000, - timeout: 5000 // 5 second timeout - }); - console.log('[verifyAuth] Got response:', response.status); - - if (response.ok) { - const data = await response.json(); - isAuthenticated.set(data.valid); - username.set(data.username); - userRole.set(data.role || 'user'); - csrfToken.set(data.csrf_token); - - // Clear detailed info until fetched - userId.set(null); - userEmail.set(null); - - // Persist minimal auth state if valid - if (data.valid) { - persistAuthState( - true, - data.username, - null, // email will be fetched separately - data.role || 'user', - null, // user_id will be fetched separately - data.csrf_token - ); - - // Fetch detailed user profile - try { - await fetchUserProfile(); - } catch (e) { - console.warn('Failed to fetch user profile during verification:', e); - // Continue anyway - basic auth is valid - } - } - - // Update cache - authCache = { - valid: data.valid, - timestamp: Date.now() - }; - - return data.valid; - } else if (response.status === 401) { - // Not authenticated - this is expected for non-logged-in users - isAuthenticated.set(false); - username.set(null); - userId.set(null); - userRole.set(null); - userEmail.set(null); - csrfToken.set(null); - - // Clear persisted auth state - persistAuthState(false); - - // Update cache - authCache = { - valid: false, - timestamp: Date.now() - }; - - return false; - } else { - // Other error - don't cache this - console.error('Token verification error:', response.status); - isAuthenticated.set(false); - username.set(null); - userId.set(null); - userRole.set(null); - userEmail.set(null); - csrfToken.set(null); - return false; - } - } catch (error) { - // Network error or other issue - don't cache this - console.error('Auth verification failed:', error); - - // If we have a cached value and network failed, use cached value - if (authCache.valid !== null) { - console.log('Using cached auth state due to network error'); - return authCache.valid; - } - - isAuthenticated.set(false); - username.set(null); - userId.set(null); - userRole.set(null); - userEmail.set(null); - csrfToken.set(null); - return false; - } finally { - // Clear the promise so future calls create a new one - verifyAuthPromise = null; - } - })(); - - return verifyAuthPromise; -} \ No newline at end of file diff --git a/frontend/src/stores/auth.ts b/frontend/src/stores/auth.ts new file mode 100644 index 00000000..d456d0a9 --- /dev/null +++ b/frontend/src/stores/auth.ts @@ -0,0 +1,174 @@ +import { writable, get } from 'svelte/store'; +import { + loginApiV1AuthLoginPost, + logoutApiV1AuthLogoutPost, + verifyTokenApiV1AuthVerifyTokenGet, + getCurrentUserProfileApiV1AuthMeGet, +} from '../lib/api'; + +interface AuthState { + isAuthenticated: boolean | null; + username: string | null; + userId: string | null; + userRole: string | null; + userEmail: string | null; + csrfToken: string | null; + timestamp: number; +} + +function getPersistedAuthState(): AuthState | null { + if (typeof window === 'undefined') return null; + try { + const data = localStorage.getItem('authState'); + if (!data) return null; + const parsed = JSON.parse(data) as AuthState; + if (Date.now() - parsed.timestamp > 24 * 60 * 60 * 1000) { + localStorage.removeItem('authState'); + return null; + } + return parsed; + } catch { return null; } +} + +function persistAuthState(state: Partial | null) { + if (typeof window === 'undefined') return; + if (!state || state.isAuthenticated === false) { + localStorage.removeItem('authState'); + return; + } + localStorage.setItem('authState', JSON.stringify({ ...state, timestamp: Date.now() })); +} + +const persisted = getPersistedAuthState(); +export const isAuthenticated = writable(persisted?.isAuthenticated ?? null); +export const username = writable(persisted?.username ?? null); +export const userId = writable(persisted?.userId ?? null); +export const userRole = writable(persisted?.userRole ?? null); +export const userEmail = writable(persisted?.userEmail ?? null); +export const csrfToken = writable(persisted?.csrfToken ?? null); + +let authCache: { valid: boolean | null; timestamp: number } = { valid: null, timestamp: 0 }; +const AUTH_CACHE_DURATION = 30000; +let verifyPromise: Promise | null = null; + +function clearAuth() { + isAuthenticated.set(false); + username.set(null); + userId.set(null); + userRole.set(null); + userEmail.set(null); + csrfToken.set(null); + persistAuthState(null); +} + +export async function login(user: string, password: string): Promise { + const { data, error } = await loginApiV1AuthLoginPost({ + body: { username: user, password, scope: '' } + }); + if (error || !data) throw error ?? new Error('Login failed'); + + isAuthenticated.set(true); + username.set(data.username ?? user); + userRole.set(data.role ?? 'user'); + csrfToken.set(data.csrf_token ?? null); + userId.set(null); + userEmail.set(null); + + persistAuthState({ + isAuthenticated: true, + username: data.username ?? user, + userRole: data.role ?? 'user', + csrfToken: data.csrf_token ?? null, + userId: null, + userEmail: null + }); + + authCache = { valid: true, timestamp: Date.now() }; + try { + await fetchUserProfile(); + } catch (err) { + console.warn('Failed to fetch user profile after login:', err); + } + return true; +} + +export async function fetchUserProfile() { + const { data, error } = await getCurrentUserProfileApiV1AuthMeGet({}); + if (error || !data) throw error ?? new Error('Failed to fetch profile'); + userId.set(data.user_id); + userEmail.set(data.email ?? null); + const current = getPersistedAuthState(); + if (current) persistAuthState({ ...current, userId: data.user_id, userEmail: data.email ?? null }); + return data; +} + +export async function logout(): Promise { + try { + await logoutApiV1AuthLogoutPost({}); + } catch (err) { + console.error('Logout API call failed:', err); + } finally { + clearAuth(); + authCache = { valid: false, timestamp: Date.now() }; + } +} + +/** + * Verifies the current authentication state with the server. + * + * OFFLINE-FIRST BEHAVIOR: On network failure, this function returns the cached + * auth state (if available) rather than immediately logging the user out. + * This provides better UX during transient network issues but means: + * - Server-revoked tokens may remain "valid" locally for up to AUTH_CACHE_DURATION (30s) + * - Security-critical operations should use forceRefresh=true + * + * Trade-off: We prioritize availability over immediate consistency for better + * offline/flaky-network UX. The 30-second cache window is acceptable for most + * UI operations; sensitive actions should force re-verification. + */ +export async function verifyAuth(forceRefresh = false): Promise { + if (!forceRefresh && authCache.valid !== null && Date.now() - authCache.timestamp < AUTH_CACHE_DURATION) { + return authCache.valid; + } + if (verifyPromise) return verifyPromise; + + verifyPromise = (async () => { + try { + const { data, error } = await verifyTokenApiV1AuthVerifyTokenGet({}); + if (error || !data?.valid) { + clearAuth(); + authCache = { valid: false, timestamp: Date.now() }; + return false; + } + isAuthenticated.set(true); + username.set(data.username ?? null); + userRole.set(data.role ?? 'user'); + csrfToken.set(data.csrf_token ?? null); + persistAuthState({ + isAuthenticated: true, + username: data.username ?? null, + userRole: data.role ?? 'user', + csrfToken: data.csrf_token ?? null, + userId: null, + userEmail: null + }); + authCache = { valid: true, timestamp: Date.now() }; + try { + await fetchUserProfile(); + } catch (err) { + console.warn('Failed to fetch user profile during verification:', err); + } + return true; + } catch (err) { + // Network error - use cached state if available (offline-first) + // See function docstring for security trade-off explanation + console.warn('Auth verification failed (network error):', err); + if (authCache.valid !== null) return authCache.valid; + clearAuth(); + return false; + } finally { + verifyPromise = null; + } + })(); + return verifyPromise; +} diff --git a/frontend/src/stores/executions.js b/frontend/src/stores/executions.js deleted file mode 100644 index 5a3232e8..00000000 --- a/frontend/src/stores/executions.js +++ /dev/null @@ -1,369 +0,0 @@ -import { writable, derived, get } from 'svelte/store'; -import { EventStreamClient, createExecutionEventStream } from '../lib/eventStreamClient.js'; -import { api } from '../lib/api.js'; - -// Store for all executions -export const executions = writable({}); - -// Store for active EventStream connections -const eventStreams = new Map(); - -// Store for connection states -export const connectionStates = writable({}); - -// Store for real-time logs -export const executionLogs = writable({}); - -// Derived store for execution list as array -export const executionList = derived( - executions, - $executions => Object.values($executions).sort((a, b) => - new Date(b.created_at || b.timestamp) - new Date(a.created_at || a.timestamp) - ) -); - -// Derived store for active executions -export const activeExecutions = derived( - executions, - $executions => Object.values($executions).filter( - exec => ['queued', 'running'].includes(exec.status) - ) -); - -// Derived store for completed executions -export const completedExecutions = derived( - executions, - $executions => Object.values($executions).filter( - exec => ['completed', 'failed', 'error'].includes(exec.status) - ) -); - -/** - * Add or update an execution in the store - */ -export function updateExecution(executionId, executionData) { - executions.update(execs => ({ - ...execs, - [executionId]: { - ...execs[executionId], - ...executionData, - execution_id: executionId, - lastUpdated: new Date().toISOString() - } - })); -} - -/** - * Remove an execution from the store - */ -export function removeExecution(executionId) { - // Close any active event stream - disconnectFromExecution(executionId); - - // Remove from stores - executions.update(execs => { - const { [executionId]: removed, ...rest } = execs; - return rest; - }); - - executionLogs.update(logs => { - const { [executionId]: removed, ...rest } = logs; - return rest; - }); - - connectionStates.update(states => { - const { [executionId]: removed, ...rest } = states; - return rest; - }); -} - -/** - * Clear all executions - */ -export function clearExecutions() { - // Close all event streams - eventStreams.forEach((stream, executionId) => { - stream.close(); - }); - eventStreams.clear(); - - // Clear stores - executions.set({}); - executionLogs.set({}); - connectionStates.set({}); -} - -/** - * Connect to real-time updates for an execution - */ -export function connectToExecution(executionId) { - // Don't connect if already connected - if (eventStreams.has(executionId)) { - console.log(`Already connected to execution ${executionId}`); - return; - } - - // Update connection state - connectionStates.update(states => ({ - ...states, - [executionId]: 'connecting' - })); - - // Create event stream - const stream = createExecutionEventStream(executionId, { - onOpen: () => { - console.log(`Connected to execution ${executionId}`); - connectionStates.update(states => ({ - ...states, - [executionId]: 'connected' - })); - }, - - onError: (error) => { - console.error(`Error in execution stream ${executionId}:`, error); - connectionStates.update(states => ({ - ...states, - [executionId]: 'error' - })); - }, - - onClose: () => { - console.log(`Disconnected from execution ${executionId}`); - connectionStates.update(states => ({ - ...states, - [executionId]: 'disconnected' - })); - eventStreams.delete(executionId); - }, - - onReconnect: (attempt) => { - console.log(`Reconnecting to execution ${executionId} (attempt ${attempt})`); - connectionStates.update(states => ({ - ...states, - [executionId]: 'reconnecting' - })); - }, - - onConnected: (event) => { - const data = JSON.parse(event.data); - console.log(`Execution ${executionId} connected:`, data); - }, - - onStatus: (event) => { - const data = JSON.parse(event.data); - console.log(`Execution ${executionId} status update:`, data); - - updateExecution(executionId, { - status: data.status, - timestamp: data.timestamp - }); - }, - - onLog: (event) => { - const data = JSON.parse(event.data); - console.log(`Execution ${executionId} log:`, data); - - // Append log to execution logs - executionLogs.update(logs => ({ - ...logs, - [executionId]: [ - ...(logs[executionId] || []), - { - type: data.type || 'output', - content: data.content, - timestamp: data.timestamp || new Date().toISOString() - } - ] - })); - }, - - onComplete: (event) => { - const data = JSON.parse(event.data); - console.log(`Execution ${executionId} completed:`, data); - - updateExecution(executionId, { - status: data.status || 'completed', - completedAt: data.timestamp, - // Don't set output/errors here - wait for fetchExecution to get the real data - needsFetch: true - }); - - // Auto-disconnect after completion - setTimeout(() => { - disconnectFromExecution(executionId); - }, 10000); - } - }); - - // Store the stream - eventStreams.set(executionId, stream); - - // Connect - stream.connect(); -} - -/** - * Disconnect from real-time updates for an execution - */ -export function disconnectFromExecution(executionId) { - const stream = eventStreams.get(executionId); - if (stream) { - stream.close(); - eventStreams.delete(executionId); - } -} - -/** - * Fetch execution details from API - */ -export async function fetchExecution(executionId) { - try { - const data = await api.get(`/api/v1/result/${executionId}`); - - // The backend already parsed the executor JSON and stored the actual values - // We just need to use them directly - updateExecution(executionId, { - status: data.status, - output: data.output || '', - errors: data.errors || '', - exitCode: data.exit_code, - errorType: data.error_type, - executionTime: data.execution_time, - resourceUsage: data.resource_usage, - needsFetch: false - }); - - return data; - } catch (error) { - console.error(`Error fetching execution ${executionId}:`, error); - throw error; - } -} - -/** - * Create a new execution - */ -export async function createExecution(script, language, languageVersion) { - // Check if authenticated - const { isAuthenticated } = await import('./auth.js'); - const { get } = await import('svelte/store'); - - if (!get(isAuthenticated)) { - throw new Error('Not authenticated. Please login first.'); - } - - try { - const data = await api.post('/api/v1/execute', { - script, - lang: language, - lang_version: languageVersion - }); - - const executionId = data.execution_id; - - // Add to store - updateExecution(executionId, { - status: data.status || 'queued', - script, - language, - languageVersion, - createdAt: new Date().toISOString() - }); - - // Connect to real-time updates - connectToExecution(executionId); - - return executionId; - } catch (error) { - console.error('Error creating execution:', error); - throw error; - } -} - -/** - * Fetch user's recent executions - */ -export async function fetchRecentExecutions(limit = 10) { - try { - const data = await api.get(`/api/v1/events/user?limit=${limit}`); - - // Process events to extract execution information - const executionMap = {}; - - data.events.forEach(event => { - const execId = event.aggregate_id || event.payload?.execution_id; - if (!execId) return; - - if (!executionMap[execId]) { - executionMap[execId] = { - execution_id: execId, - status: 'unknown', - createdAt: event.timestamp, - events: [] - }; - } - - executionMap[execId].events.push(event); - - // Update execution based on event type - if (event.event_type === 'execution.queued') { - executionMap[execId].script = event.payload.script; - executionMap[execId].language = event.payload.language; - executionMap[execId].languageVersion = event.payload.language_version; - executionMap[execId].status = 'queued'; - } else if (event.event_type === 'execution.started') { - executionMap[execId].status = 'running'; - executionMap[execId].startedAt = event.timestamp; - } else if (event.event_type === 'execution.completed') { - executionMap[execId].status = 'completed'; - executionMap[execId].completedAt = event.timestamp; - } else if (event.event_type === 'execution.failed') { - executionMap[execId].status = 'failed'; - executionMap[execId].completedAt = event.timestamp; - } - }); - - // Update store with fetched executions - Object.values(executionMap).forEach(exec => { - updateExecution(exec.execution_id, exec); - }); - - return Object.values(executionMap); - } catch (error) { - console.error('Error fetching recent executions:', error); - throw error; - } -} - -/** - * Get execution state helper - */ -export function getExecutionState(executionId) { - const $executions = get(executions); - const $connectionStates = get(connectionStates); - const $executionLogs = get(executionLogs); - - return { - execution: $executions[executionId], - connectionState: $connectionStates[executionId] || 'disconnected', - logs: $executionLogs[executionId] || [] - }; -} - -/** - * Subscribe to execution updates - */ -export function subscribeToExecution(executionId, callback) { - // Auto-connect if not connected - if (!eventStreams.has(executionId)) { - connectToExecution(executionId); - } - - // Return unsubscribe function - return executions.subscribe($executions => { - const execution = $executions[executionId]; - if (execution) { - callback(execution); - } - }); -} \ No newline at end of file diff --git a/frontend/src/stores/notificationStore.js b/frontend/src/stores/notificationStore.js deleted file mode 100644 index 9e187e26..00000000 --- a/frontend/src/stores/notificationStore.js +++ /dev/null @@ -1,134 +0,0 @@ -import { writable, derived } from 'svelte/store'; -import { api } from '../lib/api'; - -// Create the main notification store -function createNotificationStore() { - const { subscribe, set, update } = writable({ - notifications: [], - loading: false, - error: null - }); - - return { - subscribe, - - // Load notifications from API - async load(limit = 20, options = {}) { - update(state => ({ ...state, loading: true, error: null })); - try { - const params = new URLSearchParams({ limit: String(limit) }); - if (options.include_tags && Array.isArray(options.include_tags)) { - for (const t of options.include_tags.filter(Boolean)) params.append('include_tags', t); - } - if (options.exclude_tags && Array.isArray(options.exclude_tags)) { - for (const t of options.exclude_tags.filter(Boolean)) params.append('exclude_tags', t); - } - if (options.tag_prefix) params.append('tag_prefix', options.tag_prefix); - const qs = params.toString(); - const response = await api.get(`/api/v1/notifications?${qs}`); - set({ - notifications: response.notifications || [], - loading: false, - error: null - }); - return response.notifications || []; - } catch (error) { - update(state => ({ - ...state, - loading: false, - error: error.message - })); - console.error('Failed to load notifications:', error); - return []; - } - }, - - // Add a new notification - add(notification) { - update(state => ({ - ...state, - notifications: [notification, ...state.notifications].slice(0, 100) - })); - }, - - // Mark notification as read - async markAsRead(notificationId) { - try { - await api.put(`/api/v1/notifications/${notificationId}/read`); - update(state => ({ - ...state, - notifications: state.notifications.map(n => - n.notification_id === notificationId - ? { ...n, status: 'read', read_at: new Date().toISOString() } - : n - ) - })); - return true; - } catch (error) { - console.error('Failed to mark notification as read:', error); - return false; - } - }, - - // Mark all notifications as read - async markAllAsRead() { - try { - await api.post('/api/v1/notifications/mark-all-read'); - update(state => ({ - ...state, - notifications: state.notifications.map(n => ({ - ...n, - status: 'read', - read_at: new Date().toISOString() - })) - })); - return true; - } catch (error) { - console.error('Failed to mark all as read:', error); - return false; - } - }, - - // Delete a notification - async delete(notificationId) { - try { - await api.delete(`/api/v1/notifications/${notificationId}`); - update(state => ({ - ...state, - notifications: state.notifications.filter(n => n.notification_id !== notificationId) - })); - return true; - } catch (error) { - console.error('Failed to delete notification:', error); - return false; - } - }, - - // Clear all notifications from store (not from backend) - clear() { - update(state => ({ ...state, notifications: [] })); - }, - - // Refresh notifications from backend - async refresh() { - return this.load(); - } - }; -} - -// Create the store instance -export const notificationStore = createNotificationStore(); - -// Derived store for unread count -export const unreadCount = derived( - notificationStore, - $notificationStore => $notificationStore.notifications.filter( - n => n.status !== 'read' - ).length -); - -// Derived store for just the notifications array -export const notifications = derived( - notificationStore, - $notificationStore => $notificationStore.notifications -); diff --git a/frontend/src/stores/notificationStore.ts b/frontend/src/stores/notificationStore.ts new file mode 100644 index 00000000..657ede67 --- /dev/null +++ b/frontend/src/stores/notificationStore.ts @@ -0,0 +1,101 @@ +import { writable, derived } from 'svelte/store'; +import { + getNotificationsApiV1NotificationsGet, + markNotificationReadApiV1NotificationsNotificationIdReadPut, + markAllReadApiV1NotificationsMarkAllReadPost, + deleteNotificationApiV1NotificationsNotificationIdDelete, + type NotificationResponse, +} from '../lib/api'; + +interface State { + notifications: NotificationResponse[]; + loading: boolean; + error: string | null; +} + +function createNotificationStore() { + const { subscribe, set, update } = writable({ + notifications: [], + loading: false, + error: null + }); + + return { + subscribe, + + async load(limit = 20, options: { include_tags?: string[]; exclude_tags?: string[]; tag_prefix?: string } = {}) { + update(s => ({ ...s, loading: true, error: null })); + const { data, error } = await getNotificationsApiV1NotificationsGet({ + query: { + limit, + include_tags: options.include_tags?.filter(Boolean), + exclude_tags: options.exclude_tags?.filter(Boolean), + tag_prefix: options.tag_prefix + } + }); + if (error) { + const msg = (error as { detail?: Array<{ msg?: string }> }).detail?.[0]?.msg + ?? JSON.stringify(error); + update(s => ({ ...s, loading: false, error: msg })); + return []; + } + set({ notifications: data?.notifications ?? [], loading: false, error: null }); + return data?.notifications ?? []; + }, + + add(notification: NotificationResponse) { + update(s => ({ + ...s, + notifications: [notification, ...s.notifications].slice(0, 100) + })); + }, + + async markAsRead(notificationId: string) { + const { error } = await markNotificationReadApiV1NotificationsNotificationIdReadPut({ + path: { notification_id: notificationId } + }); + if (error) return false; + update(s => ({ + ...s, + notifications: s.notifications.map(n => + n.notification_id === notificationId ? { ...n, status: 'read' as const } : n + ) + })); + return true; + }, + + async markAllAsRead() { + const { error } = await markAllReadApiV1NotificationsMarkAllReadPost({}); + if (error) return false; + update(s => ({ + ...s, + notifications: s.notifications.map(n => ({ ...n, status: 'read' as const })) + })); + return true; + }, + + async delete(notificationId: string) { + const { error } = await deleteNotificationApiV1NotificationsNotificationIdDelete({ + path: { notification_id: notificationId } + }); + if (error) return false; + update(s => ({ + ...s, + notifications: s.notifications.filter(n => n.notification_id !== notificationId) + })); + return true; + }, + + clear() { + update(s => ({ ...s, notifications: [] })); + }, + + refresh() { + return this.load(); + } + }; +} + +export const notificationStore = createNotificationStore(); +export const unreadCount = derived(notificationStore, s => s.notifications.filter(n => n.status !== 'read').length); +export const notifications = derived(notificationStore, s => s.notifications); diff --git a/frontend/src/stores/notifications.js b/frontend/src/stores/notifications.js deleted file mode 100644 index 20c9dbb1..00000000 --- a/frontend/src/stores/notifications.js +++ /dev/null @@ -1,17 +0,0 @@ -import { writable } from "svelte/store"; - -export const notifications = writable([]); - -// Standard notification display duration in milliseconds -export const NOTIFICATION_DURATION = 5000; - -export function addNotification(message, type = "info") { - const id = Math.random().toString(36).substr(2, 9); - const text = `${message?.message ?? message?.detail ?? message}`; - notifications.update(n => [...n, { id, message: text, type }]); - setTimeout(() => removeNotification(id), NOTIFICATION_DURATION); -} - -export function removeNotification(id) { - notifications.update(n => n.filter(notification => notification.id !== id)); -} diff --git a/frontend/src/stores/theme.js b/frontend/src/stores/theme.js deleted file mode 100644 index 0196f64f..00000000 --- a/frontend/src/stores/theme.js +++ /dev/null @@ -1,127 +0,0 @@ -import { writable, get } from 'svelte/store'; - -// Standard check for browser environment -const browser = typeof window !== 'undefined' && typeof document !== 'undefined'; -const defaultTheme = 'auto'; // 'light', 'dark', or 'auto' -const storageKey = 'app-theme'; - -// Function to get system theme preference -function getSystemTheme() { - if (!browser) return 'light'; - - if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches) { - return 'dark'; - } - return 'light'; -} - -// Function to get the initial theme based on storage, system preference, or default -function getInitialTheme() { - if (!browser) return defaultTheme; // Default on server - - const storedTheme = localStorage.getItem(storageKey); - if (storedTheme && ['light', 'dark', 'auto'].includes(storedTheme)) { - return storedTheme; - } - - return defaultTheme; // Default to 'auto' -} - -// Create the writable store -const initialTheme = getInitialTheme(); -const { subscribe, set: internalSet, update } = writable(initialTheme); - -// Import dependencies dynamically to avoid circular imports -let saveThemeSetting; -let isAuthenticatedStore; -if (browser) { - Promise.all([ - import('../lib/user-settings.js'), - import('./auth.js') - ]).then(([userSettings, auth]) => { - saveThemeSetting = userSettings.saveThemeSetting; - isAuthenticatedStore = auth.isAuthenticated; - }); -} - -// Custom theme store that saves locally and to backend if authenticated -export const theme = { - subscribe, - set: (value) => { - internalSet(value); - // Always save locally - if (browser) { - localStorage.setItem(storageKey, value); - } - // Save to backend if authenticated - if (saveThemeSetting && isAuthenticatedStore && get(isAuthenticatedStore)) { - saveThemeSetting(value); - } - }, - update -}; - -// Function to apply the theme class to the document element -function applyTheme(newTheme) { - if (!browser) return; - - const root = document.documentElement; - let effectiveTheme = newTheme; - - // If theme is auto, use the actual system preference - if (newTheme === 'auto') { - effectiveTheme = getSystemTheme(); - } - - const isDark = effectiveTheme === 'dark'; - - root.classList.toggle('dark', isDark); - // Don't save to localStorage here - it's handled in the store's set method -} - -// Subscribe to changes in the store and apply the theme -theme.subscribe(applyTheme); - -// Initialize the theme on first load -if (browser) { - applyTheme(initialTheme); - - // Listen for system theme changes - if (window.matchMedia) { - const mediaQuery = window.matchMedia('(prefers-color-scheme: dark)'); - mediaQuery.addEventListener('change', (e) => { - // Only update if current theme is 'auto' - theme.update(currentTheme => { - if (currentTheme === 'auto') { - // Trigger re-apply by setting to same value - applyTheme('auto'); - } - return currentTheme; - }); - }); - } -} - -// Function to toggle theme (can be called from a button) -export function toggleTheme() { - const currentTheme = get(theme); - let newTheme; - - // Cycle through: light -> dark -> auto -> light - if (currentTheme === 'light') { - newTheme = 'dark'; - } else if (currentTheme === 'dark') { - newTheme = 'auto'; - } else { - newTheme = 'light'; - } - - theme.set(newTheme); -} - -// Function to set a specific theme -export function setTheme(newTheme) { - if (['light', 'dark', 'auto'].includes(newTheme)) { - theme.set(newTheme); - } -} \ No newline at end of file diff --git a/frontend/src/stores/theme.ts b/frontend/src/stores/theme.ts new file mode 100644 index 00000000..0aeb13e6 --- /dev/null +++ b/frontend/src/stores/theme.ts @@ -0,0 +1,87 @@ +import { writable, get } from 'svelte/store'; + +type ThemeValue = 'light' | 'dark' | 'auto'; + +const browser = typeof window !== 'undefined' && typeof document !== 'undefined'; +const defaultTheme: ThemeValue = 'auto'; +const storageKey = 'app-theme'; + +function getSystemTheme(): 'light' | 'dark' { + if (!browser) return 'light'; + return window.matchMedia?.('(prefers-color-scheme: dark)').matches ? 'dark' : 'light'; +} + +function getInitialTheme(): ThemeValue { + if (!browser) return defaultTheme; + const stored = localStorage.getItem(storageKey); + if (stored && ['light', 'dark', 'auto'].includes(stored)) { + return stored as ThemeValue; + } + return defaultTheme; +} + +const initialTheme = getInitialTheme(); +const { subscribe, set: internalSet, update } = writable(initialTheme); + +let saveThemeSetting: ((theme: string) => Promise) | null = null; +let isAuthenticatedStore: import('svelte/store').Readable | null = null; + +if (browser) { + Promise.all([ + import('../lib/user-settings'), + import('./auth') + ]).then(([userSettings, auth]) => { + saveThemeSetting = userSettings.saveThemeSetting; + isAuthenticatedStore = auth.isAuthenticated; + }); +} + +export const theme = { + subscribe, + set: (value: ThemeValue) => { + internalSet(value); + if (browser) { + localStorage.setItem(storageKey, value); + } + if (saveThemeSetting && isAuthenticatedStore && get(isAuthenticatedStore)) { + saveThemeSetting(value); + } + }, + update +}; + +function applyTheme(newTheme: ThemeValue): void { + if (!browser) return; + const effectiveTheme = newTheme === 'auto' ? getSystemTheme() : newTheme; + document.documentElement.classList.toggle('dark', effectiveTheme === 'dark'); +} + +theme.subscribe(applyTheme); + +if (browser) { + applyTheme(initialTheme); + window.matchMedia?.('(prefers-color-scheme: dark)').addEventListener('change', () => { + theme.update(current => { + if (current === 'auto') applyTheme('auto'); + return current; + }); + }); +} + +export function toggleTheme(): void { + const current = get(theme); + const next: ThemeValue = current === 'light' ? 'dark' : current === 'dark' ? 'auto' : 'light'; + theme.set(next); +} + +export function setTheme(newTheme: ThemeValue): void { + theme.set(newTheme); +} + +export function setThemeLocal(newTheme: ThemeValue): void { + internalSet(newTheme); + if (browser) { + localStorage.setItem(storageKey, newTheme); + } + applyTheme(newTheme); +} diff --git a/frontend/src/stores/toastStore.ts b/frontend/src/stores/toastStore.ts new file mode 100644 index 00000000..99cfe7ee --- /dev/null +++ b/frontend/src/stores/toastStore.ts @@ -0,0 +1,29 @@ +import { writable } from 'svelte/store'; + +export type ToastType = 'info' | 'success' | 'warning' | 'error'; + +export interface Toast { + id: string; + message: string; + type: ToastType; + progress?: number; + timerStarted?: boolean; +} + +export const toasts = writable([]); +export const TOAST_DURATION = 5000; + +export function addToast(message: unknown, type: ToastType = 'info'): void { + const id = Math.random().toString(36).substring(2, 11); + const text = typeof message === 'object' && message !== null + ? (message as { message?: string; detail?: string }).message + ?? (message as { message?: string; detail?: string }).detail + ?? String(message) + : String(message); + toasts.update(n => [...n, { id, message: text, type }]); + setTimeout(() => removeToast(id), TOAST_DURATION); +} + +export function removeToast(id: string): void { + toasts.update(n => n.filter(toast => toast.id !== id)); +} diff --git a/frontend/src/styles/components.css b/frontend/src/styles/components.css index 5e91bb2c..378e9159 100644 --- a/frontend/src/styles/components.css +++ b/frontend/src/styles/components.css @@ -3,377 +3,377 @@ .btn-lg { @apply px-6 py-3 text-base rounded-md; } - + .btn-md { @apply px-4 py-2 text-sm rounded-md; } - + .btn-outline { @apply bg-transparent border-2 border-current hover:bg-neutral-50 dark:hover:bg-neutral-800; } - + .btn-success { @apply text-white bg-green-600 hover:bg-green-700 focus:ring-green-500; } - + .btn-warning { @apply text-white bg-yellow-600 hover:bg-yellow-700 focus:ring-yellow-500; } - + /* Bare Input (for inline editing) */ .form-input-bare { - @apply bg-transparent border-0 border-b-2 border-neutral-300 dark:border-neutral-600 - focus:border-primary dark:focus:border-primary rounded-none px-1 py-0 - focus:outline-none focus:ring-0 transition-colors; + @apply bg-transparent border-0 border-b-2 border-neutral-300 dark:border-neutral-600 + focus:border-primary dark:focus:border-primary rounded-none px-1 py-0 + focus:outline-hidden focus:ring-0 transition-colors; } - + /* Pagination Controls */ .pagination-container { @apply flex flex-col sm:flex-row items-center justify-between gap-4; } - + .pagination-info { @apply text-sm text-fg-muted dark:text-dark-fg-muted; } - + .pagination-controls { @apply flex items-center gap-1; } - + .pagination-button { - @apply w-8 h-8 flex items-center justify-center rounded-lg border border-border-default dark:border-dark-border-default + @apply w-8 h-8 flex items-center justify-center rounded-lg border border-border-default dark:border-dark-border-default bg-bg-default dark:bg-dark-bg-default text-fg-default dark:text-dark-fg-default hover:bg-bg-alt dark:hover:bg-dark-bg-alt disabled:opacity-50 disabled:cursor-not-allowed transition-colors; } - + .pagination-text { @apply px-3 text-sm text-fg-default dark:text-dark-fg-default; } - + .pagination-selector { - @apply px-3 py-1.5 pr-8 rounded-lg border border-border-default dark:border-dark-border-default + @apply px-3 py-1.5 pr-8 rounded-lg border border-border-default dark:border-dark-border-default bg-bg-default dark:bg-dark-bg-default text-fg-default dark:text-dark-fg-default - text-sm focus:outline-none focus:ring-2 focus:ring-primary focus:border-primary + text-sm focus:outline-hidden focus:ring-2 focus:ring-primary focus:border-primary appearance-none bg-no-repeat bg-[length:16px] bg-[right_0.5rem_center] cursor-pointer; } - + /* Table Styles */ .table-container { @apply overflow-x-auto; } - + .table { @apply w-full divide-y divide-border-default dark:divide-dark-border-default; } - + .table-header { @apply bg-neutral-50 dark:bg-neutral-900; } - + .table-header-cell { @apply px-4 py-3 text-left text-xs font-medium text-fg-muted dark:text-dark-fg-muted uppercase tracking-wider; } - + .table-header-cell-sm { @apply px-3 py-2 text-left text-xs font-medium text-fg-muted dark:text-dark-fg-muted uppercase tracking-wider; } - + .table-body { @apply bg-bg-default dark:bg-dark-bg-default divide-y divide-border-default dark:divide-dark-border-default; } - + .table-row { @apply hover:bg-neutral-50 dark:hover:bg-neutral-800 transition-colors; } - + .table-row-clickable { @apply hover:bg-neutral-50 dark:hover:bg-neutral-800 cursor-pointer transition-colors; } - + .table-cell { @apply px-4 py-3 text-sm text-fg-default dark:text-dark-fg-default; } - + .table-cell-sm { @apply px-3 py-2 text-sm text-fg-default dark:text-dark-fg-default; } - + /* Modal/Dialog Styles */ .modal-backdrop { - @apply fixed inset-0 bg-black bg-opacity-50 dark:bg-opacity-70 z-50 flex items-center justify-center p-2 sm:p-4; + @apply fixed inset-0 bg-black/50 dark:bg-black/70 z-50 flex items-center justify-center p-2 sm:p-4; } - + .modal-container { @apply bg-white dark:bg-gray-800 rounded-lg shadow-xl max-w-4xl w-full max-h-[95vh] sm:max-h-[90vh] overflow-hidden; } - + .modal-header { @apply p-4 sm:p-6 border-b border-gray-200 dark:border-gray-700 flex justify-between items-center; } - + .modal-title { @apply text-lg sm:text-xl font-semibold text-gray-900 dark:text-gray-100; } - + .modal-close { @apply text-gray-500 hover:text-gray-700 dark:text-gray-400 dark:hover:text-gray-200 text-2xl leading-none; } - + .modal-body { @apply p-4 sm:p-6 overflow-y-auto max-h-[calc(95vh-100px)] sm:max-h-[calc(90vh-120px)]; } - + .modal-footer { @apply p-4 sm:p-6 border-t border-gray-200 dark:border-gray-700 flex gap-3 justify-end; } - + /* Badge/Pill Styles */ .badge { @apply inline-flex items-center px-2 py-0.5 rounded text-xs font-medium; } - + .badge-sm { @apply px-1.5 py-0.5 text-xs; } - + .badge-lg { @apply px-3 py-1 text-sm; } - + .badge-primary { @apply bg-primary/10 text-primary dark:bg-primary/20 dark:text-primary-light; } - + .badge-success { @apply bg-green-100 text-green-800 dark:bg-green-900 dark:text-green-200; } - + .badge-warning { @apply bg-yellow-100 text-yellow-800 dark:bg-yellow-900 dark:text-yellow-200; } - + .badge-danger { @apply bg-red-100 text-red-800 dark:bg-red-900 dark:text-red-200; } - + .badge-info { @apply bg-blue-100 text-blue-800 dark:bg-blue-900 dark:text-blue-200; } - + .badge-neutral { @apply bg-gray-100 text-gray-800 dark:bg-gray-700 dark:text-gray-200; } - + /* Alert/Notification Styles */ .alert { @apply p-4 rounded-lg border; } - + .alert-info { @apply bg-blue-50 dark:bg-blue-900/20 border-blue-200 dark:border-blue-800 text-blue-900 dark:text-blue-100; } - + .alert-success { @apply bg-green-50 dark:bg-green-900/20 border-green-200 dark:border-green-800 text-green-900 dark:text-green-100; } - + .alert-warning { @apply bg-yellow-50 dark:bg-yellow-900/20 border-yellow-200 dark:border-yellow-800 text-yellow-900 dark:text-yellow-100; } - + .alert-danger { @apply bg-red-50 dark:bg-red-900/20 border-red-200 dark:border-red-800 text-red-900 dark:text-red-100; } - + /* Progress Bar */ .progress-container { @apply w-full bg-gray-200 dark:bg-gray-700 rounded-full h-2; } - + .progress-bar { @apply bg-primary h-2 rounded-full transition-all duration-300; } - + .progress-bar-success { @apply bg-green-600 dark:bg-green-400; } - + .progress-bar-warning { @apply bg-yellow-600 dark:bg-yellow-400; } - + .progress-bar-danger { @apply bg-red-600 dark:bg-red-400; } - + /* Dropdown Menu (Generic) */ .dropdown-menu { @apply absolute right-0 mt-2 w-48 bg-white dark:bg-gray-800 rounded-lg shadow-lg border border-gray-200 dark:border-gray-700 z-50; } - + .dropdown-item { @apply w-full px-4 py-2 text-left hover:bg-gray-100 dark:hover:bg-gray-700 flex items-center gap-2 transition-colors; } - + .dropdown-item:first-child { @apply rounded-t-lg; } - + .dropdown-item:last-child { @apply rounded-b-lg; } - + /* Tooltip */ .tooltip { - @apply absolute bottom-8 right-0 z-10 px-2 py-1 text-xs bg-neutral-800 dark:bg-neutral-200 - text-white dark:text-neutral-800 rounded shadow-lg opacity-0 group-hover:opacity-100 + @apply absolute bottom-8 right-0 z-10 px-2 py-1 text-xs bg-neutral-800 dark:bg-neutral-200 + text-white dark:text-neutral-800 rounded shadow-lg opacity-0 group-hover:opacity-100 transition-opacity duration-200 pointer-events-none whitespace-nowrap; } - + /* Loading Skeleton */ .skeleton { @apply animate-pulse bg-gray-200 dark:bg-gray-700 rounded; } - + .skeleton-text { - @apply h-4 skeleton mb-2; + @apply h-4 animate-pulse bg-gray-200 dark:bg-gray-700 rounded mb-2; } - + .skeleton-title { - @apply h-6 skeleton mb-3; + @apply h-6 animate-pulse bg-gray-200 dark:bg-gray-700 rounded mb-3; } - + .skeleton-button { - @apply h-10 w-24 skeleton; + @apply h-10 w-24 animate-pulse bg-gray-200 dark:bg-gray-700 rounded; } - + /* Feature Card */ .feature-card { - @apply group relative flex flex-col items-start text-left p-6 sm:p-8 - bg-bg-alt dark:bg-dark-bg-alt rounded-xl - border border-border-default/50 dark:border-dark-border-default/50 - shadow-sm transition-transform duration-300 + @apply relative flex flex-col items-start text-left p-6 sm:p-8 + bg-bg-alt dark:bg-dark-bg-alt rounded-xl + border border-border-default/50 dark:border-dark-border-default/50 + shadow-xs transition-transform duration-300 hover:shadow-lg hover:-translate-y-1 hover:border-primary/40; } - + /* Empty State */ .empty-state { @apply text-center py-8 text-fg-muted dark:text-dark-fg-muted; } - + .empty-state-icon { @apply w-12 h-12 mx-auto mb-4 text-gray-400 dark:text-gray-600; } - + .empty-state-title { @apply text-lg font-medium text-fg-default dark:text-dark-fg-default mb-2; } - + .empty-state-description { @apply text-sm text-fg-muted dark:text-dark-fg-muted; } - + /* List Group */ .list-group { @apply divide-y divide-border-default dark:divide-dark-border-default; } - + .list-group-item { @apply p-4 hover:bg-bg-alt dark:hover:bg-dark-bg-alt transition-colors; } - + .list-group-item-clickable { @apply p-4 hover:bg-bg-alt dark:hover:bg-dark-bg-alt cursor-pointer transition-colors; } - + /* Avatar */ .avatar { @apply inline-flex items-center justify-center rounded-full bg-gray-500 text-white; } - + .avatar-sm { @apply w-8 h-8 text-xs; } - + .avatar-md { @apply w-10 h-10 text-sm; } - + .avatar-lg { @apply w-12 h-12 text-base; } - + /* Tabs */ .tabs-container { @apply border-b border-border-default dark:border-dark-border-default; } - + .tabs-list { @apply flex space-x-6; } - + .tab-item { @apply py-2 px-1 border-b-2 font-medium text-sm transition-colors; } - + .tab-item-active { @apply border-primary text-primary dark:text-primary-light; } - + .tab-item-inactive { @apply border-transparent text-fg-muted dark:text-dark-fg-muted hover:text-fg-default dark:hover:text-dark-fg-default hover:border-gray-300 dark:hover:border-gray-600; } - + /* Divider */ .divider { @apply border-t border-border-default dark:border-dark-border-default; } - + .divider-vertical { @apply border-l border-border-default dark:border-dark-border-default; } - + /* Status Indicators */ .status-dot { @apply w-2 h-2 rounded-full; } - + .status-dot-success { @apply bg-green-500; } - + .status-dot-warning { @apply bg-yellow-500; } - + .status-dot-danger { @apply bg-red-500; } - + .status-dot-info { @apply bg-blue-500; } - + /* Mobile Card View for Tables */ .mobile-card { @apply bg-bg-alt dark:bg-dark-bg-alt rounded-lg p-4 hover:shadow-md transition-shadow cursor-pointer; } - + .mobile-card-header { @apply flex justify-between items-start mb-2; } - + .mobile-card-body { @apply space-y-2 text-sm; } - + .mobile-card-label { @apply text-fg-muted dark:text-dark-fg-muted; } - + .mobile-card-value { @apply text-fg-default dark:text-dark-fg-default; } -} \ No newline at end of file +} diff --git a/frontend/src/styles/pages.css b/frontend/src/styles/pages.css new file mode 100644 index 00000000..4d01f409 --- /dev/null +++ b/frontend/src/styles/pages.css @@ -0,0 +1,273 @@ +/* + * Page-specific component styles + * Centralized styles for route components to avoid scattered
Content goes here