diff --git a/.github/workflows/webviz.yml b/.github/workflows/webviz.yml
index fdb3e3159..c6ffdbb21 100644
--- a/.github/workflows/webviz.yml
+++ b/.github/workflows/webviz.yml
@@ -70,9 +70,9 @@ jobs:
- name: 🕵️ Check auto-generated frontend code is in sync with backend
run: |
- docker build -f backend.Dockerfile -t backend:latest .
- CONTAINER_ID=$(docker run --detach -p 5000:5000 --env UVICORN_PORT=5000 --env UVICORN_ENTRYPOINT=src.backend.primary.main:app --env WEBVIZ_CLIENT_SECRET=0 --env WEBVIZ_SMDA_SUBSCRIPTION_KEY=0 --env WEBVIZ_SMDA_RESOURCE_SCOPE=0 --env WEBVIZ_VDS_HOST_ADDRESS=0 backend:latest)
- sleep 5 # Ensure the backend server is up and running exposing /openapi.json
+ docker build -f ./backend_py/primary/Dockerfile -t backend:latest .
+ CONTAINER_ID=$(docker run --detach -p 5000:5000 --env UVICORN_PORT=5000 --env WEBVIZ_CLIENT_SECRET=0 --env WEBVIZ_SMDA_SUBSCRIPTION_KEY=0 --env WEBVIZ_SMDA_RESOURCE_SCOPE=0 --env WEBVIZ_VDS_HOST_ADDRESS=0 backend:latest)
+ sleep 10 # Ensure the backend server is up and running exposing /openapi.json
npm run generate-api --prefix ./frontend
docker stop $CONTAINER_ID
git diff --exit-code ./frontend/src/api || exit 1
@@ -91,7 +91,7 @@ jobs:
cache: pip
- name: 📦 Install poetry and dependencies
- working-directory: ./backend
+ working-directory: ./backend_py/primary
run: |
pip install --upgrade pip
pip install poetry
@@ -100,15 +100,16 @@ jobs:
poetry install --with dev
- name: 🕵️ Check code style & linting
- working-directory: ./backend
+ working-directory: ./backend_py/primary
run: |
- black --check src/ tests/
- pylint src/ tests/
- bandit --recursive src/
- mypy src/ tests/
+ set -x
+ black --check primary/ tests/
+ pylint primary/ tests/
+ bandit --recursive primary/
+ mypy primary/ tests/
- name: 🤖 Run tests
- working-directory: ./backend
+ working-directory: ./backend_py/primary
env:
WEBVIZ_CLIENT_SECRET: 0
WEBVIZ_SMDA_SUBSCRIPTION_KEY: 0
@@ -148,4 +149,4 @@ jobs:
- name: 🐳 Verify Docker images build
run: |
docker build -f frontend-prod.Dockerfile .
- docker build -f backend.Dockerfile .
+ docker build -f ./backend_py/primary/Dockerfile .
diff --git a/.gitignore b/.gitignore
index f7f274172..4d9dd997f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -108,9 +108,10 @@ dist
.tern-port
# .vscode
-.vscode/
+**/.vscode/*
!.vscode/tasks.json
!.vscode/launch.json
+!backend_py/primary/.vscode/launch.json
# playwright results
playwright-report/
@@ -122,3 +123,6 @@ playwright-report/
# Ignore Jupyter Notebook checkpoints (hidden directories)
.ipynb_checkpoints/
+
+# Python virtual environments
+.venv*
diff --git a/.vscode/launch.json b/.vscode/launch.json
index 116c58dcb..d5196d4dc 100644
--- a/.vscode/launch.json
+++ b/.vscode/launch.json
@@ -7,8 +7,8 @@
"connect": { "host": "localhost", "port": 5678 },
"pathMappings": [
{
- "localRoot": "${workspaceFolder}/backend",
- "remoteRoot": "/home/appuser/backend"
+ "localRoot": "${workspaceFolder}/backend_py/primary",
+ "remoteRoot": "/home/appuser/backend_py/primary"
}
]
},
diff --git a/README.md b/README.md
index c5479873c..dbeddafe4 100644
--- a/README.md
+++ b/README.md
@@ -52,7 +52,8 @@ as stated above).
We have two applications in Radix built from this repository:
* [Main application](https://webviz.app.radix.equinor.com/) built from the `main` branch.
-* [Review application](https://frontend-webviz-review.radix.equinor.com/) built from the `review` branch
+* [Review application](https://frontend-webviz-review.radix.equinor.com/) built from the `review` branch.
+* [Dev application](https://frontend-webviz-dev.radix.equinor.com/) built from the `dev` branch.
The applications are automatically built and redeployed when pushing commits to the respective branch.
diff --git a/backend.Dockerfile b/backend.Dockerfile
deleted file mode 100644
index ca192388a..000000000
--- a/backend.Dockerfile
+++ /dev/null
@@ -1,15 +0,0 @@
-FROM python:3.11-slim@sha256:ad2c4e5884418404c5289acad4a471dde8500e24ba57ad574cdcae46523e507a
-
-RUN useradd --create-home --uid 1234 appuser # Changing to non-root user early
-
-USER 1234
-
-COPY --chown=appuser ./backend /home/appuser/backend
-WORKDIR /home/appuser/backend
-
-ENV PATH="${PATH}:/home/appuser/.local/bin"
-RUN pip install poetry \
- && poetry export -f requirements.txt -o requirements.txt \
- && pip install -r requirements.txt
-
-CMD exec uvicorn --proxy-headers --host=0.0.0.0 $UVICORN_ENTRYPOINT
diff --git a/backend/src/backend/primary/main.py b/backend/src/backend/primary/main.py
deleted file mode 100644
index ab73685c6..000000000
--- a/backend/src/backend/primary/main.py
+++ /dev/null
@@ -1,104 +0,0 @@
-import datetime
-import logging
-import os
-
-from fastapi import FastAPI
-from fastapi.routing import APIRoute
-from fastapi.responses import ORJSONResponse
-from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
-
-from src.backend.utils.add_process_time_to_server_timing_middleware import AddProcessTimeToServerTimingMiddleware
-from src.backend.utils.azure_monitor_setup import setup_azure_monitor_telemetry
-from src.backend.utils.exception_handlers import override_default_fastapi_exception_handlers
-from src.backend.utils.exception_handlers import configure_service_level_exception_handlers
-from src.backend.utils.logging_setup import ensure_console_log_handler_is_configured, setup_normal_log_levels
-from src.backend.shared_middleware import add_shared_middlewares
-from src.backend.auth.auth_helper import AuthHelper
-from .routers.explore import router as explore_router
-from .routers.general import router as general_router
-from .routers.inplace_volumetrics.router import router as inplace_volumetrics_router
-from .routers.surface.router import router as surface_router
-from .routers.timeseries.router import router as timeseries_router
-from .routers.parameters.router import router as parameters_router
-from .routers.correlations.router import router as correlations_router
-from .routers.grid.router import router as grid_router
-from .routers.pvt.router import router as pvt_router
-from .routers.well_completions.router import router as well_completions_router
-from .routers.well.router import router as well_router
-from .routers.seismic.router import router as seismic_router
-from .routers.polygons.router import router as polygons_router
-from .routers.graph.router import router as graph_router
-from .routers.observations.router import router as observations_router
-from .routers.rft.router import router as rft_router
-
-
-ensure_console_log_handler_is_configured()
-setup_normal_log_levels()
-
-# temporarily set some loggers to DEBUG
-# logging.getLogger().setLevel(logging.DEBUG)
-logging.getLogger("src.services.sumo_access").setLevel(logging.DEBUG)
-
-LOGGER = logging.getLogger(__name__)
-
-
-def custom_generate_unique_id(route: APIRoute) -> str:
- return f"{route.name}"
-
-
-app = FastAPI(
- generate_unique_id_function=custom_generate_unique_id,
- root_path="/api",
- default_response_class=ORJSONResponse,
-)
-
-if os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING"):
- LOGGER.info("Configuring Azure Monitor telemetry for primary backend")
- setup_azure_monitor_telemetry(app)
-else:
- LOGGER.warning("Skipping telemetry configuration, APPLICATIONINSIGHTS_CONNECTION_STRING env variable not set.")
-
-
-# The tags we add here will determine the name of the frontend api service for our endpoints as well as
-# providing some grouping when viewing the openapi documentation.
-app.include_router(explore_router, tags=["explore"])
-app.include_router(timeseries_router, prefix="/timeseries", tags=["timeseries"])
-app.include_router(
- inplace_volumetrics_router,
- prefix="/inplace_volumetrics",
- tags=["inplace_volumetrics"],
-)
-app.include_router(surface_router, prefix="/surface", tags=["surface"])
-app.include_router(parameters_router, prefix="/parameters", tags=["parameters"])
-app.include_router(correlations_router, prefix="/correlations", tags=["correlations"])
-app.include_router(grid_router, prefix="/grid", tags=["grid"])
-app.include_router(pvt_router, prefix="/pvt", tags=["pvt"])
-app.include_router(well_completions_router, prefix="/well_completions", tags=["well_completions"])
-app.include_router(well_router, prefix="/well", tags=["well"])
-app.include_router(seismic_router, prefix="/seismic", tags=["seismic"])
-app.include_router(polygons_router, prefix="/polygons", tags=["polygons"])
-app.include_router(graph_router, prefix="/graph", tags=["graph"])
-app.include_router(observations_router, prefix="/observations", tags=["observations"])
-app.include_router(rft_router, prefix="/rft", tags=["rft"])
-
-authHelper = AuthHelper()
-app.include_router(authHelper.router)
-app.include_router(general_router)
-
-configure_service_level_exception_handlers(app)
-override_default_fastapi_exception_handlers(app)
-
-# This middleware instance approximately measures execution time of the route handler itself
-app.add_middleware(AddProcessTimeToServerTimingMiddleware, metric_name="total-exec-route")
-
-add_shared_middlewares(app)
-
-app.add_middleware(ProxyHeadersMiddleware, trusted_hosts="*")
-
-# This middleware instance measures execution time of the endpoints, including the cost of other middleware
-app.add_middleware(AddProcessTimeToServerTimingMiddleware, metric_name="total")
-
-
-@app.get("/")
-async def root() -> str:
- return f"Backend is alive at this time: {datetime.datetime.now()}"
diff --git a/backend/src/backend/primary/user_session_proxy.py b/backend/src/backend/primary/user_session_proxy.py
deleted file mode 100644
index e7b8d5786..000000000
--- a/backend/src/backend/primary/user_session_proxy.py
+++ /dev/null
@@ -1,149 +0,0 @@
-import os
-import asyncio
-from typing import Any, Optional
-
-import httpx
-import redis
-from starlette.requests import Request
-from starlette.responses import StreamingResponse
-from starlette.background import BackgroundTask
-
-from src import config
-from src.services.utils.authenticated_user import AuthenticatedUser
-
-LOCALHOST_DEVELOPMENT = os.environ.get("UVICORN_RELOAD") == "true"
-
-
-class _RedisUserJobs:
- def __init__(self) -> None:
- # redis.Redis does not yet have namespace support - https://github.com/redis/redis-py/issues/12 - need to prefix manually.
- self._redis_client = redis.Redis.from_url(config.REDIS_USER_SESSION_URL, decode_responses=True)
-
- def get_job_name(self, user_id: str) -> Optional[str]:
- return self._redis_client.get("user-job-name:" + user_id)
-
- def set_job_name(self, user_id: str, job_name: str) -> None:
- self._redis_client.set("user-job-name:" + user_id, job_name)
-
-
-class RadixJobScheduler:
- """Utility class to help with spawning Radix jobs on demand,
- and provide correct URL to communicate with running Radix jobs"""
-
- def __init__(self, name: str, port: int) -> None:
- self._name = name
- self._port = port
- self._redis_user_jobs = _RedisUserJobs()
-
- def _get_job_name(self, user_id: str) -> Optional[str]:
- return self._redis_user_jobs.get_job_name(user_id)
-
- def _set_job_name(self, user_id: str, job_name: str) -> None:
- self._redis_user_jobs.set_job_name(user_id, job_name)
-
- async def _active_running_job(self, user_id: str) -> bool:
- """Returns true if there already is a running job for logged in user."""
-
- existing_job_name = self._get_job_name(user_id)
- if not existing_job_name:
- return False
- if LOCALHOST_DEVELOPMENT:
- return True
-
- async with httpx.AsyncClient() as client:
- res = await client.get(f"http://{self._name}:{self._port}/api/v1/jobs/{existing_job_name}")
-
- job = res.json()
-
- if job.get("status") != "Running" or not job.get("started"):
- return False
-
- try:
- httpx.get(f"http://{existing_job_name}:{self._port}/")
- except (ConnectionRefusedError, httpx.ConnectError, httpx.ConnectTimeout):
- print(f"User session container for user {user_id} not yet up.")
- return False
-
- return True
-
- async def _create_new_job(self, user_id: str) -> None:
- """Create a new Radix job by sending request to Radix job scheduler.
- If localhost development, simply return already running container with
- same name."""
-
- if LOCALHOST_DEVELOPMENT:
- self._set_job_name(user_id, self._name)
- else:
- print(f"Requesting new user session container for user {user_id}.")
- async with httpx.AsyncClient() as client:
- res = await client.post(
- f"http://{self._name}:{self._port}/api/v1/jobs",
- # Maximum limits in "resources" for a Radix job is as of May 2023
- # the specs of a single Standard_E16as_v4 node, i.e.:
- # * vCPU: 16
- # * memory: 128 GiB
- # * temp storage (SSD): 256 GiB
- #
- # As of now our CPU/memory requests are hardcoded below, but in the future maybe
- # these could be dynamic based on e.g. the selected ensemble sizess by the user.
- json={
- "resources": {
- "limits": {"memory": "32GiB", "cpu": "2"},
- "requests": {"memory": "32GiB", "cpu": "1"},
- }
- },
- )
- self._set_job_name(user_id, res.json()["name"])
-
- while not await self._active_running_job(user_id):
- # It takes a couple of seconds before Radix job uvicorn process has
- # started and begins to listen at the end point.
- await asyncio.sleep(1)
-
- async def get_base_url(self, user_id: str) -> str:
- """Input is ID of logged in user. Returned value is base URL towards the correct
- Radix job"""
- if not await self._active_running_job(user_id):
- await self._create_new_job(user_id)
-
- job_name = self._get_job_name(user_id)
-
- return f"http://{job_name}:{self._port}"
-
-
-# For now we only have one type of job:
-RADIX_JOB_SCHEDULER_INSTANCE = RadixJobScheduler("backend-user-session", 8000)
-
-
-async def proxy_to_user_session(request: Request, authenticated_user: AuthenticatedUser) -> Any:
- # Ideally this function should probably be a starlette/FastAPI middleware, but it appears that
- # it is not yet possible to put middleware on single routes through decorator like in express.js.
-
- base_url = await RADIX_JOB_SCHEDULER_INSTANCE.get_base_url(
- authenticated_user._user_id # pylint: disable=protected-access
- )
-
- # See https://github.com/tiangolo/fastapi/discussions/7382:
-
- client = httpx.AsyncClient(base_url=base_url)
-
- url = httpx.URL(
- path=request.url.path.removeprefix("/api").rstrip("/"),
- query=request.url.query.encode("utf-8"),
- )
-
- job_req = client.build_request(
- request.method,
- url,
- headers=request.headers.raw,
- content=request.stream(),
- timeout=600,
- )
- job_resp = await client.send(job_req, stream=True)
-
- return StreamingResponse(
- job_resp.aiter_raw(),
- status_code=job_resp.status_code,
- headers=job_resp.headers,
- background=BackgroundTask(job_resp.aclose),
- )
diff --git a/backend/src/backend/shared_middleware.py b/backend/src/backend/shared_middleware.py
deleted file mode 100644
index 60c48c1b6..000000000
--- a/backend/src/backend/shared_middleware.py
+++ /dev/null
@@ -1,21 +0,0 @@
-from fastapi import FastAPI
-from starsessions import SessionMiddleware
-from starsessions.stores.redis import RedisStore
-
-from src import config
-from src.backend.auth.enforce_logged_in_middleware import EnforceLoggedInMiddleware
-
-
-def add_shared_middlewares(app: FastAPI) -> None:
- # Add out custom middleware to enforce that user is logged in
- # Also redirects to /login endpoint for some select paths
- unprotected_paths = ["/logged_in_user", "/alive", "/openapi.json"]
- paths_redirected_to_login = ["/", "/alive_protected"]
- app.add_middleware(
- EnforceLoggedInMiddleware,
- unprotected_paths=unprotected_paths,
- paths_redirected_to_login=paths_redirected_to_login,
- )
-
- session_store = RedisStore(config.REDIS_USER_SESSION_URL, prefix="user-auth:")
- app.add_middleware(SessionMiddleware, store=session_store)
diff --git a/backend/src/backend/user_session/main.py b/backend/src/backend/user_session/main.py
deleted file mode 100644
index 223ff6596..000000000
--- a/backend/src/backend/user_session/main.py
+++ /dev/null
@@ -1,39 +0,0 @@
-import logging
-import os
-
-from fastapi import FastAPI
-from fastapi.responses import ORJSONResponse
-
-from src.backend.utils.azure_monitor_setup import setup_azure_monitor_telemetry
-from src.backend.utils.logging_setup import ensure_console_log_handler_is_configured, setup_normal_log_levels
-from src.backend.shared_middleware import add_shared_middlewares
-from .inactivity_shutdown import InactivityShutdown
-from .routers.general import router as general_router
-
-# mypy: disable-error-code="attr-defined"
-from .routers.grid.router import router as grid_router
-
-
-ensure_console_log_handler_is_configured()
-setup_normal_log_levels()
-
-LOGGER = logging.getLogger(__name__)
-
-
-app = FastAPI(default_response_class=ORJSONResponse)
-
-if os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING"):
- LOGGER.info("Configuring Azure Monitor telemetry for user session server")
- setup_azure_monitor_telemetry(app)
-else:
- LOGGER.warning("Skipping telemetry configuration, APPLICATIONINSIGHTS_CONNECTION_STRING env variable not set.")
-
-app.include_router(general_router)
-app.include_router(grid_router, prefix="/grid")
-add_shared_middlewares(app)
-
-# We shut down the user session container after some
-# minutes without receiving any new requests:
-InactivityShutdown(app, inactivity_limit_minutes=30)
-
-LOGGER.info("Successfully completed user session server initialization.")
diff --git a/backend/src/backend/user_session/routers/general.py b/backend/src/backend/user_session/routers/general.py
deleted file mode 100644
index 3d1fd4566..000000000
--- a/backend/src/backend/user_session/routers/general.py
+++ /dev/null
@@ -1,37 +0,0 @@
-import datetime
-from typing import Dict, Union, NamedTuple
-
-import psutil
-from fastapi import APIRouter, Depends
-from src.backend.auth.auth_helper import AuthHelper, AuthenticatedUser
-
-router = APIRouter()
-
-START_TIME_CONTAINER = datetime.datetime.now()
-
-
-def _convert_psutil_object_to_dict(psutil_object: NamedTuple) -> Dict[str, Union[str, Dict[str, str]]]:
- return {key: getattr(psutil_object, key) for key in psutil_object._fields}
-
-
-@router.get("/user_session_container")
-async def user_session_container(
- authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
-) -> dict:
- """Get information about user session container, like when it was started
- together with memory and disk usage. NB! Note that a session container is started
- if one is not already running when accessing this endpoint.
-
- For explanation of the different memory metrics, see e.g. psutil documentation like
- * https://psutil.readthedocs.io/en/latest/index.html?highlight=Process()#psutil.virtual_memory
- * https://psutil.readthedocs.io/en/latest/index.html?highlight=Process()#psutil.Process
- """
-
- return {
- "username": authenticated_user.get_username(),
- "startTimeContainer": START_TIME_CONTAINER,
- "rootDiskSystem": _convert_psutil_object_to_dict(psutil.disk_usage("/")),
- "memorySystem": _convert_psutil_object_to_dict(psutil.virtual_memory()),
- "memoryPythonProcess": _convert_psutil_object_to_dict(psutil.Process().memory_info()),
- "cpuPercent": psutil.cpu_percent(),
- }
diff --git a/backend/src/backend/user_session/routers/grid/router.py b/backend/src/backend/user_session/routers/grid/router.py
deleted file mode 100644
index fd55d354d..000000000
--- a/backend/src/backend/user_session/routers/grid/router.py
+++ /dev/null
@@ -1,520 +0,0 @@
-# type: ignore
-# for now
-from functools import cache
-from typing import List, Tuple
-import logging
-import os
-from concurrent.futures import ThreadPoolExecutor
-
-import psutil
-import numpy as np
-import orjson
-import xtgeo
-from vtkmodules.util.numpy_support import vtk_to_numpy
-from fastapi import APIRouter, Depends, Request
-from fastapi.responses import ORJSONResponse
-
-from src.backend.auth.auth_helper import AuthenticatedUser, AuthHelper
-from src.backend.primary.routers.grid.schemas import (
- GridSurface,
- GridIntersection,
-)
-from src.services.sumo_access.grid_access import GridAccess
-from src.services.utils.b64 import b64_encode_float_array_as_float32, b64_encode_uint_array_as_smallest_size
-from src.services.utils.vtk_utils import (
- VtkGridSurface,
- get_scalar_values,
- get_surface,
- cut_along_polyline,
- flatten_sliced_grid,
- xtgeo_grid_to_vtk_explicit_structured_grid,
- create_polyline,
- grid_to_numpy,
- get_triangles,
-)
-from src.services.utils.mpl_utils import visualize_triangles_with_scalars
-from src.services.utils.perf_timer import PerfTimer
-
-router = APIRouter()
-LOGGER = logging.getLogger(__name__)
-
-
-@router.get("/grid_surface", response_model=GridSurface)
-async def grid_surface(
- request: Request,
- authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
-):
- case_uuid = request.query_params.get("case_uuid")
- ensemble_name = request.query_params.get("ensemble_name")
- grid_name = request.query_params.get("grid_name")
- realization = request.query_params.get("realization")
-
- # Get Xtgeo grid
- xtgeo_grid = await get_grid_geometry(
- authenticated_user=authenticated_user,
- case_uuid=case_uuid,
- ensemble_name=ensemble_name,
- grid_name=grid_name,
- realization=realization,
- )
-
- # Get grid information from xtgeo (xmin, ymin, etc...)
- grid_geometrics = xtgeo_grid.get_geometrics(allcells=True, return_dict=True)
-
- # Get grid surface (visible cells)
- grid_surface_instance = get_grid_surface(grid_geometry=xtgeo_grid)
-
- # Extract points and polygons from surface
- points_np = vtk_to_numpy(grid_surface_instance.polydata.GetPoints().GetData()).ravel().astype(np.float32)
- polys_np = vtk_to_numpy(grid_surface_instance.polydata.GetPolys().GetData()).astype(np.int64)
-
- # Reduce precision of points to 2 decimals
- points_np = np.around(points_np, decimals=2)
-
- grid_surface_payload = GridSurface(
- points_b64arr=b64_encode_float_array_as_float32(points_np),
- polys_b64arr=b64_encode_uint_array_as_smallest_size(polys_np),
- **grid_geometrics,
- )
- return ORJSONResponse(grid_surface_payload.dict())
-
-
-@router.get(
- "/grid_parameter", response_model=List[float]
-) # stating response_model here instead of return type apparently disables pydantic validation of the response (https://stackoverflow.com/a/65715205)
-# type: ignore
-async def grid_parameter(
- request: Request,
- authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
-):
- case_uuid = request.query_params.get("case_uuid")
- ensemble_name = request.query_params.get("ensemble_name")
- grid_name = request.query_params.get("grid_name")
- parameter_name = request.query_params.get("parameter_name")
- realization = request.query_params.get("realization")
-
- # Get Xtgeo grid
- xtgeo_grid = await get_grid_geometry(
- authenticated_user=authenticated_user,
- case_uuid=case_uuid,
- ensemble_name=ensemble_name,
- grid_name=grid_name,
- realization=realization,
- )
- # Get grid surface (visible cells)
- grid_polydata = get_grid_surface(grid_geometry=xtgeo_grid)
-
- # Get Xtgeo parameter
- xtgeo_parameter = await get_grid_parameter(
- authenticated_user=authenticated_user,
- case_uuid=case_uuid,
- ensemble_name=ensemble_name,
- grid_name=grid_name,
- parameter_name=parameter_name,
- realization=realization,
- )
-
- # Get scalar values from parameter
- scalar_values = get_scalar_values(xtgeo_parameter, cell_ids=grid_polydata.original_cell_ids)
-
- # Handle xtgeo undefined values and truncate
- scalar_values[scalar_values == -999.0] = np.nan
- scalar_values[scalar_values < np.nanmin(scalar_values)] = np.nanmin(scalar_values)
- scalar_values[scalar_values > np.nanmax(scalar_values)] = np.nanmax(scalar_values)
-
- return ORJSONResponse(scalar_values.tolist())
-
-
-@router.get(
- "/grid_parameter_intersection", response_model=List[float]
-) # stating response_model here instead of return type apparently disables pydantic validation of the response (https://stackoverflow.com/a/65715205)
-# type: ignore
-async def grid_parameter_intersection( # pylint: disable=too-many-locals
- request: Request,
- authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
-):
- case_uuid = request.query_params.get("case_uuid")
- ensemble_name = request.query_params.get("ensemble_name")
- grid_name = request.query_params.get("grid_name")
- parameter_name = request.query_params.get("parameter_name")
- realization = request.query_params.get("realization")
-
- timer = PerfTimer()
- # Get Xtgeo grid
- xtgeo_grid = await get_grid_geometry(
- authenticated_user=authenticated_user,
- case_uuid=case_uuid,
- ensemble_name=ensemble_name,
- grid_name=grid_name,
- realization=realization,
- )
- # Activate all cells. Should we do this?
- xtgeo_grid.activate_all()
- print(
- f"DOWNLOADED/READ CACHE: grid_geometry for {grid_name}, realization: {realization}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
- # Get xtgeo parameter
- xtgeo_parameter = await get_grid_parameter(
- authenticated_user=authenticated_user,
- case_uuid=case_uuid,
- ensemble_name=ensemble_name,
- grid_name=grid_name,
- parameter_name=parameter_name,
- realization=realization,
- )
- print(
- f"DOWNLOADED/READ CACHE: grid_parameter for {parameter_name}, realization: {realization}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
-
- # HARDCODED POLYLINE FOR TESTING
- xyz_arr = tuple(
- tuple(point)
- for point in [
- [463156.911, 5929542.294, -49.0],
- [463564.402, 5931057.803, -1293.4185],
- [463637.925, 5931184.235, -1536.9384],
- [463690.658, 5931278.837, -1616.4998],
- [463910.452, 5931688.122, -1630.5153],
- [464465.876, 5932767.761, -1656.9874],
- [464765.876, 5934767.761, -1656.9874],
- ]
- )
-
- # Generate intersection data
- coords, triangles, original_cell_indices_np, polyline = generate_grid_intersection(xtgeo_grid, xyz_arr)
- print(
- f"CALCULATED INTERSECTION: realization: {realization}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
-
- # Get scalar values from parameter and select only the cells that intersect with the polyline
- values = get_scalar_values(xtgeo_parameter, cell_ids=original_cell_indices_np)
- print(
- f"READ SCALAR VALUES: realization: {realization}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
-
- # Handle undefined values and truncate
- values[values < np.nanmin(values)] = np.nanmin(values)
- values[values > np.nanmax(values)] = np.nanmax(values)
- # values[values > 0.4] = 0.4
- # values = values[original_cell_indices_np]
- # scalar_values[scalar_values == -999.0] = 0
-
- # Get polyline coordinates
- polyline_coords = np.array([polyline.GetPoint(i)[:3] for i in range(polyline.GetNumberOfPoints())])
-
- # Calculate the cumulative distance along the polyline
- polyline_distances = np.zeros(polyline_coords.shape[0])
- for i in range(1, polyline_coords.shape[0]):
- polyline_distances[i] = polyline_distances[i - 1] + np.linalg.norm(
- polyline_coords[i, :2] - polyline_coords[i - 1, :2]
- )
-
- polyline_x = polyline_distances
- polyline_y = polyline_coords[:, 2]
-
- # Visualize the intersection using matplotlib as a base64 encoded image
- image_data = visualize_triangles_with_scalars(coords, triangles, values, polyline, "55/33-A-4")
- print(
- f"MATPLOTLIB IMAGE: realization: {realization}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
-
- # Get the bounding box of the intersection
- x_min, x_max = np.min(coords[:, 0]), np.max(coords[:, 0])
- y_min, y_max = np.min(coords[:, 1]), np.max(coords[:, 1])
-
- # Create the intersection data object
- intersection_data = GridIntersection(
- image=f"data:image/png;base64,{image_data}",
- polyline_x=polyline_x.tolist(),
- polyline_y=polyline_y.tolist(),
- x_min=float(x_min),
- x_max=float(x_max),
- y_min=float(y_min),
- y_max=float(y_max),
- )
- return ORJSONResponse(intersection_data.__dict__)
-
-
-@router.get(
- "/statistical_grid_parameter_intersection", response_model=List[float]
-) # stating response_model here instead of return type apparently disables pydantic validation of the response (https://stackoverflow.com/a/65715205)
-# type: ignore
-async def statistical_grid_parameter_intersection( # pylint: disable=too-many-locals
- request: Request,
- authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
-):
- timer = PerfTimer()
- print("#" * 80, flush=True)
- print("ENTERING STATISTICAL GRID PARAMETER INTERSECTION", flush=True)
- print(
- f"Memory usage: {psutil.Process(os.getpid()).memory_info().rss / 1024 ** 2} MB",
- flush=True,
- )
- print("-" * 80, flush=True)
-
- case_uuid = request.query_params.get("case_uuid")
- ensemble_name = request.query_params.get("ensemble_name")
- grid_name = request.query_params.get("grid_name")
- parameter_name = request.query_params.get("parameter_name")
- # convert json string of realizations into list
- realizations = orjson.loads(request.query_params.get("realizations")) # pylint: disable=maybe-no-member
-
- grid_access = await GridAccess.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid, ensemble_name)
-
- # Check that all grids have equal nx, ny, nz
- # Should raise a http exception instead of a value error
- if not await grid_access.grids_have_equal_nxnynz(grid_name=grid_name):
- raise ValueError("Grids must have equal nx, ny, nz")
-
- # Get Xtgeo grid
- xtgeo_grid = await get_grid_geometry(
- authenticated_user=authenticated_user,
- case_uuid=case_uuid,
- ensemble_name=ensemble_name,
- grid_name=grid_name,
- realization=0,
- )
-
- # Activate all cells. Should we do this?
- xtgeo_grid.activate_all()
- print(
- f"DOWNLOADED/READ CACHE: grid_geometry for {grid_name}, realization: {0}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
-
- print("-" * 80, flush=True)
- print("GETTING GRID PARAMETERS", flush=True)
-
- ### Using ThreadPoolExecutor to parallelize the download of the grid parameters
- async def worker(real):
- return await get_grid_parameter(
- authenticated_user=authenticated_user,
- case_uuid=case_uuid,
- ensemble_name=ensemble_name,
- grid_name=grid_name,
- parameter_name=parameter_name,
- realization=real,
- )
-
- with ThreadPoolExecutor() as executor:
- xtgeo_parameters = list(executor.map(worker, realizations))
- print(
- f"DOWNLOADED/READ CACHE: grid_parameters for {parameter_name}, realizations: {realizations}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
-
- # HARDCODED POLYLINE FOR TESTING
- xyz_arr = tuple(
- tuple(point)
- for point in [
- [463156.911, 5929542.294, -49.0],
- [463564.402, 5931057.803, -1293.4185],
- [463637.925, 5931184.235, -1536.9384],
- [463690.658, 5931278.837, -1616.4998],
- [463910.452, 5931688.122, -1630.5153],
- [464465.876, 5932767.761, -1656.9874],
- [464765.876, 5934767.761, -1656.9874],
- ]
- )
- print("-" * 80, flush=True)
- print("GENERATING GRID INTERSECTION", flush=True)
-
- # Generate intersection data
- coords, triangles, original_cell_indices_np, polyline = generate_grid_intersection(xtgeo_grid, xyz_arr)
- print(
- f"CALCULATED INTERSECTION: realization: {0}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
- print("-" * 80, flush=True)
-
- # Get scalar values for each realization
- all_scalar_values = [
- get_scalar_values(xtgeo_parameter, cell_ids=original_cell_indices_np) for xtgeo_parameter in xtgeo_parameters
- ]
-
- # Calculate the mean scalar value for each cell
- values = np.nanmean(all_scalar_values, axis=0)
-
- # Handle xtgeo undefined values and truncate
- values[values < np.nanmin(values)] = np.nanmin(values)
- values[values > np.nanmax(values)] = np.nanmax(values)
- values[values == -999.0] = np.nan
- print(
- f"DOWNLOADED/READ CACHE: scalar_values for {parameter_name}, realizations: {realizations}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
-
- # Get polyline coordinates
- polyline_coords = np.array([polyline.GetPoint(i)[:3] for i in range(polyline.GetNumberOfPoints())])
-
- # Calculate the cumulative distance along the polyline
- polyline_distances = np.zeros(polyline_coords.shape[0])
- for i in range(1, polyline_coords.shape[0]):
- polyline_distances[i] = polyline_distances[i - 1] + np.linalg.norm(
- polyline_coords[i, :2] - polyline_coords[i - 1, :2]
- )
-
- polyline_x = polyline_distances
- polyline_y = polyline_coords[:, 2]
- print("-" * 80, flush=True)
-
- print("GENERATE MATPLOTLIB IMAGE", flush=True)
-
- # Visualize the intersection using matplotlib as a base64 encoded image
- image_data = visualize_triangles_with_scalars(coords, triangles, values, polyline, "55/33-A-4")
- print(
- f"GENERATED MATPLOTLIB IMAGE: {parameter_name}, realization: {0}: {round(timer.lap_s(),2)}s",
- flush=True,
- )
-
- # Get the bounding box of the intersection
- x_min, x_max = np.min(coords[:, 0]), np.max(coords[:, 0])
- y_min, y_max = np.min(coords[:, 1]), np.max(coords[:, 1])
-
- # Create the intersection data object
- intersection_data = GridIntersection(
- image=f"data:image/png;base64,{image_data}",
- polyline_x=polyline_x.tolist(),
- polyline_y=polyline_y.tolist(),
- x_min=float(x_min),
- x_max=float(x_max),
- y_min=float(y_min),
- y_max=float(y_max),
- )
-
- print("-" * 80, flush=True)
- print("EXITING STATISTICAL GRID PARAMETER INTERSECTION", flush=True)
- print(
- f"Memory usage: {psutil.Process(os.getpid()).memory_info().rss / 1024 ** 2} MB",
- flush=True,
- )
- print("#" * 80, flush=True)
-
- return ORJSONResponse(intersection_data.__dict__)
-
-
-@router.get(
- "/statistical_grid_parameter", response_model=List[float]
-) # stating response_model here instead of return type apparently disables pydantic validation of the response (https://stackoverflow.com/a/65715205)
-# type: ignore
-async def statistical_grid_parameter(
- request: Request,
- authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
-):
- case_uuid = request.query_params.get("case_uuid")
- ensemble_name = request.query_params.get("ensemble_name")
- grid_name = request.query_params.get("grid_name")
- parameter_name = request.query_params.get("parameter_name")
- # convert json string of realizations into list
- realizations = orjson.loads(request.query_params.get("realizations")) # pylint: disable=maybe-no-member
-
- grid_access = await GridAccess.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid, ensemble_name)
-
- # Check that all grids have equal nx, ny, nz
- # Should riase a http exception instead of a value error
- if not grid_access.grids_have_equal_nxnynz(grid_name=grid_name):
- raise ValueError("Grids must have equal nx, ny, nz")
-
- xtgeo_grid = await get_grid_geometry(
- authenticated_user=authenticated_user,
- case_uuid=case_uuid,
- ensemble_name=ensemble_name,
- grid_name=grid_name,
- realization=realizations[0],
- )
-
- # Get grid surface (visible cells)
- grid_polydata = get_grid_surface(grid_geometry=xtgeo_grid)
-
- # Get the xtgeo grid parameters for each realization
- xtgeo_parameters = [
- await get_grid_parameter(
- authenticated_user=authenticated_user,
- case_uuid=case_uuid,
- ensemble_name=ensemble_name,
- grid_name=grid_name,
- parameter_name=parameter_name,
- realization=real,
- )
- for real in realizations
- ]
-
- # Get the scalar values for each parameter
- all_scalar_values = [
- get_scalar_values(xtgeo_parameter, cell_ids=grid_polydata.original_cell_ids)
- for xtgeo_parameter in xtgeo_parameters
- ]
-
- # Calculate the mean scalar values for each cell
- mean_scalar_values = np.nanmean(all_scalar_values, axis=0)
-
- # Handle xtgeo undefined values and truncate
- mean_scalar_values[mean_scalar_values == -999.0] = np.nan
- mean_scalar_values[mean_scalar_values < np.nanmin(mean_scalar_values)] = np.nanmin(mean_scalar_values)
- mean_scalar_values[mean_scalar_values > np.nanmax(mean_scalar_values)] = np.nanmax(mean_scalar_values)
-
- return ORJSONResponse(mean_scalar_values.tolist())
-
-
-# @cache
-async def get_grid_geometry(
- authenticated_user: AuthenticatedUser,
- case_uuid: str,
- ensemble_name: str,
- grid_name: str,
- realization: int,
-) -> xtgeo.Grid:
- """Get the xtgeo grid geometry for a given realization"""
- token = authenticated_user.get_sumo_access_token()
- grid_access = await GridAccess.from_case_uuid(token, case_uuid, ensemble_name)
- grid_geometry = await grid_access.get_grid_geometry(grid_name, int(realization))
-
- return grid_geometry
-
-
-@cache
-def get_grid_surface(grid_geometry: xtgeo.Grid) -> VtkGridSurface:
- return get_surface(grid_geometry)
-
-
-# @cache
-async def get_grid_parameter(
- authenticated_user: AuthenticatedUser,
- case_uuid: str,
- ensemble_name: str,
- grid_name: str,
- parameter_name: str,
- realization: int,
-) -> xtgeo.GridProperty:
- token = authenticated_user.get_sumo_access_token()
- grid_access = await GridAccess.from_case_uuid(token, case_uuid, ensemble_name)
-
- return await grid_access.get_grid_parameter(grid_name, parameter_name, int(realization))
-
-
-@cache
-def generate_grid_intersection(grid_geometry: xtgeo.Grid, xyz_arr: Tuple[List[float]]):
- polyline = create_polyline(xyz_arr)
- poly_xy = []
- for xy in xyz_arr:
- poly_xy.extend([xy[0], xy[1]])
-
- esgrid = xtgeo_grid_to_vtk_explicit_structured_grid(grid_geometry)
- sliced_grid = cut_along_polyline(esgrid, poly_xy)
- original_cell_indices_np = [
- int(c) for c in vtk_to_numpy(sliced_grid.GetCellData().GetAbstractArray("vtkOriginalCellIds"))
- ]
-
- flattened_grid = flatten_sliced_grid(sliced_grid, polyline, original_cell_ids=original_cell_indices_np)
- coords = grid_to_numpy(flattened_grid)
- triangles = get_triangles(flattened_grid)
- original_cell_indices_np = [
- int(c) for c in vtk_to_numpy(flattened_grid.GetCellData().GetAbstractArray("vtkOriginalCellIds"))
- ]
-
- return (coords, triangles, original_cell_indices_np, polyline)
diff --git a/backend/src/services/sumo_access/queries/__init__.py b/backend/src/services/sumo_access/queries/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/backend/src/services/utils/__init__.py b/backend/src/services/utils/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/backend/src/services/utils/mpl_utils.py b/backend/src/services/utils/mpl_utils.py
deleted file mode 100644
index 855365b70..000000000
--- a/backend/src/services/utils/mpl_utils.py
+++ /dev/null
@@ -1,111 +0,0 @@
-# pylint: skip-file
-import base64
-from io import BytesIO
-
-import numpy as np
-import matplotlib.pyplot as plt
-import matplotlib.tri as tri
-import matplotlib.cm as cm
-from mpl_toolkits.axes_grid1 import make_axes_locatable
-from vtkmodules.vtkCommonDataModel import vtkPolyData
-
-
-def visualize_triangles_with_scalars(
- coords: np.ndarray,
- triangles: list,
- scalars: np.ma.core.MaskedArray,
- polyline: vtkPolyData,
- well_name: str = "Well",
- y_scale_factor: int = 20,
-) -> str:
- x = coords[:, 0]
- y = coords[:, 1] * y_scale_factor
-
- # Create triangulation
- triang = tri.Triangulation(x, y, triangles)
-
- # Create the figure
- fig, ax = plt.subplots(figsize=(8, 6), dpi=600)
-
- # Plot the triangulation with scalar values
- tpc = ax.tripcolor(triang, scalars, shading="flat", cmap=plt.cm.viridis)
- # Get the polyline coordinates
- polyline_coords = np.array([polyline.GetPoint(i)[:3] for i in range(polyline.GetNumberOfPoints())])
-
- # Calculate the cumulative distance along the polyline
- polyline_distances = np.zeros(polyline_coords.shape[0])
- for i in range(1, polyline_coords.shape[0]):
- polyline_distances[i] = polyline_distances[i - 1] + np.linalg.norm(
- polyline_coords[i, :2] - polyline_coords[i - 1, :2]
- )
-
- polyline_x = polyline_distances
- polyline_y = polyline_coords[:, 2] * y_scale_factor
-
- # Plot the polyline as a black line
- ax.plot(polyline_x, polyline_y, color="black", linewidth=3)
- # # Add text near the polyline
- # mid_index = len(polyline_x) // 2
- # ax.text(polyline_x[mid_index], polyline_y[mid_index], well_name, color="black")
-
- # Set aspect ratio
- ax.set_aspect("equal")
-
- # Remove axis
- ax.axis("off")
-
- # Set axis limits
- ax.set_xlim(x.min(), x.max())
- ax.set_ylim(y.min(), y.max())
-
- # Adjust the margins
- plt.tight_layout()
-
- # Save the plot to a file
- buf = BytesIO()
- plt.savefig(buf, bbox_inches="tight", pad_inches=0)
- buf.seek(0)
- im_base64 = base64.b64encode(buf.read()).decode("utf-8")
- plt.close(fig)
- # Show the plot
- return im_base64
-
-
-# def plot_cells_with_scalar(triangulation: tri.Triangulation, scalar, polyline):
-# fig, ax = plt.subplots(figsize=(8, 6), dpi=600)
-# divider = make_axes_locatable(ax)
-
-# cmap = cm.get_cmap("viridis")
-# tpc = ax.tripcolor(triangulation, facecolors=scalar, cmap=cmap)
-
-# # Adjust the margins
-# plt.tight_layout()
-
-# # Remove axis
-# ax.axis("off")
-
-# # Plot the polyline directly using x-axis as length and z-values from the polyline
-# x_poly = [0]
-# z_poly = [polyline[0][2]]
-
-# for i in range(1, len(polyline)):
-# x0, y0, z0 = polyline[i - 1]
-# x1, y1, z1 = polyline[i]
-# segment_length = np.sqrt((x1 - x0) ** 2 + (y1 - y0) ** 2)
-# x_poly.append(x_poly[-1] + segment_length)
-# z_poly.append(-z1)
-
-# ax.plot(x_poly, z_poly, c="k", linewidth=2)
-
-# # Set the y-axis (z-axis in our case) limits
-# min_z = np.min(triangulation.y) - 100
-# max_z = np.max(triangulation.y) + 100
-# ax.set_ylim(min_z, max_z)
-
-# buf = BytesIO()
-# plt.savefig(buf, bbox_inches="tight", pad_inches=0)
-# buf.seek(0)
-# im_base64 = base64.b64encode(buf.read()).decode("utf-8")
-# plt.close(fig)
-
-# return im_base64
diff --git a/backend/src/services/utils/vtk_utils.py b/backend/src/services/utils/vtk_utils.py
deleted file mode 100644
index 340f6cf28..000000000
--- a/backend/src/services/utils/vtk_utils.py
+++ /dev/null
@@ -1,298 +0,0 @@
-# pylint: skip-file
-# type: ignore
-# for now
-from typing import Optional, List
-from dataclasses import dataclass
-import numpy as np
-import xtgeo
-
-# pylint: disable=no-name-in-module,
-from vtkmodules.util.numpy_support import (
- numpy_to_vtk,
- numpy_to_vtkIdTypeArray,
- vtk_to_numpy,
-)
-
-# pylint: disable=no-name-in-module,
-from vtkmodules.vtkCommonCore import vtkPoints
-
-# pylint: disable=no-name-in-module,
-from vtkmodules.vtkCommonDataModel import (
- vtkCellArray,
- vtkDataSetAttributes,
- vtkExplicitStructuredGrid,
- vtkUnstructuredGrid,
- vtkPolyData,
- vtkPlane,
-)
-
-# pylint: disable=no-name-in-module,
-from vtkmodules.vtkFiltersCore import (
- vtkAppendPolyData,
- vtkClipPolyData,
- vtkExplicitStructuredGridCrop,
- vtkExplicitStructuredGridToUnstructuredGrid,
- vtkExtractCellsAlongPolyLine,
- vtkPlaneCutter,
- vtkUnstructuredGridToExplicitStructuredGrid,
-)
-
-# pylint: disable=no-name-in-module,
-from vtkmodules.vtkFiltersGeometry import vtkExplicitStructuredGridSurfaceFilter
-
-# pylint: disable=no-name-in-module,
-from vtkmodules.vtkFiltersSources import vtkPolyLineSource
-
-
-@dataclass
-class VtkGridSurface:
- polydata: vtkPolyData
- original_cell_ids: np.ndarray
-
-
-def _create_vtk_esgrid_from_verts_and_conn(
- point_dims: np.ndarray, vertex_arr_np: np.ndarray, conn_arr_np: np.ndarray
-) -> vtkExplicitStructuredGrid:
- vertex_arr_np = vertex_arr_np.reshape(-1, 3)
- points_vtkarr = numpy_to_vtk(vertex_arr_np, deep=1)
- vtk_points = vtkPoints()
- vtk_points.SetData(points_vtkarr)
-
- conn_idarr = numpy_to_vtkIdTypeArray(conn_arr_np, deep=1)
- vtk_cell_array = vtkCellArray()
- vtk_cell_array.SetData(8, conn_idarr)
-
- vtk_esgrid = vtkExplicitStructuredGrid()
- vtk_esgrid.SetDimensions(point_dims)
- vtk_esgrid.SetPoints(vtk_points)
- vtk_esgrid.SetCells(vtk_cell_array)
-
- vtk_esgrid.ComputeFacesConnectivityFlagsArray()
-
- return vtk_esgrid
-
-
-def xtgeo_grid_to_vtk_explicit_structured_grid(
- xtg_grid: xtgeo.Grid,
-) -> vtkExplicitStructuredGrid:
- # Create geometry data suitable for use with VTK's explicit structured grid
- # based on the specified xtgeo 3d grid
- pt_dims, vertex_arr, conn_arr, inactive_arr = xtg_grid.get_vtk_esg_geometry_data()
- vertex_arr[:, 2] *= -1
-
- vtk_esgrid = _create_vtk_esgrid_from_verts_and_conn(pt_dims, vertex_arr, conn_arr)
-
- # Make sure we hide the inactive cells.
- # First we let VTK allocate cell ghost array, then we obtain a numpy view
- # on the array and write to that (we're actually modifying the native VTK array)
- ghost_arr_vtk = vtk_esgrid.AllocateCellGhostArray()
- ghost_arr_np = vtk_to_numpy(ghost_arr_vtk)
- ghost_arr_np[inactive_arr] = vtkDataSetAttributes.HIDDENCELL
-
- return vtk_esgrid
-
-
-def _calc_grid_surface(esgrid: vtkExplicitStructuredGrid) -> vtkPolyData:
- surf_filter = vtkExplicitStructuredGridSurfaceFilter()
- surf_filter.SetInputData(esgrid)
- surf_filter.PassThroughCellIdsOn()
- surf_filter.Update()
-
- polydata: vtkPolyData = surf_filter.GetOutput()
- return polydata
-
-
-def get_surface(
- xtgeo_grid: xtgeo.Grid,
-) -> VtkGridSurface:
- es_grid = xtgeo_grid_to_vtk_explicit_structured_grid(xtgeo_grid)
- polydata = _calc_grid_surface(es_grid)
-
- original_cell_indices_np = vtk_to_numpy(polydata.GetCellData().GetAbstractArray("vtkOriginalCellIds"))
- return VtkGridSurface(polydata=polydata, original_cell_ids=original_cell_indices_np)
-
-
-def get_scalar_values(xtgeo_grid_property: xtgeo.GridProperty, cell_ids: Optional[np.ndarray] = None) -> np.ndarray:
- fill_value = 0.0 if not xtgeo_grid_property.isdiscrete else -1
- raw_scalar_np = xtgeo_grid_property.values.ravel(order="F")
- raw_scalar_np.filled(fill_value)
-
- if cell_ids is not None:
- return raw_scalar_np[cell_ids].astype(np.float32)
- return raw_scalar_np.astype(np.float32)
-
-
-def _vtk_esg_to_ug(vtk_esgrid: vtkExplicitStructuredGrid) -> vtkUnstructuredGrid:
- convert_filter = vtkExplicitStructuredGridToUnstructuredGrid()
- convert_filter.SetInputData(vtk_esgrid)
- convert_filter.Update()
- vtk_ugrid = convert_filter.GetOutput()
-
- return vtk_ugrid
-
-
-def cut_along_polyline(
- esgrid: vtkExplicitStructuredGrid,
- polyline_xy: List[float],
-) -> vtkPolyData:
- num_points_in_polyline = int(len(polyline_xy) / 2)
-
- ugrid = _vtk_esg_to_ug(esgrid)
-
- # !!!!!!!!!!!!!!
- # Requires VTK 9.2-ish
- # ugrid = _extract_intersected_ugrid(ugrid, polyline_xy, 10.0)
-
- cutter_alg = vtkPlaneCutter()
- cutter_alg.SetInputDataObject(ugrid)
-
- # cell_locator = vtkStaticCellLocator()
- # cell_locator.SetDataSet(esgrid)
- # cell_locator.BuildLocator()
-
- # box_clip_alg = vtkBoxClipDataSet()
- # box_clip_alg.SetInputDataObject(ugrid)
-
- append_alg = vtkAppendPolyData()
-
- et_cut_s = 0.0
- et_clip_s = 0.0
-
- for i in range(0, num_points_in_polyline - 1):
- x_0 = polyline_xy[2 * i]
- y_0 = polyline_xy[2 * i + 1]
- x_1 = polyline_xy[2 * (i + 1)]
- y_1 = polyline_xy[2 * (i + 1) + 1]
- fwd_vec = np.array([x_1 - x_0, y_1 - y_0, 0.0])
- fwd_vec /= np.linalg.norm(fwd_vec)
- right_vec = np.array([fwd_vec[1], -fwd_vec[0], 0])
-
- # box_clip_alg.SetBoxClip(x_0, x_1, y_0, y_1, min_z, max_z)
- # box_clip_alg.Update()
- # clipped_ugrid = box_clip_alg.GetOutputDataObject(0)
-
- # polyline_bounds = _calc_polyline_bounds([x_0, y_0, x_1, y_1])
- # polyline_bounds.extend([min_z, max_z])
- # cell_ids = vtkIdList()
- # cell_locator.FindCellsWithinBounds(polyline_bounds, cell_ids)
- # print(f"{cell_ids.GetNumberOfIds()} {polyline_bounds=}")
-
- plane = vtkPlane()
- plane.SetOrigin([x_0, y_0, 0])
- plane.SetNormal(right_vec)
-
- plane_0 = vtkPlane()
- plane_0.SetOrigin([x_0, y_0, 0])
- plane_0.SetNormal(fwd_vec)
-
- plane_1 = vtkPlane()
- plane_1.SetOrigin([x_1, y_1, 0])
- plane_1.SetNormal(-fwd_vec)
-
- cutter_alg.SetPlane(plane)
- cutter_alg.Update()
-
- cut_surface_polydata = cutter_alg.GetOutput()
- # print(f"{type(cut_surface_polydata)=}")
-
- # Used vtkPolyDataPlaneClipper earlier, but it seems that it doesn't
- # maintain the original cell IDs that we need for the result mapping.
- # May want to check up on any performance degradation!
- clipper_0 = vtkClipPolyData()
- clipper_0.SetInputDataObject(cut_surface_polydata)
- clipper_0.SetClipFunction(plane_0)
- clipper_0.Update()
- clipped_polydata = clipper_0.GetOutput()
-
- clipper_1 = vtkClipPolyData()
- clipper_1.SetInputDataObject(clipped_polydata)
- clipper_1.SetClipFunction(plane_1)
- clipper_1.Update()
- clipped_polydata = clipper_1.GetOutput()
-
- append_alg.AddInputData(clipped_polydata)
-
- append_alg.Update()
- comb_polydata = append_alg.GetOutput()
- return comb_polydata
-
-
-def flatten_sliced_grid(sliced_grid: vtkPolyData, polyline, original_cell_ids) -> vtkPolyData:
- """Flatten the sliced grid to a 2D grid."""
- points = sliced_grid.GetPoints()
- num_points = points.GetNumberOfPoints()
- flattened_points = vtkPoints()
-
- for i in range(num_points):
- point = np.array(points.GetPoint(i))
- min_dist = float("inf")
- closest_point = np.array(polyline.GetPoint(0))[:2]
- for j in range(polyline.GetNumberOfPoints() - 1):
- p1 = np.array(polyline.GetPoint(j))[:2]
- p2 = np.array(polyline.GetPoint(j + 1))[:2]
- segment = p2 - p1
- segment_length = np.linalg.norm(segment)
- segment_normalized = segment / segment_length
- projection = np.dot(point[:2] - p1, segment_normalized)
- if 0 <= projection <= segment_length:
- projected_point = p1 + projection * segment_normalized
- dist = np.linalg.norm(point[:2] - projected_point)
- if dist < min_dist:
- min_dist = dist
- closest_point = projected_point
-
- flattened_points.InsertNextPoint(
- (
- np.linalg.norm(closest_point - np.array(polyline.GetPoint(0))[:2]),
- point[2],
- 0,
- )
- )
-
- flattened_grid = vtkPolyData()
- flattened_grid.SetPoints(flattened_points)
- flattened_grid.SetPolys(sliced_grid.GetPolys())
-
- # Transfer original cell IDs to the flattened grid
- original_cell_ids_array = numpy_to_vtk(np.array(original_cell_ids))
- flattened_grid.GetCellData().AddArray(original_cell_ids_array)
- flattened_grid.GetCellData().GetAbstractArray(0).SetName("vtkOriginalCellIds")
-
- return flattened_grid
-
-
-def get_triangles(poly_data) -> List[List[int]]:
- triangles = []
- num_cells = poly_data.GetNumberOfCells()
- for i in range(num_cells):
- cell = poly_data.GetCell(i)
- if cell.GetNumberOfPoints() == 3:
- triangles.append([cell.GetPointId(0), cell.GetPointId(1), cell.GetPointId(2)])
- return triangles
-
-
-def create_polyline(polyline: List[List[float]]):
- points = vtkPoints()
- for point in polyline:
- points.InsertNextPoint(point)
- points.InsertNextPoint(point)
- points.InsertNextPoint(point)
- points.InsertNextPoint(point)
- points.InsertNextPoint(point)
-
- polyline = vtkPolyLineSource()
- polyline.SetPoints(points)
-
- polyline.Update()
- return polyline.GetOutput()
-
-
-def grid_to_numpy(flattened_grid):
- points = flattened_grid.GetPoints()
- num_points = points.GetNumberOfPoints()
- coords = np.zeros((num_points, 2))
-
- for i in range(num_points):
- coords[i, 0], coords[i, 1], _ = points.GetPoint(i)
-
- return coords
diff --git a/backend/src/services/vds_access/__init__.py b/backend/src/services/vds_access/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/backend/tests/__init__.py b/backend/tests/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/backend/tests/unit/__init__.py b/backend/tests/unit/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/backend/tests/unit/services/__init__.py b/backend/tests/unit/services/__init__.py
deleted file mode 100644
index e69de29bb..000000000
diff --git a/backend_py/libs/core_utils/poetry.lock b/backend_py/libs/core_utils/poetry.lock
new file mode 100644
index 000000000..f03c465b8
--- /dev/null
+++ b/backend_py/libs/core_utils/poetry.lock
@@ -0,0 +1,183 @@
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
+
+[[package]]
+name = "annotated-types"
+version = "0.6.0"
+description = "Reusable constraint types to use with typing.Annotated"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
+ {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
+]
+
+[[package]]
+name = "numpy"
+version = "1.26.4"
+description = "Fundamental package for array computing in Python"
+optional = false
+python-versions = ">=3.9"
+files = [
+ {file = "numpy-1.26.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:9ff0f4f29c51e2803569d7a51c2304de5554655a60c5d776e35b4a41413830d0"},
+ {file = "numpy-1.26.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2e4ee3380d6de9c9ec04745830fd9e2eccb3e6cf790d39d7b98ffd19b0dd754a"},
+ {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d209d8969599b27ad20994c8e41936ee0964e6da07478d6c35016bc386b66ad4"},
+ {file = "numpy-1.26.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ffa75af20b44f8dba823498024771d5ac50620e6915abac414251bd971b4529f"},
+ {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:62b8e4b1e28009ef2846b4c7852046736bab361f7aeadeb6a5b89ebec3c7055a"},
+ {file = "numpy-1.26.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a4abb4f9001ad2858e7ac189089c42178fcce737e4169dc61321660f1a96c7d2"},
+ {file = "numpy-1.26.4-cp310-cp310-win32.whl", hash = "sha256:bfe25acf8b437eb2a8b2d49d443800a5f18508cd811fea3181723922a8a82b07"},
+ {file = "numpy-1.26.4-cp310-cp310-win_amd64.whl", hash = "sha256:b97fe8060236edf3662adfc2c633f56a08ae30560c56310562cb4f95500022d5"},
+ {file = "numpy-1.26.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:4c66707fabe114439db9068ee468c26bbdf909cac0fb58686a42a24de1760c71"},
+ {file = "numpy-1.26.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:edd8b5fe47dab091176d21bb6de568acdd906d1887a4584a15a9a96a1dca06ef"},
+ {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7ab55401287bfec946ced39700c053796e7cc0e3acbef09993a9ad2adba6ca6e"},
+ {file = "numpy-1.26.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:666dbfb6ec68962c033a450943ded891bed2d54e6755e35e5835d63f4f6931d5"},
+ {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:96ff0b2ad353d8f990b63294c8986f1ec3cb19d749234014f4e7eb0112ceba5a"},
+ {file = "numpy-1.26.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:60dedbb91afcbfdc9bc0b1f3f402804070deed7392c23eb7a7f07fa857868e8a"},
+ {file = "numpy-1.26.4-cp311-cp311-win32.whl", hash = "sha256:1af303d6b2210eb850fcf03064d364652b7120803a0b872f5211f5234b399f20"},
+ {file = "numpy-1.26.4-cp311-cp311-win_amd64.whl", hash = "sha256:cd25bcecc4974d09257ffcd1f098ee778f7834c3ad767fe5db785be9a4aa9cb2"},
+ {file = "numpy-1.26.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b3ce300f3644fb06443ee2222c2201dd3a89ea6040541412b8fa189341847218"},
+ {file = "numpy-1.26.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:03a8c78d01d9781b28a6989f6fa1bb2c4f2d51201cf99d3dd875df6fbd96b23b"},
+ {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9fad7dcb1aac3c7f0584a5a8133e3a43eeb2fe127f47e3632d43d677c66c102b"},
+ {file = "numpy-1.26.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:675d61ffbfa78604709862923189bad94014bef562cc35cf61d3a07bba02a7ed"},
+ {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ab47dbe5cc8210f55aa58e4805fe224dac469cde56b9f731a4c098b91917159a"},
+ {file = "numpy-1.26.4-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1dda2e7b4ec9dd512f84935c5f126c8bd8b9f2fc001e9f54af255e8c5f16b0e0"},
+ {file = "numpy-1.26.4-cp312-cp312-win32.whl", hash = "sha256:50193e430acfc1346175fcbdaa28ffec49947a06918b7b92130744e81e640110"},
+ {file = "numpy-1.26.4-cp312-cp312-win_amd64.whl", hash = "sha256:08beddf13648eb95f8d867350f6a018a4be2e5ad54c8d8caed89ebca558b2818"},
+ {file = "numpy-1.26.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7349ab0fa0c429c82442a27a9673fc802ffdb7c7775fad780226cb234965e53c"},
+ {file = "numpy-1.26.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:52b8b60467cd7dd1e9ed082188b4e6bb35aa5cdd01777621a1658910745b90be"},
+ {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d5241e0a80d808d70546c697135da2c613f30e28251ff8307eb72ba696945764"},
+ {file = "numpy-1.26.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f870204a840a60da0b12273ef34f7051e98c3b5961b61b0c2c1be6dfd64fbcd3"},
+ {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:679b0076f67ecc0138fd2ede3a8fd196dddc2ad3254069bcb9faf9a79b1cebcd"},
+ {file = "numpy-1.26.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:47711010ad8555514b434df65f7d7b076bb8261df1ca9bb78f53d3b2db02e95c"},
+ {file = "numpy-1.26.4-cp39-cp39-win32.whl", hash = "sha256:a354325ee03388678242a4d7ebcd08b5c727033fcff3b2f536aea978e15ee9e6"},
+ {file = "numpy-1.26.4-cp39-cp39-win_amd64.whl", hash = "sha256:3373d5d70a5fe74a2c1bb6d2cfd9609ecf686d47a2d7b1d37a8f3b6bf6003aea"},
+ {file = "numpy-1.26.4-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:afedb719a9dcfc7eaf2287b839d8198e06dcd4cb5d276a3df279231138e83d30"},
+ {file = "numpy-1.26.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:95a7476c59002f2f6c590b9b7b998306fba6a5aa646b1e22ddfeaf8f78c3a29c"},
+ {file = "numpy-1.26.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7e50d0a0cc3189f9cb0aeb3a6a6af18c16f59f004b866cd2be1c14b36134a4a0"},
+ {file = "numpy-1.26.4.tar.gz", hash = "sha256:2a02aba9ed12e4ac4eb3ea9421c420301a0c6460d9830d74a9df87efa4912010"},
+]
+
+[[package]]
+name = "pydantic"
+version = "2.6.3"
+description = "Data validation using Python type hints"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic-2.6.3-py3-none-any.whl", hash = "sha256:72c6034df47f46ccdf81869fddb81aade68056003900a8724a4f160700016a2a"},
+ {file = "pydantic-2.6.3.tar.gz", hash = "sha256:e07805c4c7f5c6826e33a1d4c9d47950d7eaf34868e2690f8594d2e30241f11f"},
+]
+
+[package.dependencies]
+annotated-types = ">=0.4.0"
+pydantic-core = "2.16.3"
+typing-extensions = ">=4.6.1"
+
+[package.extras]
+email = ["email-validator (>=2.0.0)"]
+
+[[package]]
+name = "pydantic-core"
+version = "2.16.3"
+description = ""
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
+ {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
+ {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
+ {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
+ {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
+ {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
+ {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
+ {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
+ {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
+ {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
+ {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
+ {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
+ {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
+ {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
+
+[[package]]
+name = "typing-extensions"
+version = "4.10.0"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
+ {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
+]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.11"
+content-hash = "94e824aa93b25684a6ae3f9bbff99c166a956ec1cbc59a6214133d9212d42d40"
diff --git a/backend_py/libs/core_utils/pyproject.toml b/backend_py/libs/core_utils/pyproject.toml
new file mode 100644
index 000000000..6045696ff
--- /dev/null
+++ b/backend_py/libs/core_utils/pyproject.toml
@@ -0,0 +1,15 @@
+[tool.poetry]
+name = "core-utils"
+version = "0.0.1"
+description = "Package with general Webviz utilities"
+authors = ["R&T Equinor", "Ceetron Solutions AS"]
+packages = [ { include = "webviz_pkg" } ]
+
+[tool.poetry.dependencies]
+python = "^3.11"
+numpy = "^1.24.1"
+pydantic = "^2.3.0"
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
\ No newline at end of file
diff --git a/backend/src/services/utils/b64.py b/backend_py/libs/core_utils/webviz_pkg/core_utils/b64.py
similarity index 100%
rename from backend/src/services/utils/b64.py
rename to backend_py/libs/core_utils/webviz_pkg/core_utils/b64.py
diff --git a/backend/src/services/utils/perf_timer.py b/backend_py/libs/core_utils/webviz_pkg/core_utils/perf_timer.py
similarity index 100%
rename from backend/src/services/utils/perf_timer.py
rename to backend_py/libs/core_utils/webviz_pkg/core_utils/perf_timer.py
diff --git a/backend/.vscode/launch.json b/backend_py/primary/.vscode/launch.json
similarity index 82%
rename from backend/.vscode/launch.json
rename to backend_py/primary/.vscode/launch.json
index 6f7bb14f7..695c19216 100644
--- a/backend/.vscode/launch.json
+++ b/backend_py/primary/.vscode/launch.json
@@ -8,7 +8,7 @@
"pathMappings": [
{
"localRoot": "${workspaceFolder}",
- "remoteRoot": "/home/appuser/backend"
+ "remoteRoot": "/home/appuser/backend_py/primary"
}
]
}
diff --git a/backend_py/primary/Dockerfile b/backend_py/primary/Dockerfile
new file mode 100644
index 000000000..c41b46a93
--- /dev/null
+++ b/backend_py/primary/Dockerfile
@@ -0,0 +1,27 @@
+FROM python:3.11-slim@sha256:ad2c4e5884418404c5289acad4a471dde8500e24ba57ad574cdcae46523e507a
+
+RUN useradd --create-home --uid 1234 appuser # Changing to non-root user early
+
+USER 1234
+
+ENV PATH="${PATH}:/home/appuser/.local/bin"
+
+RUN python3 -m pip install --user pipx
+RUN python3 -m pipx ensurepath
+RUN pipx install poetry==1.8.2
+
+ENV VIRTUAL_ENV=/home/appuser/venv
+RUN python3 -m venv $VIRTUAL_ENV
+ENV PATH="$VIRTUAL_ENV/bin:$PATH"
+
+WORKDIR /home/appuser/backend_py/primary
+
+COPY --chown=appuser ./backend_py/primary/pyproject.toml /home/appuser/backend_py/primary/
+COPY --chown=appuser ./backend_py/primary/poetry.lock /home/appuser/backend_py/primary/
+RUN poetry install --only main --no-root --no-directory
+
+COPY --chown=appuser ./backend_py/libs /home/appuser/backend_py/libs
+COPY --chown=appuser ./backend_py/primary /home/appuser/backend_py/primary
+RUN poetry install --only main
+
+CMD exec uvicorn --proxy-headers --host=0.0.0.0 primary.main:app
diff --git a/backend/README.md b/backend_py/primary/README.md
similarity index 100%
rename from backend/README.md
rename to backend_py/primary/README.md
diff --git a/backend/poetry.lock b/backend_py/primary/poetry.lock
similarity index 95%
rename from backend/poetry.lock
rename to backend_py/primary/poetry.lock
index 62b40f8bd..1f65263f7 100644
--- a/backend/poetry.lock
+++ b/backend_py/primary/poetry.lock
@@ -1,4 +1,4 @@
-# This file is automatically @generated by Poetry 1.6.1 and should not be changed by hand.
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
[[package]]
name = "annotated-types"
@@ -594,6 +594,23 @@ mypy = ["contourpy[bokeh]", "docutils-stubs", "mypy (==0.991)", "types-Pillow"]
test = ["Pillow", "matplotlib", "pytest"]
test-no-images = ["pytest"]
+[[package]]
+name = "core-utils"
+version = "0.0.1"
+description = "Package with general Webviz utilities"
+optional = false
+python-versions = "^3.11"
+files = []
+develop = true
+
+[package.dependencies]
+numpy = "^1.24.1"
+pydantic = "^2.3.0"
+
+[package.source]
+type = "directory"
+url = "../libs/core_utils"
+
[[package]]
name = "cryptography"
version = "39.0.0"
@@ -1322,6 +1339,98 @@ files = [
{file = "mdurl-0.1.2.tar.gz", hash = "sha256:bb413d29f5eea38f31dd4754dd7377d4465116fb207585f97bf925588687c1ba"},
]
+[[package]]
+name = "mmh3"
+version = "4.1.0"
+description = "Python extension for MurmurHash (MurmurHash3), a set of fast and robust hash functions."
+optional = false
+python-versions = "*"
+files = [
+ {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:be5ac76a8b0cd8095784e51e4c1c9c318c19edcd1709a06eb14979c8d850c31a"},
+ {file = "mmh3-4.1.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:98a49121afdfab67cd80e912b36404139d7deceb6773a83620137aaa0da5714c"},
+ {file = "mmh3-4.1.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:5259ac0535874366e7d1a5423ef746e0d36a9e3c14509ce6511614bdc5a7ef5b"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c5950827ca0453a2be357696da509ab39646044e3fa15cad364eb65d78797437"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1dd0f652ae99585b9dd26de458e5f08571522f0402155809fd1dc8852a613a39"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:99d25548070942fab1e4a6f04d1626d67e66d0b81ed6571ecfca511f3edf07e6"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:53db8d9bad3cb66c8f35cbc894f336273f63489ce4ac416634932e3cbe79eb5b"},
+ {file = "mmh3-4.1.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75da0f615eb55295a437264cc0b736753f830b09d102aa4c2a7d719bc445ec05"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:b926b07fd678ea84b3a2afc1fa22ce50aeb627839c44382f3d0291e945621e1a"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c5b053334f9b0af8559d6da9dc72cef0a65b325ebb3e630c680012323c950bb6"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:5bf33dc43cd6de2cb86e0aa73a1cc6530f557854bbbe5d59f41ef6de2e353d7b"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fa7eacd2b830727ba3dd65a365bed8a5c992ecd0c8348cf39a05cc77d22f4970"},
+ {file = "mmh3-4.1.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:42dfd6742b9e3eec599f85270617debfa0bbb913c545bb980c8a4fa7b2d047da"},
+ {file = "mmh3-4.1.0-cp310-cp310-win32.whl", hash = "sha256:2974ad343f0d39dcc88e93ee6afa96cedc35a9883bc067febd7ff736e207fa47"},
+ {file = "mmh3-4.1.0-cp310-cp310-win_amd64.whl", hash = "sha256:74699a8984ded645c1a24d6078351a056f5a5f1fe5838870412a68ac5e28d865"},
+ {file = "mmh3-4.1.0-cp310-cp310-win_arm64.whl", hash = "sha256:f0dc874cedc23d46fc488a987faa6ad08ffa79e44fb08e3cd4d4cf2877c00a00"},
+ {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:3280a463855b0eae64b681cd5b9ddd9464b73f81151e87bb7c91a811d25619e6"},
+ {file = "mmh3-4.1.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:97ac57c6c3301769e757d444fa7c973ceb002cb66534b39cbab5e38de61cd896"},
+ {file = "mmh3-4.1.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a7b6502cdb4dbd880244818ab363c8770a48cdccecf6d729ade0241b736b5ec0"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52ba2da04671a9621580ddabf72f06f0e72c1c9c3b7b608849b58b11080d8f14"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5a5fef4c4ecc782e6e43fbeab09cff1bac82c998a1773d3a5ee6a3605cde343e"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5135358a7e00991f73b88cdc8eda5203bf9de22120d10a834c5761dbeb07dd13"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cff9ae76a54f7c6fe0167c9c4028c12c1f6de52d68a31d11b6790bb2ae685560"},
+ {file = "mmh3-4.1.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f6f02576a4d106d7830ca90278868bf0983554dd69183b7bbe09f2fcd51cf54f"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:073d57425a23721730d3ff5485e2da489dd3c90b04e86243dd7211f889898106"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:71e32ddec7f573a1a0feb8d2cf2af474c50ec21e7a8263026e8d3b4b629805db"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7cbb20b29d57e76a58b40fd8b13a9130db495a12d678d651b459bf61c0714cea"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:a42ad267e131d7847076bb7e31050f6c4378cd38e8f1bf7a0edd32f30224d5c9"},
+ {file = "mmh3-4.1.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4a013979fc9390abadc445ea2527426a0e7a4495c19b74589204f9b71bcaafeb"},
+ {file = "mmh3-4.1.0-cp311-cp311-win32.whl", hash = "sha256:1d3b1cdad7c71b7b88966301789a478af142bddcb3a2bee563f7a7d40519a00f"},
+ {file = "mmh3-4.1.0-cp311-cp311-win_amd64.whl", hash = "sha256:0dc6dc32eb03727467da8e17deffe004fbb65e8b5ee2b502d36250d7a3f4e2ec"},
+ {file = "mmh3-4.1.0-cp311-cp311-win_arm64.whl", hash = "sha256:9ae3a5c1b32dda121c7dc26f9597ef7b01b4c56a98319a7fe86c35b8bc459ae6"},
+ {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:0033d60c7939168ef65ddc396611077a7268bde024f2c23bdc283a19123f9e9c"},
+ {file = "mmh3-4.1.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d6af3e2287644b2b08b5924ed3a88c97b87b44ad08e79ca9f93d3470a54a41c5"},
+ {file = "mmh3-4.1.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:d82eb4defa245e02bb0b0dc4f1e7ee284f8d212633389c91f7fba99ba993f0a2"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ba245e94b8d54765e14c2d7b6214e832557e7856d5183bc522e17884cab2f45d"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bb04e2feeabaad6231e89cd43b3d01a4403579aa792c9ab6fdeef45cc58d4ec0"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e3b1a27def545ce11e36158ba5d5390cdbc300cfe456a942cc89d649cf7e3b2"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ce0ab79ff736d7044e5e9b3bfe73958a55f79a4ae672e6213e92492ad5e734d5"},
+ {file = "mmh3-4.1.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b02268be6e0a8eeb8a924d7db85f28e47344f35c438c1e149878bb1c47b1cd3"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:deb887f5fcdaf57cf646b1e062d56b06ef2f23421c80885fce18b37143cba828"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:99dd564e9e2b512eb117bd0cbf0f79a50c45d961c2a02402787d581cec5448d5"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:08373082dfaa38fe97aa78753d1efd21a1969e51079056ff552e687764eafdfe"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:54b9c6a2ea571b714e4fe28d3e4e2db37abfd03c787a58074ea21ee9a8fd1740"},
+ {file = "mmh3-4.1.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a7b1edf24c69e3513f879722b97ca85e52f9032f24a52284746877f6a7304086"},
+ {file = "mmh3-4.1.0-cp312-cp312-win32.whl", hash = "sha256:411da64b951f635e1e2284b71d81a5a83580cea24994b328f8910d40bed67276"},
+ {file = "mmh3-4.1.0-cp312-cp312-win_amd64.whl", hash = "sha256:bebc3ecb6ba18292e3d40c8712482b4477abd6981c2ebf0e60869bd90f8ac3a9"},
+ {file = "mmh3-4.1.0-cp312-cp312-win_arm64.whl", hash = "sha256:168473dd608ade6a8d2ba069600b35199a9af837d96177d3088ca91f2b3798e3"},
+ {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:372f4b7e1dcde175507640679a2a8790185bb71f3640fc28a4690f73da986a3b"},
+ {file = "mmh3-4.1.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:438584b97f6fe13e944faf590c90fc127682b57ae969f73334040d9fa1c7ffa5"},
+ {file = "mmh3-4.1.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:6e27931b232fc676675fac8641c6ec6b596daa64d82170e8597f5a5b8bdcd3b6"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:571a92bad859d7b0330e47cfd1850b76c39b615a8d8e7aa5853c1f971fd0c4b1"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4a69d6afe3190fa08f9e3a58e5145549f71f1f3fff27bd0800313426929c7068"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:afb127be0be946b7630220908dbea0cee0d9d3c583fa9114a07156f98566dc28"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:940d86522f36348ef1a494cbf7248ab3f4a1638b84b59e6c9e90408bd11ad729"},
+ {file = "mmh3-4.1.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b3dcccc4935686619a8e3d1f7b6e97e3bd89a4a796247930ee97d35ea1a39341"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:01bb9b90d61854dfc2407c5e5192bfb47222d74f29d140cb2dd2a69f2353f7cc"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bcb1b8b951a2c0b0fb8a5426c62a22557e2ffc52539e0a7cc46eb667b5d606a9"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:6477a05d5e5ab3168e82e8b106e316210ac954134f46ec529356607900aea82a"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:da5892287e5bea6977364b15712a2573c16d134bc5fdcdd4cf460006cf849278"},
+ {file = "mmh3-4.1.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:99180d7fd2327a6fffbaff270f760576839dc6ee66d045fa3a450f3490fda7f5"},
+ {file = "mmh3-4.1.0-cp38-cp38-win32.whl", hash = "sha256:9b0d4f3949913a9f9a8fb1bb4cc6ecd52879730aab5ff8c5a3d8f5b593594b73"},
+ {file = "mmh3-4.1.0-cp38-cp38-win_amd64.whl", hash = "sha256:598c352da1d945108aee0c3c3cfdd0e9b3edef74108f53b49d481d3990402169"},
+ {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:475d6d1445dd080f18f0f766277e1237fa2914e5fe3307a3b2a3044f30892103"},
+ {file = "mmh3-4.1.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:5ca07c41e6a2880991431ac717c2a049056fff497651a76e26fc22224e8b5732"},
+ {file = "mmh3-4.1.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0ebe052fef4bbe30c0548d12ee46d09f1b69035ca5208a7075e55adfe091be44"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:eaefd42e85afb70f2b855a011f7b4d8a3c7e19c3f2681fa13118e4d8627378c5"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ac0ae43caae5a47afe1b63a1ae3f0986dde54b5fb2d6c29786adbfb8edc9edfb"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6218666f74c8c013c221e7f5f8a693ac9cf68e5ac9a03f2373b32d77c48904de"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:ac59294a536ba447b5037f62d8367d7d93b696f80671c2c45645fa9f1109413c"},
+ {file = "mmh3-4.1.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:086844830fcd1e5c84fec7017ea1ee8491487cfc877847d96f86f68881569d2e"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e42b38fad664f56f77f6fbca22d08450f2464baa68acdbf24841bf900eb98e87"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:d08b790a63a9a1cde3b5d7d733ed97d4eb884bfbc92f075a091652d6bfd7709a"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:73ea4cc55e8aea28c86799ecacebca09e5f86500414870a8abaedfcbaf74d288"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:f90938ff137130e47bcec8dc1f4ceb02f10178c766e2ef58a9f657ff1f62d124"},
+ {file = "mmh3-4.1.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:aa1f13e94b8631c8cd53259250556edcf1de71738936b60febba95750d9632bd"},
+ {file = "mmh3-4.1.0-cp39-cp39-win32.whl", hash = "sha256:a3b680b471c181490cf82da2142029edb4298e1bdfcb67c76922dedef789868d"},
+ {file = "mmh3-4.1.0-cp39-cp39-win_amd64.whl", hash = "sha256:fefef92e9c544a8dbc08f77a8d1b6d48006a750c4375bbcd5ff8199d761e263b"},
+ {file = "mmh3-4.1.0-cp39-cp39-win_arm64.whl", hash = "sha256:8e2c1f6a2b41723a4f82bd5a762a777836d29d664fc0095f17910bea0adfd4a6"},
+ {file = "mmh3-4.1.0.tar.gz", hash = "sha256:a1cf25348b9acd229dda464a094d6170f47d2850a1fcb762a3b6172d2ce6ca4a"},
+]
+
+[package.extras]
+test = ["mypy (>=1.0)", "pytest (>=7.0.0)"]
+
[[package]]
name = "msal"
version = "1.20.0"
@@ -2236,30 +2345,20 @@ redis = ["redis"]
tests = ["pytest (>=5.4.1)", "pytest-cov (>=2.8.1)", "pytest-mypy (>=0.8.0)", "pytest-timeout (>=2.1.0)", "redis", "sphinx (>=6.0.0)"]
[[package]]
-name = "psutil"
-version = "5.9.5"
-description = "Cross-platform lib for process and system monitoring in Python."
+name = "pottery"
+version = "3.0.0"
+description = "Redis for Humans."
optional = false
-python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*"
+python-versions = ">=3.7, <4"
files = [
- {file = "psutil-5.9.5-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:be8929ce4313f9f8146caad4272f6abb8bf99fc6cf59344a3167ecd74f4f203f"},
- {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:ab8ed1a1d77c95453db1ae00a3f9c50227ebd955437bcf2a574ba8adbf6a74d5"},
- {file = "psutil-5.9.5-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:4aef137f3345082a3d3232187aeb4ac4ef959ba3d7c10c33dd73763fbc063da4"},
- {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:ea8518d152174e1249c4f2a1c89e3e6065941df2fa13a1ab45327716a23c2b48"},
- {file = "psutil-5.9.5-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:acf2aef9391710afded549ff602b5887d7a2349831ae4c26be7c807c0a39fac4"},
- {file = "psutil-5.9.5-cp27-none-win32.whl", hash = "sha256:5b9b8cb93f507e8dbaf22af6a2fd0ccbe8244bf30b1baad6b3954e935157ae3f"},
- {file = "psutil-5.9.5-cp27-none-win_amd64.whl", hash = "sha256:8c5f7c5a052d1d567db4ddd231a9d27a74e8e4a9c3f44b1032762bd7b9fdcd42"},
- {file = "psutil-5.9.5-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:3c6f686f4225553615612f6d9bc21f1c0e305f75d7d8454f9b46e901778e7217"},
- {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7a7dd9997128a0d928ed4fb2c2d57e5102bb6089027939f3b722f3a210f9a8da"},
- {file = "psutil-5.9.5-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:89518112647f1276b03ca97b65cc7f64ca587b1eb0278383017c2a0dcc26cbe4"},
- {file = "psutil-5.9.5-cp36-abi3-win32.whl", hash = "sha256:104a5cc0e31baa2bcf67900be36acde157756b9c44017b86b2c049f11957887d"},
- {file = "psutil-5.9.5-cp36-abi3-win_amd64.whl", hash = "sha256:b258c0c1c9d145a1d5ceffab1134441c4c5113b2417fafff7315a917a026c3c9"},
- {file = "psutil-5.9.5-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:c607bb3b57dc779d55e1554846352b4e358c10fff3abf3514a7a6601beebdb30"},
- {file = "psutil-5.9.5.tar.gz", hash = "sha256:5410638e4df39c54d957fc51ce03048acd8e6d60abc0f5107af51e5fb566eb3c"},
+ {file = "pottery-3.0.0-py3-none-any.whl", hash = "sha256:0190323bbb1289d40c5cd683feb04c4b8cff76a6c723f3ded9137c8bcc9fb5f8"},
+ {file = "pottery-3.0.0.tar.gz", hash = "sha256:adda303e9357442bcac1d4c7f86aa7deec855e0190c101d09448afbcf5676a74"},
]
-[package.extras]
-test = ["enum34", "ipaddress", "mock", "pywin32", "wmi"]
+[package.dependencies]
+mmh3 = "*"
+redis = ">=4,<5"
+typing-extensions = "*"
[[package]]
name = "py-cpuinfo"
@@ -3208,43 +3307,6 @@ h11 = ">=0.8"
[package.extras]
standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
-[[package]]
-name = "vtk"
-version = "9.2.6"
-description = "VTK is an open-source toolkit for 3D computer graphics, image processing, and visualization"
-optional = false
-python-versions = "*"
-files = [
- {file = "vtk-9.2.6-cp310-cp310-macosx_10_10_x86_64.whl", hash = "sha256:acf8b0e0a2b51b8aa36cee1ea1ba0b73c565871efaa14cf2606d9bef36feba3a"},
- {file = "vtk-9.2.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8ec9827287f1743c736ea9b51572d20dcd15a065170808f97408eebd404275b4"},
- {file = "vtk-9.2.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3473f3b3dc919d3e2ef0cc9927654731941fd7b79d3dcaa343cdaff3e4e40838"},
- {file = "vtk-9.2.6-cp310-cp310-win_amd64.whl", hash = "sha256:37561b19b4b70c7034d9e689238560d7afec49ff89704b9bb3c9bb89a90ee54e"},
- {file = "vtk-9.2.6-cp311-cp311-macosx_10_10_x86_64.whl", hash = "sha256:9289f6ee5432f0a00aeb7b674d7ca03054bc50fa6c74126751f8b19f931f52fc"},
- {file = "vtk-9.2.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:0b947a33a7c5562ac4d9c8dce389f4ed720cc2559389048993ae45cbed3bbeb1"},
- {file = "vtk-9.2.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87930115c8067a2d482beebc48a50fcacdc0154d8d7c763471a9be8b5eb76cc3"},
- {file = "vtk-9.2.6-cp311-cp311-win_amd64.whl", hash = "sha256:6c3ca0663f251fbd6e26d93294801ceee6c3cc329f6070dccde3b68046ab9ee7"},
- {file = "vtk-9.2.6-cp36-cp36m-macosx_10_10_x86_64.whl", hash = "sha256:86c548da22a0bd9ce9e060364925e8fa0a551064f9660ae1d486ac3118ffb770"},
- {file = "vtk-9.2.6-cp36-cp36m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f7622e98b3590bf909f056a1bad55575760727fd673c3e8e224134d52b11d00d"},
- {file = "vtk-9.2.6-cp36-cp36m-win_amd64.whl", hash = "sha256:bb28432277136774e91eb1084a8f5f1c4c952d4e74f74626a16ac6e199eba5c5"},
- {file = "vtk-9.2.6-cp37-cp37m-macosx_10_10_x86_64.whl", hash = "sha256:feb9d211583d7b1dd45ca6616bf2f9622d0eadf9e3084f53d20de819e5808d42"},
- {file = "vtk-9.2.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bc1123b6f2f3746d35325cf1a48630c8f49a3516c9970a5bdea15823909bbca"},
- {file = "vtk-9.2.6-cp37-cp37m-win_amd64.whl", hash = "sha256:78103568e97d947026cd39a70e6719277d7341f984c06abaec64d3429e200a6f"},
- {file = "vtk-9.2.6-cp38-cp38-macosx_10_10_x86_64.whl", hash = "sha256:8236e00d0ad24730f4b783bbc038108426e6a78c892fd6ae9a8e8eb846f3e8e3"},
- {file = "vtk-9.2.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:affbb15762bcb6d9632a668ec53c6a3102d4f6c14c4178f01489c0b711114521"},
- {file = "vtk-9.2.6-cp38-cp38-win_amd64.whl", hash = "sha256:f9d3450c00ced28f942a0a7dc5f27a667cf6b171d9ef5a090cb7c8e21dd1a121"},
- {file = "vtk-9.2.6-cp39-cp39-macosx_10_10_x86_64.whl", hash = "sha256:9b396909a4372d3be4a01fde4a0af4f3e410742d73d185982c6f48a61090ebfe"},
- {file = "vtk-9.2.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:9d41a18bbd6fac18a814bbaeeb615044da036afc2bd98cdf7ea52853fd1ef950"},
- {file = "vtk-9.2.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:79991dccbc483a8e5d23e5d3ae1e358fee0526fe8f710d07868ecae58c6b9535"},
- {file = "vtk-9.2.6-cp39-cp39-win_amd64.whl", hash = "sha256:2d905a686ee1b28dd2ac3c3595a3fbcbd171e4b1f9aabac3c8019c6f3a4f8157"},
-]
-
-[package.dependencies]
-matplotlib = ">=2.0.0"
-
-[package.extras]
-numpy = ["numpy (>=1.9)"]
-web = ["wslink (>=1.0.4)"]
-
[[package]]
name = "wrapt"
version = "1.15.0"
@@ -3390,4 +3452,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p
[metadata]
lock-version = "2.0"
python-versions = "^3.11"
-content-hash = "915e85bde4cdc6ef0a517edef88864703109e1623a43b2f3f4ea1ad99d7af5bb"
+content-hash = "0138b0a8902575704f558577c37e40fc9128819a11bde186e407ce839da40cf3"
diff --git a/backend/src/__init__.py b/backend_py/primary/primary/__init__.py
similarity index 100%
rename from backend/src/__init__.py
rename to backend_py/primary/primary/__init__.py
diff --git a/backend/src/backend/auth/auth_helper.py b/backend_py/primary/primary/auth/auth_helper.py
similarity index 98%
rename from backend/src/backend/auth/auth_helper.py
rename to backend_py/primary/primary/auth/auth_helper.py
index 9d5678df6..58846258f 100644
--- a/backend/src/backend/auth/auth_helper.py
+++ b/backend_py/primary/primary/auth/auth_helper.py
@@ -1,5 +1,5 @@
-import os
import base64
+import os
import time
from typing import List, Optional
@@ -8,10 +8,10 @@
import starsessions
from fastapi import APIRouter, Request, Response
from fastapi.responses import RedirectResponse
+from webviz_pkg.core_utils.perf_timer import PerfTimer
-from src.services.utils.authenticated_user import AuthenticatedUser
-from src.services.utils.perf_timer import PerfTimer
-from src import config
+from primary import config
+from primary.services.utils.authenticated_user import AuthenticatedUser
class AuthHelper:
diff --git a/backend/src/backend/auth/enforce_logged_in_middleware.py b/backend_py/primary/primary/auth/enforce_logged_in_middleware.py
similarity index 98%
rename from backend/src/backend/auth/enforce_logged_in_middleware.py
rename to backend_py/primary/primary/auth/enforce_logged_in_middleware.py
index 255fe5649..57a6e27e2 100644
--- a/backend/src/backend/auth/enforce_logged_in_middleware.py
+++ b/backend_py/primary/primary/auth/enforce_logged_in_middleware.py
@@ -6,7 +6,7 @@
from fastapi.responses import PlainTextResponse, RedirectResponse
from starlette.middleware.base import BaseHTTPMiddleware, RequestResponseEndpoint
-from src.backend.auth.auth_helper import AuthHelper
+from .auth_helper import AuthHelper
class EnforceLoggedInMiddleware(BaseHTTPMiddleware):
diff --git a/backend/src/config.py b/backend_py/primary/primary/config.py
similarity index 100%
rename from backend/src/config.py
rename to backend_py/primary/primary/config.py
diff --git a/backend_py/primary/primary/main.py b/backend_py/primary/primary/main.py
new file mode 100644
index 000000000..c5e6f030b
--- /dev/null
+++ b/backend_py/primary/primary/main.py
@@ -0,0 +1,122 @@
+import datetime
+import logging
+import os
+
+from fastapi import FastAPI
+from fastapi.responses import ORJSONResponse
+from fastapi.routing import APIRoute
+from starsessions import SessionMiddleware
+from starsessions.stores.redis import RedisStore
+from uvicorn.middleware.proxy_headers import ProxyHeadersMiddleware
+
+from primary.auth.auth_helper import AuthHelper
+from primary.auth.enforce_logged_in_middleware import EnforceLoggedInMiddleware
+from primary.middleware.add_process_time_to_server_timing_middleware import AddProcessTimeToServerTimingMiddleware
+from primary.routers.correlations.router import router as correlations_router
+from primary.routers.dev.router import router as dev_router
+from primary.routers.explore import router as explore_router
+from primary.routers.general import router as general_router
+from primary.routers.graph.router import router as graph_router
+from primary.routers.grid3d.router import router as grid3d_router
+from primary.routers.grid3d.router_vtk import router as grid3d_router_vtk
+from primary.routers.inplace_volumetrics.router import router as inplace_volumetrics_router
+from primary.routers.observations.router import router as observations_router
+from primary.routers.parameters.router import router as parameters_router
+from primary.routers.polygons.router import router as polygons_router
+from primary.routers.pvt.router import router as pvt_router
+from primary.routers.rft.router import router as rft_router
+from primary.routers.seismic.router import router as seismic_router
+from primary.routers.surface.router import router as surface_router
+from primary.routers.timeseries.router import router as timeseries_router
+from primary.routers.well.router import router as well_router
+from primary.routers.well_completions.router import router as well_completions_router
+from primary.utils.azure_monitor_setup import setup_azure_monitor_telemetry
+from primary.utils.exception_handlers import configure_service_level_exception_handlers
+from primary.utils.exception_handlers import override_default_fastapi_exception_handlers
+from primary.utils.logging_setup import ensure_console_log_handler_is_configured, setup_normal_log_levels
+
+from . import config
+
+
+ensure_console_log_handler_is_configured()
+setup_normal_log_levels()
+
+# temporarily set some loggers to DEBUG
+# logging.getLogger().setLevel(logging.DEBUG)
+logging.getLogger("primary.services.sumo_access").setLevel(logging.DEBUG)
+logging.getLogger("primary.services.user_session_manager").setLevel(logging.DEBUG)
+logging.getLogger("primary.routers.dev").setLevel(logging.DEBUG)
+
+LOGGER = logging.getLogger(__name__)
+
+
+def custom_generate_unique_id(route: APIRoute) -> str:
+ return f"{route.name}"
+
+
+app = FastAPI(
+ generate_unique_id_function=custom_generate_unique_id,
+ root_path="/api",
+ default_response_class=ORJSONResponse,
+)
+
+if os.environ.get("APPLICATIONINSIGHTS_CONNECTION_STRING"):
+ LOGGER.info("Configuring Azure Monitor telemetry for primary backend")
+ setup_azure_monitor_telemetry(app)
+else:
+ LOGGER.warning("Skipping telemetry configuration, APPLICATIONINSIGHTS_CONNECTION_STRING env variable not set.")
+
+
+# The tags we add here will determine the name of the frontend api service for our endpoints as well as
+# providing some grouping when viewing the openapi documentation.
+app.include_router(explore_router, tags=["explore"])
+app.include_router(timeseries_router, prefix="/timeseries", tags=["timeseries"])
+app.include_router(inplace_volumetrics_router, prefix="/inplace_volumetrics", tags=["inplace_volumetrics"])
+app.include_router(surface_router, prefix="/surface", tags=["surface"])
+app.include_router(parameters_router, prefix="/parameters", tags=["parameters"])
+app.include_router(correlations_router, prefix="/correlations", tags=["correlations"])
+app.include_router(grid3d_router, prefix="/grid3d", tags=["grid3d"])
+app.include_router(grid3d_router_vtk, prefix="/grid3d", tags=["grid3d"])
+app.include_router(pvt_router, prefix="/pvt", tags=["pvt"])
+app.include_router(well_completions_router, prefix="/well_completions", tags=["well_completions"])
+app.include_router(well_router, prefix="/well", tags=["well"])
+app.include_router(seismic_router, prefix="/seismic", tags=["seismic"])
+app.include_router(polygons_router, prefix="/polygons", tags=["polygons"])
+app.include_router(graph_router, prefix="/graph", tags=["graph"])
+app.include_router(observations_router, prefix="/observations", tags=["observations"])
+app.include_router(rft_router, prefix="/rft", tags=["rft"])
+app.include_router(dev_router, prefix="/dev", tags=["dev"], include_in_schema=False)
+
+auth_helper = AuthHelper()
+app.include_router(auth_helper.router)
+app.include_router(general_router)
+
+configure_service_level_exception_handlers(app)
+override_default_fastapi_exception_handlers(app)
+
+
+# This middleware instance approximately measures execution time of the route handler itself
+app.add_middleware(AddProcessTimeToServerTimingMiddleware, metric_name="total-exec-route")
+
+# Add out custom middleware to enforce that user is logged in
+# Also redirects to /login endpoint for some select paths
+unprotected_paths = ["/logged_in_user", "/alive", "/openapi.json"]
+paths_redirected_to_login = ["/", "/alive_protected"]
+app.add_middleware(
+ EnforceLoggedInMiddleware,
+ unprotected_paths=unprotected_paths,
+ paths_redirected_to_login=paths_redirected_to_login,
+)
+
+session_store = RedisStore(config.REDIS_USER_SESSION_URL, prefix="user-auth:")
+app.add_middleware(SessionMiddleware, store=session_store)
+
+app.add_middleware(ProxyHeadersMiddleware, trusted_hosts="*")
+
+# This middleware instance measures execution time of the endpoints, including the cost of other middleware
+app.add_middleware(AddProcessTimeToServerTimingMiddleware, metric_name="total")
+
+
+@app.get("/")
+async def root() -> str:
+ return f"Primary backend is alive at this time: {datetime.datetime.now()}"
diff --git a/backend/src/backend/utils/add_process_time_to_server_timing_middleware.py b/backend_py/primary/primary/middleware/add_process_time_to_server_timing_middleware.py
similarity index 100%
rename from backend/src/backend/utils/add_process_time_to_server_timing_middleware.py
rename to backend_py/primary/primary/middleware/add_process_time_to_server_timing_middleware.py
diff --git a/backend/src/backend/__init__.py b/backend_py/primary/primary/routers/__init__.py
similarity index 100%
rename from backend/src/backend/__init__.py
rename to backend_py/primary/primary/routers/__init__.py
diff --git a/backend/src/backend/auth/__init__.py b/backend_py/primary/primary/routers/correlations/__init__.py
similarity index 100%
rename from backend/src/backend/auth/__init__.py
rename to backend_py/primary/primary/routers/correlations/__init__.py
diff --git a/backend/src/backend/primary/routers/correlations/router.py b/backend_py/primary/primary/routers/correlations/router.py
similarity index 100%
rename from backend/src/backend/primary/routers/correlations/router.py
rename to backend_py/primary/primary/routers/correlations/router.py
diff --git a/backend_py/primary/primary/routers/dev/router.py b/backend_py/primary/primary/routers/dev/router.py
new file mode 100644
index 000000000..5b859b3a3
--- /dev/null
+++ b/backend_py/primary/primary/routers/dev/router.py
@@ -0,0 +1,171 @@
+import asyncio
+import logging
+from typing import Annotated
+
+import httpx
+from fastapi import APIRouter, Depends, HTTPException, Query, Path
+
+from primary.auth.auth_helper import AuthenticatedUser, AuthHelper
+from primary.services.user_session_manager.user_session_manager import UserSessionManager
+from primary.services.user_session_manager.user_session_manager import UserComponent
+from primary.services.user_session_manager.user_session_manager import _USER_SESSION_DEFS
+from primary.services.user_session_manager._radix_helpers import create_new_radix_job, RadixResourceRequests
+from primary.services.user_session_manager._radix_helpers import get_all_radix_jobs, get_radix_job_state
+from primary.services.user_session_manager._radix_helpers import delete_all_radix_jobs
+from primary.services.user_session_manager._user_session_directory import UserSessionDirectory
+from primary.services.user_session_manager._background_tasks import run_in_background_task
+
+LOGGER = logging.getLogger(__name__)
+
+
+router = APIRouter()
+
+
+@router.get("/usersession/{user_component}/call")
+async def usersession_call(
+ authenticated_user: Annotated[AuthenticatedUser, Depends(AuthHelper.get_authenticated_user)],
+ user_component: Annotated[UserComponent, Path(description="User session component")],
+ instance_str: Annotated[str, Query(description="Instance string")] = "myInst",
+) -> str:
+ LOGGER.debug(f"usersession_call() {user_component=}, {instance_str=}")
+
+ manager = UserSessionManager(authenticated_user.get_user_id())
+ session_base_url = await manager.get_or_create_session_async(user_component, instance_str)
+ if session_base_url is None:
+ LOGGER.error("Failed to get user session URL")
+ raise HTTPException(status_code=500, detail="Failed to get user session URL")
+
+ endpoint = f"{session_base_url}/dowork?duration=5"
+
+ LOGGER.debug("======================")
+ LOGGER.debug(f"{session_base_url=}")
+ LOGGER.debug(f"{endpoint=}")
+ LOGGER.debug("======================")
+
+ LOGGER.debug(f"before call to: {endpoint=}")
+
+ async with httpx.AsyncClient(timeout=30) as client:
+ response = await client.get(endpoint)
+ response.raise_for_status()
+
+ LOGGER.debug(f"after call to: {endpoint=}")
+
+ resp_text = response.text
+ LOGGER.debug(f"{type(resp_text)=}")
+ LOGGER.debug(f"{resp_text=}")
+
+ return resp_text
+
+
+@router.get("/usersession/{user_component}/radixlist")
+async def usersession_radixlist(user_component: UserComponent) -> str:
+ LOGGER.debug(f"usersession_radixlist() {user_component=}")
+
+ session_def = _USER_SESSION_DEFS[user_component]
+
+ job_list = await get_all_radix_jobs(session_def.job_component_name, session_def.port)
+ LOGGER.debug("---")
+ LOGGER.debug(job_list)
+ LOGGER.debug("---")
+ return str(job_list)
+
+
+@router.get("/usersession/{user_component}/radixcreate")
+async def usersession_radixcreate(user_component: UserComponent) -> str:
+ LOGGER.debug(f"usersession_radixcreate() {user_component=}")
+
+ session_def = _USER_SESSION_DEFS[user_component]
+
+ resource_req = RadixResourceRequests(cpu="50m", memory="100Mi")
+ new_radix_job_name = await create_new_radix_job(session_def.job_component_name, session_def.port, resource_req)
+ LOGGER.debug(f"Created new job: {new_radix_job_name=}")
+ if new_radix_job_name is None:
+ return "Failed to create new job"
+
+ LOGGER.debug(f"Polling job until receiving running status: {new_radix_job_name=}")
+ max_state_calls = 20
+ for _i in range(max_state_calls):
+ radix_job_state = await get_radix_job_state(
+ session_def.job_component_name, session_def.port, new_radix_job_name
+ )
+ session_status = radix_job_state.status if radix_job_state else "N/A"
+ LOGGER.debug(f"Status: {session_status=}")
+ await asyncio.sleep(0.1)
+
+ return str(radix_job_state)
+
+
+@router.get("/usersession/{user_component}/radixdelete")
+async def usersession_radixdelete(user_component: UserComponent) -> str:
+ LOGGER.debug(f"usersession_radixdelete() {user_component=}")
+
+ session_def = _USER_SESSION_DEFS[user_component]
+
+ await delete_all_radix_jobs(session_def.job_component_name, session_def.port)
+ return "Delete done"
+
+
+@router.get("/usersession/dirlist")
+async def usersession_dirlist(
+ authenticated_user: Annotated[AuthenticatedUser, Depends(AuthHelper.get_authenticated_user)],
+ user_component: UserComponent | None = None,
+) -> str:
+ LOGGER.debug(f"usersession_dirlist() {user_component=}")
+
+ job_component_name: str | None = None
+ if user_component is not None:
+ job_component_name = _USER_SESSION_DEFS[user_component].job_component_name
+
+ session_dir = UserSessionDirectory(authenticated_user.get_user_id())
+ session_info_arr = session_dir.get_session_info_arr(job_component_name)
+
+ resp_text = ""
+
+ LOGGER.debug("======================")
+ for session_info in session_info_arr:
+ LOGGER.debug(f"{session_info=}")
+ resp_text += str(session_info) + "\n"
+ LOGGER.debug("======================")
+
+ return resp_text
+
+
+@router.get("/usersession/dirdel")
+async def usersession_dirdel(
+ authenticated_user: Annotated[AuthenticatedUser, Depends(AuthHelper.get_authenticated_user)],
+ user_component: UserComponent | None = None,
+) -> str:
+ LOGGER.debug(f"usersession_dirdel() {user_component=}")
+
+ job_component_name: str | None = None
+ if user_component is not None:
+ job_component_name = _USER_SESSION_DEFS[user_component].job_component_name
+
+ session_dir = UserSessionDirectory(authenticated_user.get_user_id())
+ session_dir.delete_session_info(job_component_name)
+
+ session_info_arr = session_dir.get_session_info_arr(None)
+ LOGGER.debug("======================")
+ for session_info in session_info_arr:
+ LOGGER.debug(f"{session_info=}")
+ LOGGER.debug("======================")
+
+ return "Session info deleted"
+
+
+@router.get("/bgtask")
+async def bgtask() -> str:
+ LOGGER.debug(f"bgtask() - start")
+
+ async def funcThatThrows() -> None:
+ raise ValueError("This is a test error")
+
+ async def funcThatLogs(msg: str) -> None:
+ LOGGER.debug(f"This is a test log {msg=}")
+
+ run_in_background_task(funcThatThrows())
+ run_in_background_task(funcThatLogs(msg="HELO HELLO"))
+
+ LOGGER.debug(f"bgtask() - done")
+
+ return "Background tasks were run"
diff --git a/backend/src/backend/primary/routers/explore.py b/backend_py/primary/primary/routers/explore.py
similarity index 80%
rename from backend/src/backend/primary/routers/explore.py
rename to backend_py/primary/primary/routers/explore.py
index 8838100c5..b2ba82811 100644
--- a/backend/src/backend/primary/routers/explore.py
+++ b/backend_py/primary/primary/routers/explore.py
@@ -3,10 +3,10 @@
from fastapi import APIRouter, Depends, Path, Query
from pydantic import BaseModel
-from src.backend.auth.auth_helper import AuthHelper
-from src.services.sumo_access.sumo_explore import SumoExplore
-from src.services.utils.authenticated_user import AuthenticatedUser
-from src.services.sumo_access._helpers import SumoEnsemble
+from primary.auth.auth_helper import AuthHelper
+from primary.services.sumo_access.sumo_explore import SumoExplore
+from primary.services.utils.authenticated_user import AuthenticatedUser
+from primary.services.sumo_access._helpers import SumoEnsemble
router = APIRouter()
@@ -29,6 +29,7 @@ class EnsembleInfo(BaseModel):
class EnsembleDetails(BaseModel):
name: str
+ field_identifier: str
case_name: str
case_uuid: str
realizations: Sequence[int]
@@ -89,5 +90,15 @@ async def get_ensemble_details(
iteration = await SumoEnsemble.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid, ensemble_name)
case_name = iteration.get_case_name()
realizations = iteration.get_realizations()
-
- return EnsembleDetails(name=ensemble_name, case_name=case_name, case_uuid=case_uuid, realizations=realizations)
+ field_identifiers = await iteration.get_field_identifiers()
+
+ if len(field_identifiers) != 1:
+ raise NotImplementedError("Multiple field identifiers not supported")
+
+ return EnsembleDetails(
+ name=ensemble_name,
+ case_name=case_name,
+ case_uuid=case_uuid,
+ realizations=realizations,
+ field_identifier=field_identifiers[0],
+ )
diff --git a/backend/src/backend/primary/routers/general.py b/backend_py/primary/primary/routers/general.py
similarity index 79%
rename from backend/src/backend/primary/routers/general.py
rename to backend_py/primary/primary/routers/general.py
index bcb6b6b45..58ede3f30 100644
--- a/backend/src/backend/primary/routers/general.py
+++ b/backend_py/primary/primary/routers/general.py
@@ -4,13 +4,11 @@
import httpx
import starsessions
-from starlette.responses import StreamingResponse
-from fastapi import APIRouter, HTTPException, Request, status, Depends, Query
+from fastapi import APIRouter, HTTPException, Request, status, Query
from pydantic import BaseModel
-from src.backend.auth.auth_helper import AuthHelper, AuthenticatedUser
-from src.backend.primary.user_session_proxy import proxy_to_user_session
-from src.services.graph_access.graph_access import GraphApiAccess
+from primary.auth.auth_helper import AuthHelper
+from primary.services.graph_access.graph_access import GraphApiAccess
LOGGER = logging.getLogger(__name__)
@@ -81,11 +79,3 @@ async def logged_in_user(
print("Error while fetching user avatar and info from Microsoft Graph API (Invalid URL):\n", exc)
return user_info
-
-
-@router.get("/user_session_container")
-async def user_session_container(
- request: Request, authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user)
-) -> StreamingResponse:
- """Get information about user session container (note that one is started if not already running)."""
- return await proxy_to_user_session(request, authenticated_user)
diff --git a/backend/src/backend/primary/__init__.py b/backend_py/primary/primary/routers/graph/__init__.py
similarity index 100%
rename from backend/src/backend/primary/__init__.py
rename to backend_py/primary/primary/routers/graph/__init__.py
diff --git a/backend/src/backend/primary/routers/graph/router.py b/backend_py/primary/primary/routers/graph/router.py
similarity index 86%
rename from backend/src/backend/primary/routers/graph/router.py
rename to backend_py/primary/primary/routers/graph/router.py
index 0deb3fb2a..9d913a09b 100644
--- a/backend/src/backend/primary/routers/graph/router.py
+++ b/backend_py/primary/primary/routers/graph/router.py
@@ -3,9 +3,9 @@
import httpx
from fastapi import APIRouter, Depends, Query
-from src.backend.auth.auth_helper import AuthHelper
-from src.services.utils.authenticated_user import AuthenticatedUser
-from src.services.graph_access.graph_access import GraphApiAccess
+from primary.auth.auth_helper import AuthHelper
+from primary.services.utils.authenticated_user import AuthenticatedUser
+from primary.services.graph_access.graph_access import GraphApiAccess
from .schemas import GraphUserPhoto
diff --git a/backend/src/backend/primary/routers/graph/schemas.py b/backend_py/primary/primary/routers/graph/schemas.py
similarity index 100%
rename from backend/src/backend/primary/routers/graph/schemas.py
rename to backend_py/primary/primary/routers/graph/schemas.py
diff --git a/backend/src/backend/primary/routers/__init__.py b/backend_py/primary/primary/routers/grid3d/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/__init__.py
rename to backend_py/primary/primary/routers/grid3d/__init__.py
diff --git a/backend_py/primary/primary/routers/grid3d/router.py b/backend_py/primary/primary/routers/grid3d/router.py
new file mode 100644
index 000000000..85adb6c68
--- /dev/null
+++ b/backend_py/primary/primary/routers/grid3d/router.py
@@ -0,0 +1,68 @@
+from typing import List
+
+from fastapi import APIRouter, Depends, Query, HTTPException, status
+from starlette.requests import Request
+
+from primary.services.utils.authenticated_user import AuthenticatedUser
+from primary.auth.auth_helper import AuthHelper
+
+from primary.services.sumo_access.grid_access import GridAccess
+from .schemas import GridSurface
+
+router = APIRouter()
+
+# pylint: disable=unused-argument
+# pylint: disable=unused-variable
+
+
+@router.get("/grid_model_names/")
+async def get_grid_model_names(
+ authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
+ case_uuid: str = Query(description="Sumo case uuid"),
+ ensemble_name: str = Query(description="Ensemble name"),
+) -> List[str]:
+ """
+ Get a list of grid model names
+ """
+ access = await GridAccess.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid, ensemble_name)
+ return await access.grid_model_names()
+
+
+@router.get("/parameter_names/")
+async def get_parameter_names(
+ authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
+ case_uuid: str = Query(description="Sumo case uuid"),
+ ensemble_name: str = Query(description="Ensemble name"),
+ grid_name: str = Query(description="Grid name"),
+) -> List[str]:
+ """
+ Get a list of grid parameter names
+ """
+ access = await GridAccess.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid, ensemble_name)
+ return await access.static_parameter_names(grid_name)
+
+
+# Primary backend
+@router.get("/grid_surface")
+async def grid_surface(
+ request: Request,
+ case_uuid: str = Query(description="Sumo case uuid"),
+ ensemble_name: str = Query(description="Ensemble name"),
+ grid_name: str = Query(description="Grid name"),
+ realization: str = Query(description="Realization"),
+ authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
+) -> GridSurface:
+ raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED)
+
+
+@router.get("/grid_parameter")
+async def grid_parameter(
+ request: Request,
+ case_uuid: str = Query(description="Sumo case uuid"),
+ ensemble_name: str = Query(description="Ensemble name"),
+ grid_name: str = Query(description="Grid name"),
+ parameter_name: str = Query(description="Grid parameter"),
+ realization: str = Query(description="Realization"),
+ authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
+) -> List[float]:
+ raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED)
diff --git a/backend/src/backend/primary/routers/grid/router.py b/backend_py/primary/primary/routers/grid3d/router_vtk.py
similarity index 69%
rename from backend/src/backend/primary/routers/grid/router.py
rename to backend_py/primary/primary/routers/grid3d/router_vtk.py
index fc064fec3..dba4f65e2 100644
--- a/backend/src/backend/primary/routers/grid/router.py
+++ b/backend_py/primary/primary/routers/grid3d/router_vtk.py
@@ -1,55 +1,29 @@
from typing import List
-from fastapi import APIRouter, Depends, Query
+from fastapi import APIRouter, Depends, Query, HTTPException, status
from starlette.requests import Request
-from src.services.utils.authenticated_user import AuthenticatedUser
-from src.backend.auth.auth_helper import AuthHelper
-from src.backend.primary.user_session_proxy import proxy_to_user_session
+from primary.services.utils.authenticated_user import AuthenticatedUser
+from primary.auth.auth_helper import AuthHelper
-from src.services.sumo_access.grid_access import GridAccess
-from .schemas import GridSurface, GridIntersection
+from .schemas_vtk import GridSurfaceVtk, GridIntersectionVtk
router = APIRouter()
-
-@router.get("/grid_model_names/")
-async def get_grid_model_names(
- authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
- case_uuid: str = Query(description="Sumo case uuid"),
- ensemble_name: str = Query(description="Ensemble name"),
-) -> List[str]:
- """
- Get a list of grid model names
- """
- access = await GridAccess.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid, ensemble_name)
- return await access.grid_model_names()
-
-
-@router.get("/parameter_names/")
-async def get_parameter_names(
- authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
- case_uuid: str = Query(description="Sumo case uuid"),
- ensemble_name: str = Query(description="Ensemble name"),
- grid_name: str = Query(description="Grid name"),
-) -> List[str]:
- """
- Get a list of grid parameter names
- """
- access = await GridAccess.from_case_uuid(authenticated_user.get_sumo_access_token(), case_uuid, ensemble_name)
- return await access.static_parameter_names(grid_name)
+# pylint: disable=unused-argument
+# pylint: disable=unused-variable
# Primary backend
-@router.get("/grid_surface")
-async def grid_surface(
+@router.get("/grid_surface_vtk")
+async def grid_surface_vtk(
request: Request,
case_uuid: str = Query(description="Sumo case uuid"),
ensemble_name: str = Query(description="Ensemble name"),
grid_name: str = Query(description="Grid name"),
realization: str = Query(description="Realization"),
authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
-) -> GridSurface:
+) -> GridSurfaceVtk:
"""Get a grid"""
query_params = {
@@ -71,12 +45,11 @@ async def grid_surface(
receive=request._receive, # pylint: disable=protected-access
)
- response = await proxy_to_user_session(updated_request, authenticated_user)
- return response
+ raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED)
-@router.get("/grid_parameter")
-async def grid_parameter(
+@router.get("/grid_parameter_vtk")
+async def grid_parameter_vtk(
request: Request,
case_uuid: str = Query(description="Sumo case uuid"),
ensemble_name: str = Query(description="Ensemble name"),
@@ -107,12 +80,11 @@ async def grid_parameter(
receive=request._receive, # pylint: disable=protected-access
)
- response = await proxy_to_user_session(updated_request, authenticated_user)
- return response
+ raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED)
-@router.get("/grid_parameter_intersection")
-async def grid_parameter_intersection(
+@router.get("/grid_parameter_intersection_vtk")
+async def grid_parameter_intersection_vtk(
request: Request,
case_uuid: str = Query(description="Sumo case uuid"),
ensemble_name: str = Query(description="Ensemble name"),
@@ -120,7 +92,7 @@ async def grid_parameter_intersection(
parameter_name: str = Query(description="Grid parameter"),
realization: str = Query(description="Realization"),
authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
-) -> GridIntersection:
+) -> GridIntersectionVtk:
"""Get a grid parameter"""
query_params = {
@@ -143,12 +115,11 @@ async def grid_parameter_intersection(
receive=request._receive, # pylint: disable=protected-access
)
- response = await proxy_to_user_session(updated_request, authenticated_user)
- return response
+ raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED)
-@router.get("/statistical_grid_parameter_intersection")
-async def statistical_grid_parameter_intersection(
+@router.get("/statistical_grid_parameter_intersection_vtk")
+async def statistical_grid_parameter_intersection_vtk(
request: Request,
case_uuid: str = Query(description="Sumo case uuid"),
ensemble_name: str = Query(description="Ensemble name"),
@@ -156,7 +127,7 @@ async def statistical_grid_parameter_intersection(
parameter_name: str = Query(description="Grid parameter"),
realizations: List[str] = Query(description="Realizations"),
authenticated_user: AuthenticatedUser = Depends(AuthHelper.get_authenticated_user),
-) -> GridIntersection:
+) -> GridIntersectionVtk:
"""Get a grid parameter"""
query_params = {
@@ -179,12 +150,11 @@ async def statistical_grid_parameter_intersection(
receive=request._receive, # pylint: disable=protected-access
)
- response = await proxy_to_user_session(updated_request, authenticated_user)
- return response
+ raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED)
-@router.get("/statistical_grid_parameter")
-async def statistical_grid_parameter(
+@router.get("/statistical_grid_parameter_vtk")
+async def statistical_grid_parameter_vtk(
request: Request,
case_uuid: str = Query(description="Sumo case uuid"),
ensemble_name: str = Query(description="Ensemble name"),
@@ -214,5 +184,4 @@ async def statistical_grid_parameter(
receive=request._receive, # pylint: disable=protected-access
)
- response = await proxy_to_user_session(updated_request, authenticated_user)
- return response
+ raise HTTPException(status.HTTP_501_NOT_IMPLEMENTED)
diff --git a/backend_py/primary/primary/routers/grid3d/schemas.py b/backend_py/primary/primary/routers/grid3d/schemas.py
new file mode 100644
index 000000000..a38049a89
--- /dev/null
+++ b/backend_py/primary/primary/routers/grid3d/schemas.py
@@ -0,0 +1,13 @@
+from pydantic import BaseModel
+from webviz_pkg.core_utils.b64 import B64FloatArray, B64UintArray
+
+
+class GridSurface(BaseModel):
+ polys_b64arr: B64UintArray
+ points_b64arr: B64FloatArray
+ xmin: float
+ xmax: float
+ ymin: float
+ ymax: float
+ zmin: float
+ zmax: float
diff --git a/backend/src/backend/primary/routers/grid/schemas.py b/backend_py/primary/primary/routers/grid3d/schemas_vtk.py
similarity index 72%
rename from backend/src/backend/primary/routers/grid/schemas.py
rename to backend_py/primary/primary/routers/grid3d/schemas_vtk.py
index c8a3abe03..1e91d0b4d 100644
--- a/backend/src/backend/primary/routers/grid/schemas.py
+++ b/backend_py/primary/primary/routers/grid3d/schemas_vtk.py
@@ -1,11 +1,10 @@
from typing import List
from pydantic import BaseModel
+from webviz_pkg.core_utils.b64 import B64FloatArray, B64UintArray
-from src.services.utils.b64 import B64FloatArray, B64UintArray
-
-class GridSurface(BaseModel):
+class GridSurfaceVtk(BaseModel):
polys_b64arr: B64UintArray
points_b64arr: B64FloatArray
xmin: float
@@ -16,7 +15,7 @@ class GridSurface(BaseModel):
zmax: float
-class GridIntersection(BaseModel):
+class GridIntersectionVtk(BaseModel):
image: str
polyline_x: List[float]
polyline_y: List[float]
diff --git a/backend/src/backend/primary/routers/correlations/__init__.py b/backend_py/primary/primary/routers/inplace_volumetrics/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/correlations/__init__.py
rename to backend_py/primary/primary/routers/inplace_volumetrics/__init__.py
diff --git a/backend/src/backend/primary/routers/inplace_volumetrics/router.py b/backend_py/primary/primary/routers/inplace_volumetrics/router.py
similarity index 93%
rename from backend/src/backend/primary/routers/inplace_volumetrics/router.py
rename to backend_py/primary/primary/routers/inplace_volumetrics/router.py
index 7e2df6b0e..828a53bf7 100644
--- a/backend/src/backend/primary/routers/inplace_volumetrics/router.py
+++ b/backend_py/primary/primary/routers/inplace_volumetrics/router.py
@@ -1,16 +1,16 @@
from typing import List, Optional, Sequence
from fastapi import APIRouter, Depends, Query
-from src.services.sumo_access.inplace_volumetrics_access import (
+from primary.services.sumo_access.inplace_volumetrics_access import (
InplaceVolumetricsAccess,
InplaceVolumetricsTableMetaData,
InplaceVolumetricsCategoricalMetaData,
)
-from src.services.sumo_access.generic_types import EnsembleScalarResponse
-from src.services.utils.authenticated_user import AuthenticatedUser
+from primary.services.sumo_access.generic_types import EnsembleScalarResponse
+from primary.services.utils.authenticated_user import AuthenticatedUser
-from src.backend.auth.auth_helper import AuthHelper
+from primary.auth.auth_helper import AuthHelper
router = APIRouter()
diff --git a/backend/src/backend/primary/routers/observations/router.py b/backend_py/primary/primary/routers/observations/router.py
similarity index 75%
rename from backend/src/backend/primary/routers/observations/router.py
rename to backend_py/primary/primary/routers/observations/router.py
index c22f9f020..33578c4cd 100644
--- a/backend/src/backend/primary/routers/observations/router.py
+++ b/backend_py/primary/primary/routers/observations/router.py
@@ -1,11 +1,10 @@
import logging
-from typing import List, Optional, Literal
from fastapi import APIRouter, Depends, Query
-from src.backend.auth.auth_helper import AuthHelper
-from src.services.sumo_access.observation_access import ObservationAccess
-from src.services.utils.authenticated_user import AuthenticatedUser
+from primary.auth.auth_helper import AuthHelper
+from primary.services.sumo_access.observation_access import ObservationAccess
+from primary.services.utils.authenticated_user import AuthenticatedUser
from . import schemas
diff --git a/backend/src/backend/primary/routers/observations/schemas.py b/backend_py/primary/primary/routers/observations/schemas.py
similarity index 100%
rename from backend/src/backend/primary/routers/observations/schemas.py
rename to backend_py/primary/primary/routers/observations/schemas.py
diff --git a/backend/src/backend/primary/routers/parameters/__init__,py b/backend_py/primary/primary/routers/parameters/__init__,py
similarity index 100%
rename from backend/src/backend/primary/routers/parameters/__init__,py
rename to backend_py/primary/primary/routers/parameters/__init__,py
diff --git a/backend/src/backend/primary/routers/parameters/router.py b/backend_py/primary/primary/routers/parameters/router.py
similarity index 93%
rename from backend/src/backend/primary/routers/parameters/router.py
rename to backend_py/primary/primary/routers/parameters/router.py
index d670d31d1..983b88d6a 100644
--- a/backend/src/backend/primary/routers/parameters/router.py
+++ b/backend_py/primary/primary/routers/parameters/router.py
@@ -3,10 +3,10 @@
from fastapi import APIRouter, Depends, Query
-from src.backend.auth.auth_helper import AuthHelper
-from src.services.sumo_access.parameter_access import ParameterAccess
-from src.services.sumo_access.parameter_types import EnsembleParameter, EnsembleSensitivity
-from src.services.utils.authenticated_user import AuthenticatedUser
+from primary.auth.auth_helper import AuthHelper
+from primary.services.sumo_access.parameter_access import ParameterAccess
+from primary.services.sumo_access.parameter_types import EnsembleParameter, EnsembleSensitivity
+from primary.services.utils.authenticated_user import AuthenticatedUser
from . import schemas
diff --git a/backend/src/backend/primary/routers/parameters/schemas.py b/backend_py/primary/primary/routers/parameters/schemas.py
similarity index 100%
rename from backend/src/backend/primary/routers/parameters/schemas.py
rename to backend_py/primary/primary/routers/parameters/schemas.py
diff --git a/backend/src/backend/primary/routers/graph/__init__.py b/backend_py/primary/primary/routers/polygons/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/graph/__init__.py
rename to backend_py/primary/primary/routers/polygons/__init__.py
diff --git a/backend/src/backend/primary/routers/polygons/converters.py b/backend_py/primary/primary/routers/polygons/converters.py
similarity index 95%
rename from backend/src/backend/primary/routers/polygons/converters.py
rename to backend_py/primary/primary/routers/polygons/converters.py
index fbcf8b1f6..6aef1f0d3 100644
--- a/backend/src/backend/primary/routers/polygons/converters.py
+++ b/backend_py/primary/primary/routers/polygons/converters.py
@@ -1,8 +1,8 @@
from typing import List
import xtgeo
-from src.services.smda_access.types import StratigraphicSurface
-from src.services.sumo_access.polygons_types import PolygonsMeta as SumoPolygonsMeta
+from primary.services.smda_access.types import StratigraphicSurface
+from primary.services.sumo_access.polygons_types import PolygonsMeta as SumoPolygonsMeta
from . import schemas
diff --git a/backend/src/backend/primary/routers/polygons/router.py b/backend_py/primary/primary/routers/polygons/router.py
similarity index 80%
rename from backend/src/backend/primary/routers/polygons/router.py
rename to backend_py/primary/primary/routers/polygons/router.py
index cc0b683c1..d3f4a79c9 100644
--- a/backend/src/backend/primary/routers/polygons/router.py
+++ b/backend_py/primary/primary/routers/polygons/router.py
@@ -2,19 +2,17 @@
from typing import List, Union
from fastapi import APIRouter, Depends, HTTPException, Query
+from webviz_pkg.core_utils.perf_timer import PerfTimer
-from src.services.sumo_access._helpers import SumoCase
-from src.services.smda_access.stratigraphy_access import StratigraphyAccess
-from src.services.sumo_access.polygons_access import PolygonsAccess
-from src.services.smda_access.stratigraphy_utils import sort_stratigraphic_names_by_hierarchy
-from src.services.smda_access.mocked_drogon_smda_access import _mocked_stratigraphy_access
-from src.services.utils.authenticated_user import AuthenticatedUser
-from src.services.utils.perf_timer import PerfTimer
-from src.backend.auth.auth_helper import AuthHelper
+from primary.auth.auth_helper import AuthHelper
+from primary.services.smda_access.mocked_drogon_smda_access import _mocked_stratigraphy_access
+from primary.services.smda_access.stratigraphy_access import StratigraphyAccess
+from primary.services.smda_access.stratigraphy_utils import sort_stratigraphic_names_by_hierarchy
+from primary.services.sumo_access._helpers import SumoCase
+from primary.services.sumo_access.polygons_access import PolygonsAccess
+from primary.services.utils.authenticated_user import AuthenticatedUser
-
-from . import schemas
-from . import converters
+from . import converters, schemas
LOGGER = logging.getLogger(__name__)
diff --git a/backend/src/backend/primary/routers/polygons/schemas.py b/backend_py/primary/primary/routers/polygons/schemas.py
similarity index 100%
rename from backend/src/backend/primary/routers/polygons/schemas.py
rename to backend_py/primary/primary/routers/polygons/schemas.py
diff --git a/backend/src/backend/primary/routers/grid/__init__.py b/backend_py/primary/primary/routers/pvt/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/grid/__init__.py
rename to backend_py/primary/primary/routers/pvt/__init__.py
diff --git a/backend/src/backend/primary/routers/pvt/converters.py b/backend_py/primary/primary/routers/pvt/converters.py
similarity index 100%
rename from backend/src/backend/primary/routers/pvt/converters.py
rename to backend_py/primary/primary/routers/pvt/converters.py
diff --git a/backend/src/backend/primary/routers/pvt/router.py b/backend_py/primary/primary/routers/pvt/router.py
similarity index 92%
rename from backend/src/backend/primary/routers/pvt/router.py
rename to backend_py/primary/primary/routers/pvt/router.py
index 6aeb694ff..a50e1175a 100644
--- a/backend/src/backend/primary/routers/pvt/router.py
+++ b/backend_py/primary/primary/routers/pvt/router.py
@@ -3,9 +3,9 @@
from fastapi import APIRouter, Depends, HTTPException, Query
-from src.backend.auth.auth_helper import AuthHelper
-from src.services.sumo_access.table_access import TableAccess
-from src.services.utils.authenticated_user import AuthenticatedUser
+from primary.auth.auth_helper import AuthHelper
+from primary.services.sumo_access.table_access import TableAccess
+from primary.services.utils.authenticated_user import AuthenticatedUser
from .converters import pvt_dataframe_to_api_data
from .schemas import PvtData
diff --git a/backend/src/backend/primary/routers/pvt/schemas.py b/backend_py/primary/primary/routers/pvt/schemas.py
similarity index 100%
rename from backend/src/backend/primary/routers/pvt/schemas.py
rename to backend_py/primary/primary/routers/pvt/schemas.py
diff --git a/backend/src/backend/primary/routers/rft/router.py b/backend_py/primary/primary/routers/rft/router.py
similarity index 76%
rename from backend/src/backend/primary/routers/rft/router.py
rename to backend_py/primary/primary/routers/rft/router.py
index 178313a1d..7de32ceee 100644
--- a/backend/src/backend/primary/routers/rft/router.py
+++ b/backend_py/primary/primary/routers/rft/router.py
@@ -1,16 +1,11 @@
import logging
from typing import Annotated
-import pyarrow as pa
-import pyarrow.compute as pc
-from fastapi import APIRouter, Depends, HTTPException, Query
-
-from src.backend.auth.auth_helper import AuthHelper
-from src.services.summary_vector_statistics import compute_vector_statistics
-from src.services.sumo_access.generic_types import EnsembleScalarResponse
-from src.services.sumo_access.parameter_access import ParameterAccess
-from src.services.sumo_access.rft_access import RftAccess
-from src.services.utils.authenticated_user import AuthenticatedUser
+from fastapi import APIRouter, Depends, Query
+
+from primary.auth.auth_helper import AuthHelper
+from primary.services.sumo_access.rft_access import RftAccess
+from primary.services.utils.authenticated_user import AuthenticatedUser
from . import schemas
diff --git a/backend/src/backend/primary/routers/rft/schemas.py b/backend_py/primary/primary/routers/rft/schemas.py
similarity index 100%
rename from backend/src/backend/primary/routers/rft/schemas.py
rename to backend_py/primary/primary/routers/rft/schemas.py
diff --git a/backend/src/backend/primary/routers/inplace_volumetrics/__init__.py b/backend_py/primary/primary/routers/seismic/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/inplace_volumetrics/__init__.py
rename to backend_py/primary/primary/routers/seismic/__init__.py
diff --git a/backend/src/backend/primary/routers/seismic/router.py b/backend_py/primary/primary/routers/seismic/router.py
similarity index 87%
rename from backend/src/backend/primary/routers/seismic/router.py
rename to backend_py/primary/primary/routers/seismic/router.py
index 90b037e50..781a548f3 100644
--- a/backend/src/backend/primary/routers/seismic/router.py
+++ b/backend_py/primary/primary/routers/seismic/router.py
@@ -1,19 +1,18 @@
import logging
from typing import List, Optional
-from fastapi import APIRouter, Depends, HTTPException, Query, Body
+from fastapi import APIRouter, Body, Depends, HTTPException, Query
+from webviz_pkg.core_utils.b64 import b64_encode_float_array_as_float32
-from src.services.sumo_access.seismic_access import SeismicAccess, VdsHandle
-from src.services.vds_access.vds_access import VdsAccess
-from src.services.utils.authenticated_user import AuthenticatedUser
-from src.backend.auth.auth_helper import AuthHelper
-from src.services.utils.b64 import b64_encode_float_array_as_float32
-from src.services.vds_access.response_types import VdsMetadata
-from src.services.vds_access.request_types import VdsCoordinateSystem, VdsCoordinates
+from primary.auth.auth_helper import AuthHelper
+from primary.services.sumo_access.seismic_access import SeismicAccess, VdsHandle
+from primary.services.utils.authenticated_user import AuthenticatedUser
+from primary.services.vds_access.request_types import VdsCoordinates, VdsCoordinateSystem
+from primary.services.vds_access.response_types import VdsMetadata
+from primary.services.vds_access.vds_access import VdsAccess
from . import schemas
-
LOGGER = logging.getLogger(__name__)
router = APIRouter()
diff --git a/backend/src/backend/primary/routers/seismic/schemas.py b/backend_py/primary/primary/routers/seismic/schemas.py
similarity index 97%
rename from backend/src/backend/primary/routers/seismic/schemas.py
rename to backend_py/primary/primary/routers/seismic/schemas.py
index 3e2c4b087..dbcf7430c 100644
--- a/backend/src/backend/primary/routers/seismic/schemas.py
+++ b/backend_py/primary/primary/routers/seismic/schemas.py
@@ -1,8 +1,7 @@
from typing import List
from pydantic import BaseModel
-
-from src.services.utils.b64 import B64FloatArray
+from webviz_pkg.core_utils.b64 import B64FloatArray
class SeismicCubeMeta(BaseModel):
diff --git a/backend/src/backend/primary/routers/polygons/__init__.py b/backend_py/primary/primary/routers/surface/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/polygons/__init__.py
rename to backend_py/primary/primary/routers/surface/__init__.py
diff --git a/backend/src/backend/primary/routers/surface/converters.py b/backend_py/primary/primary/routers/surface/converters.py
similarity index 92%
rename from backend/src/backend/primary/routers/surface/converters.py
rename to backend_py/primary/primary/routers/surface/converters.py
index 5b6a48f3f..26568174b 100644
--- a/backend/src/backend/primary/routers/surface/converters.py
+++ b/backend_py/primary/primary/routers/surface/converters.py
@@ -3,12 +3,12 @@
import numpy as np
import xtgeo
from numpy.typing import NDArray
+from webviz_pkg.core_utils.b64 import b64_encode_float_array_as_float32
-from src.services.smda_access.types import StratigraphicSurface
-from src.services.sumo_access.surface_types import SurfaceMeta as SumoSurfaceMeta
-from src.services.sumo_access.surface_types import XtgeoSurfaceIntersectionPolyline, XtgeoSurfaceIntersectionResult
-from src.services.utils.b64 import b64_encode_float_array_as_float32
-from src.services.utils.surface_to_float32 import surface_to_float32_numpy_array
+from primary.services.smda_access.types import StratigraphicSurface
+from primary.services.sumo_access.surface_types import SurfaceMeta as SumoSurfaceMeta
+from primary.services.sumo_access.surface_types import XtgeoSurfaceIntersectionPolyline, XtgeoSurfaceIntersectionResult
+from primary.services.utils.surface_to_float32 import surface_to_float32_numpy_array
from . import schemas
diff --git a/backend/src/backend/primary/routers/surface/router.py b/backend_py/primary/primary/routers/surface/router.py
similarity index 92%
rename from backend/src/backend/primary/routers/surface/router.py
rename to backend_py/primary/primary/routers/surface/router.py
index 4ac930c5a..8fcf3e863 100644
--- a/backend/src/backend/primary/routers/surface/router.py
+++ b/backend_py/primary/primary/routers/surface/router.py
@@ -2,19 +2,19 @@
from typing import List, Union, Optional
from fastapi import APIRouter, Depends, HTTPException, Query, Response, Body
-
-from src.services.sumo_access.surface_access import SurfaceAccess
-from src.services.smda_access.stratigraphy_access import StratigraphyAccess
-from src.services.smda_access.stratigraphy_utils import sort_stratigraphic_names_by_hierarchy
-from src.services.smda_access.mocked_drogon_smda_access import _mocked_stratigraphy_access
-from src.services.utils.statistic_function import StatisticFunction
-from src.services.utils.authenticated_user import AuthenticatedUser
-from src.services.utils.perf_timer import PerfTimer
-from src.backend.auth.auth_helper import AuthHelper
-from src.backend.utils.perf_metrics import PerfMetrics
-from src.services.sumo_access._helpers import SumoCase
-from src.services.surface_query_service.surface_query_service import batch_sample_surface_in_points_async
-from src.services.surface_query_service.surface_query_service import RealizationSampleResult
+from webviz_pkg.core_utils.perf_timer import PerfTimer
+
+from primary.services.sumo_access.surface_access import SurfaceAccess
+from primary.services.smda_access.stratigraphy_access import StratigraphyAccess
+from primary.services.smda_access.stratigraphy_utils import sort_stratigraphic_names_by_hierarchy
+from primary.services.smda_access.mocked_drogon_smda_access import _mocked_stratigraphy_access
+from primary.services.utils.statistic_function import StatisticFunction
+from primary.services.utils.authenticated_user import AuthenticatedUser
+from primary.auth.auth_helper import AuthHelper
+from primary.utils.perf_metrics import PerfMetrics
+from primary.services.sumo_access._helpers import SumoCase
+from primary.services.surface_query_service.surface_query_service import batch_sample_surface_in_points_async
+from primary.services.surface_query_service.surface_query_service import RealizationSampleResult
from . import converters
from . import schemas
diff --git a/backend/src/backend/primary/routers/surface/schemas.py b/backend_py/primary/primary/routers/surface/schemas.py
similarity index 96%
rename from backend/src/backend/primary/routers/surface/schemas.py
rename to backend_py/primary/primary/routers/surface/schemas.py
index 2a2b7338c..43a807c8e 100644
--- a/backend/src/backend/primary/routers/surface/schemas.py
+++ b/backend_py/primary/primary/routers/surface/schemas.py
@@ -2,9 +2,9 @@
from typing import List, Optional
from pydantic import BaseModel
+from webviz_pkg.core_utils.b64 import B64FloatArray
-from src.services.smda_access.types import StratigraphicFeature
-from src.services.utils.b64 import B64FloatArray
+from primary.services.smda_access.types import StratigraphicFeature
class SurfaceStatisticFunction(str, Enum):
diff --git a/backend/src/backend/primary/routers/timeseries/converters.py b/backend_py/primary/primary/routers/timeseries/converters.py
similarity index 89%
rename from backend/src/backend/primary/routers/timeseries/converters.py
rename to backend_py/primary/primary/routers/timeseries/converters.py
index da715f8e2..e449e6e8d 100644
--- a/backend/src/backend/primary/routers/timeseries/converters.py
+++ b/backend_py/primary/primary/routers/timeseries/converters.py
@@ -1,8 +1,8 @@
from typing import List, Optional, Sequence
-from src.services.summary_vector_statistics import VectorStatistics
-from src.services.sumo_access.summary_access import VectorMetadata
-from src.services.utils.statistic_function import StatisticFunction
+from primary.services.summary_vector_statistics import VectorStatistics
+from primary.services.sumo_access.summary_access import VectorMetadata
+from primary.services.utils.statistic_function import StatisticFunction
from . import schemas
diff --git a/backend/src/backend/primary/routers/timeseries/router.py b/backend_py/primary/primary/routers/timeseries/router.py
similarity index 96%
rename from backend/src/backend/primary/routers/timeseries/router.py
rename to backend_py/primary/primary/routers/timeseries/router.py
index 45882129b..9e494a642 100644
--- a/backend/src/backend/primary/routers/timeseries/router.py
+++ b/backend_py/primary/primary/routers/timeseries/router.py
@@ -5,13 +5,13 @@
import pyarrow.compute as pc
from fastapi import APIRouter, Depends, HTTPException, Query, Response
-from src.backend.auth.auth_helper import AuthHelper
-from src.backend.utils.perf_metrics import PerfMetrics
-from src.services.summary_vector_statistics import compute_vector_statistics
-from src.services.sumo_access.generic_types import EnsembleScalarResponse
-from src.services.sumo_access.parameter_access import ParameterAccess
-from src.services.sumo_access.summary_access import Frequency, SummaryAccess
-from src.services.utils.authenticated_user import AuthenticatedUser
+from primary.auth.auth_helper import AuthHelper
+from primary.utils.perf_metrics import PerfMetrics
+from primary.services.summary_vector_statistics import compute_vector_statistics
+from primary.services.sumo_access.generic_types import EnsembleScalarResponse
+from primary.services.sumo_access.parameter_access import ParameterAccess
+from primary.services.sumo_access.summary_access import Frequency, SummaryAccess
+from primary.services.utils.authenticated_user import AuthenticatedUser
from . import converters, schemas
diff --git a/backend/src/backend/primary/routers/timeseries/schemas.py b/backend_py/primary/primary/routers/timeseries/schemas.py
similarity index 100%
rename from backend/src/backend/primary/routers/timeseries/schemas.py
rename to backend_py/primary/primary/routers/timeseries/schemas.py
diff --git a/backend/src/backend/primary/routers/pvt/__init__.py b/backend_py/primary/primary/routers/well/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/pvt/__init__.py
rename to backend_py/primary/primary/routers/well/__init__.py
diff --git a/backend/src/backend/primary/routers/well/converters.py b/backend_py/primary/primary/routers/well/converters.py
similarity index 91%
rename from backend/src/backend/primary/routers/well/converters.py
rename to backend_py/primary/primary/routers/well/converters.py
index d52be1ce3..21e8569d8 100644
--- a/backend/src/backend/primary/routers/well/converters.py
+++ b/backend_py/primary/primary/routers/well/converters.py
@@ -1,7 +1,8 @@
from typing import List
-from src.backend.primary.routers.well import schemas
-from src.services.smda_access.types import WellBorePick, StratigraphicUnit
+from primary.services.smda_access.types import WellBorePick, StratigraphicUnit
+
+from . import schemas
def convert_wellbore_picks_to_schema(wellbore_picks: List[WellBorePick]) -> List[schemas.WellBorePick]:
diff --git a/backend/src/backend/primary/routers/well/router.py b/backend_py/primary/primary/routers/well/router.py
similarity index 91%
rename from backend/src/backend/primary/routers/well/router.py
rename to backend_py/primary/primary/routers/well/router.py
index f3583cf9e..605f6694c 100644
--- a/backend/src/backend/primary/routers/well/router.py
+++ b/backend_py/primary/primary/routers/well/router.py
@@ -3,13 +3,13 @@
from fastapi import APIRouter, Depends, Query
-from src.services.smda_access import mocked_drogon_smda_access
-from src.services.smda_access.well_access import WellAccess
-from src.services.smda_access.stratigraphy_access import StratigraphyAccess
-from src.services.utils.authenticated_user import AuthenticatedUser
-from src.backend.auth.auth_helper import AuthHelper
-from src.services.sumo_access._helpers import SumoCase
-from src.services.smda_access.types import WellBoreHeader, WellBoreTrajectory
+from primary.services.smda_access import mocked_drogon_smda_access
+from primary.services.smda_access.well_access import WellAccess
+from primary.services.smda_access.stratigraphy_access import StratigraphyAccess
+from primary.services.utils.authenticated_user import AuthenticatedUser
+from primary.auth.auth_helper import AuthHelper
+from primary.services.sumo_access._helpers import SumoCase
+from primary.services.smda_access.types import WellBoreHeader, WellBoreTrajectory
from . import schemas
from . import converters
diff --git a/backend/src/backend/primary/routers/well/schemas.py b/backend_py/primary/primary/routers/well/schemas.py
similarity index 100%
rename from backend/src/backend/primary/routers/well/schemas.py
rename to backend_py/primary/primary/routers/well/schemas.py
diff --git a/backend/src/backend/primary/routers/well_completions/router.py b/backend_py/primary/primary/routers/well_completions/router.py
similarity index 77%
rename from backend/src/backend/primary/routers/well_completions/router.py
rename to backend_py/primary/primary/routers/well_completions/router.py
index 8e7dc5eaa..acce7fec6 100644
--- a/backend/src/backend/primary/routers/well_completions/router.py
+++ b/backend_py/primary/primary/routers/well_completions/router.py
@@ -2,11 +2,11 @@
from fastapi import APIRouter, Depends, HTTPException, Query
-from src.backend.auth.auth_helper import AuthHelper
-from src.services.utils.authenticated_user import AuthenticatedUser
+from primary.auth.auth_helper import AuthHelper
+from primary.services.utils.authenticated_user import AuthenticatedUser
-from src.services.sumo_access.well_completions_access import WellCompletionsAccess
-from src.services.sumo_access.well_completions_types import WellCompletionsData
+from primary.services.sumo_access.well_completions_access import WellCompletionsAccess
+from primary.services.sumo_access.well_completions_types import WellCompletionsData
router = APIRouter()
diff --git a/backend/src/backend/primary/routers/seismic/__init__.py b/backend_py/primary/primary/services/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/seismic/__init__.py
rename to backend_py/primary/primary/services/__init__.py
diff --git a/backend/src/services/graph_access/graph_access.py b/backend_py/primary/primary/services/graph_access/graph_access.py
similarity index 100%
rename from backend/src/services/graph_access/graph_access.py
rename to backend_py/primary/primary/services/graph_access/graph_access.py
diff --git a/backend/src/services/parameter_correlations.py b/backend_py/primary/primary/services/parameter_correlations.py
similarity index 92%
rename from backend/src/services/parameter_correlations.py
rename to backend_py/primary/primary/services/parameter_correlations.py
index 227204f69..ba5894e73 100644
--- a/backend/src/services/parameter_correlations.py
+++ b/backend_py/primary/primary/services/parameter_correlations.py
@@ -2,8 +2,8 @@
import pandas as pd
-from src.services.sumo_access.parameter_access import EnsembleParameter
-from src.services.sumo_access.generic_types import EnsembleScalarResponse, EnsembleCorrelations
+from primary.services.sumo_access.parameter_access import EnsembleParameter
+from primary.services.sumo_access.generic_types import EnsembleScalarResponse, EnsembleCorrelations
def correlate_parameters_with_response(
diff --git a/backend/src/services/service_exceptions.py b/backend_py/primary/primary/services/service_exceptions.py
similarity index 100%
rename from backend/src/services/service_exceptions.py
rename to backend_py/primary/primary/services/service_exceptions.py
diff --git a/backend/src/backend/primary/routers/surface/__init__.py b/backend_py/primary/primary/services/smda_access/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/surface/__init__.py
rename to backend_py/primary/primary/services/smda_access/__init__.py
diff --git a/backend/src/services/smda_access/mocked_drogon_smda_access/__init__.py b/backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/__init__.py
similarity index 100%
rename from backend/src/services/smda_access/mocked_drogon_smda_access/__init__.py
rename to backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/__init__.py
diff --git a/backend/src/services/smda_access/mocked_drogon_smda_access/_generate_testdata.py b/backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/_generate_testdata.py
similarity index 100%
rename from backend/src/services/smda_access/mocked_drogon_smda_access/_generate_testdata.py
rename to backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/_generate_testdata.py
diff --git a/backend/src/services/smda_access/mocked_drogon_smda_access/_mocked_stratigraphy_access.py b/backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/_mocked_stratigraphy_access.py
similarity index 100%
rename from backend/src/services/smda_access/mocked_drogon_smda_access/_mocked_stratigraphy_access.py
rename to backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/_mocked_stratigraphy_access.py
diff --git a/backend/src/services/smda_access/mocked_drogon_smda_access/_mocked_well_access.py b/backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/_mocked_well_access.py
similarity index 100%
rename from backend/src/services/smda_access/mocked_drogon_smda_access/_mocked_well_access.py
rename to backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/_mocked_well_access.py
diff --git a/backend/src/services/smda_access/mocked_drogon_smda_access/_mocked_wellbore_picks.py b/backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/_mocked_wellbore_picks.py
similarity index 98%
rename from backend/src/services/smda_access/mocked_drogon_smda_access/_mocked_wellbore_picks.py
rename to backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/_mocked_wellbore_picks.py
index 39ef35785..efd6f282a 100644
--- a/backend/src/services/smda_access/mocked_drogon_smda_access/_mocked_wellbore_picks.py
+++ b/backend_py/primary/primary/services/smda_access/mocked_drogon_smda_access/_mocked_wellbore_picks.py
@@ -1,6 +1,6 @@
from typing import List
-from src.services.smda_access.types import WellBorePick
+from primary.services.smda_access.types import WellBorePick
mocked_wellbore_picks: List[WellBorePick] = [
WellBorePick(
diff --git a/backend/src/backend/primary/routers/well/__init__.py b/backend_py/primary/primary/services/smda_access/queries/__init__.py
similarity index 100%
rename from backend/src/backend/primary/routers/well/__init__.py
rename to backend_py/primary/primary/services/smda_access/queries/__init__.py
diff --git a/backend/src/services/smda_access/queries/_get_request.py b/backend_py/primary/primary/services/smda_access/queries/_get_request.py
similarity index 95%
rename from backend/src/services/smda_access/queries/_get_request.py
rename to backend_py/primary/primary/services/smda_access/queries/_get_request.py
index b03ed4abd..52c14d3fe 100644
--- a/backend/src/services/smda_access/queries/_get_request.py
+++ b/backend_py/primary/primary/services/smda_access/queries/_get_request.py
@@ -2,9 +2,9 @@
import httpx
from dotenv import load_dotenv
+from webviz_pkg.core_utils.perf_timer import PerfTimer
-from src import config
-from src.services.utils.perf_timer import PerfTimer
+from primary import config
load_dotenv()
diff --git a/backend/src/services/smda_access/queries/get_field_wellbore_trajectories.py b/backend_py/primary/primary/services/smda_access/queries/get_field_wellbore_trajectories.py
similarity index 96%
rename from backend/src/services/smda_access/queries/get_field_wellbore_trajectories.py
rename to backend_py/primary/primary/services/smda_access/queries/get_field_wellbore_trajectories.py
index 4fc498163..f8cf57d69 100644
--- a/backend/src/services/smda_access/queries/get_field_wellbore_trajectories.py
+++ b/backend_py/primary/primary/services/smda_access/queries/get_field_wellbore_trajectories.py
@@ -2,7 +2,7 @@
import pandas as pd
-from src.services.utils.perf_timer import PerfTimer
+from webviz_pkg.core_utils.perf_timer import PerfTimer
from ..types import WellBoreTrajectory
from ._get_request import get
diff --git a/backend/src/services/smda_access/queries/get_picks_for_wellbore.py b/backend_py/primary/primary/services/smda_access/queries/get_picks_for_wellbore.py
similarity index 100%
rename from backend/src/services/smda_access/queries/get_picks_for_wellbore.py
rename to backend_py/primary/primary/services/smda_access/queries/get_picks_for_wellbore.py
diff --git a/backend/src/services/smda_access/queries/get_stratigraphic_units.py b/backend_py/primary/primary/services/smda_access/queries/get_stratigraphic_units.py
similarity index 93%
rename from backend/src/services/smda_access/queries/get_stratigraphic_units.py
rename to backend_py/primary/primary/services/smda_access/queries/get_stratigraphic_units.py
index 2828affdf..6d5ac97c7 100644
--- a/backend/src/services/smda_access/queries/get_stratigraphic_units.py
+++ b/backend_py/primary/primary/services/smda_access/queries/get_stratigraphic_units.py
@@ -1,6 +1,6 @@
from typing import List
-from src.services.utils.perf_timer import PerfTimer
+from webviz_pkg.core_utils.perf_timer import PerfTimer
from ..types import StratigraphicUnit
from ._get_request import get
diff --git a/backend/src/services/smda_access/queries/get_well_headers.py b/backend_py/primary/primary/services/smda_access/queries/get_well_headers.py
similarity index 93%
rename from backend/src/services/smda_access/queries/get_well_headers.py
rename to backend_py/primary/primary/services/smda_access/queries/get_well_headers.py
index 978035344..746e97236 100644
--- a/backend/src/services/smda_access/queries/get_well_headers.py
+++ b/backend_py/primary/primary/services/smda_access/queries/get_well_headers.py
@@ -1,7 +1,7 @@
from typing import List
-from src.services.utils.perf_timer import PerfTimer
+from webviz_pkg.core_utils.perf_timer import PerfTimer
from ..types import WellBoreHeader
from ._get_request import get
diff --git a/backend/src/services/smda_access/queries/get_wellbore_picks_for_field.py b/backend_py/primary/primary/services/smda_access/queries/get_wellbore_picks_for_field.py
similarity index 94%
rename from backend/src/services/smda_access/queries/get_wellbore_picks_for_field.py
rename to backend_py/primary/primary/services/smda_access/queries/get_wellbore_picks_for_field.py
index 2f6537558..4cf513703 100644
--- a/backend/src/services/smda_access/queries/get_wellbore_picks_for_field.py
+++ b/backend_py/primary/primary/services/smda_access/queries/get_wellbore_picks_for_field.py
@@ -1,6 +1,6 @@
from typing import List, Optional
-from src.services.utils.perf_timer import PerfTimer
+from webviz_pkg.core_utils.perf_timer import PerfTimer
from ..types import WellBorePick
from ._get_request import get
diff --git a/backend/src/services/smda_access/queries/get_wellbore_trajectory.py b/backend_py/primary/primary/services/smda_access/queries/get_wellbore_trajectory.py
similarity index 96%
rename from backend/src/services/smda_access/queries/get_wellbore_trajectory.py
rename to backend_py/primary/primary/services/smda_access/queries/get_wellbore_trajectory.py
index 698fb0278..2f8c8da5c 100644
--- a/backend/src/services/smda_access/queries/get_wellbore_trajectory.py
+++ b/backend_py/primary/primary/services/smda_access/queries/get_wellbore_trajectory.py
@@ -2,7 +2,7 @@
import pandas as pd
-from src.services.utils.perf_timer import PerfTimer
+from webviz_pkg.core_utils.perf_timer import PerfTimer
from ..types import WellBoreTrajectory
from ._get_request import get
diff --git a/backend/src/services/smda_access/stratigraphy_access.py b/backend_py/primary/primary/services/smda_access/stratigraphy_access.py
similarity index 100%
rename from backend/src/services/smda_access/stratigraphy_access.py
rename to backend_py/primary/primary/services/smda_access/stratigraphy_access.py
diff --git a/backend/src/services/smda_access/stratigraphy_utils.py b/backend_py/primary/primary/services/smda_access/stratigraphy_utils.py
similarity index 100%
rename from backend/src/services/smda_access/stratigraphy_utils.py
rename to backend_py/primary/primary/services/smda_access/stratigraphy_utils.py
diff --git a/backend/src/services/smda_access/types.py b/backend_py/primary/primary/services/smda_access/types.py
similarity index 100%
rename from backend/src/services/smda_access/types.py
rename to backend_py/primary/primary/services/smda_access/types.py
diff --git a/backend/src/services/smda_access/well_access.py b/backend_py/primary/primary/services/smda_access/well_access.py
similarity index 100%
rename from backend/src/services/smda_access/well_access.py
rename to backend_py/primary/primary/services/smda_access/well_access.py
diff --git a/backend/src/services/summary_vector_statistics.py b/backend_py/primary/primary/services/summary_vector_statistics.py
similarity index 100%
rename from backend/src/services/summary_vector_statistics.py
rename to backend_py/primary/primary/services/summary_vector_statistics.py
diff --git a/backend/src/backend/user_session/__init__.py b/backend_py/primary/primary/services/sumo_access/__init__.py
similarity index 100%
rename from backend/src/backend/user_session/__init__.py
rename to backend_py/primary/primary/services/sumo_access/__init__.py
diff --git a/backend/src/services/sumo_access/_field_metadata.py b/backend_py/primary/primary/services/sumo_access/_field_metadata.py
similarity index 100%
rename from backend/src/services/sumo_access/_field_metadata.py
rename to backend_py/primary/primary/services/sumo_access/_field_metadata.py
diff --git a/backend/src/services/sumo_access/_helpers.py b/backend_py/primary/primary/services/sumo_access/_helpers.py
similarity index 90%
rename from backend/src/services/sumo_access/_helpers.py
rename to backend_py/primary/primary/services/sumo_access/_helpers.py
index 6285710c4..e6167c1b0 100644
--- a/backend/src/services/sumo_access/_helpers.py
+++ b/backend_py/primary/primary/services/sumo_access/_helpers.py
@@ -2,9 +2,10 @@
from sumo.wrapper import SumoClient
from fmu.sumo.explorer.objects import CaseCollection, Case
+from fmu.sumo.explorer.explorer import Pit
-from src import config
-from src.services.service_exceptions import Service, NoDataError, MultipleDataMatchesError
+from primary import config
+from primary.services.service_exceptions import Service, NoDataError, MultipleDataMatchesError
from .queries.case import get_stratigraphic_column_identifier, get_field_identifiers
@@ -15,7 +16,7 @@ def create_sumo_client_instance(access_token: str) -> SumoClient:
async def _init_helper(access_token: str, case_uuid: str) -> Tuple[SumoClient, Case]:
sumo_client: SumoClient = create_sumo_client_instance(access_token)
- case_collection = CaseCollection(sumo_client).filter(uuid=case_uuid)
+ case_collection = CaseCollection(sumo_client, pit=Pit(sumo_client, keep_alive="1m")).filter(uuid=case_uuid)
matching_case_count = await case_collection.length_async()
if matching_case_count == 0:
diff --git a/backend/src/services/sumo_access/_resampling.py b/backend_py/primary/primary/services/sumo_access/_resampling.py
similarity index 100%
rename from backend/src/services/sumo_access/_resampling.py
rename to backend_py/primary/primary/services/sumo_access/_resampling.py
diff --git a/backend/src/services/sumo_access/dev/dev_summary_access_test_driver.py b/backend_py/primary/primary/services/sumo_access/dev/dev_summary_access_test_driver.py
similarity index 97%
rename from backend/src/services/sumo_access/dev/dev_summary_access_test_driver.py
rename to backend_py/primary/primary/services/sumo_access/dev/dev_summary_access_test_driver.py
index 0f7ac2ef5..bf84280d4 100644
--- a/backend/src/services/sumo_access/dev/dev_summary_access_test_driver.py
+++ b/backend_py/primary/primary/services/sumo_access/dev/dev_summary_access_test_driver.py
@@ -7,7 +7,7 @@
from fmu.sumo.explorer.explorer import SumoClient
-from src.services.summary_vector_statistics import compute_vector_statistics_table, compute_vector_statistics
+from primary.services.summary_vector_statistics import compute_vector_statistics_table, compute_vector_statistics
from ..summary_access import SummaryAccess, RealizationVector, Frequency
from ..sumo_explore import SumoExplore
diff --git a/backend/src/services/sumo_access/generic_types.py b/backend_py/primary/primary/services/sumo_access/generic_types.py
similarity index 100%
rename from backend/src/services/sumo_access/generic_types.py
rename to backend_py/primary/primary/services/sumo_access/generic_types.py
diff --git a/backend/src/services/sumo_access/grid_access.py b/backend_py/primary/primary/services/sumo_access/grid_access.py
similarity index 97%
rename from backend/src/services/sumo_access/grid_access.py
rename to backend_py/primary/primary/services/sumo_access/grid_access.py
index a59b9229e..fa9b5b9b6 100644
--- a/backend/src/services/sumo_access/grid_access.py
+++ b/backend_py/primary/primary/services/sumo_access/grid_access.py
@@ -4,7 +4,7 @@
import xtgeo
-from src.services.utils.perf_timer import PerfTimer
+from webviz_pkg.core_utils.perf_timer import PerfTimer
from ._helpers import SumoEnsemble
from .queries.cpgrid import (
diff --git a/backend/src/services/sumo_access/inplace_volumetrics_access.py b/backend_py/primary/primary/services/sumo_access/inplace_volumetrics_access.py
similarity index 100%
rename from backend/src/services/sumo_access/inplace_volumetrics_access.py
rename to backend_py/primary/primary/services/sumo_access/inplace_volumetrics_access.py
diff --git a/backend/src/services/sumo_access/observation_access.py b/backend_py/primary/primary/services/sumo_access/observation_access.py
similarity index 100%
rename from backend/src/services/sumo_access/observation_access.py
rename to backend_py/primary/primary/services/sumo_access/observation_access.py
diff --git a/backend/src/services/sumo_access/observation_types.py b/backend_py/primary/primary/services/sumo_access/observation_types.py
similarity index 100%
rename from backend/src/services/sumo_access/observation_types.py
rename to backend_py/primary/primary/services/sumo_access/observation_types.py
diff --git a/backend/src/services/sumo_access/parameter_access.py b/backend_py/primary/primary/services/sumo_access/parameter_access.py
similarity index 98%
rename from backend/src/services/sumo_access/parameter_access.py
rename to backend_py/primary/primary/services/sumo_access/parameter_access.py
index 119c4a869..ac4dafd3b 100644
--- a/backend/src/services/sumo_access/parameter_access.py
+++ b/backend_py/primary/primary/services/sumo_access/parameter_access.py
@@ -6,7 +6,7 @@
import pyarrow as pa
import pyarrow.parquet as pq
-from ..utils.perf_timer import PerfTimer
+from webviz_pkg.core_utils.perf_timer import PerfTimer
from ._helpers import SumoEnsemble
from .parameter_types import (
EnsembleParameter,
diff --git a/backend/src/services/sumo_access/parameter_types.py b/backend_py/primary/primary/services/sumo_access/parameter_types.py
similarity index 100%
rename from backend/src/services/sumo_access/parameter_types.py
rename to backend_py/primary/primary/services/sumo_access/parameter_types.py
diff --git a/backend/src/services/sumo_access/polygons_access.py b/backend_py/primary/primary/services/sumo_access/polygons_access.py
similarity index 98%
rename from backend/src/services/sumo_access/polygons_access.py
rename to backend_py/primary/primary/services/sumo_access/polygons_access.py
index cb65a225c..81bc44018 100644
--- a/backend/src/services/sumo_access/polygons_access.py
+++ b/backend_py/primary/primary/services/sumo_access/polygons_access.py
@@ -6,7 +6,7 @@
import xtgeo
from fmu.sumo.explorer.objects import PolygonsCollection
-from src.services.utils.perf_timer import PerfTimer
+from webviz_pkg.core_utils.perf_timer import PerfTimer
from ._helpers import SumoEnsemble
from .polygons_types import PolygonsMeta
diff --git a/backend/src/services/sumo_access/polygons_types.py b/backend_py/primary/primary/services/sumo_access/polygons_types.py
similarity index 100%
rename from backend/src/services/sumo_access/polygons_types.py
rename to backend_py/primary/primary/services/sumo_access/polygons_types.py
diff --git a/backend/src/backend/user_session/routers/__init__.py b/backend_py/primary/primary/services/sumo_access/queries/__init__.py
similarity index 100%
rename from backend/src/backend/user_session/routers/__init__.py
rename to backend_py/primary/primary/services/sumo_access/queries/__init__.py
diff --git a/backend/src/services/sumo_access/queries/case.py b/backend_py/primary/primary/services/sumo_access/queries/case.py
similarity index 100%
rename from backend/src/services/sumo_access/queries/case.py
rename to backend_py/primary/primary/services/sumo_access/queries/case.py
diff --git a/backend/src/services/sumo_access/queries/cpgrid.py b/backend_py/primary/primary/services/sumo_access/queries/cpgrid.py
similarity index 100%
rename from backend/src/services/sumo_access/queries/cpgrid.py
rename to backend_py/primary/primary/services/sumo_access/queries/cpgrid.py
diff --git a/backend/src/services/sumo_access/rft_access.py b/backend_py/primary/primary/services/sumo_access/rft_access.py
similarity index 99%
rename from backend/src/services/sumo_access/rft_access.py
rename to backend_py/primary/primary/services/sumo_access/rft_access.py
index be5b49d4c..602383947 100644
--- a/backend/src/services/sumo_access/rft_access.py
+++ b/backend_py/primary/primary/services/sumo_access/rft_access.py
@@ -7,9 +7,9 @@
import pyarrow.compute as pc
import pyarrow.parquet as pq
from fmu.sumo.explorer.objects import Case, TableCollection
+from webviz_pkg.core_utils.perf_timer import PerfTimer
from ._helpers import SumoEnsemble
-from ..utils.perf_timer import PerfTimer
from .rft_types import RftInfo, RftRealizationData
LOGGER = logging.getLogger(__name__)
diff --git a/backend/src/services/sumo_access/rft_types.py b/backend_py/primary/primary/services/sumo_access/rft_types.py
similarity index 100%
rename from backend/src/services/sumo_access/rft_types.py
rename to backend_py/primary/primary/services/sumo_access/rft_types.py
diff --git a/backend/src/services/sumo_access/seismic_access.py b/backend_py/primary/primary/services/sumo_access/seismic_access.py
similarity index 100%
rename from backend/src/services/sumo_access/seismic_access.py
rename to backend_py/primary/primary/services/sumo_access/seismic_access.py
diff --git a/backend/src/services/sumo_access/seismic_types.py b/backend_py/primary/primary/services/sumo_access/seismic_types.py
similarity index 100%
rename from backend/src/services/sumo_access/seismic_types.py
rename to backend_py/primary/primary/services/sumo_access/seismic_types.py
diff --git a/backend/src/services/sumo_access/summary_access.py b/backend_py/primary/primary/services/sumo_access/summary_access.py
similarity index 98%
rename from backend/src/services/sumo_access/summary_access.py
rename to backend_py/primary/primary/services/sumo_access/summary_access.py
index 225c8529b..cb1077028 100644
--- a/backend/src/services/sumo_access/summary_access.py
+++ b/backend_py/primary/primary/services/sumo_access/summary_access.py
@@ -6,11 +6,11 @@
import pyarrow as pa
import pyarrow.compute as pc
from fmu.sumo.explorer.objects import Case, TableCollection, Table
+from webviz_pkg.core_utils.perf_timer import PerfTimer
-from src.services.utils.arrow_helpers import sort_table_on_real_then_date, is_date_column_monotonically_increasing
-from src.services.utils.arrow_helpers import find_first_non_increasing_date_pair
-from src.services.utils.perf_timer import PerfTimer
-from src.services.service_exceptions import (
+from primary.services.utils.arrow_helpers import sort_table_on_real_then_date, is_date_column_monotonically_increasing
+from primary.services.utils.arrow_helpers import find_first_non_increasing_date_pair
+from primary.services.service_exceptions import (
Service,
NoDataError,
InvalidDataError,
diff --git a/backend/src/services/sumo_access/summary_types.py b/backend_py/primary/primary/services/sumo_access/summary_types.py
similarity index 100%
rename from backend/src/services/sumo_access/summary_types.py
rename to backend_py/primary/primary/services/sumo_access/summary_types.py
diff --git a/backend/src/services/sumo_access/sumo_explore.py b/backend_py/primary/primary/services/sumo_access/sumo_explore.py
similarity index 100%
rename from backend/src/services/sumo_access/sumo_explore.py
rename to backend_py/primary/primary/services/sumo_access/sumo_explore.py
diff --git a/backend/src/services/sumo_access/surface_access.py b/backend_py/primary/primary/services/sumo_access/surface_access.py
similarity index 98%
rename from backend/src/services/sumo_access/surface_access.py
rename to backend_py/primary/primary/services/sumo_access/surface_access.py
index 90f7a8ab3..d0353be1b 100644
--- a/backend/src/services/sumo_access/surface_access.py
+++ b/backend_py/primary/primary/services/sumo_access/surface_access.py
@@ -8,8 +8,8 @@
from fmu.sumo.explorer import TimeFilter, TimeType
from fmu.sumo.explorer.objects import SurfaceCollection, Surface
-from src.services.utils.perf_timer import PerfTimer
-from src.services.utils.statistic_function import StatisticFunction
+from webviz_pkg.core_utils.perf_timer import PerfTimer
+from primary.services.utils.statistic_function import StatisticFunction
from ._helpers import SumoEnsemble
from .surface_types import SurfaceMeta, XtgeoSurfaceIntersectionResult, XtgeoSurfaceIntersectionPolyline
diff --git a/backend/src/services/sumo_access/surface_types.py b/backend_py/primary/primary/services/sumo_access/surface_types.py
similarity index 100%
rename from backend/src/services/sumo_access/surface_types.py
rename to backend_py/primary/primary/services/sumo_access/surface_types.py
diff --git a/backend/src/services/sumo_access/table_access.py b/backend_py/primary/primary/services/sumo_access/table_access.py
similarity index 100%
rename from backend/src/services/sumo_access/table_access.py
rename to backend_py/primary/primary/services/sumo_access/table_access.py
diff --git a/backend/src/services/sumo_access/well_completions_access.py b/backend_py/primary/primary/services/sumo_access/well_completions_access.py
similarity index 100%
rename from backend/src/services/sumo_access/well_completions_access.py
rename to backend_py/primary/primary/services/sumo_access/well_completions_access.py
diff --git a/backend/src/services/sumo_access/well_completions_types.py b/backend_py/primary/primary/services/sumo_access/well_completions_types.py
similarity index 100%
rename from backend/src/services/sumo_access/well_completions_types.py
rename to backend_py/primary/primary/services/sumo_access/well_completions_types.py
diff --git a/backend/src/services/surface_query_service/surface_query_service.py b/backend_py/primary/primary/services/surface_query_service/surface_query_service.py
similarity index 97%
rename from backend/src/services/surface_query_service/surface_query_service.py
rename to backend_py/primary/primary/services/surface_query_service/surface_query_service.py
index ffefda94c..c6ba807ff 100644
--- a/backend/src/services/surface_query_service/surface_query_service.py
+++ b/backend_py/primary/primary/services/surface_query_service/surface_query_service.py
@@ -9,8 +9,8 @@
from pydantic import BaseModel
from sumo.wrapper import SumoClient
-from src import config
-from src.services.service_exceptions import AuthorizationError, Service
+from primary import config
+from primary.services.service_exceptions import AuthorizationError, Service
LOGGER = logging.getLogger(__name__)
diff --git a/backend_py/primary/primary/services/user_session_manager/_background_tasks.py b/backend_py/primary/primary/services/user_session_manager/_background_tasks.py
new file mode 100644
index 000000000..3c0c45d8f
--- /dev/null
+++ b/backend_py/primary/primary/services/user_session_manager/_background_tasks.py
@@ -0,0 +1,37 @@
+import logging
+import asyncio
+from typing import Coroutine
+
+
+LOGGER = logging.getLogger(__name__)
+
+_background_tasks: set[asyncio.Task] = set()
+
+
+def _task_done_cb(task: asyncio.Task) -> None:
+ # To prevent keeping references to finished tasks forever, make each task remove its
+ # own reference from the set after completion
+ _background_tasks.discard(task)
+
+ # Look for exceptions and log them
+ try:
+ # Also marks that the exception has been handled
+ exc = task.exception()
+ if exc:
+ LOGGER.exception("Background task raised an exception", exc_info=exc)
+ except asyncio.exceptions.CancelledError:
+ pass
+
+
+def run_in_background_task(coroutine: Coroutine) -> asyncio.Task:
+ """
+ Create a background task and schedule it to run in a fire-and-forget fashion
+ """
+ task = asyncio.create_task(coroutine)
+
+ # Add task to the set, creating a strong reference to the task, which prevents it from being garbage collected
+ # See https://docs.python.org/3/library/asyncio-task.html#asyncio.create_task
+ _background_tasks.add(task)
+
+ task.add_done_callback(_task_done_cb)
+ return task
diff --git a/backend_py/primary/primary/services/user_session_manager/_radix_helpers.py b/backend_py/primary/primary/services/user_session_manager/_radix_helpers.py
new file mode 100644
index 000000000..1687d00cc
--- /dev/null
+++ b/backend_py/primary/primary/services/user_session_manager/_radix_helpers.py
@@ -0,0 +1,206 @@
+import asyncio
+import logging
+import os
+from typing import List, Literal
+
+import httpx
+from pydantic import BaseModel, TypeAdapter
+
+LOGGER = logging.getLogger(__name__)
+
+
+# This is a bit of a hack, but it's one way to know if we're running in Radix or locally
+IS_ON_RADIX_PLATFORM = True if os.getenv("RADIX_APP") is not None else False
+print(f"{IS_ON_RADIX_PLATFORM=}")
+
+
+# Notes on RadixResourceRequests:
+# * cpu: typical units are 'm' or no unit. '100m' means 100 milli-cpu, which is 0.1 cpu. 1000m is 1 cpu
+# * memory: typical units are 'Mi' or 'Gi'. 500Mi means 500 Mebibytes, 4Gi means 4 Gibibyte (i.e. 4 * 1024^3 bytes)
+class RadixResourceRequests(BaseModel):
+ cpu: str
+ memory: str
+
+
+# Notes on RadixJobState:
+# * The 'Waiting' status is not documented, but it seems to be the status of a job that has been created but not yet running
+# * We're not always getting a job status, in particular when querying the status of a named job, so include a None entry for status
+# * Sometimes we get an extra (undocumented) field returned, 'message'
+class RadixJobState(BaseModel):
+ name: str
+ status: Literal["Waiting", "Running", "Succeeded", "Stopped", "Failed"] | None = None
+ started: str | None = None
+ ended: str | None = None
+ message: str | None = None
+
+
+async def create_new_radix_job(
+ job_component_name: str, job_scheduler_port: int, resource_req: RadixResourceRequests
+) -> str | None:
+ LOGGER.debug(f"create_new_radix_job() - {job_component_name=}, {resource_req=}")
+
+ radix_job_manager_url = f"http://{job_component_name}:{job_scheduler_port}/api/v1/jobs"
+
+ # Setting memory request equal to memory limit on purpose
+ # Also, cpu limit is omitted on purpose.
+ # Following advice here:
+ # https://home.robusta.dev/blog/kubernetes-memory-limit
+ # https://home.robusta.dev/blog/stop-using-cpu-limits
+ #
+ # Note that this might not be the best solution if we end up running golang apps inside the jobs since there
+ # we might want to auto discover the number of available cpus and set the GOMAXPROCS environment variable accordingly.
+ # As of now, it seems that it's the cpu limit value that will be picked up by for example by automaxprocs.
+ request_body = {
+ "resources": {
+ "requests": {
+ "memory": resource_req.memory,
+ "cpu": resource_req.cpu,
+ },
+ "limits": {
+ "memory": resource_req.memory,
+ },
+ }
+ }
+
+ async with httpx.AsyncClient() as client:
+ try:
+ response = await client.post(url=radix_job_manager_url, json=request_body)
+ response.raise_for_status()
+ except httpx.RequestError as e:
+ LOGGER.error(f"Error creating radix job, request error occurred for POST to: {e.request.url}")
+ return None
+ except httpx.HTTPStatusError as e:
+ LOGGER.error(f"Error creating radix job, HTTP error {e.response.status_code} for POST to {e.request.url}")
+ return None
+
+ # According to the docs it seems we should be getting a json back that contains
+ # a status field, which should be "Running" if the job was started successfully.
+ # Apparently this is not the case, as of Feb 2024, the only useful piece of information we're
+ # getting back from this call is the name of the newly created job.
+ response_dict = response.json()
+
+ LOGGER.debug("------")
+ LOGGER.debug(f"{response_dict=}")
+ LOGGER.debug("------")
+
+ radix_job_name = response_dict["name"]
+ LOGGER.debug(f"create_new_radix_job() - new job created {radix_job_name=}")
+
+ return radix_job_name
+
+
+async def get_radix_job_state(
+ job_component_name: str, job_scheduler_port: int, radix_job_name: str
+) -> RadixJobState | None:
+ LOGGER.debug(f"get_radix_job_state() - {job_component_name=}, {radix_job_name=}")
+
+ url = f"http://{job_component_name}:{job_scheduler_port}/api/v1/jobs/{radix_job_name}"
+
+ async with httpx.AsyncClient() as client:
+ try:
+ response = await client.get(url=url)
+ response.raise_for_status()
+ except httpx.HTTPError as exception:
+ LOGGER.debug(f"get_radix_job_state() - could not get job state {exception=}")
+ return None
+
+ # LOGGER.debug("------")
+ # LOGGER.debug(f"{response.json()=}")
+ # LOGGER.debug("------")
+
+ # Note that the response we're getting back does not always contain an entry for status
+ # Therefore we're allowing None for the status field of RadixJobState
+ radix_job_state = RadixJobState.model_validate_json(response.content)
+ LOGGER.debug(f"get_radix_job_state() - got job state {radix_job_state=}")
+ return radix_job_state
+
+
+async def is_radix_job_running(job_component_name: str, job_scheduler_port: int, radix_job_name: str) -> bool:
+ radix_job_state = await get_radix_job_state(job_component_name, job_scheduler_port, radix_job_name)
+ if radix_job_state and radix_job_state.status == "Running":
+ return True
+
+ return False
+
+
+async def get_all_radix_jobs(job_component_name: str, job_scheduler_port: int) -> List[RadixJobState]:
+ LOGGER.debug(f"get_all_radix_jobs() - {job_component_name=}")
+
+ url = f"http://{job_component_name}:{job_scheduler_port}/api/v1/jobs"
+ async with httpx.AsyncClient() as client:
+ try:
+ response = await client.get(url)
+ response.raise_for_status()
+ except httpx.RequestError as e:
+ LOGGER.error(f"Error getting radix jobs, request error occurred for GET to: {e.request.url}")
+ return []
+ except httpx.HTTPStatusError as e:
+ LOGGER.error(f"Error getting radix jobs, HTTP error {e.response.status_code} for GET to {e.request.url}")
+ return []
+
+ # LOGGER.debug("------")
+ # LOGGER.debug(f"{response.json()=}")
+ # LOGGER.debug("------")
+
+ tadapter = TypeAdapter(List[RadixJobState])
+ ret_list = tadapter.validate_json(response.content)
+
+ LOGGER.debug(f"get_all_radix_jobs() - got list with {len(ret_list)} jobs")
+
+ return ret_list
+
+
+async def delete_named_radix_job(job_component_name: str, job_scheduler_port: int, radix_job_name: str) -> bool:
+ async with httpx.AsyncClient() as client:
+ return await _delete_named_radix_job_with_client(client, job_component_name, job_scheduler_port, radix_job_name)
+
+
+async def _delete_named_radix_job_with_client(
+ client: httpx.AsyncClient, job_component_name: str, job_scheduler_port: int, radix_job_name: str
+) -> bool:
+ LOGGER.debug(f"_delete_named_radix_job_with_client() - {job_component_name=}, {radix_job_name=}")
+
+ url = f"http://{job_component_name}:{job_scheduler_port}/api/v1/jobs/{radix_job_name}"
+ try:
+ response = await client.delete(url)
+ response.raise_for_status()
+ except httpx.RequestError as e:
+ LOGGER.error(f"Error deleting radix job, request error occurred for DELETE to: {e.request.url}.")
+ return False
+ except httpx.HTTPStatusError as e:
+ LOGGER.error(f"Error deleting radix job, HTTP error {e.response.status_code} for DELETE to {e.request.url}")
+ return False
+
+ LOGGER.debug(f"_delete_named_radix_job_with_client() - deleted radix job {radix_job_name=}")
+ return True
+
+
+async def delete_all_radix_jobs(job_component_name: str, job_scheduler_port: int) -> None:
+ LOGGER.debug(f"delete_all_radix_jobs() - {job_component_name=}")
+
+ job_list = await get_all_radix_jobs(job_component_name, job_scheduler_port)
+ if not job_list:
+ LOGGER.debug(f"delete_all_radix_jobs() - no jobs to delete")
+ return
+
+ delete_coros_arr = []
+
+ async with httpx.AsyncClient() as client:
+ for job in job_list:
+ radix_job_name = job.name
+ LOGGER.debug(f"delete_all_radix_jobs() - deleting job {radix_job_name}")
+ del_coro = _delete_named_radix_job_with_client(
+ client=client,
+ job_component_name=job_component_name,
+ job_scheduler_port=job_scheduler_port,
+ radix_job_name=radix_job_name,
+ )
+ delete_coros_arr.append(del_coro)
+
+ result_arr = await asyncio.gather(*delete_coros_arr)
+
+ # LOGGER.debug("------")
+ # LOGGER.debug(f"{result_arr=}")
+ # LOGGER.debug("------")
+
+ LOGGER.debug(f"delete_all_radix_jobs() - finished")
diff --git a/backend_py/primary/primary/services/user_session_manager/_user_session_directory.py b/backend_py/primary/primary/services/user_session_manager/_user_session_directory.py
new file mode 100644
index 000000000..328a6d330
--- /dev/null
+++ b/backend_py/primary/primary/services/user_session_manager/_user_session_directory.py
@@ -0,0 +1,180 @@
+import logging
+from dataclasses import dataclass
+from enum import Enum
+
+import redis
+
+from primary import config
+
+LOGGER = logging.getLogger(__name__)
+
+
+class SessionRunState(str, Enum):
+ CREATING_RADIX_JOB = "CREATING_RADIX_JOB"
+ WAITING_TO_COME_ONLINE = "WAITING_TO_COME_ONLINE"
+ RUNNING = "RUNNING"
+
+
+_USER_SESSIONS_REDIS_PREFIX = "user-session"
+
+
+@dataclass(frozen=True, kw_only=True)
+class JobAddress:
+ user_id: str
+ job_component_name: str
+ instance_str: str
+
+
+def _encode_redis_hash_name_str(address: JobAddress) -> str:
+ if not address.user_id:
+ raise ValueError("address.user_id cannot be empty")
+ if address.user_id.find(":") != -1:
+ raise ValueError("address.user_id cannot contain ':'")
+
+ return f"{_USER_SESSIONS_REDIS_PREFIX}:{address.user_id}:{address.job_component_name}:{address.instance_str}"
+
+
+def _decode_redis_hash_name_str(hash_name_str: str) -> JobAddress:
+ key_parts = hash_name_str.split(":")
+ if len(key_parts) != 4:
+ raise ValueError(f"Unexpected hash_name_str format {hash_name_str=}")
+ if key_parts[0] != _USER_SESSIONS_REDIS_PREFIX:
+ raise ValueError(f"Unexpected hash_name_str format, wrong prefix, {hash_name_str=}")
+ if not key_parts[1]:
+ raise ValueError(f"Unexpected hash_name_str format, empty user_id, {hash_name_str=}")
+ if not key_parts[2]:
+ raise ValueError(f"Unexpected hash_name_str format, empty job_component_name, {hash_name_str=}")
+
+ return JobAddress(user_id=key_parts[1], job_component_name=key_parts[2], instance_str=key_parts[3])
+
+
+class SessionInfoUpdater:
+ def __init__(self, redis_client: redis.Redis, user_id: str, job_component_name: str, instance_str: str) -> None:
+ self._redis_client = redis_client
+ self._user_id = user_id
+ self._job_component_name = job_component_name
+ self._instance_str = instance_str
+
+ def delete_all_state(self) -> None:
+ hash_name = self._make_hash_name()
+ self._redis_client.delete(hash_name)
+
+ def set_state_creating(self) -> None:
+ hash_name = self._make_hash_name()
+ self._redis_client.hset(
+ name=hash_name,
+ mapping={
+ "state": SessionRunState.CREATING_RADIX_JOB,
+ "radix_job_name": "",
+ },
+ )
+
+ def set_state_waiting(self, radix_job_name: str) -> None:
+ hash_name = self._make_hash_name()
+ self._redis_client.hset(
+ name=hash_name,
+ mapping={
+ "state": SessionRunState.WAITING_TO_COME_ONLINE,
+ "radix_job_name": radix_job_name,
+ },
+ )
+
+ def set_state_running(self) -> None:
+ hash_name = self._make_hash_name()
+ self._redis_client.hset(
+ name=hash_name,
+ mapping={
+ "state": SessionRunState.RUNNING,
+ },
+ )
+
+ def _make_hash_name(self) -> str:
+ addr = JobAddress(
+ user_id=self._user_id, job_component_name=self._job_component_name, instance_str=self._instance_str
+ )
+ return _encode_redis_hash_name_str(addr)
+
+
+@dataclass(frozen=True, kw_only=True)
+class SessionInfo:
+ job_component_name: str
+ instance_str: str
+ run_state: SessionRunState
+ radix_job_name: str | None
+
+
+class UserSessionDirectory:
+ def __init__(self, user_id: str) -> None:
+ self._user_id = user_id
+ self._redis_client = redis.Redis.from_url(config.REDIS_USER_SESSION_URL, decode_responses=True)
+
+ def get_session_info(self, job_component_name: str, instance_str: str) -> SessionInfo | None:
+ addr = JobAddress(user_id=self._user_id, job_component_name=job_component_name, instance_str=instance_str)
+ hash_name = _encode_redis_hash_name_str(addr)
+ value_dict = self._redis_client.hgetall(name=hash_name)
+ if not value_dict:
+ return None
+
+ state_str = value_dict.get("state")
+ radix_job_name = value_dict.get("radix_job_name")
+ if not state_str:
+ return None
+
+ run_state = SessionRunState(state_str)
+ return SessionInfo(
+ job_component_name=job_component_name,
+ instance_str=instance_str,
+ run_state=run_state,
+ radix_job_name=radix_job_name,
+ )
+
+ def get_session_info_arr(self, job_component_name: str | None) -> list[SessionInfo]:
+ if job_component_name is None:
+ job_component_name = "*"
+
+ pattern = f"{_USER_SESSIONS_REDIS_PREFIX}:{self._user_id}:{job_component_name}:*"
+ LOGGER.debug(f"Redis scan pattern pattern {pattern=}")
+
+ ret_list: list[SessionInfo] = []
+ for key in self._redis_client.scan_iter(pattern):
+ LOGGER.debug(f"{key=}")
+ job_address = _decode_redis_hash_name_str(key)
+ if job_address.user_id != self._user_id:
+ raise ValueError(f"Unexpected key format, mismatch in user_id {key=}")
+ matched_job_component_name = job_address.job_component_name
+ matched_instance_str = job_address.instance_str
+ job_info = self.get_session_info(matched_job_component_name, matched_instance_str)
+ if job_info is not None:
+ ret_list.append(job_info)
+
+ return ret_list
+
+ def delete_session_info(self, job_component_name: str | None) -> None:
+ if job_component_name is None:
+ job_component_name = "*"
+
+ pattern = f"{_USER_SESSIONS_REDIS_PREFIX}:{self._user_id}:{job_component_name}:*"
+ LOGGER.debug(f"Redis scan pattern pattern {pattern=}")
+
+ key_list = []
+ for key in self._redis_client.scan_iter(pattern):
+ LOGGER.debug(f"{key=}")
+ key_list.append(key)
+
+ self._redis_client.delete(*key_list)
+
+ def make_lock_key(self, job_component_name: str, instance_str: str) -> str:
+ addr = JobAddress(user_id=self._user_id, job_component_name=job_component_name, instance_str=instance_str)
+ hash_name = _encode_redis_hash_name_str(addr)
+ return f"{hash_name}:lock"
+
+ def create_session_info_updater(self, job_component_name: str, instance_str: str) -> SessionInfoUpdater:
+ return SessionInfoUpdater(
+ redis_client=self._redis_client,
+ user_id=self._user_id,
+ job_component_name=job_component_name,
+ instance_str=instance_str,
+ )
+
+ def get_redis_client(self) -> redis.Redis:
+ return self._redis_client
diff --git a/backend_py/primary/primary/services/user_session_manager/_util_classes.py b/backend_py/primary/primary/services/user_session_manager/_util_classes.py
new file mode 100644
index 000000000..e350eb9a5
--- /dev/null
+++ b/backend_py/primary/primary/services/user_session_manager/_util_classes.py
@@ -0,0 +1,47 @@
+import logging
+import time
+from contextlib import AbstractContextManager
+from types import TracebackType
+
+from pottery import Redlock
+
+LOGGER = logging.getLogger(__name__)
+
+
+class TimeCounter:
+ def __init__(self, duration_s: float) -> None:
+ self._start_s = time.perf_counter()
+ self._end_s = self._start_s + duration_s
+
+ def elapsed_s(self) -> float:
+ return time.perf_counter() - self._start_s
+
+ def remaining_s(self) -> float:
+ time_now = time.perf_counter()
+ remaining = self._end_s - time_now
+ return remaining if remaining > 0 else 0
+
+
+class LockReleasingContext(AbstractContextManager):
+ def __init__(self, acquired_lock: Redlock) -> None:
+ self._acquired_lock: Redlock = acquired_lock
+
+ def __enter__(self) -> Redlock:
+ LOGGER.debug("LockReleasingContext.__enter__()")
+ return self._acquired_lock
+
+ def __exit__(
+ self, _exc_type: type[BaseException] | None, _exc_value: BaseException | None, _traceback: TracebackType | None
+ ) -> bool | None:
+ LOGGER.debug("LockReleasingContext.__exit__() - releasing lock")
+ self._acquired_lock.release()
+
+ # What is the correct return value here?
+ # If there was an exception, AND we want to suppress it, return True
+ return None
+
+ # We may want to silence this exception, but not until we have control
+ # try:
+ # self._acquired_lock.release()
+ # except ReleaseUnlockedLock:
+ # pass
diff --git a/backend_py/primary/primary/services/user_session_manager/user_session_manager.py b/backend_py/primary/primary/services/user_session_manager/user_session_manager.py
new file mode 100644
index 000000000..b269c29b0
--- /dev/null
+++ b/backend_py/primary/primary/services/user_session_manager/user_session_manager.py
@@ -0,0 +1,317 @@
+import asyncio
+import logging
+from dataclasses import dataclass
+from enum import Enum
+from typing import Tuple
+
+import httpx
+from pottery import Redlock
+
+from webviz_pkg.core_utils.perf_timer import PerfTimer
+
+from ._radix_helpers import IS_ON_RADIX_PLATFORM
+from ._radix_helpers import create_new_radix_job, RadixResourceRequests
+from ._radix_helpers import is_radix_job_running, delete_named_radix_job
+from ._user_session_directory import SessionInfo, SessionRunState, UserSessionDirectory
+from ._util_classes import LockReleasingContext, TimeCounter
+from ._background_tasks import run_in_background_task
+
+LOGGER = logging.getLogger(__name__)
+
+
+class UserComponent(str, Enum):
+ GRID3D_RI = "GRID3D_RI"
+ GRID3D_VTK = "GRID3D_VTK"
+ MOCK = "MOCK"
+
+
+@dataclass(frozen=True, kw_only=True)
+class _UserSessionDef:
+ # fmt:off
+ job_component_name: str # The job's component name in radix, or the service name in docker compose, e.g. "user-mock"
+ port: int # The port number for the radix job manager AND the actual port of the service. These must be the same for our current docker compose setup
+ resource_req: RadixResourceRequests # The resource requests for the radix job
+ # fmt:on
+
+
+_USER_SESSION_DEFS: dict[UserComponent, _UserSessionDef] = {
+ UserComponent.MOCK: _UserSessionDef(
+ job_component_name="user-mock", port=8001, resource_req=RadixResourceRequests(cpu="100m", memory="200Mi")
+ ),
+ UserComponent.GRID3D_RI: _UserSessionDef(
+ job_component_name="user-grid3d-ri", port=8002, resource_req=RadixResourceRequests(cpu="200m", memory="400Mi")
+ ),
+ UserComponent.GRID3D_VTK: _UserSessionDef(
+ job_component_name="user-grid3d-vtk", port=8003, resource_req=RadixResourceRequests(cpu="200m", memory="400Mi")
+ ),
+}
+
+
+class UserSessionManager:
+ def __init__(self, user_id: str) -> None:
+ self._user_id = user_id
+
+ async def get_or_create_session_async(self, user_component: UserComponent, instance_str: str | None) -> str | None:
+ timer = PerfTimer()
+ LOGGER.debug(f"Get or create user session for: {user_component=}, {instance_str=}")
+
+ session_def = _USER_SESSION_DEFS[user_component]
+ effective_instance_str = instance_str if instance_str else "DEFAULT"
+ actual_service_port = session_def.port
+
+ session_dir = UserSessionDirectory(self._user_id)
+
+ # Note that currently the timeout values (approx_timeout_s) used here are purely experimental at the moment.
+ # We may be able to get some insights from the Radix team on this, but still this will have to
+ # be weighed up against how long a timeout is acceptable from a user standpoint.
+
+ existing_session_info = await _get_info_for_running_session(
+ session_dir=session_dir,
+ job_component_name=session_def.job_component_name,
+ job_scheduler_port=session_def.port,
+ instance_str=effective_instance_str,
+ actual_service_port=actual_service_port,
+ approx_timeout_s=40,
+ )
+ if existing_session_info:
+ session_url = f"http://{existing_session_info.radix_job_name}:{actual_service_port}"
+ LOGGER.info(
+ f"Got existing user session in: {timer.elapsed_ms()}ms ({user_component=}, {instance_str=}, {session_url=})"
+ )
+ return session_url
+
+ LOGGER.debug(
+ f"Unable to get existing user session, starting new session for: {user_component=}, {instance_str=}"
+ )
+ new_session_info = await _create_new_session(
+ session_dir=session_dir,
+ job_component_name=session_def.job_component_name,
+ job_scheduler_port=session_def.port,
+ resource_req=session_def.resource_req,
+ instance_str=effective_instance_str,
+ actual_service_port=actual_service_port,
+ approx_timeout_s=30,
+ )
+
+ if not new_session_info:
+ LOGGER.error(f"Failed to create new user session for: {user_component=}, {instance_str=}")
+ return None
+
+ session_url = f"http://{new_session_info.radix_job_name}:{actual_service_port}"
+ LOGGER.info(
+ f"Created new user session in: {timer.elapsed_ms()}ms ({user_component=}, {instance_str=}, {session_url=})"
+ )
+
+ return session_url
+
+
+# Look for existing session info, possibly waiting for a partially created session to come online
+#
+# Reasons why this function may return None
+# 1. We found the session, but it's not running yet (it's in the process of being created/spinning
+# up or has got stuck while being created)
+# 2. We did not find the session in the directory, and it needs to be created
+# 3. We found the session and the info says it is running, but our verification probe against
+# radix or a probe against the service's health endpoint says it's not
+async def _get_info_for_running_session(
+ session_dir: UserSessionDirectory,
+ job_component_name: str,
+ job_scheduler_port: int,
+ instance_str: str,
+ actual_service_port: int,
+ approx_timeout_s: float,
+) -> SessionInfo | None:
+
+ time_counter = TimeCounter(approx_timeout_s)
+ sleep_time_s = 1
+ num_calls = 1
+
+ session_info = session_dir.get_session_info(job_component_name, instance_str)
+ if not session_info:
+ return None
+
+ # Given that we found info on the session and it's not in the running state, we will try and wait for it to come online.
+ # The job/session might be in the process of being created and spinning up, so we will try and wait for it.
+ # How much time should we spend here before giving up? Currently we just consume an approximate timeout here, and
+ # leave it to the caller to decide how much time should be allowed.
+ while session_info and session_info.run_state != SessionRunState.RUNNING:
+ elapsed_s = time_counter.elapsed_s()
+ if elapsed_s + sleep_time_s > approx_timeout_s:
+ LOGGER.debug(
+ "Giving up waiting for user session to enter running state after {num_calls} failed attempts, time spent: {elapsed_s:.2f}s"
+ )
+ return None
+
+ num_calls += 1
+ LOGGER.debug(f"Waiting for user session to enter running state, attempt {num_calls}")
+ await asyncio.sleep(sleep_time_s)
+ session_info = session_dir.get_session_info(job_component_name, instance_str)
+
+ # So by now the session either evaporated from the directory, or it has entered the running state
+ # Bail out if it is gone or for some reason is missing the crucial radix job name
+ if not session_info or not session_info.radix_job_name:
+ return None
+
+ if IS_ON_RADIX_PLATFORM:
+ LOGGER.debug("Found user session, verifying its existence against radix job manager")
+ radix_job_is_running = await is_radix_job_running(
+ job_component_name, job_scheduler_port, session_info.radix_job_name
+ )
+ if not radix_job_is_running:
+ LOGGER.debug("Could not find running job in radix job manager")
+ return None
+
+ # Can we afford the more extensive live check against the service's health endpoint?
+ live_endpoint = f"http://{session_info.radix_job_name}:{actual_service_port}/health/live"
+ LOGGER.debug(f"Job is running in radix, probing health endpoint of contained service at: {live_endpoint=}")
+ is_ready, msg = await call_health_endpoint(live_endpoint, timeout_s=2)
+ if not is_ready:
+ LOGGER.debug(f"Contained service seems to be dead {msg=}")
+ return None
+
+ LOGGER.debug("Contained service is alive")
+
+ return session_info
+
+
+# Try and create a new session with a new radix job and wait for it to come online
+async def _create_new_session(
+ session_dir: UserSessionDirectory,
+ job_component_name: str,
+ job_scheduler_port: int,
+ resource_req: RadixResourceRequests,
+ instance_str: str,
+ actual_service_port: int,
+ approx_timeout_s: float,
+) -> SessionInfo | None:
+
+ time_counter = TimeCounter(approx_timeout_s)
+
+ # We're going to be modifying the directory which means we need to acquire a lock
+ redis_client = session_dir.get_redis_client()
+ lock_key_name: str = session_dir.make_lock_key(job_component_name, instance_str)
+
+ # May have to look closer into the auto release timeout here
+ # Using redlock in our case is probably a bit overkill, there's a ready implementation
+ # For our use case it may be better to implement our own locking akin to this: https://redis.io/commands/set/#patterns
+ LOGGER.debug(f"Trying to acquire distributed redlock {lock_key_name=}")
+ distributed_lock = Redlock(key=lock_key_name, masters={redis_client}, auto_release_time=approx_timeout_s + 30)
+ got_the_lock = distributed_lock.acquire(blocking=False, timeout=-1)
+ if not got_the_lock:
+ LOGGER.error(f"Failed to acquire distributed redlock {lock_key_name=}")
+ return None
+
+ with LockReleasingContext(distributed_lock):
+ # Now that we have the lock, kill off existing job info and start creating new job
+ # But before proceeding, grab the old session info so we can try and whack the radix job if possible
+ old_session_info = session_dir.get_session_info(job_component_name, instance_str)
+ session_info_updater = session_dir.create_session_info_updater(job_component_name, instance_str)
+ session_info_updater.delete_all_state()
+ session_info_updater.set_state_creating()
+
+ if IS_ON_RADIX_PLATFORM:
+ if old_session_info and old_session_info.radix_job_name:
+ LOGGER.debug(f"Trying to delete old radix job {old_session_info.radix_job_name=}")
+ run_in_background_task(
+ delete_named_radix_job(job_component_name, job_scheduler_port, old_session_info.radix_job_name)
+ )
+
+ LOGGER.debug(f"Creating new job using radix job manager ({job_component_name=}, {job_scheduler_port=})")
+ new_radix_job_name = await create_new_radix_job(job_component_name, job_scheduler_port, resource_req)
+ if new_radix_job_name is None:
+ LOGGER.error(f"Failed to create new job in radix ({job_component_name=}, {job_scheduler_port=})")
+ session_info_updater.delete_all_state()
+ return None
+
+ LOGGER.debug(f"New radix job created, will try and wait for it to come alive {new_radix_job_name=}")
+ session_info_updater.set_state_waiting(new_radix_job_name)
+ else:
+ LOGGER.debug("Running locally, will not create a radix job")
+ new_radix_job_name = job_component_name
+ session_info_updater.set_state_waiting(new_radix_job_name)
+
+ LOGGER.debug(f"lock status, {distributed_lock.locked()=}")
+
+ # It is a bit hard to decide on how long we should wait here before giving up.
+ # This must be aligned with the auto release time for our lock and also the polling for session info that is done against redis
+ ready_endpoint = f"http://{new_radix_job_name}:{actual_service_port}/health/ready"
+ probe_time_budget_s = time_counter.remaining_s()
+ is_ready, msg = await call_health_endpoint_with_retries(ready_endpoint, probe_time_budget_s)
+ if not is_ready:
+ LOGGER.error("The newly created radix job failed to come online, giving up and deleting it")
+ session_info_updater.delete_all_state()
+ # Should delete the radix job as well
+ run_in_background_task(delete_named_radix_job(job_component_name, job_scheduler_port, new_radix_job_name))
+ return None
+
+ session_info_updater.set_state_running()
+
+ session_info = session_dir.get_session_info(job_component_name, instance_str)
+ if not session_info:
+ LOGGER.error("Failed to get session info after creating new radix job")
+ return None
+
+ if session_info.run_state != SessionRunState.RUNNING:
+ LOGGER.error(f"Unexpected session info, expected run_state to be running but got {session_info.run_state=}")
+ return None
+
+ if not session_info.radix_job_name:
+ LOGGER.error("Unexpected empty radix_job_name in session info after creating new radix job")
+ return None
+
+ LOGGER.debug(f"New radix job created and online: {session_info.radix_job_name=}")
+
+ return session_info
+
+
+async def call_health_endpoint_with_retries(health_url: str, stop_after_delay_s: float) -> Tuple[bool, str]:
+ LOGGER.debug(f"call_health_endpoint_with_retries() - {health_url=} {stop_after_delay_s=}")
+
+ target_request_timeout_s = 3
+ min_request_timeout_s = 1
+ sleep_time_s = 1
+
+ time_counter = TimeCounter(stop_after_delay_s)
+ num_calls = 0
+
+ async with httpx.AsyncClient(timeout=target_request_timeout_s) as client:
+ while True:
+ request_timeout_s = min(target_request_timeout_s, max(min_request_timeout_s, time_counter.remaining_s()))
+ LOGGER.debug(f"call_health_endpoint_with_retries() - querying endpoint with {request_timeout_s=}")
+ success, msg = await _call_health_endpoint_with_client(client, health_url, request_timeout_s)
+ num_calls += 1
+ if success:
+ LOGGER.debug(
+ f"call_health_endpoint_with_retries() - succeeded on attempt {num_calls}, time spent: {time_counter.elapsed_s():.2f}s, {msg=}"
+ )
+ return success, msg
+
+ LOGGER.debug(f"call_health_endpoint_with_retries() - attempt {num_calls} failed with error: {msg=}")
+
+ elapsed_s = time_counter.elapsed_s()
+ if elapsed_s + sleep_time_s + min_request_timeout_s > stop_after_delay_s:
+ LOGGER.debug(
+ f"call_health_endpoint_with_retries() - giving up after {num_calls} failed attempts, time spent: {elapsed_s:.2f}s"
+ )
+ return False, f"Giving up after {num_calls} failed attempts, time spent: {elapsed_s:.2f}s"
+
+ await asyncio.sleep(sleep_time_s)
+
+
+async def call_health_endpoint(health_url: str, timeout_s: float) -> Tuple[bool, str]:
+ async with httpx.AsyncClient() as client:
+ return await _call_health_endpoint_with_client(client, health_url, timeout_s)
+
+
+async def _call_health_endpoint_with_client(
+ client: httpx.AsyncClient, health_url: str, timeout_s: float
+) -> Tuple[bool, str]:
+ try:
+ response = await client.get(url=health_url, timeout=timeout_s)
+ if response.status_code == 200:
+ return True, f"{response.text=}"
+
+ return False, f"{response.status_code=}, {response.text=}"
+
+ except httpx.RequestError as exception:
+ return False, f"Request error: {exception=}"
diff --git a/backend/src/backend/user_session/routers/grid/__init__.py b/backend_py/primary/primary/services/utils/__init__.py
similarity index 100%
rename from backend/src/backend/user_session/routers/grid/__init__.py
rename to backend_py/primary/primary/services/utils/__init__.py
diff --git a/backend/src/services/utils/arrow_helpers.py b/backend_py/primary/primary/services/utils/arrow_helpers.py
similarity index 100%
rename from backend/src/services/utils/arrow_helpers.py
rename to backend_py/primary/primary/services/utils/arrow_helpers.py
diff --git a/backend/src/services/utils/authenticated_user.py b/backend_py/primary/primary/services/utils/authenticated_user.py
similarity index 94%
rename from backend/src/services/utils/authenticated_user.py
rename to backend_py/primary/primary/services/utils/authenticated_user.py
index 2b3561420..4e38d3ba7 100644
--- a/backend/src/services/utils/authenticated_user.py
+++ b/backend_py/primary/primary/services/utils/authenticated_user.py
@@ -2,7 +2,7 @@
from typing import Any, Optional, TypedDict
-from src.services.service_exceptions import Service, AuthorizationError
+from primary.services.service_exceptions import Service, AuthorizationError
class AccessTokens(TypedDict):
@@ -30,6 +30,9 @@ def __hash__(self) -> int:
def __eq__(self, other: Any) -> bool:
return isinstance(other, AuthenticatedUser) and self._user_id == other._user_id
+ def get_user_id(self) -> str:
+ return self._user_id
+
def get_username(self) -> str:
return self._username
diff --git a/backend/src/services/utils/statistic_function.py b/backend_py/primary/primary/services/utils/statistic_function.py
similarity index 100%
rename from backend/src/services/utils/statistic_function.py
rename to backend_py/primary/primary/services/utils/statistic_function.py
diff --git a/backend/src/services/utils/surface_orientation.py b/backend_py/primary/primary/services/utils/surface_orientation.py
similarity index 100%
rename from backend/src/services/utils/surface_orientation.py
rename to backend_py/primary/primary/services/utils/surface_orientation.py
diff --git a/backend/src/services/utils/surface_to_float32.py b/backend_py/primary/primary/services/utils/surface_to_float32.py
similarity index 100%
rename from backend/src/services/utils/surface_to_float32.py
rename to backend_py/primary/primary/services/utils/surface_to_float32.py
diff --git a/backend/src/services/utils/surface_to_png.py b/backend_py/primary/primary/services/utils/surface_to_png.py
similarity index 100%
rename from backend/src/services/utils/surface_to_png.py
rename to backend_py/primary/primary/services/utils/surface_to_png.py
diff --git a/backend/src/services/__init__.py b/backend_py/primary/primary/services/vds_access/__init__.py
similarity index 100%
rename from backend/src/services/__init__.py
rename to backend_py/primary/primary/services/vds_access/__init__.py
diff --git a/backend/src/services/vds_access/request_types.py b/backend_py/primary/primary/services/vds_access/request_types.py
similarity index 100%
rename from backend/src/services/vds_access/request_types.py
rename to backend_py/primary/primary/services/vds_access/request_types.py
diff --git a/backend/src/services/vds_access/response_types.py b/backend_py/primary/primary/services/vds_access/response_types.py
similarity index 100%
rename from backend/src/services/vds_access/response_types.py
rename to backend_py/primary/primary/services/vds_access/response_types.py
diff --git a/backend/src/services/vds_access/vds_access.py b/backend_py/primary/primary/services/vds_access/vds_access.py
similarity index 99%
rename from backend/src/services/vds_access/vds_access.py
rename to backend_py/primary/primary/services/vds_access/vds_access.py
index af79d88ba..acc99de4c 100644
--- a/backend/src/services/vds_access/vds_access.py
+++ b/backend_py/primary/primary/services/vds_access/vds_access.py
@@ -7,7 +7,7 @@
from requests_toolbelt.multipart.decoder import MultipartDecoder, BodyPart
import httpx
-from src import config
+from primary import config
from .response_types import VdsMetadata, VdsFenceMetadata
from .request_types import (
diff --git a/backend/src/backend/utils/azure_monitor_setup.py b/backend_py/primary/primary/utils/azure_monitor_setup.py
similarity index 100%
rename from backend/src/backend/utils/azure_monitor_setup.py
rename to backend_py/primary/primary/utils/azure_monitor_setup.py
diff --git a/backend/src/backend/utils/exception_handlers.py b/backend_py/primary/primary/utils/exception_handlers.py
similarity index 98%
rename from backend/src/backend/utils/exception_handlers.py
rename to backend_py/primary/primary/utils/exception_handlers.py
index 0030cf9d4..988921077 100644
--- a/backend/src/backend/utils/exception_handlers.py
+++ b/backend_py/primary/primary/utils/exception_handlers.py
@@ -10,7 +10,7 @@
from starlette.responses import JSONResponse, Response
from starlette.status import HTTP_422_UNPROCESSABLE_ENTITY, HTTP_500_INTERNAL_SERVER_ERROR
-from src.services.service_exceptions import ServiceLayerException
+from primary.services.service_exceptions import ServiceLayerException
def my_http_exception_handler(request: Request, exc: StarletteHTTPException) -> Response | JSONResponse:
diff --git a/backend/src/backend/utils/logging_setup.py b/backend_py/primary/primary/utils/logging_setup.py
similarity index 100%
rename from backend/src/backend/utils/logging_setup.py
rename to backend_py/primary/primary/utils/logging_setup.py
diff --git a/backend/src/backend/utils/perf_metrics.py b/backend_py/primary/primary/utils/perf_metrics.py
similarity index 97%
rename from backend/src/backend/utils/perf_metrics.py
rename to backend_py/primary/primary/utils/perf_metrics.py
index 6c7ee71ad..24540a9c4 100644
--- a/backend/src/backend/utils/perf_metrics.py
+++ b/backend_py/primary/primary/utils/perf_metrics.py
@@ -1,6 +1,6 @@
from starlette.responses import MutableHeaders, Response
-from src.services.utils.perf_timer import PerfTimer
+from webviz_pkg.core_utils.perf_timer import PerfTimer
class PerfMetrics:
diff --git a/backend/pyproject.toml b/backend_py/primary/pyproject.toml
similarity index 91%
rename from backend/pyproject.toml
rename to backend_py/primary/pyproject.toml
index 37ea3f1d2..da59054f1 100644
--- a/backend/pyproject.toml
+++ b/backend_py/primary/pyproject.toml
@@ -1,7 +1,6 @@
[tool.poetry]
-name = "backend"
-version = "0.1.0"
-description = ""
+package-mode = false
+name = "primary"
authors = ["R&T Equinor", "Ceetron Solutions AS"]
readme = "README.md"
@@ -12,7 +11,7 @@ fastapi = "^0.103.1"
uvicorn = "^0.20.0"
msal = "1.20.0" # Lock version until we fix issues introduced by 1.21.0, see https://github.com/equinor/webviz/issues/105
starsessions = "^2.1.2"
-redis = "^4.4.2"
+redis = "^4.6.0"
pyarrow = "^12.0.1"
python-dotenv = "^0.21.0"
pyjwt = "^2.6.0"
@@ -21,13 +20,12 @@ numpy = "^1.24.1"
orjson = "^3.8.10"
pandas = {version = "2.0.1", extras = ["performance"]}
httpx = "^0.24.0"
-psutil = "^5.9.5"
-vtk = "^9.2.6"
fmu-sumo = "1.0.3"
sumo-wrapper-python = "1.0.6"
azure-monitor-opentelemetry = "^1.1.0"
requests-toolbelt = "^1.0.0"
-
+pottery = "^3.0.0"
+core_utils = {path = "../libs/core_utils", develop = true}
[tool.poetry.group.dev.dependencies]
black = "^22.12.0"
diff --git a/backend/src/services/smda_access/__init__.py b/backend_py/primary/tests/__init__.py
similarity index 100%
rename from backend/src/services/smda_access/__init__.py
rename to backend_py/primary/tests/__init__.py
diff --git a/backend/tests/integration/services/conftest.py b/backend_py/primary/tests/integration/services/conftest.py
similarity index 100%
rename from backend/tests/integration/services/conftest.py
rename to backend_py/primary/tests/integration/services/conftest.py
diff --git a/backend/tests/integration/services/sumo_access/test_parameter_access.py b/backend_py/primary/tests/integration/services/sumo_access/test_parameter_access.py
similarity index 100%
rename from backend/tests/integration/services/sumo_access/test_parameter_access.py
rename to backend_py/primary/tests/integration/services/sumo_access/test_parameter_access.py
diff --git a/backend/src/services/smda_access/queries/__init__.py b/backend_py/primary/tests/unit/__init__.py
similarity index 100%
rename from backend/src/services/smda_access/queries/__init__.py
rename to backend_py/primary/tests/unit/__init__.py
diff --git a/backend/src/services/sumo_access/__init__.py b/backend_py/primary/tests/unit/services/__init__.py
similarity index 100%
rename from backend/src/services/sumo_access/__init__.py
rename to backend_py/primary/tests/unit/services/__init__.py
diff --git a/backend/tests/unit/services/smda_access/test_stratigraphy_utils.py b/backend_py/primary/tests/unit/services/smda_access/test_stratigraphy_utils.py
similarity index 89%
rename from backend/tests/unit/services/smda_access/test_stratigraphy_utils.py
rename to backend_py/primary/tests/unit/services/smda_access/test_stratigraphy_utils.py
index 13eab9066..913f50bf9 100644
--- a/backend/tests/unit/services/smda_access/test_stratigraphy_utils.py
+++ b/backend_py/primary/tests/unit/services/smda_access/test_stratigraphy_utils.py
@@ -1,12 +1,12 @@
from typing import List
import pytest
-from services.smda_access.stratigraphy_utils import (
+from primary.services.smda_access.stratigraphy_utils import (
sort_stratigraphic_names_by_hierarchy,
sort_stratigraphic_units_by_hierarchy,
)
-from services.smda_access.types import StratigraphicUnit, StratigraphicSurface, StratigraphicFeature
-from services.smda_access.mocked_drogon_smda_access._mocked_stratigraphy_access import DROGON_STRAT_UNITS
+from primary.services.smda_access.types import StratigraphicUnit, StratigraphicSurface, StratigraphicFeature
+from primary.services.smda_access.mocked_drogon_smda_access._mocked_stratigraphy_access import DROGON_STRAT_UNITS
@pytest.mark.parametrize(
@@ -48,7 +48,7 @@ def test_sort_stratigraphic_units_by_hierarchy(
],
)
def test_sort_stratigraphic_names_by_hierarchy(
- strat_units: List[StratigraphicUnit], expected_output: List[StratigraphicUnit]
+ strat_units: List[StratigraphicUnit], expected_output: List[StratigraphicSurface]
) -> None:
sorted_surfaces = sort_stratigraphic_names_by_hierarchy(strat_units)
sorted_surface_names = [surf.name for surf in sorted_surfaces]
diff --git a/backend/tests/unit/services/sumo_access/test_resampling.py b/backend_py/primary/tests/unit/services/sumo_access/test_resampling.py
similarity index 99%
rename from backend/tests/unit/services/sumo_access/test_resampling.py
rename to backend_py/primary/tests/unit/services/sumo_access/test_resampling.py
index 7f59d3031..b5475711c 100644
--- a/backend/tests/unit/services/sumo_access/test_resampling.py
+++ b/backend_py/primary/tests/unit/services/sumo_access/test_resampling.py
@@ -2,7 +2,7 @@
import pyarrow as pa
import pyarrow.compute as pc
-from services.sumo_access._resampling import (
+from primary.services.sumo_access._resampling import (
Frequency,
generate_normalized_sample_dates,
interpolate_backfill,
diff --git a/backend/tests/unit/services/utils/test_arrow_helpers.py b/backend_py/primary/tests/unit/services/utils/test_arrow_helpers.py
similarity index 88%
rename from backend/tests/unit/services/utils/test_arrow_helpers.py
rename to backend_py/primary/tests/unit/services/utils/test_arrow_helpers.py
index 40108f117..a7feb2acd 100644
--- a/backend/tests/unit/services/utils/test_arrow_helpers.py
+++ b/backend_py/primary/tests/unit/services/utils/test_arrow_helpers.py
@@ -1,5 +1,6 @@
-from services.utils.arrow_helpers import is_date_column_monotonically_increasing, find_first_non_increasing_date_pair
-from services.utils.arrow_helpers import detect_missing_realizations
+from primary.services.utils.arrow_helpers import is_date_column_monotonically_increasing
+from primary.services.utils.arrow_helpers import find_first_non_increasing_date_pair
+from primary.services.utils.arrow_helpers import detect_missing_realizations
import pyarrow as pa
import numpy as np
diff --git a/backend_py/user_grid3d_ri/Dockerfile b/backend_py/user_grid3d_ri/Dockerfile
new file mode 100644
index 000000000..7deadac18
--- /dev/null
+++ b/backend_py/user_grid3d_ri/Dockerfile
@@ -0,0 +1,15 @@
+FROM python:3.11-slim
+
+RUN useradd --create-home --uid 1234 appuser
+USER 1234
+
+COPY --chown=appuser ./backend_py/user_grid3d_ri /home/appuser/backend_py/user_grid3d_ri
+
+WORKDIR /home/appuser/backend_py/user_grid3d_ri
+
+ENV PATH="${PATH}:/home/appuser/.local/bin"
+
+RUN pip install -r requirements.txt
+
+# Relevant uvicorn environment variables are: UVICORN_PORT, UVICORN_RELOAD
+CMD ["uvicorn", "user_grid3d_ri_app:app", "--host", "0.0.0.0"]
diff --git a/backend_py/user_grid3d_ri/requirements.txt b/backend_py/user_grid3d_ri/requirements.txt
new file mode 100644
index 000000000..f0615cfd0
--- /dev/null
+++ b/backend_py/user_grid3d_ri/requirements.txt
@@ -0,0 +1,2 @@
+fastapi
+uvicorn
\ No newline at end of file
diff --git a/backend_py/user_grid3d_ri/user_grid3d_ri_app.py b/backend_py/user_grid3d_ri/user_grid3d_ri_app.py
new file mode 100644
index 000000000..aa34fa43d
--- /dev/null
+++ b/backend_py/user_grid3d_ri/user_grid3d_ri_app.py
@@ -0,0 +1,55 @@
+import asyncio
+import datetime
+import logging
+from typing import Annotated
+
+from fastapi import FastAPI
+from fastapi import Query
+
+logging.basicConfig(format="%(asctime)s %(levelname)-3s [%(name)s]: %(message)s", datefmt="%H:%M:%S")
+logging.getLogger().setLevel(logging.DEBUG)
+
+LOGGER = logging.getLogger(__name__)
+
+
+app = FastAPI()
+
+
+@app.get("/")
+async def root() -> str:
+ ret_str = f"user-grid3d-ri is alive at this time: {datetime.datetime.now()}"
+ LOGGER.debug("Sending: ", ret_str)
+ return ret_str
+
+
+# Probe if service is alive
+# HTTP status code 200 means we're alive, all other status codes indicate trouble
+# The response is only for debugging, and is basically ignored.
+@app.get("/health/live")
+async def health_live() -> str:
+ ret_str = f"LIVE at: {datetime.datetime.now()}"
+ LOGGER.debug(f"health_live() returning: {ret_str!r}")
+ return ret_str
+
+
+# Probe if service is ready to receive requests
+# HTTP status code 200 means we're ready, 500 (and all other status codes) signals we're not ready
+# The response is only for debugging, and is basically ignored.
+@app.get("/health/ready")
+async def health_ready() -> str:
+ ret_str = f"READY at: {datetime.datetime.now()}"
+ LOGGER.debug(f"health_ready() returning: {ret_str!r}")
+ return ret_str
+
+
+# Simulate doing some work
+@app.get("/dowork")
+async def dowork(
+ duration: Annotated[float, Query(description="Duration of work in seconds")] = 1.0,
+) -> str:
+ LOGGER.debug(f"dowork() doing fake GRID3D work for: {duration=}s")
+ await asyncio.sleep(duration)
+
+ ret_str = f"GRID3D work done at: {datetime.datetime.now()}"
+ LOGGER.debug(f"dowork() GRID3D returning: {ret_str!r}")
+ return ret_str
diff --git a/backend_py/user_grid3d_vtk/Dockerfile b/backend_py/user_grid3d_vtk/Dockerfile
new file mode 100644
index 000000000..199ffc8d1
--- /dev/null
+++ b/backend_py/user_grid3d_vtk/Dockerfile
@@ -0,0 +1,26 @@
+FROM python:3.11-slim
+
+RUN useradd --create-home --uid 1234 appuser
+USER 1234
+
+ENV PATH="${PATH}:/home/appuser/.local/bin"
+
+RUN python3 -m pip install --user pipx
+RUN python3 -m pipx ensurepath
+RUN pipx install poetry==1.8.2
+
+ENV VIRTUAL_ENV=/home/appuser/venv
+RUN python3 -m venv $VIRTUAL_ENV
+ENV PATH="$VIRTUAL_ENV/bin:$PATH"
+
+WORKDIR /home/appuser/backend_py/user_grid3d_vtk
+
+COPY --chown=appuser ./backend_py/user_grid3d_vtk/pyproject.toml /home/appuser/backend_py/user_grid3d_vtk
+COPY --chown=appuser ./backend_py/user_grid3d_vtk/poetry.lock /home/appuser/backend_py/user_grid3d_vtk
+RUN poetry install --only main --no-root --no-directory
+
+COPY --chown=appuser ./backend_py/user_grid3d_vtk/user_grid3d_vtk /home/appuser/backend_py/user_grid3d_vtk/user_grid3d_vtk
+RUN poetry install --only main
+
+# Relevant uvicorn environment variables are: UVICORN_PORT, UVICORN_RELOAD
+CMD ["uvicorn", "user_grid3d_vtk.fastapi_app:app", "--host", "0.0.0.0"]
diff --git a/backend_py/user_grid3d_vtk/poetry.lock b/backend_py/user_grid3d_vtk/poetry.lock
new file mode 100644
index 000000000..97fcd2ff8
--- /dev/null
+++ b/backend_py/user_grid3d_vtk/poetry.lock
@@ -0,0 +1,271 @@
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
+
+[[package]]
+name = "annotated-types"
+version = "0.6.0"
+description = "Reusable constraint types to use with typing.Annotated"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
+ {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
+]
+
+[[package]]
+name = "anyio"
+version = "3.7.1"
+description = "High level compatibility layer for multiple asynchronous event loop implementations"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"},
+ {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"},
+]
+
+[package.dependencies]
+idna = ">=2.8"
+sniffio = ">=1.1"
+
+[package.extras]
+doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"]
+test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
+trio = ["trio (<0.22)"]
+
+[[package]]
+name = "click"
+version = "8.1.7"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "fastapi"
+version = "0.103.2"
+description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "fastapi-0.103.2-py3-none-any.whl", hash = "sha256:3270de872f0fe9ec809d4bd3d4d890c6d5cc7b9611d721d6438f9dacc8c4ef2e"},
+ {file = "fastapi-0.103.2.tar.gz", hash = "sha256:75a11f6bfb8fc4d2bec0bd710c2d5f2829659c0e8c0afd5560fdda6ce25ec653"},
+]
+
+[package.dependencies]
+anyio = ">=3.7.1,<4.0.0"
+pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
+starlette = ">=0.27.0,<0.28.0"
+typing-extensions = ">=4.5.0"
+
+[package.extras]
+all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
+
+[[package]]
+name = "h11"
+version = "0.14.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
+ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
+]
+
+[[package]]
+name = "idna"
+version = "3.6"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
+ {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
+]
+
+[[package]]
+name = "pydantic"
+version = "2.6.4"
+description = "Data validation using Python type hints"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic-2.6.4-py3-none-any.whl", hash = "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5"},
+ {file = "pydantic-2.6.4.tar.gz", hash = "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6"},
+]
+
+[package.dependencies]
+annotated-types = ">=0.4.0"
+pydantic-core = "2.16.3"
+typing-extensions = ">=4.6.1"
+
+[package.extras]
+email = ["email-validator (>=2.0.0)"]
+
+[[package]]
+name = "pydantic-core"
+version = "2.16.3"
+description = ""
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
+ {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
+ {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
+ {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
+ {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
+ {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
+ {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
+ {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
+ {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
+ {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
+ {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
+ {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
+ {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
+ {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
+
+[[package]]
+name = "sniffio"
+version = "1.3.1"
+description = "Sniff out which async library your code is running under"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
+ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
+]
+
+[[package]]
+name = "starlette"
+version = "0.27.0"
+description = "The little ASGI library that shines."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"},
+ {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"},
+]
+
+[package.dependencies]
+anyio = ">=3.4.0,<5"
+
+[package.extras]
+full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.10.0"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
+ {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
+]
+
+[[package]]
+name = "uvicorn"
+version = "0.20.0"
+description = "The lightning-fast ASGI server."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "uvicorn-0.20.0-py3-none-any.whl", hash = "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd"},
+ {file = "uvicorn-0.20.0.tar.gz", hash = "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8"},
+]
+
+[package.dependencies]
+click = ">=7.0"
+h11 = ">=0.8"
+
+[package.extras]
+standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.11"
+content-hash = "1c1900c103a60137142a48f7698b943ffebf2eab40628b1bf69c65fa232af688"
diff --git a/backend_py/user_grid3d_vtk/pyproject.toml b/backend_py/user_grid3d_vtk/pyproject.toml
new file mode 100644
index 000000000..53cad62ac
--- /dev/null
+++ b/backend_py/user_grid3d_vtk/pyproject.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+package-mode = false
+name = "user-grid3d-vtk"
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.poetry.dependencies]
+python = "^3.11"
+fastapi = "^0.103.1"
+uvicorn = "^0.20.0"
diff --git a/backend_py/user_grid3d_vtk/user_grid3d_vtk/fastapi_app.py b/backend_py/user_grid3d_vtk/user_grid3d_vtk/fastapi_app.py
new file mode 100644
index 000000000..b4de8582d
--- /dev/null
+++ b/backend_py/user_grid3d_vtk/user_grid3d_vtk/fastapi_app.py
@@ -0,0 +1,55 @@
+import asyncio
+import datetime
+import logging
+from typing import Annotated
+
+from fastapi import FastAPI
+from fastapi import Query
+
+logging.basicConfig(format="%(asctime)s %(levelname)-3s [%(name)s]: %(message)s", datefmt="%H:%M:%S")
+logging.getLogger().setLevel(logging.DEBUG)
+
+LOGGER = logging.getLogger(__name__)
+
+
+app = FastAPI()
+
+
+@app.get("/")
+async def root() -> str:
+ ret_str = f"user-grid3d-vtk is alive at this time: {datetime.datetime.now()}"
+ LOGGER.debug("Sending: ", ret_str)
+ return ret_str
+
+
+# Probe if service is alive
+# HTTP status code 200 means we're alive, all other status codes indicate trouble
+# The response is only for debugging, and is basically ignored.
+@app.get("/health/live")
+async def health_live() -> str:
+ ret_str = f"LIVE at: {datetime.datetime.now()}"
+ LOGGER.debug(f"health_live() returning: {ret_str!r}")
+ return ret_str
+
+
+# Probe if service is ready to receive requests
+# HTTP status code 200 means we're ready, 500 (and all other status codes) signals we're not ready
+# The response is only for debugging, and is basically ignored.
+@app.get("/health/ready")
+async def health_ready() -> str:
+ ret_str = f"READY at: {datetime.datetime.now()}"
+ LOGGER.debug(f"health_ready() returning: {ret_str!r}")
+ return ret_str
+
+
+# Simulate doing some work
+@app.get("/dowork")
+async def dowork(
+ duration: Annotated[float, Query(description="Duration of work in seconds")] = 1.0,
+) -> str:
+ LOGGER.debug(f"dowork() doing fake GRID3D VTK work for: {duration=}s")
+ await asyncio.sleep(duration)
+
+ ret_str = f"GRID3D VTK work done at: {datetime.datetime.now()}"
+ LOGGER.debug(f"dowork() GRID3D VTK returning: {ret_str!r}")
+ return ret_str
diff --git a/backend_py/user_mock/Dockerfile b/backend_py/user_mock/Dockerfile
new file mode 100644
index 000000000..0fb88d556
--- /dev/null
+++ b/backend_py/user_mock/Dockerfile
@@ -0,0 +1,26 @@
+FROM python:3.11-slim
+
+RUN useradd --create-home --uid 1234 appuser
+USER 1234
+
+ENV PATH="${PATH}:/home/appuser/.local/bin"
+
+RUN python3 -m pip install --user pipx
+RUN python3 -m pipx ensurepath
+RUN pipx install poetry==1.8.2
+
+ENV VIRTUAL_ENV=/home/appuser/venv
+RUN python3 -m venv $VIRTUAL_ENV
+ENV PATH="$VIRTUAL_ENV/bin:$PATH"
+
+WORKDIR /home/appuser/backend_py/user_mock
+
+COPY --chown=appuser ./backend_py/user_mock/pyproject.toml /home/appuser/backend_py/user_mock
+COPY --chown=appuser ./backend_py/user_mock/poetry.lock /home/appuser/backend_py/user_mock
+RUN poetry install --only main --no-root --no-directory
+
+COPY --chown=appuser ./backend_py/user_mock/user_mock /home/appuser/backend_py/user_mock/user_mock
+RUN poetry install --only main
+
+# Relevant uvicorn environment variables are: UVICORN_PORT, UVICORN_RELOAD
+CMD ["uvicorn", "user_mock.user_mock_app:app", "--host", "0.0.0.0"]
diff --git a/backend_py/user_mock/poetry.lock b/backend_py/user_mock/poetry.lock
new file mode 100644
index 000000000..97fcd2ff8
--- /dev/null
+++ b/backend_py/user_mock/poetry.lock
@@ -0,0 +1,271 @@
+# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand.
+
+[[package]]
+name = "annotated-types"
+version = "0.6.0"
+description = "Reusable constraint types to use with typing.Annotated"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"},
+ {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"},
+]
+
+[[package]]
+name = "anyio"
+version = "3.7.1"
+description = "High level compatibility layer for multiple asynchronous event loop implementations"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "anyio-3.7.1-py3-none-any.whl", hash = "sha256:91dee416e570e92c64041bd18b900d1d6fa78dff7048769ce5ac5ddad004fbb5"},
+ {file = "anyio-3.7.1.tar.gz", hash = "sha256:44a3c9aba0f5defa43261a8b3efb97891f2bd7d804e0e1f56419befa1adfc780"},
+]
+
+[package.dependencies]
+idna = ">=2.8"
+sniffio = ">=1.1"
+
+[package.extras]
+doc = ["Sphinx", "packaging", "sphinx-autodoc-typehints (>=1.2.0)", "sphinx-rtd-theme (>=1.2.2)", "sphinxcontrib-jquery"]
+test = ["anyio[trio]", "coverage[toml] (>=4.5)", "hypothesis (>=4.0)", "mock (>=4)", "psutil (>=5.9)", "pytest (>=7.0)", "pytest-mock (>=3.6.1)", "trustme", "uvloop (>=0.17)"]
+trio = ["trio (<0.22)"]
+
+[[package]]
+name = "click"
+version = "8.1.7"
+description = "Composable command line interface toolkit"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "click-8.1.7-py3-none-any.whl", hash = "sha256:ae74fb96c20a0277a1d615f1e4d73c8414f5a98db8b799a7931d1582f3390c28"},
+ {file = "click-8.1.7.tar.gz", hash = "sha256:ca9853ad459e787e2192211578cc907e7594e294c7ccc834310722b41b9ca6de"},
+]
+
+[package.dependencies]
+colorama = {version = "*", markers = "platform_system == \"Windows\""}
+
+[[package]]
+name = "colorama"
+version = "0.4.6"
+description = "Cross-platform colored terminal text."
+optional = false
+python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7"
+files = [
+ {file = "colorama-0.4.6-py2.py3-none-any.whl", hash = "sha256:4f1d9991f5acc0ca119f9d443620b77f9d6b33703e51011c16baf57afb285fc6"},
+ {file = "colorama-0.4.6.tar.gz", hash = "sha256:08695f5cb7ed6e0531a20572697297273c47b8cae5a63ffc6d6ed5c201be6e44"},
+]
+
+[[package]]
+name = "fastapi"
+version = "0.103.2"
+description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "fastapi-0.103.2-py3-none-any.whl", hash = "sha256:3270de872f0fe9ec809d4bd3d4d890c6d5cc7b9611d721d6438f9dacc8c4ef2e"},
+ {file = "fastapi-0.103.2.tar.gz", hash = "sha256:75a11f6bfb8fc4d2bec0bd710c2d5f2829659c0e8c0afd5560fdda6ce25ec653"},
+]
+
+[package.dependencies]
+anyio = ">=3.7.1,<4.0.0"
+pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0"
+starlette = ">=0.27.0,<0.28.0"
+typing-extensions = ">=4.5.0"
+
+[package.extras]
+all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"]
+
+[[package]]
+name = "h11"
+version = "0.14.0"
+description = "A pure-Python, bring-your-own-I/O implementation of HTTP/1.1"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "h11-0.14.0-py3-none-any.whl", hash = "sha256:e3fe4ac4b851c468cc8363d500db52c2ead036020723024a109d37346efaa761"},
+ {file = "h11-0.14.0.tar.gz", hash = "sha256:8f19fbbe99e72420ff35c00b27a34cb9937e902a8b810e2c88300c6f0a3b699d"},
+]
+
+[[package]]
+name = "idna"
+version = "3.6"
+description = "Internationalized Domain Names in Applications (IDNA)"
+optional = false
+python-versions = ">=3.5"
+files = [
+ {file = "idna-3.6-py3-none-any.whl", hash = "sha256:c05567e9c24a6b9faaa835c4821bad0590fbb9d5779e7caa6e1cc4978e7eb24f"},
+ {file = "idna-3.6.tar.gz", hash = "sha256:9ecdbbd083b06798ae1e86adcbfe8ab1479cf864e4ee30fe4e46a003d12491ca"},
+]
+
+[[package]]
+name = "pydantic"
+version = "2.6.4"
+description = "Data validation using Python type hints"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic-2.6.4-py3-none-any.whl", hash = "sha256:cc46fce86607580867bdc3361ad462bab9c222ef042d3da86f2fb333e1d916c5"},
+ {file = "pydantic-2.6.4.tar.gz", hash = "sha256:b1704e0847db01817624a6b86766967f552dd9dbf3afba4004409f908dcc84e6"},
+]
+
+[package.dependencies]
+annotated-types = ">=0.4.0"
+pydantic-core = "2.16.3"
+typing-extensions = ">=4.6.1"
+
+[package.extras]
+email = ["email-validator (>=2.0.0)"]
+
+[[package]]
+name = "pydantic-core"
+version = "2.16.3"
+description = ""
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "pydantic_core-2.16.3-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:75b81e678d1c1ede0785c7f46690621e4c6e63ccd9192af1f0bd9d504bbb6bf4"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9c865a7ee6f93783bd5d781af5a4c43dadc37053a5b42f7d18dc019f8c9d2bd1"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:162e498303d2b1c036b957a1278fa0899d02b2842f1ff901b6395104c5554a45"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2f583bd01bbfbff4eaee0868e6fc607efdfcc2b03c1c766b06a707abbc856187"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b926dd38db1519ed3043a4de50214e0d600d404099c3392f098a7f9d75029ff8"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:716b542728d4c742353448765aa7cdaa519a7b82f9564130e2b3f6766018c9ec"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fc4ad7f7ee1a13d9cb49d8198cd7d7e3aa93e425f371a68235f784e99741561f"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:bd87f48924f360e5d1c5f770d6155ce0e7d83f7b4e10c2f9ec001c73cf475c99"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0df446663464884297c793874573549229f9eca73b59360878f382a0fc085979"},
+ {file = "pydantic_core-2.16.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4df8a199d9f6afc5ae9a65f8f95ee52cae389a8c6b20163762bde0426275b7db"},
+ {file = "pydantic_core-2.16.3-cp310-none-win32.whl", hash = "sha256:456855f57b413f077dff513a5a28ed838dbbb15082ba00f80750377eed23d132"},
+ {file = "pydantic_core-2.16.3-cp310-none-win_amd64.whl", hash = "sha256:732da3243e1b8d3eab8c6ae23ae6a58548849d2e4a4e03a1924c8ddf71a387cb"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:519ae0312616026bf4cedc0fe459e982734f3ca82ee8c7246c19b650b60a5ee4"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:b3992a322a5617ded0a9f23fd06dbc1e4bd7cf39bc4ccf344b10f80af58beacd"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d62da299c6ecb04df729e4b5c52dc0d53f4f8430b4492b93aa8de1f541c4aac"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:2acca2be4bb2f2147ada8cac612f8a98fc09f41c89f87add7256ad27332c2fda"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1b662180108c55dfbf1280d865b2d116633d436cfc0bba82323554873967b340"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e7c6ed0dc9d8e65f24f5824291550139fe6f37fac03788d4580da0d33bc00c97"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a6b1bb0827f56654b4437955555dc3aeeebeddc47c2d7ed575477f082622c49e"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e56f8186d6210ac7ece503193ec84104da7ceb98f68ce18c07282fcc2452e76f"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:936e5db01dd49476fa8f4383c259b8b1303d5dd5fb34c97de194560698cc2c5e"},
+ {file = "pydantic_core-2.16.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:33809aebac276089b78db106ee692bdc9044710e26f24a9a2eaa35a0f9fa70ba"},
+ {file = "pydantic_core-2.16.3-cp311-none-win32.whl", hash = "sha256:ded1c35f15c9dea16ead9bffcde9bb5c7c031bff076355dc58dcb1cb436c4721"},
+ {file = "pydantic_core-2.16.3-cp311-none-win_amd64.whl", hash = "sha256:d89ca19cdd0dd5f31606a9329e309d4fcbb3df860960acec32630297d61820df"},
+ {file = "pydantic_core-2.16.3-cp311-none-win_arm64.whl", hash = "sha256:6162f8d2dc27ba21027f261e4fa26f8bcb3cf9784b7f9499466a311ac284b5b9"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:0f56ae86b60ea987ae8bcd6654a887238fd53d1384f9b222ac457070b7ac4cff"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:c9bd22a2a639e26171068f8ebb5400ce2c1bc7d17959f60a3b753ae13c632975"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4204e773b4b408062960e65468d5346bdfe139247ee5f1ca2a378983e11388a2"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:f651dd19363c632f4abe3480a7c87a9773be27cfe1341aef06e8759599454120"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:aaf09e615a0bf98d406657e0008e4a8701b11481840be7d31755dc9f97c44053"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8e47755d8152c1ab5b55928ab422a76e2e7b22b5ed8e90a7d584268dd49e9c6b"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:500960cb3a0543a724a81ba859da816e8cf01b0e6aaeedf2c3775d12ee49cade"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cf6204fe865da605285c34cf1172879d0314ff267b1c35ff59de7154f35fdc2e"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:d33dd21f572545649f90c38c227cc8631268ba25c460b5569abebdd0ec5974ca"},
+ {file = "pydantic_core-2.16.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:49d5d58abd4b83fb8ce763be7794d09b2f50f10aa65c0f0c1696c677edeb7cbf"},
+ {file = "pydantic_core-2.16.3-cp312-none-win32.whl", hash = "sha256:f53aace168a2a10582e570b7736cc5bef12cae9cf21775e3eafac597e8551fbe"},
+ {file = "pydantic_core-2.16.3-cp312-none-win_amd64.whl", hash = "sha256:0d32576b1de5a30d9a97f300cc6a3f4694c428d956adbc7e6e2f9cad279e45ed"},
+ {file = "pydantic_core-2.16.3-cp312-none-win_arm64.whl", hash = "sha256:ec08be75bb268473677edb83ba71e7e74b43c008e4a7b1907c6d57e940bf34b6"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:b1f6f5938d63c6139860f044e2538baeee6f0b251a1816e7adb6cbce106a1f01"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2a1ef6a36fdbf71538142ed604ad19b82f67b05749512e47f247a6ddd06afdc7"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:704d35ecc7e9c31d48926150afada60401c55efa3b46cd1ded5a01bdffaf1d48"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d937653a696465677ed583124b94a4b2d79f5e30b2c46115a68e482c6a591c8a"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c9803edf8e29bd825f43481f19c37f50d2b01899448273b3a7758441b512acf8"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:72282ad4892a9fb2da25defeac8c2e84352c108705c972db82ab121d15f14e6d"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f752826b5b8361193df55afcdf8ca6a57d0232653494ba473630a83ba50d8c9"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:4384a8f68ddb31a0b0c3deae88765f5868a1b9148939c3f4121233314ad5532c"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a4b2bf78342c40b3dc830880106f54328928ff03e357935ad26c7128bbd66ce8"},
+ {file = "pydantic_core-2.16.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:13dcc4802961b5f843a9385fc821a0b0135e8c07fc3d9949fd49627c1a5e6ae5"},
+ {file = "pydantic_core-2.16.3-cp38-none-win32.whl", hash = "sha256:e3e70c94a0c3841e6aa831edab1619ad5c511199be94d0c11ba75fe06efe107a"},
+ {file = "pydantic_core-2.16.3-cp38-none-win_amd64.whl", hash = "sha256:ecdf6bf5f578615f2e985a5e1f6572e23aa632c4bd1dc67f8f406d445ac115ed"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:bda1ee3e08252b8d41fa5537413ffdddd58fa73107171a126d3b9ff001b9b820"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:21b888c973e4f26b7a96491c0965a8a312e13be108022ee510248fe379a5fa23"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be0ec334369316fa73448cc8c982c01e5d2a81c95969d58b8f6e272884df0074"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b5b6079cc452a7c53dd378c6f881ac528246b3ac9aae0f8eef98498a75657805"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ee8d5f878dccb6d499ba4d30d757111847b6849ae07acdd1205fffa1fc1253c"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7233d65d9d651242a68801159763d09e9ec96e8a158dbf118dc090cd77a104c9"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c6119dc90483a5cb50a1306adb8d52c66e447da88ea44f323e0ae1a5fcb14256"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:578114bc803a4c1ff9946d977c221e4376620a46cf78da267d946397dc9514a8"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d8f99b147ff3fcf6b3cc60cb0c39ea443884d5559a30b1481e92495f2310ff2b"},
+ {file = "pydantic_core-2.16.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4ac6b4ce1e7283d715c4b729d8f9dab9627586dafce81d9eaa009dd7f25dd972"},
+ {file = "pydantic_core-2.16.3-cp39-none-win32.whl", hash = "sha256:e7774b570e61cb998490c5235740d475413a1f6de823169b4cf94e2fe9e9f6b2"},
+ {file = "pydantic_core-2.16.3-cp39-none-win_amd64.whl", hash = "sha256:9091632a25b8b87b9a605ec0e61f241c456e9248bfdcf7abdf344fdb169c81cf"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:36fa178aacbc277bc6b62a2c3da95226520da4f4e9e206fdf076484363895d2c"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:dcca5d2bf65c6fb591fff92da03f94cd4f315972f97c21975398bd4bd046854a"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2a72fb9963cba4cd5793854fd12f4cfee731e86df140f59ff52a49b3552db241"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b60cc1a081f80a2105a59385b92d82278b15d80ebb3adb200542ae165cd7d183"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:cbcc558401de90a746d02ef330c528f2e668c83350f045833543cd57ecead1ad"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:fee427241c2d9fb7192b658190f9f5fd6dfe41e02f3c1489d2ec1e6a5ab1e04a"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f4cb85f693044e0f71f394ff76c98ddc1bc0953e48c061725e540396d5c8a2e1"},
+ {file = "pydantic_core-2.16.3-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:b29eeb887aa931c2fcef5aa515d9d176d25006794610c264ddc114c053bf96fe"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a425479ee40ff021f8216c9d07a6a3b54b31c8267c6e17aa88b70d7ebd0e5e5b"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:5c5cbc703168d1b7a838668998308018a2718c2130595e8e190220238addc96f"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:99b6add4c0b39a513d323d3b93bc173dac663c27b99860dd5bf491b240d26137"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:75f76ee558751746d6a38f89d60b6228fa174e5172d143886af0f85aa306fd89"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:00ee1c97b5364b84cb0bd82e9bbf645d5e2871fb8c58059d158412fee2d33d8a"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:287073c66748f624be4cef893ef9174e3eb88fe0b8a78dc22e88eca4bc357ca6"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed25e1835c00a332cb10c683cd39da96a719ab1dfc08427d476bce41b92531fc"},
+ {file = "pydantic_core-2.16.3-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:86b3d0033580bd6bbe07590152007275bd7af95f98eaa5bd36f3da219dcd93da"},
+ {file = "pydantic_core-2.16.3.tar.gz", hash = "sha256:1cac689f80a3abab2d3c0048b29eea5751114054f032a941a32de4c852c59cad"},
+]
+
+[package.dependencies]
+typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0"
+
+[[package]]
+name = "sniffio"
+version = "1.3.1"
+description = "Sniff out which async library your code is running under"
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "sniffio-1.3.1-py3-none-any.whl", hash = "sha256:2f6da418d1f1e0fddd844478f41680e794e6051915791a034ff65e5f100525a2"},
+ {file = "sniffio-1.3.1.tar.gz", hash = "sha256:f4324edc670a0f49750a81b895f35c3adb843cca46f0530f79fc1babb23789dc"},
+]
+
+[[package]]
+name = "starlette"
+version = "0.27.0"
+description = "The little ASGI library that shines."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "starlette-0.27.0-py3-none-any.whl", hash = "sha256:918416370e846586541235ccd38a474c08b80443ed31c578a418e2209b3eef91"},
+ {file = "starlette-0.27.0.tar.gz", hash = "sha256:6a6b0d042acb8d469a01eba54e9cda6cbd24ac602c4cd016723117d6a7e73b75"},
+]
+
+[package.dependencies]
+anyio = ">=3.4.0,<5"
+
+[package.extras]
+full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"]
+
+[[package]]
+name = "typing-extensions"
+version = "4.10.0"
+description = "Backported and Experimental Type Hints for Python 3.8+"
+optional = false
+python-versions = ">=3.8"
+files = [
+ {file = "typing_extensions-4.10.0-py3-none-any.whl", hash = "sha256:69b1a937c3a517342112fb4c6df7e72fc39a38e7891a5730ed4985b5214b5475"},
+ {file = "typing_extensions-4.10.0.tar.gz", hash = "sha256:b0abd7c89e8fb96f98db18d86106ff1d90ab692004eb746cf6eda2682f91b3cb"},
+]
+
+[[package]]
+name = "uvicorn"
+version = "0.20.0"
+description = "The lightning-fast ASGI server."
+optional = false
+python-versions = ">=3.7"
+files = [
+ {file = "uvicorn-0.20.0-py3-none-any.whl", hash = "sha256:c3ed1598a5668208723f2bb49336f4509424ad198d6ab2615b7783db58d919fd"},
+ {file = "uvicorn-0.20.0.tar.gz", hash = "sha256:a4e12017b940247f836bc90b72e725d7dfd0c8ed1c51eb365f5ba30d9f5127d8"},
+]
+
+[package.dependencies]
+click = ">=7.0"
+h11 = ">=0.8"
+
+[package.extras]
+standard = ["colorama (>=0.4)", "httptools (>=0.5.0)", "python-dotenv (>=0.13)", "pyyaml (>=5.1)", "uvloop (>=0.14.0,!=0.15.0,!=0.15.1)", "watchfiles (>=0.13)", "websockets (>=10.4)"]
+
+[metadata]
+lock-version = "2.0"
+python-versions = "^3.11"
+content-hash = "1c1900c103a60137142a48f7698b943ffebf2eab40628b1bf69c65fa232af688"
diff --git a/backend_py/user_mock/pyproject.toml b/backend_py/user_mock/pyproject.toml
new file mode 100644
index 000000000..53cad62ac
--- /dev/null
+++ b/backend_py/user_mock/pyproject.toml
@@ -0,0 +1,12 @@
+[tool.poetry]
+package-mode = false
+name = "user-grid3d-vtk"
+
+[build-system]
+requires = ["poetry-core"]
+build-backend = "poetry.core.masonry.api"
+
+[tool.poetry.dependencies]
+python = "^3.11"
+fastapi = "^0.103.1"
+uvicorn = "^0.20.0"
diff --git a/backend/src/backend/user_session/inactivity_shutdown.py b/backend_py/user_mock/user_mock/inactivity_shutdown.py
similarity index 54%
rename from backend/src/backend/user_session/inactivity_shutdown.py
rename to backend_py/user_mock/user_mock/inactivity_shutdown.py
index a86f49a64..ff317d2b1 100644
--- a/backend/src/backend/user_session/inactivity_shutdown.py
+++ b/backend_py/user_mock/user_mock/inactivity_shutdown.py
@@ -2,10 +2,11 @@
import time
from threading import Timer
from typing import Callable, Any
+import logging
from fastapi import Request, FastAPI
-LOCALHOST_DEVELOPMENT = os.environ.get("UVICORN_RELOAD") == "true"
+LOGGER = logging.getLogger(__name__)
class InactivityShutdown:
@@ -18,11 +19,15 @@ async def _update_time_last_request(request: Request, call_next: Callable) -> An
self._time_last_request = time.time()
return await call_next(request)
- if not LOCALHOST_DEVELOPMENT:
- Timer(60.0, self.check_inactivity_threshold).start()
+ LOGGER.info(f"Enabled shutdown after {inactivity_limit_minutes} min of inactivity")
+ Timer(10.0, self.check_inactivity_threshold).start()
def check_inactivity_threshold(self) -> None:
- if time.time() > self._time_last_request + self._inactivity_limit_seconds:
+ inactive_time_s = time.time() - self._time_last_request
+ LOGGER.debug(f"check_inactivity_threshold() {inactive_time_s=:.2f}")
+
+ if inactive_time_s > self._inactivity_limit_seconds:
+ LOGGER.info(f"Shutting down due to inactivity for {inactive_time_s=:.2f}")
os._exit(0)
- else:
- Timer(60.0, self.check_inactivity_threshold).start()
+
+ Timer(10.0, self.check_inactivity_threshold).start()
diff --git a/backend_py/user_mock/user_mock/user_mock_app.py b/backend_py/user_mock/user_mock/user_mock_app.py
new file mode 100644
index 000000000..903ee8d36
--- /dev/null
+++ b/backend_py/user_mock/user_mock/user_mock_app.py
@@ -0,0 +1,85 @@
+import asyncio
+import datetime
+import os
+import logging
+from typing import Annotated
+
+from fastapi import FastAPI
+from fastapi import Query
+
+from .inactivity_shutdown import InactivityShutdown
+
+
+logging.basicConfig(format="%(asctime)s %(levelname)-3s [%(name)s]: %(message)s", datefmt="%H:%M:%S")
+logging.getLogger().setLevel(logging.DEBUG)
+
+# Seems to be one way of know if we're running in Radix or locally
+IS_ON_RADIX_PLATFORM = True if os.getenv("RADIX_APP") is not None else False
+
+LOGGER = logging.getLogger(__name__)
+
+
+RADIX_JOB_NAME = os.getenv("RADIX_JOB_NAME")
+RADIX_APP = os.getenv("RADIX_APP")
+RADIX_ENVIRONMENT = os.getenv("RADIX_ENVIRONMENT")
+RADIX_COMPONENT = os.getenv("RADIX_COMPONENT")
+LOGGER.debug(f"{RADIX_JOB_NAME=}")
+LOGGER.debug(f"{RADIX_APP=}")
+LOGGER.debug(f"{RADIX_ENVIRONMENT=}")
+LOGGER.debug(f"{RADIX_COMPONENT=}")
+
+
+def dump_env_vars():
+ LOGGER.debug(f"{RADIX_JOB_NAME=}")
+ LOGGER.debug(f"{RADIX_APP=}")
+ LOGGER.debug(f"{RADIX_ENVIRONMENT=}")
+ LOGGER.debug(f"{RADIX_COMPONENT=}")
+
+
+app = FastAPI()
+
+
+@app.get("/")
+async def root() -> str:
+ dump_env_vars()
+ ret_str = f"user-mock is alive at this time: {datetime.datetime.now()} [RADIX_JOB_NAME={RADIX_JOB_NAME}] [RADIX_APP={RADIX_APP}] [RADIX_ENVIRONMENT={RADIX_ENVIRONMENT}] [RADIX_COMPONENT={RADIX_COMPONENT}"
+ LOGGER.debug("Sending: ", ret_str)
+ return ret_str
+
+
+# Probe if service is alive
+# HTTP status code 200 means we're alive, all other status codes indicate trouble
+# The response is only for debugging, and is basically ignored.
+@app.get("/health/live")
+async def health_live() -> str:
+ ret_str = f"LIVE at: {datetime.datetime.now()}"
+ LOGGER.debug(f"health_live() returning: {ret_str!r}")
+ return ret_str
+
+
+# Probe if service is ready to receive requests
+# HTTP status code 200 means we're ready, 500 (and all other status codes) signals we're not ready
+# The response is only for debugging, and is basically ignored.
+@app.get("/health/ready")
+async def health_ready() -> str:
+ ret_str = f"READY at: {datetime.datetime.now()}"
+ LOGGER.debug(f"health_ready() returning: {ret_str!r}")
+ return ret_str
+
+
+# Simulate doing some work
+@app.get("/dowork")
+async def dowork(
+ duration: Annotated[float, Query(description="Duration of work in seconds")] = 1.0,
+) -> str:
+ LOGGER.debug(f"dowork() doing MOCK work for: {duration=}s")
+
+ await asyncio.sleep(duration)
+
+ ret_str = f"MOCK work done at: {datetime.datetime.now()}"
+ LOGGER.debug(f"dowork() MOCK returning: {ret_str!r}")
+ return ret_str
+
+
+if IS_ON_RADIX_PLATFORM:
+ InactivityShutdown(app, inactivity_limit_minutes=1.0)
diff --git a/docker-compose.yml b/docker-compose.yml
index 49471b007..914a6c77e 100644
--- a/docker-compose.yml
+++ b/docker-compose.yml
@@ -19,14 +19,13 @@ services:
backend-primary:
build:
context: .
- dockerfile: backend.Dockerfile
+ dockerfile: ./backend_py/primary/Dockerfile
ports:
- 5000:5000
- 5678:5678
environment:
- UVICORN_PORT=5000
- UVICORN_RELOAD=true
- - UVICORN_ENTRYPOINT=src.backend.primary.main:app
- WEBVIZ_CLIENT_SECRET
- WEBVIZ_SMDA_RESOURCE_SCOPE
- WEBVIZ_SMDA_SUBSCRIPTION_KEY
@@ -37,12 +36,13 @@ services:
- OTEL_RESOURCE_ATTRIBUTES=service.namespace=local, service.version=dummy0.1.2
- CODESPACE_NAME # Automatically set env. variable by GitHub codespace
volumes:
- - ./backend/src:/home/appuser/backend/src
+ - ./backend_py/primary/primary:/home/appuser/backend_py/primary/primary
+ - ./backend_py/libs:/home/appuser/backend_py/libs
command:
[
"sh",
"-c",
- "pip install debugpy && python -m debugpy --listen 0.0.0.0:5678 -m uvicorn --proxy-headers --host=0.0.0.0 $${UVICORN_ENTRYPOINT}",
+ "pip install debugpy && python -m debugpy --listen 0.0.0.0:5678 -m uvicorn --proxy-headers --host=0.0.0.0 primary.main:app",
]
surface-query:
@@ -54,26 +54,41 @@ services:
volumes:
- ./backend_go/surface_query:/home/appuser/backend_go/surface_query
- backend-user-session:
+ user-mock:
build:
context: .
- dockerfile: backend.Dockerfile
+ dockerfile: ./backend_py/user_mock/Dockerfile
ports:
- - 8000:8000
+ - 8001:8001
environment:
- - UVICORN_PORT=8000
+ - UVICORN_PORT=8001
+ - UVICORN_RELOAD=true
+ volumes:
+ - ./backend_py/user_mock:/home/appuser/backend_py/user_mock
+
+ user-grid3d-ri:
+ build:
+ context: .
+ dockerfile: ./backend_py/user_grid3d_ri/Dockerfile
+ ports:
+ - 8002:8002
+ environment:
+ - UVICORN_PORT=8002
+ - UVICORN_RELOAD=true
+ volumes:
+ - ./backend_py/user_grid3d_ri:/home/appuser/backend_py/user_grid3d_ri
+
+ user-grid3d-vtk:
+ build:
+ context: .
+ dockerfile: ./backend_py/user_grid3d_vtk/Dockerfile
+ ports:
+ - 8003:8003
+ environment:
+ - UVICORN_PORT=8003
- UVICORN_RELOAD=true
- - UVICORN_ENTRYPOINT=src.backend.user_session.main:app
- - WEBVIZ_CLIENT_SECRET
- - WEBVIZ_SMDA_RESOURCE_SCOPE
- - WEBVIZ_SMDA_SUBSCRIPTION_KEY
- - WEBVIZ_SUMO_ENV
- - WEBVIZ_VDS_HOST_ADDRESS
- - APPLICATIONINSIGHTS_CONNECTION_STRING
- - OTEL_SERVICE_NAME=user-session
- - OTEL_RESOURCE_ATTRIBUTES=service.namespace=local, service.version=dummy0.1.2
volumes:
- - ./backend/src:/home/appuser/backend/src
+ - ./backend_py/user_grid3d_vtk:/home/appuser/backend_py/user_grid3d_vtk
redis-user-session:
image: bitnami/redis:6.2.10@sha256:bd42fcdab5959ce2b21b6ea8410d4b3ee87ecb2e320260326ec731ecfcffbd0e
diff --git a/frontend-dev.Dockerfile b/frontend-dev.Dockerfile
index 5f0488058..57606c4d9 100644
--- a/frontend-dev.Dockerfile
+++ b/frontend-dev.Dockerfile
@@ -8,6 +8,9 @@ COPY --chown=node:node . /usr/src/app
WORKDIR /usr/src/app/frontend
+RUN npm config set fetch-retry-mintimeout 100000
+RUN npm config set fetch-retry-maxtimeout 600000
+
RUN npm ci --ignore-scripts
CMD ["npm", "run", "dev"]
diff --git a/frontend/package-lock.json b/frontend/package-lock.json
index 67998246d..524180f7b 100644
--- a/frontend/package-lock.json
+++ b/frontend/package-lock.json
@@ -12,18 +12,23 @@
"@headlessui/react": "^1.7.8",
"@mui/base": "^5.0.0-beta.3",
"@mui/icons-material": "^5.14.9",
+ "@tanstack/query-core": "^5.17.19",
"@tanstack/react-query": "^5.0.5",
"@tanstack/react-query-devtools": "^5.4.2",
- "@webviz/subsurface-viewer": "^0.3.1",
+ "@webviz/subsurface-viewer": "^0.21.0",
"@webviz/well-completions-plot": "^0.0.1-alpha.1",
"animate.css": "^4.1.1",
"axios": "^1.6.5",
"culori": "^3.2.0",
+ "jotai": "^2.6.2",
+ "jotai-scope": "^0.5.1",
+ "jotai-tanstack-query": "^0.8.2",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-plotly.js": "^2.6.0",
- "uuid": "^9.0.0"
+ "uuid": "^9.0.0",
+ "wonka": "^6.3.4"
},
"devDependencies": {
"@playwright/experimental-ct-react": "^1.39.0",
@@ -85,6 +90,7 @@
"version": "2.2.1",
"resolved": "https://registry.npmjs.org/@ampproject/remapping/-/remapping-2.2.1.tgz",
"integrity": "sha512-lFMjJTrFL3j7L9yBxwYfCq2k6qqwHyzuUl/XBnif78PWTJYyL/dfowQHWE3sp6U6ZzqWiiIZnpTMO96zhkjwtg==",
+ "dev": true,
"dependencies": {
"@jridgewell/gen-mapping": "^0.3.0",
"@jridgewell/trace-mapping": "^0.3.9"
@@ -128,6 +134,7 @@
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/compat-data/-/compat-data-7.23.5.tgz",
"integrity": "sha512-uU27kfDRlhfKl+w1U6vp16IuvSLtjAxdArVXPa9BvLkrr7CYIsxH5adpHObeAGY/41+syctUWOZ140a2Rvkgjw==",
+ "dev": true,
"engines": {
"node": ">=6.9.0"
}
@@ -136,6 +143,7 @@
"version": "7.23.7",
"resolved": "https://registry.npmjs.org/@babel/core/-/core-7.23.7.tgz",
"integrity": "sha512-+UpDgowcmqe36d4NwqvKsyPMlOLNGMsfMmQ5WGCu+siCe3t3dfe9njrzGfdN4qq+bcNUt0+Vw6haRxBOycs4dw==",
+ "dev": true,
"dependencies": {
"@ampproject/remapping": "^2.2.0",
"@babel/code-frame": "^7.23.5",
@@ -164,12 +172,14 @@
"node_modules/@babel/core/node_modules/convert-source-map": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
+ "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg==",
+ "dev": true
},
"node_modules/@babel/generator": {
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/generator/-/generator-7.23.6.tgz",
"integrity": "sha512-qrSfCYxYQB5owCmGLbl8XRpX1ytXlpueOb0N0UmQwA073KZxejgQTzAmJezxvpwQD9uGtK2shHdi55QT+MbjIw==",
+ "dev": true,
"dependencies": {
"@babel/types": "^7.23.6",
"@jridgewell/gen-mapping": "^0.3.2",
@@ -180,22 +190,11 @@
"node": ">=6.9.0"
}
},
- "node_modules/@babel/helper-annotate-as-pure": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/helper-annotate-as-pure/-/helper-annotate-as-pure-7.22.5.tgz",
- "integrity": "sha512-LvBTxu8bQSQkcyKOU+a1btnNFQ1dMAd0R6PyW3arXes06F6QLWLIrd681bxRPIXlrMGR3XYnW9JyML7dP3qgxg==",
- "peer": true,
- "dependencies": {
- "@babel/types": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- }
- },
"node_modules/@babel/helper-compilation-targets": {
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/helper-compilation-targets/-/helper-compilation-targets-7.23.6.tgz",
"integrity": "sha512-9JB548GZoQVmzrFgp8o7KxdgkTGm6xs9DW0o/Pim72UDjzr5ObUQ6ZzYPqA+g9OTS2bBQoctLJrky0RDCAWRgQ==",
+ "dev": true,
"dependencies": {
"@babel/compat-data": "^7.23.5",
"@babel/helper-validator-option": "^7.23.5",
@@ -211,6 +210,7 @@
"version": "7.22.20",
"resolved": "https://registry.npmjs.org/@babel/helper-environment-visitor/-/helper-environment-visitor-7.22.20.tgz",
"integrity": "sha512-zfedSIzFhat/gFhWfHtgWvlec0nqB9YEIVrpuwjruLlXfUSnA8cJB0miHKwqDnQ7d32aKo2xt88/xZptwxbfhA==",
+ "dev": true,
"engines": {
"node": ">=6.9.0"
}
@@ -219,6 +219,7 @@
"version": "7.23.0",
"resolved": "https://registry.npmjs.org/@babel/helper-function-name/-/helper-function-name-7.23.0.tgz",
"integrity": "sha512-OErEqsrxjZTJciZ4Oo+eoZqeW9UIiOcuYKRJA4ZAgV9myA+pOXhhmpfNCKjEH/auVfEYVFJ6y1Tc4r0eIApqiw==",
+ "dev": true,
"dependencies": {
"@babel/template": "^7.22.15",
"@babel/types": "^7.23.0"
@@ -231,6 +232,7 @@
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-hoist-variables/-/helper-hoist-variables-7.22.5.tgz",
"integrity": "sha512-wGjk9QZVzvknA6yKIUURb8zY3grXCcOZt+/7Wcy8O2uctxhplmUPkOdlgoNhmdVee2c92JXbf1xpMtVNbfoxRw==",
+ "dev": true,
"dependencies": {
"@babel/types": "^7.22.5"
},
@@ -253,6 +255,7 @@
"version": "7.23.3",
"resolved": "https://registry.npmjs.org/@babel/helper-module-transforms/-/helper-module-transforms-7.23.3.tgz",
"integrity": "sha512-7bBs4ED9OmswdfDzpz4MpWgSrV7FXlc3zIagvLFjS5H+Mk7Snr21vQ6QwrsoCGMfNC4e4LQPdoULEt4ykz0SRQ==",
+ "dev": true,
"dependencies": {
"@babel/helper-environment-visitor": "^7.22.20",
"@babel/helper-module-imports": "^7.22.15",
@@ -271,6 +274,7 @@
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-plugin-utils/-/helper-plugin-utils-7.22.5.tgz",
"integrity": "sha512-uLls06UVKgFG9QD4OeFYLEGteMIAa5kpTPcFL28yuCIIzsf6ZyKZMllKVOCZFhiZ5ptnwX4mtKdWCBE/uT4amg==",
+ "dev": true,
"engines": {
"node": ">=6.9.0"
}
@@ -279,6 +283,7 @@
"version": "7.22.5",
"resolved": "https://registry.npmjs.org/@babel/helper-simple-access/-/helper-simple-access-7.22.5.tgz",
"integrity": "sha512-n0H99E/K+Bika3++WNL17POvo4rKWZ7lZEp1Q+fStVbUi8nxPQEBOlTmCOxW/0JsS56SKKQ+ojAe2pHKJHN35w==",
+ "dev": true,
"dependencies": {
"@babel/types": "^7.22.5"
},
@@ -290,6 +295,7 @@
"version": "7.22.6",
"resolved": "https://registry.npmjs.org/@babel/helper-split-export-declaration/-/helper-split-export-declaration-7.22.6.tgz",
"integrity": "sha512-AsUnxuLhRYsisFiaJwvp1QF+I3KjD5FOxut14q/GzovUe6orHLesW2C7d754kRm53h5gqrz6sFl6sxc4BVtE/g==",
+ "dev": true,
"dependencies": {
"@babel/types": "^7.22.5"
},
@@ -317,6 +323,7 @@
"version": "7.23.5",
"resolved": "https://registry.npmjs.org/@babel/helper-validator-option/-/helper-validator-option-7.23.5.tgz",
"integrity": "sha512-85ttAOMLsr53VgXkTbkx8oA6YTfT4q7/HzXSLEYmjcSTJPMPQtvq1BD79Byep5xMUYbGRzEpDsjUf3dyp54IKw==",
+ "dev": true,
"engines": {
"node": ">=6.9.0"
}
@@ -325,6 +332,7 @@
"version": "7.23.7",
"resolved": "https://registry.npmjs.org/@babel/helpers/-/helpers-7.23.7.tgz",
"integrity": "sha512-6AMnjCoC8wjqBzDHkuqpa7jAKwvMo4dC+lr/TFBz+ucfulO1XMpDnwWPGBNwClOKZ8h6xn5N81W/R5OrcKtCbQ==",
+ "dev": true,
"dependencies": {
"@babel/template": "^7.22.15",
"@babel/traverse": "^7.23.7",
@@ -351,6 +359,7 @@
"version": "7.23.6",
"resolved": "https://registry.npmjs.org/@babel/parser/-/parser-7.23.6.tgz",
"integrity": "sha512-Z2uID7YJ7oNvAI20O9X0bblw7Qqs8Q2hFy0R9tAfnfLkp5MW0UH9eUvnDSnFwKZ0AvgS1ucqR4KzvVHgnke1VQ==",
+ "dev": true,
"bin": {
"parser": "bin/babel-parser.js"
},
@@ -358,156 +367,6 @@
"node": ">=6.0.0"
}
},
- "node_modules/@babel/plugin-syntax-async-generators": {
- "version": "7.8.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-async-generators/-/plugin-syntax-async-generators-7.8.4.tgz",
- "integrity": "sha512-tycmZxkGfZaxhMRbXlPXuVFpdWlXpir2W4AMhSJgRKzk/eDlIXOhb2LHWoLpDF7TEHylV5zNhykX6KAgHJmTNw==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-bigint": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-bigint/-/plugin-syntax-bigint-7.8.3.tgz",
- "integrity": "sha512-wnTnFlG+YxQm3vDxpGE57Pj0srRU4sHE/mDkt1qv2YJJSeUAec2ma4WLUnUPeKjyrfntVwe/N6dCXpU+zL3Npg==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-class-properties": {
- "version": "7.12.13",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-class-properties/-/plugin-syntax-class-properties-7.12.13.tgz",
- "integrity": "sha512-fm4idjKla0YahUNgFNLCB0qySdsoPiZP3iQE3rky0mBUtMZ23yDJ9SJdg6dXTSDnulOVqiF3Hgr9nbXvXTQZYA==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.12.13"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-import-meta": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-import-meta/-/plugin-syntax-import-meta-7.10.4.tgz",
- "integrity": "sha512-Yqfm+XDx0+Prh3VSeEQCPU81yC+JWZ2pDPFSS4ZdpfZhp4MkFMaDC1UqseovEKwSUpnIL7+vK+Clp7bfh0iD7g==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-json-strings": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-json-strings/-/plugin-syntax-json-strings-7.8.3.tgz",
- "integrity": "sha512-lY6kdGpWHvjoe2vk4WrAapEuBR69EMxZl+RoGRhrFGNYVK8mOPAW8VfbT/ZgrFbXlDNiiaxQnAtgVCZ6jv30EA==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-jsx": {
- "version": "7.22.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-jsx/-/plugin-syntax-jsx-7.22.5.tgz",
- "integrity": "sha512-gvyP4hZrgrs/wWMaocvxZ44Hw0b3W8Pe+cMxc8V1ULQ07oh8VNbIRaoD1LRZVTvD+0nieDKjfgKg89sD7rrKrg==",
- "peer": true,
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.22.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-logical-assignment-operators": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-logical-assignment-operators/-/plugin-syntax-logical-assignment-operators-7.10.4.tgz",
- "integrity": "sha512-d8waShlpFDinQ5MtvGU9xDAOzKH47+FFoney2baFIoMr952hKOLp1HR7VszoZvOsV/4+RRszNY7D17ba0te0ig==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-nullish-coalescing-operator": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-nullish-coalescing-operator/-/plugin-syntax-nullish-coalescing-operator-7.8.3.tgz",
- "integrity": "sha512-aSff4zPII1u2QD7y+F8oDsz19ew4IGEJg9SVW+bqwpwtfFleiQDMdzA/R+UlWDzfnHFCxxleFT0PMIrR36XLNQ==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-numeric-separator": {
- "version": "7.10.4",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-numeric-separator/-/plugin-syntax-numeric-separator-7.10.4.tgz",
- "integrity": "sha512-9H6YdfkcK/uOnY/K7/aA2xpzaAgkQn37yzWUMRK7OaPOqOpGS1+n0H5hxT9AUw9EsSjPW8SVyMJwYRtWs3X3ug==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.10.4"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-object-rest-spread": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-object-rest-spread/-/plugin-syntax-object-rest-spread-7.8.3.tgz",
- "integrity": "sha512-XoqMijGZb9y3y2XskN+P1wUGiVwWZ5JmoDRwx5+3GmEplNyVM2s2Dg8ILFQm8rWM48orGy5YpI5Bl8U1y7ydlA==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-catch-binding": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-catch-binding/-/plugin-syntax-optional-catch-binding-7.8.3.tgz",
- "integrity": "sha512-6VPD0Pc1lpTqw0aKoeRTMiB+kWhAoT24PA+ksWSBrFtl5SIRVpZlwN3NNPQjehA2E/91FV3RjLWoVTglWcSV3Q==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-optional-chaining": {
- "version": "7.8.3",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-optional-chaining/-/plugin-syntax-optional-chaining-7.8.3.tgz",
- "integrity": "sha512-KoK9ErH1MBlCPxV0VANkXW2/dw4vlbGDrFgz8bmUsBGYkFRcbRwMh6cIJubdPrkxRwuGdtCk0v/wPTKbQgBjkg==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.8.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
- "node_modules/@babel/plugin-syntax-top-level-await": {
- "version": "7.14.5",
- "resolved": "https://registry.npmjs.org/@babel/plugin-syntax-top-level-await/-/plugin-syntax-top-level-await-7.14.5.tgz",
- "integrity": "sha512-hx++upLv5U1rgYfwe1xBQUhRmU41NEvpUvrp8jkrSCdvGSnM5/qdRMtylJ6PG5OFkBaHkbTAKTnd3/YyESRHFw==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.14.5"
- },
- "engines": {
- "node": ">=6.9.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0-0"
- }
- },
"node_modules/@babel/plugin-transform-react-jsx-self": {
"version": "7.23.3",
"resolved": "https://registry.npmjs.org/@babel/plugin-transform-react-jsx-self/-/plugin-transform-react-jsx-self-7.23.3.tgz",
@@ -539,9 +398,9 @@
}
},
"node_modules/@babel/runtime": {
- "version": "7.22.15",
- "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.22.15.tgz",
- "integrity": "sha512-T0O+aa+4w0u06iNmapipJXMV4HoUir03hpx3/YqXXhu9xim3w+dVphjFWl1OH8NbZHw5Lbm9k45drDkgq2VNNA==",
+ "version": "7.24.1",
+ "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.24.1.tgz",
+ "integrity": "sha512-+BIznRzyqBf+2wCTxcKE3wDjfGeCoVE61KSHGpkzqrLi8qxqFwBeUFyId2cxkTmm55fzDGnm0+yCxaxygrLUnQ==",
"dependencies": {
"regenerator-runtime": "^0.14.0"
},
@@ -553,6 +412,7 @@
"version": "7.22.15",
"resolved": "https://registry.npmjs.org/@babel/template/-/template-7.22.15.tgz",
"integrity": "sha512-QPErUVm4uyJa60rkI73qneDacvdvzxshT3kksGqlGWYdOTIUOwJ7RDUL8sGqslY1uXWSL6xMFKEXDS3ox2uF0w==",
+ "dev": true,
"dependencies": {
"@babel/code-frame": "^7.22.13",
"@babel/parser": "^7.22.15",
@@ -566,6 +426,7 @@
"version": "7.23.7",
"resolved": "https://registry.npmjs.org/@babel/traverse/-/traverse-7.23.7.tgz",
"integrity": "sha512-tY3mM8rH9jM0YHFGyfC0/xf+SB5eKUu7HPj7/k3fpi9dAlsMc5YbQvDi0Sh2QTPXqMhyaAtzAr807TIyfQrmyg==",
+ "dev": true,
"dependencies": {
"@babel/code-frame": "^7.23.5",
"@babel/generator": "^7.23.6",
@@ -607,12 +468,6 @@
"findup": "bin/findup.js"
}
},
- "node_modules/@choojs/findup/node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "peer": true
- },
"node_modules/@danmarshall/deckgl-typings": {
"version": "4.9.12",
"resolved": "https://registry.npmjs.org/@danmarshall/deckgl-typings/-/deckgl-typings-4.9.12.tgz",
@@ -625,13 +480,13 @@
}
},
"node_modules/@deck.gl/aggregation-layers": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/aggregation-layers/-/aggregation-layers-8.9.22.tgz",
- "integrity": "sha512-cw2duTxcZI0i0+295ivo/tsLffB6GPhuwkCYhqrVfO61JsK9GFuISGB7C5tMcfSOSxzgN6JwNA4fJEK1bCGozQ==",
+ "version": "8.9.35",
+ "resolved": "https://registry.npmjs.org/@deck.gl/aggregation-layers/-/aggregation-layers-8.9.35.tgz",
+ "integrity": "sha512-OjJhHt/ZXLIP3cs8yD2xwa9KACBOjfvJpdMkly704y6SuM0k+qSj81VwkpdOA54DCvAhQQTAYCJ4rvnwmtcPQQ==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@luma.gl/constants": "^8.5.20",
- "@luma.gl/shadertools": "^8.5.20",
+ "@luma.gl/constants": "^8.5.21",
+ "@luma.gl/shadertools": "^8.5.21",
"@math.gl/web-mercator": "^3.6.2",
"d3-hexbin": "^0.2.1"
},
@@ -641,56 +496,17 @@
"@luma.gl/core": "^8.0.0"
}
},
- "node_modules/@deck.gl/carto": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/carto/-/carto-8.9.22.tgz",
- "integrity": "sha512-sfSmzUtXrhvMX5JaFiIpQtmfqVHRxcVIxnSZz6F5Q7DtvBhjNMEt3jq3qJ3IWH0EyxX0Xu+HMjmw6ScnsVAcXQ==",
- "dependencies": {
- "@babel/runtime": "^7.0.0",
- "@loaders.gl/gis": "^3.4.2",
- "@loaders.gl/loader-utils": "^3.4.2",
- "@loaders.gl/mvt": "^3.4.2",
- "@loaders.gl/tiles": "^3.4.2",
- "@luma.gl/constants": "^8.5.20",
- "@math.gl/web-mercator": "^3.6.2",
- "cartocolor": "^4.0.2",
- "d3-array": "^3.2.0",
- "d3-color": "^3.1.0",
- "d3-format": "^3.1.0",
- "d3-scale": "^4.0.0",
- "h3-js": "^3.7.0",
- "moment-timezone": "^0.5.33",
- "pbf": "^3.2.1",
- "quadbin": "^0.1.9"
- },
- "peerDependencies": {
- "@deck.gl/aggregation-layers": "^8.0.0",
- "@deck.gl/core": "^8.0.0",
- "@deck.gl/extensions": "^8.0.0",
- "@deck.gl/geo-layers": "^8.0.0",
- "@deck.gl/layers": "^8.0.0",
- "@loaders.gl/core": "^3.4.2"
- }
- },
- "node_modules/@deck.gl/carto/node_modules/d3-format": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
- "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
- "engines": {
- "node": ">=12"
- }
- },
"node_modules/@deck.gl/core": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-8.9.22.tgz",
- "integrity": "sha512-HnUPB6qKgRfKQ3Dstw6vlI7+fyO9Ni4gukh8ysQM94mw89BRLkVcuQV0XvlzbbojrG1Z6QpC7KZmodW0y5o2og==",
+ "version": "8.9.35",
+ "resolved": "https://registry.npmjs.org/@deck.gl/core/-/core-8.9.35.tgz",
+ "integrity": "sha512-xOASWScUCB5fpfuSjPaJrwas8pCJpbKXNIfwQElhvnfP3Yk8GGkAcRbPgiPNCfpkbEno7eDpAWJt6+6UJsSp9g==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@loaders.gl/core": "^3.4.2",
- "@loaders.gl/images": "^3.4.2",
- "@luma.gl/constants": "^8.5.20",
- "@luma.gl/core": "^8.5.20",
- "@luma.gl/webgl": "^8.5.20",
+ "@loaders.gl/core": "^3.4.13",
+ "@loaders.gl/images": "^3.4.13",
+ "@luma.gl/constants": "^8.5.21",
+ "@luma.gl/core": "^8.5.21",
+ "@luma.gl/webgl": "^8.5.21",
"@math.gl/core": "^3.6.2",
"@math.gl/sun": "^3.6.2",
"@math.gl/web-mercator": "^3.6.2",
@@ -703,12 +519,12 @@
}
},
"node_modules/@deck.gl/extensions": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/extensions/-/extensions-8.9.22.tgz",
- "integrity": "sha512-MYyWjnf94Ibs3BNfTIq/oJJLrNMWUpS2+qkmkQie03EGeO7/wJ9BAQAXWYdFdrbvCykw60mLBX78a68+XLvbmQ==",
+ "version": "8.9.35",
+ "resolved": "https://registry.npmjs.org/@deck.gl/extensions/-/extensions-8.9.35.tgz",
+ "integrity": "sha512-qMZzeQpvtcw4zbh4HJJIF8Q73/u0Unwwe8aSC2r+apjuyUVPQInwlCil++LznBY3JA37M7SvW2TSK6IgCuaSyA==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@luma.gl/shadertools": "^8.5.20"
+ "@luma.gl/shadertools": "^8.5.21"
},
"peerDependencies": {
"@deck.gl/core": "^8.0.0",
@@ -720,21 +536,21 @@
}
},
"node_modules/@deck.gl/geo-layers": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/geo-layers/-/geo-layers-8.9.22.tgz",
- "integrity": "sha512-/P6kGxlWhfRPAaG0UDklANTQpQGevAE1zGTOyFVYEAMyRBws/CetLCq5rKfYibTjWBa5FO2U0u837HzG0PJRUw==",
+ "version": "8.9.35",
+ "resolved": "https://registry.npmjs.org/@deck.gl/geo-layers/-/geo-layers-8.9.35.tgz",
+ "integrity": "sha512-7sczznSjC7GjpDxuXPvPN7/WbVgSYHnFNNyWr8hMGm/WlUMK4z9QpZo6UFvrHL5rQ5Uudd4vD56xB1fs3b2lMA==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@loaders.gl/3d-tiles": "^3.4.2",
- "@loaders.gl/gis": "^3.4.2",
- "@loaders.gl/loader-utils": "^3.4.2",
- "@loaders.gl/mvt": "^3.4.2",
- "@loaders.gl/schema": "^3.4.2",
- "@loaders.gl/terrain": "^3.4.2",
- "@loaders.gl/tiles": "^3.4.2",
- "@loaders.gl/wms": "^3.4.2",
- "@luma.gl/constants": "^8.5.20",
- "@luma.gl/experimental": "^8.5.20",
+ "@loaders.gl/3d-tiles": "^3.4.13",
+ "@loaders.gl/gis": "^3.4.13",
+ "@loaders.gl/loader-utils": "^3.4.13",
+ "@loaders.gl/mvt": "^3.4.13",
+ "@loaders.gl/schema": "^3.4.13",
+ "@loaders.gl/terrain": "^3.4.13",
+ "@loaders.gl/tiles": "^3.4.13",
+ "@loaders.gl/wms": "^3.4.13",
+ "@luma.gl/constants": "^8.5.21",
+ "@luma.gl/experimental": "^8.5.21",
"@math.gl/core": "^3.6.2",
"@math.gl/culling": "^3.6.2",
"@math.gl/web-mercator": "^3.6.2",
@@ -747,28 +563,14 @@
"@deck.gl/extensions": "^8.0.0",
"@deck.gl/layers": "^8.0.0",
"@deck.gl/mesh-layers": "^8.0.0",
- "@loaders.gl/core": "^3.4.2",
+ "@loaders.gl/core": "^3.4.13",
"@luma.gl/core": "^8.0.0"
}
},
- "node_modules/@deck.gl/google-maps": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/google-maps/-/google-maps-8.9.22.tgz",
- "integrity": "sha512-x+9yqxkjLN0P5uKxYB6GEaM0KV2djBotvHX0BaHL9LbyWzdAvGJP1kmTg4SOpi0I7XG8jdkoca/tAZ2yy7A9RQ==",
- "dependencies": {
- "@babel/runtime": "^7.0.0"
- },
- "peerDependencies": {
- "@deck.gl/core": "^8.0.0",
- "@luma.gl/constants": "^8.5.0",
- "@luma.gl/core": "^8.5.0",
- "@math.gl/core": "^3.6.0"
- }
- },
"node_modules/@deck.gl/json": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/json/-/json-8.9.22.tgz",
- "integrity": "sha512-rYFZqp7mW8XvExtLAfGiAxTV7oLPaLmPVDPTYmMU2owSkfGYE3q6YvwqzHq37k5/5jLfJMA0cZy1fQrfJW3+gg==",
+ "version": "8.9.35",
+ "resolved": "https://registry.npmjs.org/@deck.gl/json/-/json-8.9.35.tgz",
+ "integrity": "sha512-0mp4ckb1n0kRGPPFqtx6Q13uGNRBYGrpYN/NuibQZSW1EMNqmxTqSJekoqzXrlI1W6u35Tu9E5+DHpw9WJiJkg==",
"dependencies": {
"@babel/runtime": "^7.0.0",
"d3-dsv": "^1.0.8",
@@ -778,52 +580,15 @@
"@deck.gl/core": "^8.0.0"
}
},
- "node_modules/@deck.gl/json/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/@deck.gl/json/node_modules/d3-dsv": {
- "version": "1.2.0",
- "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz",
- "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==",
- "dependencies": {
- "commander": "2",
- "iconv-lite": "0.4",
- "rw": "1"
- },
- "bin": {
- "csv2json": "bin/dsv2json",
- "csv2tsv": "bin/dsv2dsv",
- "dsv2dsv": "bin/dsv2dsv",
- "dsv2json": "bin/dsv2json",
- "json2csv": "bin/json2dsv",
- "json2dsv": "bin/json2dsv",
- "json2tsv": "bin/json2dsv",
- "tsv2csv": "bin/dsv2dsv",
- "tsv2json": "bin/dsv2json"
- }
- },
- "node_modules/@deck.gl/json/node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/@deck.gl/layers": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-8.9.22.tgz",
- "integrity": "sha512-1IipECeORaT2fdU9k8KPnZ3DjUeH02h6oZYl4ffihNAIoVXKNivghgJ8ZeELLiEOkrxlbK+KjoH1zej7yuMwmg==",
+ "version": "8.9.35",
+ "resolved": "https://registry.npmjs.org/@deck.gl/layers/-/layers-8.9.35.tgz",
+ "integrity": "sha512-4amaGO+tGvaCNi2KZ90twmajGh5xUAaQzBIyh42dnM10GRj/62sOIYD9uT032oV/KpjKY+TfOstx5ooXBGKDjg==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@loaders.gl/images": "^3.4.2",
- "@loaders.gl/schema": "^3.4.2",
- "@luma.gl/constants": "^8.5.20",
+ "@loaders.gl/images": "^3.4.13",
+ "@loaders.gl/schema": "^3.4.13",
+ "@luma.gl/constants": "^8.5.21",
"@mapbox/tiny-sdf": "^2.0.5",
"@math.gl/core": "^3.6.2",
"@math.gl/polygon": "^3.6.2",
@@ -832,32 +597,20 @@
},
"peerDependencies": {
"@deck.gl/core": "^8.0.0",
- "@loaders.gl/core": "^3.4.2",
+ "@loaders.gl/core": "^3.4.13",
"@luma.gl/core": "^8.0.0"
}
},
- "node_modules/@deck.gl/mapbox": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/mapbox/-/mapbox-8.9.22.tgz",
- "integrity": "sha512-VanA1V/BE6vmHn/W9f8ug4ilMDEfP3JUQWegVaCiG2EA8yjML6QVmO31gNARTefBjgMsfkWDBwm325coIUkxBQ==",
- "dependencies": {
- "@babel/runtime": "^7.0.0",
- "@types/mapbox-gl": "^2.6.3"
- },
- "peerDependencies": {
- "@deck.gl/core": "^8.0.0"
- }
- },
"node_modules/@deck.gl/mesh-layers": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/mesh-layers/-/mesh-layers-8.9.22.tgz",
- "integrity": "sha512-XJ6WdHphBtdumQYseFQCfGQ8KLRzgOGu89qsiEcuRTQwgW5GxXi4WJSpZmXZGtXObubwuEX6YqrN4BkX3F/nWg==",
+ "version": "8.9.35",
+ "resolved": "https://registry.npmjs.org/@deck.gl/mesh-layers/-/mesh-layers-8.9.35.tgz",
+ "integrity": "sha512-0l7+zi/6bkYVz7zZ0J4+WLoxOh+hFMPUQKCujTOcqYWbvJ2fEQze0Z1ZHCAG0RQOFJITEMamDigo9dN2BMxPBA==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@loaders.gl/gltf": "^3.4.2",
- "@luma.gl/constants": "^8.5.20",
- "@luma.gl/experimental": "^8.5.20",
- "@luma.gl/shadertools": "^8.5.20"
+ "@loaders.gl/gltf": "^3.4.13",
+ "@luma.gl/constants": "^8.5.21",
+ "@luma.gl/experimental": "^8.5.21",
+ "@luma.gl/shadertools": "^8.5.21"
},
"peerDependencies": {
"@deck.gl/core": "^8.0.0",
@@ -865,9 +618,9 @@
}
},
"node_modules/@deck.gl/react": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/@deck.gl/react/-/react-8.9.22.tgz",
- "integrity": "sha512-NZcWBlOWYPs+DQqYSZQFLxfguFe0GP2AE1ojlrstnckV1N3bsMf1dT6AI5AvX5h9DbiBc216ZrV9iwVhlfkLng==",
+ "version": "8.9.35",
+ "resolved": "https://registry.npmjs.org/@deck.gl/react/-/react-8.9.35.tgz",
+ "integrity": "sha512-eDwYCeBBzHXIpgZbAxcAEnpjnAoMiWcec8rMgYot7VOB+RnBTPYUaO3GPPImlk1uiezNGQel0YK4OLI1f6cDHg==",
"dependencies": {
"@babel/runtime": "^7.0.0"
},
@@ -879,17 +632,17 @@
}
},
"node_modules/@emerson-eps/color-tables": {
- "version": "0.4.61",
- "resolved": "https://registry.npmjs.org/@emerson-eps/color-tables/-/color-tables-0.4.61.tgz",
- "integrity": "sha512-hQZgEoTbfllCI6by14RI/Jpqftn9m3wBT6afNOu/ffM4/IxjxpKYaG1ycle310AOAJWoTj9wByIwE7YlkJIFoQ==",
+ "version": "0.4.80",
+ "resolved": "https://registry.npmjs.org/@emerson-eps/color-tables/-/color-tables-0.4.80.tgz",
+ "integrity": "sha512-2G0u+ZOREJA4g1Tmj9FQYCUDZdC6FP2740ps47jyq9r4a9aYQn8dGOipmtjkwQcV3LANk4G6xDEL4nJbILfWWg==",
"dependencies": {
- "@emotion/react": "^11.10.6",
+ "@emotion/react": "^11.11.4",
"@emotion/styled": "^11.10.0",
"d3": "^7.8.4",
"d3-color": "^3.0.1",
"d3-interpolate": "^3.0.1",
"react-color": "^2.19.3",
- "react-resize-detector": "^9.1.0"
+ "react-resize-detector": "^9.1.1"
},
"peerDependencies": {
"@mui/icons-material": "^5.11.16",
@@ -948,14 +701,14 @@
"integrity": "sha512-W2P2c/VRW1/1tLox0mVUalvnWXxavmv/Oum2aPsRcoDJuob75FC3Y8FbpfLwUegRcxINtGUMPq0tFCvYNTBXNA=="
},
"node_modules/@emotion/react": {
- "version": "11.11.1",
- "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.1.tgz",
- "integrity": "sha512-5mlW1DquU5HaxjLkfkGN1GA/fvVGdyHURRiX/0FHl2cfIfRxSOfmxEH5YS43edp0OldZrZ+dkBKbngxcNCdZvA==",
+ "version": "11.11.4",
+ "resolved": "https://registry.npmjs.org/@emotion/react/-/react-11.11.4.tgz",
+ "integrity": "sha512-t8AjMlF0gHpvvxk5mAtCqR4vmxiGHCeJBaQO6gncUSdklELOgtwjerNY2yuJNfwnc6vi16U/+uMF+afIawJ9iw==",
"dependencies": {
"@babel/runtime": "^7.18.3",
"@emotion/babel-plugin": "^11.11.0",
"@emotion/cache": "^11.11.0",
- "@emotion/serialize": "^1.1.2",
+ "@emotion/serialize": "^1.1.3",
"@emotion/use-insertion-effect-with-fallbacks": "^1.0.1",
"@emotion/utils": "^1.2.1",
"@emotion/weak-memoize": "^0.3.1",
@@ -971,9 +724,9 @@
}
},
"node_modules/@emotion/serialize": {
- "version": "1.1.2",
- "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.2.tgz",
- "integrity": "sha512-zR6a/fkFP4EAcCMQtLOhIgpprZOwNmCldtpaISpvz348+DP4Mz8ZoKaGGCQpbzepNIUWbq4w6hNZkwDyKoS+HA==",
+ "version": "1.1.4",
+ "resolved": "https://registry.npmjs.org/@emotion/serialize/-/serialize-1.1.4.tgz",
+ "integrity": "sha512-RIN04MBT8g+FnDwgvIUi8czvr1LU1alUMI05LekWB5DGyTm8cCBMCRpq3GqaiyEDRptEXOyXnvZ58GZYu4kBxQ==",
"dependencies": {
"@emotion/hash": "^0.9.1",
"@emotion/memoize": "^0.8.1",
@@ -1009,12 +762,6 @@
}
}
},
- "node_modules/@emotion/stylis": {
- "version": "0.8.5",
- "resolved": "https://registry.npmjs.org/@emotion/stylis/-/stylis-0.8.5.tgz",
- "integrity": "sha512-h6KtPihKFn3T9fuIrwvXXUOwlx3rfUvfZIcP5a6rh8Y7zjE3O06hT5Ss4S/YI1AYhuZ1kjaE/5EaOOI2NqSylQ==",
- "peer": true
- },
"node_modules/@emotion/unitless": {
"version": "0.8.1",
"resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.1.tgz",
@@ -1039,17 +786,17 @@
"integrity": "sha512-EsBwpc7hBUJWAsNPBmJy4hxWx12v6bshQsldrVmjxJoc3isbxhOrF2IcCpaXxfvq03NwkI7sbsOLXbYuqF/8Ww=="
},
"node_modules/@equinor/eds-core-react": {
- "version": "0.32.4",
- "resolved": "https://registry.npmjs.org/@equinor/eds-core-react/-/eds-core-react-0.32.4.tgz",
- "integrity": "sha512-UTUE8TImQkVxl3srR0dOkPHTkLtmqsp+lcZz509sl3WRaGFlBseBiPgWrCTdgfT4EtAKRimmXhqsrAHllhGgJA==",
+ "version": "0.36.1",
+ "resolved": "https://registry.npmjs.org/@equinor/eds-core-react/-/eds-core-react-0.36.1.tgz",
+ "integrity": "sha512-cFpmsT4+EEFDhGE1DLNDT9Scr6SNBF4xnIfAgkMZcK6wmmZZT30lV2zdGgFC1JN9FfyvlisQukgpurynuBoJTw==",
"dependencies": {
- "@babel/runtime": "^7.22.5",
- "@equinor/eds-icons": "^0.19.3",
+ "@babel/runtime": "^7.24.0",
+ "@equinor/eds-icons": "^0.21.0",
"@equinor/eds-tokens": "0.9.2",
- "@equinor/eds-utils": "0.8.1",
- "@floating-ui/react": "^0.25.1",
- "@tanstack/react-virtual": "3.0.0-beta.54",
- "downshift": "^8.1.0"
+ "@equinor/eds-utils": "0.8.4",
+ "@floating-ui/react": "^0.26.9",
+ "@tanstack/react-virtual": "3.1.3",
+ "downshift": "8.3.3"
},
"engines": {
"node": ">=10.0.0",
@@ -1058,13 +805,13 @@
"peerDependencies": {
"react": ">=16.8",
"react-dom": ">=16.8",
- "styled-components": ">=4.2 < 6"
+ "styled-components": ">=4.2"
}
},
"node_modules/@equinor/eds-icons": {
- "version": "0.19.3",
- "resolved": "https://registry.npmjs.org/@equinor/eds-icons/-/eds-icons-0.19.3.tgz",
- "integrity": "sha512-Sh0W01PrwXPCi8/p9YKj0qKNtRU9R/xYJORinIzsNNRllpiu9wvuGAsQNE0gQaDDnrprsiRBH3+MdMSRXVs3Wg==",
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/@equinor/eds-icons/-/eds-icons-0.21.0.tgz",
+ "integrity": "sha512-k2keACHou9h9D5QLfSBeojTApqbPCkHNBWplUA/B9FQv8FMCMSBbjJAo2L/3yAExMylQN9LdwKo81T2tijRXoA==",
"engines": {
"node": ">=10.0.0",
"pnpm": ">=4"
@@ -1080,13 +827,12 @@
}
},
"node_modules/@equinor/eds-utils": {
- "version": "0.8.1",
- "resolved": "https://registry.npmjs.org/@equinor/eds-utils/-/eds-utils-0.8.1.tgz",
- "integrity": "sha512-MqKqHhfOxGxbZPhHlZqiR58ei11CQ+UGJ/qEa7wC5pA/c+W9kyu7OveiK9OVvaswRiOmLaahnhSEC9JTFa7ICw==",
+ "version": "0.8.4",
+ "resolved": "https://registry.npmjs.org/@equinor/eds-utils/-/eds-utils-0.8.4.tgz",
+ "integrity": "sha512-njvqXd3Hzfy5vkEqnx+uEBAu00vnG/5R+gDgWCReVDjjUoHdQNcrqfjBLsGF2UungtO0LbYV8YuBP+9l4V7ywQ==",
"dependencies": {
- "@babel/runtime": "^7.22.5",
- "@equinor/eds-tokens": "0.9.2",
- "babel-jest": "^29.5.0"
+ "@babel/runtime": "^7.23.8",
+ "@equinor/eds-tokens": "0.9.2"
},
"engines": {
"node": ">=10.0.0",
@@ -1629,13 +1375,13 @@
}
},
"node_modules/@floating-ui/react": {
- "version": "0.25.2",
- "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.25.2.tgz",
- "integrity": "sha512-3e10G9LFOgl32/SMWLBOwT7oVCtB+d5zBsU2GxTSVOvRgZexwno5MlYbc0BaXr+TR5EEGpqe9tg9OUbjlrVRnQ==",
+ "version": "0.26.10",
+ "resolved": "https://registry.npmjs.org/@floating-ui/react/-/react-0.26.10.tgz",
+ "integrity": "sha512-sh6f9gVvWQdEzLObrWbJ97c0clJObiALsFe0LiR/kb3tDRKwEhObASEH2QyfdoO/ZBPzwxa9j+nYFo+sqgbioA==",
"dependencies": {
- "@floating-ui/react-dom": "^2.0.1",
- "@floating-ui/utils": "^0.1.1",
- "tabbable": "^6.0.1"
+ "@floating-ui/react-dom": "^2.0.0",
+ "@floating-ui/utils": "^0.2.0",
+ "tabbable": "^6.0.0"
},
"peerDependencies": {
"react": ">=16.8.0",
@@ -1654,6 +1400,11 @@
"react-dom": ">=16.8.0"
}
},
+ "node_modules/@floating-ui/react/node_modules/@floating-ui/utils": {
+ "version": "0.2.1",
+ "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.1.tgz",
+ "integrity": "sha512-9TANp6GPoMtYzQdt54kfAyMmz1+osLlXdg2ENroU7zzrtflTLrrC/lgrIfaSe+Wu0b89GKccT7vxXA0MoAIO+Q=="
+ },
"node_modules/@floating-ui/utils": {
"version": "0.1.1",
"resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.1.1.tgz",
@@ -1748,305 +1499,43 @@
"version": "7.1.0",
"resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz",
"integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==",
- "dev": true,
- "dependencies": {
- "ansi-regex": "^6.0.1"
- },
- "engines": {
- "node": ">=12"
- },
- "funding": {
- "url": "https://github.com/chalk/strip-ansi?sponsor=1"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/@istanbuljs/load-nyc-config/-/load-nyc-config-1.1.0.tgz",
- "integrity": "sha512-VjeHSlIzpv/NyD3N0YuHfXOPDIixcA1q2ZV98wsMqcYlPmv2n3Yb2lYP9XMElnaFVXg5A7YLTeLu6V84uQDjmQ==",
- "dependencies": {
- "camelcase": "^5.3.1",
- "find-up": "^4.1.0",
- "get-package-type": "^0.1.0",
- "js-yaml": "^3.13.1",
- "resolve-from": "^5.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/argparse": {
- "version": "1.0.10",
- "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz",
- "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==",
- "dependencies": {
- "sprintf-js": "~1.0.2"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/find-up": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/find-up/-/find-up-4.1.0.tgz",
- "integrity": "sha512-PpOwAdQ/YlXQ2vj8a3h8IipDuYRi3wceVQQGYWxNINccq40Anw7BlsEXCMbt1Zt+OLA6Fq9suIpIWD0OsnISlw==",
- "dependencies": {
- "locate-path": "^5.0.0",
- "path-exists": "^4.0.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/js-yaml": {
- "version": "3.14.1",
- "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.14.1.tgz",
- "integrity": "sha512-okMH7OXXJ7YrN9Ok3/SXrnu4iX9yOk+25nqX4imS2npuvTYDmo/QEZoqwZkYaIDk3jVvBOTOIEgEhaLOynBS9g==",
- "dependencies": {
- "argparse": "^1.0.7",
- "esprima": "^4.0.0"
- },
- "bin": {
- "js-yaml": "bin/js-yaml.js"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/locate-path": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
- "integrity": "sha512-t7hw9pI+WvuwNJXwk5zVHpyhIqzg2qTlklJOf0mVxGSbe3Fp2VieZcduNYjaLDoy6p9uGpQEGWG87WpMKlNq8g==",
- "dependencies": {
- "p-locate": "^4.1.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/p-limit": {
- "version": "2.3.0",
- "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz",
- "integrity": "sha512-//88mFWSJx8lxCzwdAABTJL2MyWB12+eIY7MDL2SqLmAkeKU9qxRvWuSyTjm3FUmpBEMuFfckAIqEaVGUDxb6w==",
- "dependencies": {
- "p-try": "^2.0.0"
- },
- "engines": {
- "node": ">=6"
- },
- "funding": {
- "url": "https://github.com/sponsors/sindresorhus"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/p-locate": {
- "version": "4.1.0",
- "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-4.1.0.tgz",
- "integrity": "sha512-R79ZZ/0wAxKGu3oYMlz8jy/kbhsNrS7SKZ7PxEHBgJ5+F2mtFW2fK2cOtBh1cHYkQsbzFV7I+EoRKe6Yt0oK7A==",
- "dependencies": {
- "p-limit": "^2.2.0"
- },
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@istanbuljs/load-nyc-config/node_modules/resolve-from": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-5.0.0.tgz",
- "integrity": "sha512-qYg9KP24dD5qka9J47d0aVky0N+b4fTU89LN9iDnjB5waksiC49rvMB0PrUJQGoTmH50XPiqOvAjDfaijGxYZw==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@istanbuljs/schema": {
- "version": "0.1.3",
- "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
- "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/@jest/schemas": {
- "version": "29.6.3",
- "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
- "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
- "dependencies": {
- "@sinclair/typebox": "^0.27.8"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/transform": {
- "version": "29.6.2",
- "resolved": "https://registry.npmjs.org/@jest/transform/-/transform-29.6.2.tgz",
- "integrity": "sha512-ZqCqEISr58Ce3U+buNFJYUktLJZOggfyvR+bZMaiV1e8B1SIvJbwZMrYz3gx/KAPn9EXmOmN+uB08yLCjWkQQg==",
- "dependencies": {
- "@babel/core": "^7.11.6",
- "@jest/types": "^29.6.1",
- "@jridgewell/trace-mapping": "^0.3.18",
- "babel-plugin-istanbul": "^6.1.1",
- "chalk": "^4.0.0",
- "convert-source-map": "^2.0.0",
- "fast-json-stable-stringify": "^2.1.0",
- "graceful-fs": "^4.2.9",
- "jest-haste-map": "^29.6.2",
- "jest-regex-util": "^29.4.3",
- "jest-util": "^29.6.2",
- "micromatch": "^4.0.4",
- "pirates": "^4.0.4",
- "slash": "^3.0.0",
- "write-file-atomic": "^4.0.2"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/transform/node_modules/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/@jest/transform/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/@jest/transform/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/@jest/transform/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/@jest/transform/node_modules/convert-source-map": {
- "version": "2.0.0",
- "resolved": "https://registry.npmjs.org/convert-source-map/-/convert-source-map-2.0.0.tgz",
- "integrity": "sha512-Kvp459HrV2FEJ1CAsi1Ku+MY3kasH19TFykTz2xWmMeq6bk2NU3XXvfJ+Q61m0xktWwt+1HSYf3JZsTms3aRJg=="
- },
- "node_modules/@jest/transform/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/@jest/transform/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/@jest/types": {
- "version": "29.6.1",
- "resolved": "https://registry.npmjs.org/@jest/types/-/types-29.6.1.tgz",
- "integrity": "sha512-tPKQNMPuXgvdOn2/Lg9HNfUvjYVGolt04Hp03f5hAk878uwOLikN+JzeLY0HcVgKgFl9Hs3EIqpu3WX27XNhnw==",
- "dependencies": {
- "@jest/schemas": "^29.6.0",
- "@types/istanbul-lib-coverage": "^2.0.0",
- "@types/istanbul-reports": "^3.0.0",
- "@types/node": "*",
- "@types/yargs": "^17.0.8",
- "chalk": "^4.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/@jest/types/node_modules/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/@jest/types/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "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/@jest/types/node_modules/color-convert": {
- "version": "2.0.1",
- "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
- "integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
+ "dev": true,
"dependencies": {
- "color-name": "~1.1.4"
+ "ansi-regex": "^6.0.1"
},
"engines": {
- "node": ">=7.0.0"
+ "node": ">=12"
+ },
+ "funding": {
+ "url": "https://github.com/chalk/strip-ansi?sponsor=1"
}
},
- "node_modules/@jest/types/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/@jest/types/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==",
+ "node_modules/@istanbuljs/schema": {
+ "version": "0.1.3",
+ "resolved": "https://registry.npmjs.org/@istanbuljs/schema/-/schema-0.1.3.tgz",
+ "integrity": "sha512-ZXRY4jNvVgSVQ8DL3LTcakaAtXwTVUxE81hslsyD2AtoXW/wVob10HkOJ1X/pAlcI7D+2YoZKg5do8G/w6RYgA==",
+ "dev": true,
"engines": {
"node": ">=8"
}
},
- "node_modules/@jest/types/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==",
+ "node_modules/@jest/schemas": {
+ "version": "29.6.3",
+ "resolved": "https://registry.npmjs.org/@jest/schemas/-/schemas-29.6.3.tgz",
+ "integrity": "sha512-mo5j5X+jIZmJQveBKeS/clAueipV7KgiX1vMgCxam1RNYiqE1w62n0/tJJnHtjW8ZHcQco5gY85jA3mi0L+nSA==",
+ "dev": true,
"dependencies": {
- "has-flag": "^4.0.0"
+ "@sinclair/typebox": "^0.27.8"
},
"engines": {
- "node": ">=8"
+ "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
}
},
"node_modules/@jridgewell/gen-mapping": {
"version": "0.3.3",
"resolved": "https://registry.npmjs.org/@jridgewell/gen-mapping/-/gen-mapping-0.3.3.tgz",
"integrity": "sha512-HLhSWOLRi875zjjMG/r+Nv0oCW8umGb0BgEhyX3dDX3egwZtB8PqLnjz3yedt8R5StBrzcg4aBpnh8UA9D1BoQ==",
+ "dev": true,
"dependencies": {
"@jridgewell/set-array": "^1.0.1",
"@jridgewell/sourcemap-codec": "^1.4.10",
@@ -2060,6 +1549,7 @@
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/@jridgewell/resolve-uri/-/resolve-uri-3.1.0.tgz",
"integrity": "sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==",
+ "dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -2068,6 +1558,7 @@
"version": "1.1.2",
"resolved": "https://registry.npmjs.org/@jridgewell/set-array/-/set-array-1.1.2.tgz",
"integrity": "sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==",
+ "dev": true,
"engines": {
"node": ">=6.0.0"
}
@@ -2075,12 +1566,14 @@
"node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.15",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.15.tgz",
- "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg=="
+ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==",
+ "dev": true
},
"node_modules/@jridgewell/trace-mapping": {
"version": "0.3.18",
"resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.18.tgz",
"integrity": "sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==",
+ "dev": true,
"dependencies": {
"@jridgewell/resolve-uri": "3.1.0",
"@jridgewell/sourcemap-codec": "1.4.14"
@@ -2089,7 +1582,8 @@
"node_modules/@jridgewell/trace-mapping/node_modules/@jridgewell/sourcemap-codec": {
"version": "1.4.14",
"resolved": "https://registry.npmjs.org/@jridgewell/sourcemap-codec/-/sourcemap-codec-1.4.14.tgz",
- "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw=="
+ "integrity": "sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==",
+ "dev": true
},
"node_modules/@jsdevtools/ono": {
"version": "7.1.3",
@@ -2098,15 +1592,15 @@
"dev": true
},
"node_modules/@loaders.gl/3d-tiles": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/3d-tiles/-/3d-tiles-3.4.8.tgz",
- "integrity": "sha512-v4Ejtp4Pb5RhFQyI37oDy9IZtBKEUZ+2xWNtyDgeV8Vni5ht532hsPVGY8CkUMMZFAyzl3zcDFUQo0cIbiqKKg==",
- "dependencies": {
- "@loaders.gl/draco": "3.4.8",
- "@loaders.gl/gltf": "3.4.8",
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/math": "3.4.8",
- "@loaders.gl/tiles": "3.4.8",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/3d-tiles/-/3d-tiles-3.4.15.tgz",
+ "integrity": "sha512-JR67bEfLrD7Lzb6pWyEIRg2L6W3n6y43DKcWofRLpwPqLA7qHuY7SlO7E72Lz7Tniye8VhawqY1wO8gCx8T72Q==",
+ "dependencies": {
+ "@loaders.gl/draco": "3.4.15",
+ "@loaders.gl/gltf": "3.4.15",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/math": "3.4.15",
+ "@loaders.gl/tiles": "3.4.15",
"@math.gl/core": "^3.5.1",
"@math.gl/geospatial": "^3.5.1",
"long": "^5.2.1"
@@ -2121,237 +1615,204 @@
"integrity": "sha512-lcHwpNoggQTObv5apGNCTdJrO69eHOZMi4BNC+rTLER8iHAqGrUVeLh/irVIM7zTw2bOXA8T6uNPeujwOLg/2Q=="
},
"node_modules/@loaders.gl/core": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/core/-/core-3.4.8.tgz",
- "integrity": "sha512-pAaAISNmxiUQn8iz0yDhX5DCt3geaaJtSTxAHgz25G2Z5kWqYS00g5bc7XIGNT2BwqD5pgVLRch+BdTQ/Q8lJA==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/core/-/core-3.4.15.tgz",
+ "integrity": "sha512-rPOOTuusWlRRNMWg7hymZBoFmPCXWThsA5ZYRfqqXnsgVeQIi8hzcAhJ7zDUIFAd/OSR8ravtqb0SH+3k6MOFQ==",
"dependencies": {
"@babel/runtime": "^7.3.1",
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/worker-utils": "3.4.8",
- "@probe.gl/log": "^4.0.1"
- }
- },
- "node_modules/@loaders.gl/core/node_modules/@probe.gl/env": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/@probe.gl/env/-/env-4.0.4.tgz",
- "integrity": "sha512-sYNGqesDfWD6dFP5oNZtTeFA4Z6ak5T4a8BNPdNhoqy7PK9w70JHrb6mv+RKWqKXq33KiwCDWL7fYxx2HuEH2w==",
- "dependencies": {
- "@babel/runtime": "^7.0.0"
- }
- },
- "node_modules/@loaders.gl/core/node_modules/@probe.gl/log": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/@probe.gl/log/-/log-4.0.4.tgz",
- "integrity": "sha512-WpmXl6njlBMwrm8HBh/b4kSp/xnY1VVmeT4PWUKF+RkVbFuKQbsU11dA1IxoMd7gSY+5DGIwxGfAv1H5OMzA4A==",
- "dependencies": {
- "@babel/runtime": "^7.0.0",
- "@probe.gl/env": "4.0.4"
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/worker-utils": "3.4.15",
+ "@probe.gl/log": "^3.5.0"
}
},
"node_modules/@loaders.gl/draco": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/draco/-/draco-3.4.8.tgz",
- "integrity": "sha512-x127QX/CCzbSXTk5IL4WBmL6RjvMZhedzMoEiWE4NhAEiwTFKXvWUZLluoFlGzJhxSL6xiR2KBF8tN1EMv4L1Q==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/draco/-/draco-3.4.15.tgz",
+ "integrity": "sha512-SStmyP0ZnS4JbWZb2NhrfiHW65uy3pVTTzQDTgXfkR5cD9oDAEu4nCaHbQ8x38/m39FHliCPgS9b1xWvLKQo8w==",
"dependencies": {
"@babel/runtime": "^7.3.1",
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/schema": "3.4.8",
- "@loaders.gl/worker-utils": "3.4.8",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/schema": "3.4.15",
+ "@loaders.gl/worker-utils": "3.4.15",
"draco3d": "1.5.5"
}
},
"node_modules/@loaders.gl/gis": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/gis/-/gis-3.4.8.tgz",
- "integrity": "sha512-I0Q8n1XhxXfZ6QoHvW6ayUkrOiifARGvSm4xTZxkydFNM5MULp9ICrZkFeqGMAVeevbssR3h9JKR111AmQvrPw==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/gis/-/gis-3.4.15.tgz",
+ "integrity": "sha512-h+LJI35P6ze8DFPSUylTKuml0l4HIfHMczML6u+ZXG6E2w5tbdM3Eh5AzHjXGQPuwUnaYPn3Mq/2t2N1rz98pg==",
"dependencies": {
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/schema": "3.4.8",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/schema": "3.4.15",
"@mapbox/vector-tile": "^1.3.1",
"@math.gl/polygon": "^3.5.1",
"pbf": "^3.2.1"
}
},
"node_modules/@loaders.gl/gltf": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/gltf/-/gltf-3.4.8.tgz",
- "integrity": "sha512-nvDj0LmkOXtQWUr7MkGShQ2WUmZlUnWTs6PatPxueevdL49vR16SB8VAWTx+8XUPq3Wno+gVZJxG8HBRkFVHng==",
- "dependencies": {
- "@loaders.gl/draco": "3.4.8",
- "@loaders.gl/images": "3.4.8",
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/textures": "3.4.8",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/gltf/-/gltf-3.4.15.tgz",
+ "integrity": "sha512-Y6kMNPLiHQPr6aWQw/4BMTxgPHWx3fcib4LPpZCbhyfM8PRn6pOqATVngUXdoOf5XY0QtdKVld6N1kxlr4pJtw==",
+ "dependencies": {
+ "@loaders.gl/draco": "3.4.15",
+ "@loaders.gl/images": "3.4.15",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/textures": "3.4.15",
"@math.gl/core": "^3.5.1"
}
},
"node_modules/@loaders.gl/images": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/images/-/images-3.4.8.tgz",
- "integrity": "sha512-cKoQ20aMBgBXYKVVJuDLuH1wTeXZyinbG4otSBf4D+gAhQ09Gd3dVMYF7RWIxXp0CdL4jiqGHnJ470y0AvrT4w==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/images/-/images-3.4.15.tgz",
+ "integrity": "sha512-QpjYhEetHabY/z9mWZYJXZZp4XJAxa38f9Ii/DjPlnJErepzY5GLBUTDHMu4oZ6n99gGImtuGFicDnFV6mb60g==",
"dependencies": {
- "@loaders.gl/loader-utils": "3.4.8"
+ "@loaders.gl/loader-utils": "3.4.15"
}
},
"node_modules/@loaders.gl/loader-utils": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/loader-utils/-/loader-utils-3.4.8.tgz",
- "integrity": "sha512-/3sZ2J3Y29t50HSo6X6mtLNDYID+s77cmFWxjq+R4/uDekYx2vmgiw/WCFbupKse6NrAKe1KgqEBac1Q7yARSQ==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/loader-utils/-/loader-utils-3.4.15.tgz",
+ "integrity": "sha512-uUx6tCaky6QgCRkqCNuuXiUfpTzKV+ZlJOf6C9bKp62lpvFOv9AwqoXmL23j8nfsENdlzsX3vPhc3en6QQyksA==",
"dependencies": {
"@babel/runtime": "^7.3.1",
- "@loaders.gl/worker-utils": "3.4.8",
- "@probe.gl/stats": "^4.0.1"
- }
- },
- "node_modules/@loaders.gl/loader-utils/node_modules/@probe.gl/stats": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-4.0.4.tgz",
- "integrity": "sha512-SDuSY/D4yDL6LQDa69l/GCcnZLRiGYdyvYkxWb0CgnzTPdPrcdrzGkzkvpC3zsA4fEFw2smlDje370QGHwlisg==",
- "dependencies": {
- "@babel/runtime": "^7.0.0"
+ "@loaders.gl/worker-utils": "3.4.15",
+ "@probe.gl/stats": "^3.5.0"
}
},
"node_modules/@loaders.gl/math": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/math/-/math-3.4.8.tgz",
- "integrity": "sha512-+9Hy1k44tj+v8IYKh+Zp0xXOijH94HoT/8ILdt5kG8MdjDU6VYyz2t/D4ZawSM+DBgXLYhDIIKkqrdND5ct2AQ==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/math/-/math-3.4.15.tgz",
+ "integrity": "sha512-zTN8BUU/1fcppyVc8WzvdZcCyNGVYmNinxcn/A+a7mi1ug4OBGwEsZOj09Wjg0/s52c/cAL3h9ylPIZdjntscQ==",
"dependencies": {
- "@loaders.gl/images": "3.4.8",
- "@loaders.gl/loader-utils": "3.4.8",
+ "@loaders.gl/images": "3.4.15",
+ "@loaders.gl/loader-utils": "3.4.15",
"@math.gl/core": "^3.5.1"
}
},
"node_modules/@loaders.gl/mvt": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/mvt/-/mvt-3.4.8.tgz",
- "integrity": "sha512-JvgSsg7+oypRAhGmUKvLSH8h146HRopxf25c9hzyPWX1MeAPfVWgwTou0syy5TwOyRlrLtGp4Rs/6AmNAWBtnw==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/mvt/-/mvt-3.4.15.tgz",
+ "integrity": "sha512-Q8e1ZyfNkJtPF/C4WSZ2qhWDEbzOvquP7OyG1NzQ2cp8R6eUfbexu48IgcnL/oAu8VPql3zIxQ+bQUyDReyN5g==",
"dependencies": {
- "@loaders.gl/gis": "3.4.8",
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/schema": "3.4.8",
+ "@loaders.gl/gis": "3.4.15",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/schema": "3.4.15",
"@math.gl/polygon": "^3.5.1",
"pbf": "^3.2.1"
}
},
"node_modules/@loaders.gl/schema": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-3.4.8.tgz",
- "integrity": "sha512-nu+mT8LgeoCF65xs+F9qegJsIWqYOzwkzJLEd7zmHGRMMYqaFDqcp63J3CUQy+UvS4dGTZph38aQuVfncS/fJA==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/schema/-/schema-3.4.15.tgz",
+ "integrity": "sha512-8oRtstz0IsqES7eZd2jQbmCnmExCMtL8T6jWd1+BfmnuyZnQ0B6TNccy++NHtffHdYuzEoQgSELwcdmhSApYew==",
"dependencies": {
"@types/geojson": "^7946.0.7"
}
},
"node_modules/@loaders.gl/terrain": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/terrain/-/terrain-3.4.8.tgz",
- "integrity": "sha512-bWLePOb6+4N8DNMXP0D3aqkwyU3phuUjzjQLvfoP9dySUuX4E9kwarCcmkaCYyqp2swp57cHaylSd6tHXOFR6w==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/terrain/-/terrain-3.4.15.tgz",
+ "integrity": "sha512-ouv41J84uOnLEtXLM+iPEPFfeq7aRgIOls6esdvhBx2/dXJRNkt8Mx0wShXAi8VNHz77D+gZFrKARa7wqjmftg==",
"dependencies": {
"@babel/runtime": "^7.3.1",
- "@loaders.gl/images": "3.4.8",
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/schema": "3.4.8",
+ "@loaders.gl/images": "3.4.15",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/schema": "3.4.15",
"@mapbox/martini": "^0.2.0"
}
},
"node_modules/@loaders.gl/textures": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/textures/-/textures-3.4.8.tgz",
- "integrity": "sha512-lFlV1/3yQqBANP5FoywuQwh+Br++BU3/6eT/Eb/zDbKOqTuqtHp7yAUz207tAO3mRqTkPvtKi9fv+0QrBGoxtw==",
- "dependencies": {
- "@loaders.gl/images": "3.4.8",
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/schema": "3.4.8",
- "@loaders.gl/worker-utils": "3.4.8",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/textures/-/textures-3.4.15.tgz",
+ "integrity": "sha512-QHnmxBYtLvTdG1uMz2KWcxVY8KPb1+XyPJUoZV9GMcQkulz+CwFB8BaX8nROfMDz9KKYoPfksCzjig0LZ0WBJQ==",
+ "dependencies": {
+ "@loaders.gl/images": "3.4.15",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/schema": "3.4.15",
+ "@loaders.gl/worker-utils": "3.4.15",
"ktx-parse": "^0.0.4",
"texture-compressor": "^1.0.2"
}
},
"node_modules/@loaders.gl/tiles": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/tiles/-/tiles-3.4.8.tgz",
- "integrity": "sha512-rA3ULOokiUTH6Y3sr37wGaTx3P0g/hRti9yB6q/8kSBy+fE1gSD801O4VluNx6DbOELR2zWkM8TqLTep6sBN1A==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/tiles/-/tiles-3.4.15.tgz",
+ "integrity": "sha512-o85aRSXq+YeVSK2ndW9aBwTMi5FhEsQ7k18J4DG+T5Oc+zz3tKui5X1SuBDiKbQN+kYtFpj0oYO1QG3ndNI6jg==",
"dependencies": {
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/math": "3.4.8",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/math": "3.4.15",
"@math.gl/core": "^3.5.1",
"@math.gl/culling": "^3.5.1",
"@math.gl/geospatial": "^3.5.1",
"@math.gl/web-mercator": "^3.5.1",
- "@probe.gl/stats": "^4.0.1"
+ "@probe.gl/stats": "^3.5.0"
},
"peerDependencies": {
"@loaders.gl/core": "^3.4.0"
}
},
- "node_modules/@loaders.gl/tiles/node_modules/@probe.gl/stats": {
- "version": "4.0.4",
- "resolved": "https://registry.npmjs.org/@probe.gl/stats/-/stats-4.0.4.tgz",
- "integrity": "sha512-SDuSY/D4yDL6LQDa69l/GCcnZLRiGYdyvYkxWb0CgnzTPdPrcdrzGkzkvpC3zsA4fEFw2smlDje370QGHwlisg==",
- "dependencies": {
- "@babel/runtime": "^7.0.0"
- }
- },
"node_modules/@loaders.gl/wms": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/wms/-/wms-3.4.8.tgz",
- "integrity": "sha512-4ESwVUa6dStmGqHIqdz6XFo/b/uyB6O+A1iy/mhMGTW8JodrzTcPQl5Iq8fA6EEYP0xviXFL652IEn+dR/BsGg==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/wms/-/wms-3.4.15.tgz",
+ "integrity": "sha512-zY++Oxx+cNGF9ptuSTFxCmEnpRbR5VZYjvyLraylaRbuynZv+JiWrehymFzEfq3hJcQ/cGvIjaG6rSVtPuqCIA==",
"dependencies": {
"@babel/runtime": "^7.3.1",
- "@loaders.gl/images": "3.4.8",
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/schema": "3.4.8",
- "@loaders.gl/xml": "3.4.8",
+ "@loaders.gl/images": "3.4.15",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/schema": "3.4.15",
+ "@loaders.gl/xml": "3.4.15",
"@turf/rewind": "^5.1.5",
"deep-strict-equal": "^0.2.0",
"lerc": "^4.0.1"
}
},
"node_modules/@loaders.gl/worker-utils": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/worker-utils/-/worker-utils-3.4.8.tgz",
- "integrity": "sha512-cioo1rKtUkbDPJVQZ5ytEc6r/LdR1eIOCszgRh1VymtYvWGT+prZxfCIAmM1uZBV2SLWYTnH17dR0PR+cNopzA==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/worker-utils/-/worker-utils-3.4.15.tgz",
+ "integrity": "sha512-zUUepOYRYmcYIcr/c4Mchox9h5fBFNkD81rsGnLlZyq19QvyHzN+93SVxrLc078gw93t2RKrVcOOZY13zT3t1w==",
"dependencies": {
"@babel/runtime": "^7.3.1"
}
},
"node_modules/@loaders.gl/xml": {
- "version": "3.4.8",
- "resolved": "https://registry.npmjs.org/@loaders.gl/xml/-/xml-3.4.8.tgz",
- "integrity": "sha512-8lrmdsnaobENpEPalEAzP720UY3kA/w6w7vCUKABB60QHnq+D5Rvw1PLPfQCACMFhYF+vR56KcQjtEbuqhs5wA==",
+ "version": "3.4.15",
+ "resolved": "https://registry.npmjs.org/@loaders.gl/xml/-/xml-3.4.15.tgz",
+ "integrity": "sha512-iMWHaDzYSe8JoS8W5k9IbxQ6S3VHPr7M+UBejIVeYGCp1jzWF0ri498olwJWWDRvg4kqAWolrkj8Pcgkg8Jf8A==",
"dependencies": {
"@babel/runtime": "^7.3.1",
- "@loaders.gl/loader-utils": "3.4.8",
- "@loaders.gl/schema": "3.4.8",
+ "@loaders.gl/loader-utils": "3.4.15",
+ "@loaders.gl/schema": "3.4.15",
"fast-xml-parser": "^4.2.5"
}
},
"node_modules/@luma.gl/constants": {
- "version": "8.5.20",
- "resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-8.5.20.tgz",
- "integrity": "sha512-5yG+ybkUZ4j6kLPWMZjN4Hun2yLB0MyEpNCRKAUN9/yS9UIWA7unyVxjSf2vnE7k/7dywtxlbXegASNFgNVGxw=="
+ "version": "8.5.21",
+ "resolved": "https://registry.npmjs.org/@luma.gl/constants/-/constants-8.5.21.tgz",
+ "integrity": "sha512-aJxayGxTT+IRd1vfpcgD/cKSCiVJjBNiuiChS96VulrmCvkzUOLvYXr42y5qKB4RyR7vOIda5uQprNzoHrhQAA=="
},
"node_modules/@luma.gl/core": {
- "version": "8.5.20",
- "resolved": "https://registry.npmjs.org/@luma.gl/core/-/core-8.5.20.tgz",
- "integrity": "sha512-xJr96G6vhYcznYHC84fbeOG3fgNM4lFwj9bd0VPcg/Kfe8otUeN1Hl0AKHCCtNn48PiMSg3LKbaiRfNUMhaffQ==",
+ "version": "8.5.21",
+ "resolved": "https://registry.npmjs.org/@luma.gl/core/-/core-8.5.21.tgz",
+ "integrity": "sha512-11jQJQEMoR/IN2oIsd4zFxiQJk6FE+xgVIMUcsCTBuzafTtQZ8Po9df8mt+MVewpDyBlTVs6g8nxHRH4np1ukA==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@luma.gl/constants": "8.5.20",
- "@luma.gl/engine": "8.5.20",
- "@luma.gl/gltools": "8.5.20",
- "@luma.gl/shadertools": "8.5.20",
- "@luma.gl/webgl": "8.5.20"
+ "@luma.gl/constants": "8.5.21",
+ "@luma.gl/engine": "8.5.21",
+ "@luma.gl/gltools": "8.5.21",
+ "@luma.gl/shadertools": "8.5.21",
+ "@luma.gl/webgl": "8.5.21"
}
},
"node_modules/@luma.gl/engine": {
- "version": "8.5.20",
- "resolved": "https://registry.npmjs.org/@luma.gl/engine/-/engine-8.5.20.tgz",
- "integrity": "sha512-+0ryJ/4gL1pWaEgZimY21jUPt1LYiO6Cqte8TNUprCfAHoAStsuzD7jwgEqnM6jJOUEdIxQ3w0z3Dzw/0KIE+w==",
+ "version": "8.5.21",
+ "resolved": "https://registry.npmjs.org/@luma.gl/engine/-/engine-8.5.21.tgz",
+ "integrity": "sha512-IG3WQSKXFNUEs8QG7ZjHtGiOtsakUu+BAxtJ6997A6/F06yynZ44tPe5NU70jG9Yfu3kV0LykPZg7hO3vXZDiA==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@luma.gl/constants": "8.5.20",
- "@luma.gl/gltools": "8.5.20",
- "@luma.gl/shadertools": "8.5.20",
- "@luma.gl/webgl": "8.5.20",
+ "@luma.gl/constants": "8.5.21",
+ "@luma.gl/gltools": "8.5.21",
+ "@luma.gl/shadertools": "8.5.21",
+ "@luma.gl/webgl": "8.5.21",
"@math.gl/core": "^3.5.0",
"@probe.gl/env": "^3.5.0",
"@probe.gl/stats": "^3.5.0",
@@ -2359,11 +1820,11 @@
}
},
"node_modules/@luma.gl/experimental": {
- "version": "8.5.20",
- "resolved": "https://registry.npmjs.org/@luma.gl/experimental/-/experimental-8.5.20.tgz",
- "integrity": "sha512-V1Jp68rYMPtwMdf+50r3NSYsGV3srjwZ+lcK2ew4DshjedDbYwLqTGMWcOyBhY3K3aCl2LH3Fhn0hAY+3NTLGA==",
+ "version": "8.5.21",
+ "resolved": "https://registry.npmjs.org/@luma.gl/experimental/-/experimental-8.5.21.tgz",
+ "integrity": "sha512-uFKPChGofyihOKxtqJy78QCQCDFnuMTK4QHrUX/qiTnvFSO8BgtTUevKvWGN9lBvq+uDD0lSieeF9yBzhQfAzw==",
"dependencies": {
- "@luma.gl/constants": "8.5.20",
+ "@luma.gl/constants": "8.5.21",
"@math.gl/core": "^3.5.0",
"earcut": "^2.0.6"
},
@@ -2377,34 +1838,34 @@
}
},
"node_modules/@luma.gl/gltools": {
- "version": "8.5.20",
- "resolved": "https://registry.npmjs.org/@luma.gl/gltools/-/gltools-8.5.20.tgz",
- "integrity": "sha512-5pP6ph9FSX5gHiVWQM1DmYRUnriklzKUG9yaqlQsKEqCFsOcKB0EfK3MfBVXIfsOdP/1bJZ9Dlz/zV19soWVhg==",
+ "version": "8.5.21",
+ "resolved": "https://registry.npmjs.org/@luma.gl/gltools/-/gltools-8.5.21.tgz",
+ "integrity": "sha512-6qZ0LaT2Mxa4AJT5F44TFoaziokYiHUwO45vnM/NYUOIu9xevcmS6VtToawytMEACGL6PDeDyVqP3Y80SDzq5g==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@luma.gl/constants": "8.5.20",
+ "@luma.gl/constants": "8.5.21",
"@probe.gl/env": "^3.5.0",
"@probe.gl/log": "^3.5.0",
"@types/offscreencanvas": "^2019.7.0"
}
},
"node_modules/@luma.gl/shadertools": {
- "version": "8.5.20",
- "resolved": "https://registry.npmjs.org/@luma.gl/shadertools/-/shadertools-8.5.20.tgz",
- "integrity": "sha512-q1lrCZy1ncIFb4mMjsYgISLzNP6eMnhLUY+Oltj/qjAMcPEssCeHN2+XGfP/CVtU+O7sC+5JY2bQGaTs6HQ/Qw==",
+ "version": "8.5.21",
+ "resolved": "https://registry.npmjs.org/@luma.gl/shadertools/-/shadertools-8.5.21.tgz",
+ "integrity": "sha512-WQah7yFDJ8cNCLPYpIm3r0wSlXLvjoA279fcknmATvvkW3/i8PcCJ/nYEBJO3hHEwwMQxD16+YZu/uwGiifLMg==",
"dependencies": {
"@babel/runtime": "^7.0.0",
"@math.gl/core": "^3.5.0"
}
},
"node_modules/@luma.gl/webgl": {
- "version": "8.5.20",
- "resolved": "https://registry.npmjs.org/@luma.gl/webgl/-/webgl-8.5.20.tgz",
- "integrity": "sha512-p/kt9KztywH4l+09XHoZ4cPFOoE7xlZXIBMT8rxRVgfe1w0lvi7QYh4tOG7gk+iixQ34EyDQacoHCsabdpmqQg==",
+ "version": "8.5.21",
+ "resolved": "https://registry.npmjs.org/@luma.gl/webgl/-/webgl-8.5.21.tgz",
+ "integrity": "sha512-ZVLO4W5UuaOlzZIwmFWhnmZ1gYoU97a+heMqxLrSSmCUAsSu3ZETUex9gOmzdM1WWxcdWaa3M68rvKCNEgwz0Q==",
"dependencies": {
"@babel/runtime": "^7.0.0",
- "@luma.gl/constants": "8.5.20",
- "@luma.gl/gltools": "8.5.20",
+ "@luma.gl/constants": "8.5.21",
+ "@luma.gl/gltools": "8.5.21",
"@probe.gl/env": "^3.5.0",
"@probe.gl/stats": "^3.5.0"
}
@@ -2456,14 +1917,6 @@
"resolved": "https://registry.npmjs.org/@mapbox/point-geometry/-/point-geometry-0.1.0.tgz",
"integrity": "sha512-6j56HdLTwWGO0fJPlrZtdU/B13q8Uwmo18Ck2GnGgN9PCFyKTZ3UbXeEdRFh18i9XQ92eH2VdtpJHpBD3aripQ=="
},
- "node_modules/@mapbox/tile-cover": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@mapbox/tile-cover/-/tile-cover-3.0.1.tgz",
- "integrity": "sha512-R8aoFY/87HWBOL9E2eBqzOY2lpfWYXCcTNgBpIxAv67rqQeD4IfnHD0iPXg/Z1cqXrklegEYZCp/7ZR/RsWqBQ==",
- "dependencies": {
- "tilebelt": "^1.0.1"
- }
- },
"node_modules/@mapbox/tiny-sdf": {
"version": "2.0.6",
"resolved": "https://registry.npmjs.org/@mapbox/tiny-sdf/-/tiny-sdf-2.0.6.tgz",
@@ -4134,12 +3587,13 @@
"node_modules/@sinclair/typebox": {
"version": "0.27.8",
"resolved": "https://registry.npmjs.org/@sinclair/typebox/-/typebox-0.27.8.tgz",
- "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA=="
+ "integrity": "sha512-+Fj43pSMwJs4KRrH/938Uf+uAELIgVBmQzg/q1YG10djyfA3TnrU8N8XzqCh/okZdszqBQTZf96idMfE5lnwTA==",
+ "dev": true
},
"node_modules/@tanstack/query-core": {
- "version": "5.0.5",
- "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.0.5.tgz",
- "integrity": "sha512-MThCETMkHDHTnFZHp71L+SqTtD5d6XHftFCVR1xRJdWM3qGrlQ2VCXaj0SKVcyJej2e1Opa2c7iknu1llxCDNQ==",
+ "version": "5.17.19",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.17.19.tgz",
+ "integrity": "sha512-Lzw8FUtnLCc9Jwz0sw9xOjZB+/mCCmJev38v2wHMUl/ioXNIhnNWeMxu0NKUjIhAd62IRB3eAtvxAGDJ55UkyA==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
@@ -4196,25 +3650,35 @@
"react-dom": "^18.0.0"
}
},
+ "node_modules/@tanstack/react-query/node_modules/@tanstack/query-core": {
+ "version": "5.0.5",
+ "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.0.5.tgz",
+ "integrity": "sha512-MThCETMkHDHTnFZHp71L+SqTtD5d6XHftFCVR1xRJdWM3qGrlQ2VCXaj0SKVcyJej2e1Opa2c7iknu1llxCDNQ==",
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/tannerlinsley"
+ }
+ },
"node_modules/@tanstack/react-virtual": {
- "version": "3.0.0-beta.54",
- "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.0.0-beta.54.tgz",
- "integrity": "sha512-D1mDMf4UPbrtHRZZriCly5bXTBMhylslm4dhcHqTtDJ6brQcgGmk8YD9JdWBGWfGSWPKoh2x1H3e7eh+hgPXtQ==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.1.3.tgz",
+ "integrity": "sha512-YCzcbF/Ws/uZ0q3Z6fagH+JVhx4JLvbSflgldMgLsuvB8aXjZLLb3HvrEVxY480F9wFlBiXlvQxOyXb5ENPrNA==",
"dependencies": {
- "@tanstack/virtual-core": "3.0.0-beta.54"
+ "@tanstack/virtual-core": "3.1.3"
},
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
},
"peerDependencies": {
- "react": "^16.8.0 || ^17.0.0 || ^18.0.0"
+ "react": "^16.8.0 || ^17.0.0 || ^18.0.0",
+ "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0"
}
},
"node_modules/@tanstack/virtual-core": {
- "version": "3.0.0-beta.54",
- "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.0.0-beta.54.tgz",
- "integrity": "sha512-jtkwqdP2rY2iCCDVAFuaNBH3fiEi29aTn2RhtIoky8DTTiCdc48plpHHreLwmv1PICJ4AJUUESaq3xa8fZH8+g==",
+ "version": "3.1.3",
+ "resolved": "https://registry.npmjs.org/@tanstack/virtual-core/-/virtual-core-3.1.3.tgz",
+ "integrity": "sha512-Y5B4EYyv1j9V8LzeAoOVeTg0LI7Fo5InYKgAjkY1Pu9GjtUwX/EKxNcU7ng3sKr99WEf+bPTcktAeybyMOYo+g==",
"funding": {
"type": "github",
"url": "https://github.com/sponsors/tannerlinsley"
@@ -4820,6 +4284,7 @@
"version": "7.20.5",
"resolved": "https://registry.npmjs.org/@types/babel__core/-/babel__core-7.20.5.tgz",
"integrity": "sha512-qoQprZvz5wQFJwMDqeseRXWv3rqMvhgpbXFfVyWhbx9X47POIA6i/+dXefEmZKoAgOaTdaIgNSMqMIU61yRyzA==",
+ "dev": true,
"dependencies": {
"@babel/parser": "^7.20.7",
"@babel/types": "^7.20.7",
@@ -4832,6 +4297,7 @@
"version": "7.6.4",
"resolved": "https://registry.npmjs.org/@types/babel__generator/-/babel__generator-7.6.4.tgz",
"integrity": "sha512-tFkciB9j2K755yrTALxD44McOrk+gfpIpvC3sxHjRawj6PfnQxrse4Clq5y/Rq+G3mrBurMax/lG8Qn2t9mSsg==",
+ "dev": true,
"dependencies": {
"@babel/types": "^7.0.0"
}
@@ -4840,6 +4306,7 @@
"version": "7.4.1",
"resolved": "https://registry.npmjs.org/@types/babel__template/-/babel__template-7.4.1.tgz",
"integrity": "sha512-azBFKemX6kMg5Io+/rdGT0dkGreboUVR0Cdm3fz9QJWpaQGJRQXl7C+6hOTCZcMll7KFyEQpgbYI2lHdsS4U7g==",
+ "dev": true,
"dependencies": {
"@babel/parser": "^7.1.0",
"@babel/types": "^7.0.0"
@@ -4849,6 +4316,7 @@
"version": "7.20.1",
"resolved": "https://registry.npmjs.org/@types/babel__traverse/-/babel__traverse-7.20.1.tgz",
"integrity": "sha512-MitHFXnhtgwsGZWtT68URpOvLN4EREih1u3QtQiN4VdAxWKRVvGCSvw/Qth0M0Qq3pJpnGOu5JaM/ydK7OGbqg==",
+ "dev": true,
"dependencies": {
"@babel/types": "^7.20.7"
}
@@ -4882,14 +4350,6 @@
"resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.10.tgz",
"integrity": "sha512-Nmh0K3iWQJzniTuPRcJn5hxXkfB1T1pgB89SBig5PlJQU5yocazeu4jATJlaA0GYFKWMqDdvYemoSnF2pXgLVA=="
},
- "node_modules/@types/graceful-fs": {
- "version": "4.1.6",
- "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.6.tgz",
- "integrity": "sha512-Sig0SNORX9fdW+bQuTEovKj3uHcUL6LQKbCrrqb1X7J6/ReAbhCXRAhc+SMejhLELFj2QcyuxmUooZ4bt5ReSw==",
- "dependencies": {
- "@types/node": "*"
- }
- },
"node_modules/@types/hammerjs": {
"version": "2.0.41",
"resolved": "https://registry.npmjs.org/@types/hammerjs/-/hammerjs-2.0.41.tgz",
@@ -4904,27 +4364,6 @@
"hoist-non-react-statics": "^3.3.0"
}
},
- "node_modules/@types/istanbul-lib-coverage": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-coverage/-/istanbul-lib-coverage-2.0.4.tgz",
- "integrity": "sha512-z/QT1XN4K4KYuslS23k62yDIDLwLFkzxOuMplDtObz0+y7VqJCaO2o+SPwHCvLFZh7xazvvoor2tA/hPz9ee7g=="
- },
- "node_modules/@types/istanbul-lib-report": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/@types/istanbul-lib-report/-/istanbul-lib-report-3.0.0.tgz",
- "integrity": "sha512-plGgXAPfVKFoYfa9NpYDAkseG+g6Jr294RqeqcqDixSbU34MZVJRi/P+7Y8GDpzkEwLaGZZOpKIEmeVZNtKsrg==",
- "dependencies": {
- "@types/istanbul-lib-coverage": "*"
- }
- },
- "node_modules/@types/istanbul-reports": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/@types/istanbul-reports/-/istanbul-reports-3.0.1.tgz",
- "integrity": "sha512-c3mAZEuK0lvBp8tmuL74XRKn1+y2dcwOUpH7x4WrF6gk1GIgiluDRgMYQtw2OFcBvAJWlt6ASU3tSqxp0Uu0Aw==",
- "dependencies": {
- "@types/istanbul-lib-report": "*"
- }
- },
"node_modules/@types/json-schema": {
"version": "7.0.15",
"resolved": "https://registry.npmjs.org/@types/json-schema/-/json-schema-7.0.15.tgz",
@@ -4961,18 +4400,11 @@
"@types/lodash": "*"
}
},
- "node_modules/@types/mapbox-gl": {
- "version": "2.7.12",
- "resolved": "https://registry.npmjs.org/@types/mapbox-gl/-/mapbox-gl-2.7.12.tgz",
- "integrity": "sha512-aEMMOWlSTn2lp0liLqHsI/vAkV8858mkhn4fFYZELdLO1o6PEKCkkUfQ/GBp603Xfc3xmasLZsoELJBbje+atw==",
- "dependencies": {
- "@types/geojson": "*"
- }
- },
"node_modules/@types/node": {
"version": "18.17.1",
"resolved": "https://registry.npmjs.org/@types/node/-/node-18.17.1.tgz",
- "integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw=="
+ "integrity": "sha512-xlR1jahfizdplZYRU59JlUx9uzF1ARa8jbhM11ccpCJya8kvos5jwdm2ZAgxSCwOl0fq21svP18EVwPBXMQudw==",
+ "dev": true
},
"node_modules/@types/offscreencanvas": {
"version": "2019.7.0",
@@ -5052,6 +4484,12 @@
"integrity": "sha512-dn1l8LaMea/IjDoHNd9J52uBbInB796CDffS6VdIxvqYCPSG0V0DzHp76GpaWnlhg88uYyPbXCDIowa86ybd5A==",
"dev": true
},
+ "node_modules/@types/stylis": {
+ "version": "4.2.0",
+ "resolved": "https://registry.npmjs.org/@types/stylis/-/stylis-4.2.0.tgz",
+ "integrity": "sha512-n4sx2bqL0mW1tvDf/loQ+aMX7GQD3lc3fkCMC55VFNDu/vBOabO+LTIeXKM14xK0ppk5TUGcWRjiSpIlUpghKw==",
+ "peer": true
+ },
"node_modules/@types/use-sync-external-store": {
"version": "0.0.3",
"resolved": "https://registry.npmjs.org/@types/use-sync-external-store/-/use-sync-external-store-0.0.3.tgz",
@@ -5063,19 +4501,6 @@
"integrity": "sha512-kNnC1GFBLuhImSnV7w4njQkUiJi0ZXUycu1rUaouPqiKlXkh77JKgdRnTAp1x5eBwcIwbtI+3otwzuIDEuDoxQ==",
"dev": true
},
- "node_modules/@types/yargs": {
- "version": "17.0.24",
- "resolved": "https://registry.npmjs.org/@types/yargs/-/yargs-17.0.24.tgz",
- "integrity": "sha512-6i0aC7jV6QzQB8ne1joVZ0eSFIstHsCrobmOtghM11yGlH0j43FKL2UhWdELkyps0zuf7qVTUVCCR+tgSlyLLw==",
- "dependencies": {
- "@types/yargs-parser": "*"
- }
- },
- "node_modules/@types/yargs-parser": {
- "version": "21.0.0",
- "resolved": "https://registry.npmjs.org/@types/yargs-parser/-/yargs-parser-21.0.0.tgz",
- "integrity": "sha512-iO9ZQHkZxHn4mSakYV0vFHAVDyEOIJQrV2uZ06HxEPcx+mt8swXoZHIbaaJ2crJYFfErySgktuTZ3BeLz+XmFA=="
- },
"node_modules/@typescript-eslint/eslint-plugin": {
"version": "6.21.0",
"resolved": "https://registry.npmjs.org/@typescript-eslint/eslint-plugin/-/eslint-plugin-6.21.0.tgz",
@@ -5585,29 +5010,36 @@
}
},
"node_modules/@webviz/subsurface-viewer": {
- "version": "0.3.1",
- "resolved": "https://registry.npmjs.org/@webviz/subsurface-viewer/-/subsurface-viewer-0.3.1.tgz",
- "integrity": "sha512-1sfL50xZIn+Jub/Xkv9kJ+d2x4rpOzj2rIIoWlV1AI4SVRhT1jseQUtrM9AOnraB53USYeZZl22T7xp94zmNVA==",
- "dependencies": {
- "@deck.gl/core": "^8.8.25",
- "@emerson-eps/color-tables": "^0.4.61",
- "@equinor/eds-core-react": "^0.32.3",
- "@equinor/eds-icons": "^0.19.1",
+ "version": "0.21.0",
+ "resolved": "https://registry.npmjs.org/@webviz/subsurface-viewer/-/subsurface-viewer-0.21.0.tgz",
+ "integrity": "sha512-tX2H8C/H05EcY/DABnIWL2FxfeN4n2ALDy08MgYCs8gXnEHSTGaNSQExMnOL4xmYh5egEV21BkXZAXcKFFAjSQ==",
+ "dependencies": {
+ "@deck.gl/aggregation-layers": "^8.9.35",
+ "@deck.gl/core": "^8.9.35",
+ "@deck.gl/extensions": "^8.9.35",
+ "@deck.gl/geo-layers": "^8.9.35",
+ "@deck.gl/json": "^8.9.35",
+ "@deck.gl/layers": "^8.9.35",
+ "@deck.gl/mesh-layers": "^8.9.35",
+ "@deck.gl/react": "^8.9.35",
+ "@emerson-eps/color-tables": "^0.4.71",
+ "@equinor/eds-core-react": "^0.36.0",
+ "@equinor/eds-icons": "^0.21.0",
"@nebula.gl/layers": "^1.0.4",
"@reduxjs/toolkit": "^1.7.2",
"@turf/simplify": "^6.5.0",
"@vivaxy/png": "^1.3.0",
"@webviz/wsc-common": "*",
- "ajv": "^7.2.1",
+ "ajv": "^8.12.0",
"convert-units": "^2.3.4",
"d3": "^7.8.2",
"d3-color": "^3.1.0",
- "d3-format": "^1.4.5",
- "deck.gl": "^8.9.19",
+ "d3-format": "^3.1.0",
"gl-matrix": "^3.4.3",
"lodash": "^4.17.21",
- "mathjs": "^9.4.2",
- "react-redux": "^8.1.1"
+ "mathjs": "^12.4.1",
+ "react-redux": "^8.1.1",
+ "workerpool": "^9.1.0"
},
"peerDependencies": {
"@mui/material": "^5.11",
@@ -5616,6 +5048,29 @@
"react-dom": "^17 || ^18"
}
},
+ "node_modules/@webviz/subsurface-viewer/node_modules/ajv": {
+ "version": "8.12.0",
+ "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.12.0.tgz",
+ "integrity": "sha512-sRu1kpcO9yLtYxBKvqfTeh9KzZEwO3STyX1HT+4CaDzC6HpTGYhIhPIzj9XuKU7KYDwnaeh5hcOwjy1QuJzBPA==",
+ "dependencies": {
+ "fast-deep-equal": "^3.1.1",
+ "json-schema-traverse": "^1.0.0",
+ "require-from-string": "^2.0.2",
+ "uri-js": "^4.2.2"
+ },
+ "funding": {
+ "type": "github",
+ "url": "https://github.com/sponsors/epoberezkin"
+ }
+ },
+ "node_modules/@webviz/subsurface-viewer/node_modules/d3-format": {
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
+ "integrity": "sha512-YyUI6AEuY/Wpt8KWLgZHsIU86atmikuoOmCfommt0LYHiQSPjvX2AcFc38PX0CBpr2RCyZhjex+NS/LPOv6YqA==",
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/@webviz/well-completions-plot": {
"version": "0.0.1-alpha.1",
"resolved": "https://registry.npmjs.org/@webviz/well-completions-plot/-/well-completions-plot-0.0.1-alpha.1.tgz",
@@ -5758,6 +5213,7 @@
"version": "3.1.3",
"resolved": "https://registry.npmjs.org/anymatch/-/anymatch-3.1.3.tgz",
"integrity": "sha512-KMReFUr0B4t+D+OBkjR3KYqvocp2XaSzO55UcB6mgQMd3KbcE+mWTyvVV7D/zsdEbNnV6acZUutkiHQXvTr1Rw==",
+ "dev": true,
"dependencies": {
"normalize-path": "^3.0.0",
"picomatch": "^2.0.4"
@@ -5941,188 +5397,75 @@
},
"funding": {
"url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/assertion-error": {
- "version": "1.1.0",
- "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
- "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
- "dev": true,
- "engines": {
- "node": "*"
- }
- },
- "node_modules/asynckit": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
- "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
- },
- "node_modules/autoprefixer": {
- "version": "10.4.14",
- "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
- "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==",
- "dev": true,
- "funding": [
- {
- "type": "opencollective",
- "url": "https://opencollective.com/postcss/"
- },
- {
- "type": "tidelift",
- "url": "https://tidelift.com/funding/github/npm/autoprefixer"
- }
- ],
- "dependencies": {
- "browserslist": "^4.21.5",
- "caniuse-lite": "^1.0.30001464",
- "fraction.js": "^4.2.0",
- "normalize-range": "^0.1.2",
- "picocolors": "^1.0.0",
- "postcss-value-parser": "^4.2.0"
- },
- "bin": {
- "autoprefixer": "bin/autoprefixer"
- },
- "engines": {
- "node": "^10 || ^12 || >=14"
- },
- "peerDependencies": {
- "postcss": "^8.1.0"
- }
- },
- "node_modules/available-typed-arrays": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
- "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
- "dev": true,
- "engines": {
- "node": ">= 0.4"
- },
- "funding": {
- "url": "https://github.com/sponsors/ljharb"
- }
- },
- "node_modules/axios": {
- "version": "1.6.5",
- "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
- "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
- "dependencies": {
- "follow-redirects": "^1.15.4",
- "form-data": "^4.0.0",
- "proxy-from-env": "^1.1.0"
- }
- },
- "node_modules/babel-jest": {
- "version": "29.6.2",
- "resolved": "https://registry.npmjs.org/babel-jest/-/babel-jest-29.6.2.tgz",
- "integrity": "sha512-BYCzImLos6J3BH/+HvUCHG1dTf2MzmAB4jaVxHV+29RZLjR29XuYTmsf2sdDwkrb+FczkGo3kOhE7ga6sI0P4A==",
- "dependencies": {
- "@jest/transform": "^29.6.2",
- "@types/babel__core": "^7.1.14",
- "babel-plugin-istanbul": "^6.1.1",
- "babel-preset-jest": "^29.5.0",
- "chalk": "^4.0.0",
- "graceful-fs": "^4.2.9",
- "slash": "^3.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.8.0"
- }
- },
- "node_modules/babel-jest/node_modules/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/babel-jest/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/babel-jest/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/babel-jest/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/babel-jest/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==",
+ }
+ },
+ "node_modules/assertion-error": {
+ "version": "1.1.0",
+ "resolved": "https://registry.npmjs.org/assertion-error/-/assertion-error-1.1.0.tgz",
+ "integrity": "sha512-jgsaNduz+ndvGyFt3uSuWqvy4lCnIJiovtouQN5JZHOKCS2QuhEdbcQHFhVksz2N2U9hXJo8odG7ETyWlEeuDw==",
+ "dev": true,
"engines": {
- "node": ">=8"
+ "node": "*"
}
},
- "node_modules/babel-jest/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==",
+ "node_modules/asynckit": {
+ "version": "0.4.0",
+ "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz",
+ "integrity": "sha512-Oei9OH4tRh0YqU3GxhX79dM/mwVgvbZJaSNaRk+bshkj0S5cfHcgYakreBjrHwatXKbz+IoIdYLxrKim2MjW0Q=="
+ },
+ "node_modules/autoprefixer": {
+ "version": "10.4.14",
+ "resolved": "https://registry.npmjs.org/autoprefixer/-/autoprefixer-10.4.14.tgz",
+ "integrity": "sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==",
+ "dev": true,
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/autoprefixer"
+ }
+ ],
"dependencies": {
- "has-flag": "^4.0.0"
+ "browserslist": "^4.21.5",
+ "caniuse-lite": "^1.0.30001464",
+ "fraction.js": "^4.2.0",
+ "normalize-range": "^0.1.2",
+ "picocolors": "^1.0.0",
+ "postcss-value-parser": "^4.2.0"
+ },
+ "bin": {
+ "autoprefixer": "bin/autoprefixer"
},
"engines": {
- "node": ">=8"
+ "node": "^10 || ^12 || >=14"
+ },
+ "peerDependencies": {
+ "postcss": "^8.1.0"
}
},
- "node_modules/babel-plugin-istanbul": {
- "version": "6.1.1",
- "resolved": "https://registry.npmjs.org/babel-plugin-istanbul/-/babel-plugin-istanbul-6.1.1.tgz",
- "integrity": "sha512-Y1IQok9821cC9onCx5otgFfRm7Lm+I+wwxOx738M/WLPZ9Q42m4IG5W0FNX8WLL2gYMZo3JkuXIH2DOpWM+qwA==",
- "dependencies": {
- "@babel/helper-plugin-utils": "^7.0.0",
- "@istanbuljs/load-nyc-config": "^1.0.0",
- "@istanbuljs/schema": "^0.1.2",
- "istanbul-lib-instrument": "^5.0.4",
- "test-exclude": "^6.0.0"
- },
+ "node_modules/available-typed-arrays": {
+ "version": "1.0.5",
+ "resolved": "https://registry.npmjs.org/available-typed-arrays/-/available-typed-arrays-1.0.5.tgz",
+ "integrity": "sha512-DMD0KiN46eipeziST1LPP/STfDU0sufISXmjSgvVsoU2tqxctQeASejWcfNtxYKqETM1UxQ8sp2OrSBWpHY6sw==",
+ "dev": true,
"engines": {
- "node": ">=8"
+ "node": ">= 0.4"
+ },
+ "funding": {
+ "url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/babel-plugin-jest-hoist": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/babel-plugin-jest-hoist/-/babel-plugin-jest-hoist-29.5.0.tgz",
- "integrity": "sha512-zSuuuAlTMT4mzLj2nPnUm6fsE6270vdOfnpbJ+RmruU75UhLFvL0N2NgI7xpeS7NaB6hGqmd5pVpGTDYvi4Q3w==",
+ "node_modules/axios": {
+ "version": "1.6.5",
+ "resolved": "https://registry.npmjs.org/axios/-/axios-1.6.5.tgz",
+ "integrity": "sha512-Ii012v05KEVuUoFWmMW/UQv9aRIc3ZwkWDcM+h5Il8izZCtRVpDUfwpoFf7eOtajT3QiGR4yDUx7lPqHJULgbg==",
"dependencies": {
- "@babel/template": "^7.3.3",
- "@babel/types": "^7.3.3",
- "@types/babel__core": "^7.1.14",
- "@types/babel__traverse": "^7.0.6"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
+ "follow-redirects": "^1.15.4",
+ "form-data": "^4.0.0",
+ "proxy-from-env": "^1.1.0"
}
},
"node_modules/babel-plugin-macros": {
@@ -6139,63 +5482,11 @@
"npm": ">=6"
}
},
- "node_modules/babel-plugin-styled-components": {
- "version": "2.1.4",
- "resolved": "https://registry.npmjs.org/babel-plugin-styled-components/-/babel-plugin-styled-components-2.1.4.tgz",
- "integrity": "sha512-Xgp9g+A/cG47sUyRwwYxGM4bR/jDRg5N6it/8+HxCnbT5XNKSKDT9xm4oag/osgqjC2It/vH0yXsomOG6k558g==",
- "peer": true,
- "dependencies": {
- "@babel/helper-annotate-as-pure": "^7.22.5",
- "@babel/helper-module-imports": "^7.22.5",
- "@babel/plugin-syntax-jsx": "^7.22.5",
- "lodash": "^4.17.21",
- "picomatch": "^2.3.1"
- },
- "peerDependencies": {
- "styled-components": ">= 2"
- }
- },
- "node_modules/babel-preset-current-node-syntax": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/babel-preset-current-node-syntax/-/babel-preset-current-node-syntax-1.0.1.tgz",
- "integrity": "sha512-M7LQ0bxarkxQoN+vz5aJPsLBn77n8QgTFmo8WK0/44auK2xlCXrYcUxHFxgU7qW5Yzw/CjmLRK2uJzaCd7LvqQ==",
- "dependencies": {
- "@babel/plugin-syntax-async-generators": "^7.8.4",
- "@babel/plugin-syntax-bigint": "^7.8.3",
- "@babel/plugin-syntax-class-properties": "^7.8.3",
- "@babel/plugin-syntax-import-meta": "^7.8.3",
- "@babel/plugin-syntax-json-strings": "^7.8.3",
- "@babel/plugin-syntax-logical-assignment-operators": "^7.8.3",
- "@babel/plugin-syntax-nullish-coalescing-operator": "^7.8.3",
- "@babel/plugin-syntax-numeric-separator": "^7.8.3",
- "@babel/plugin-syntax-object-rest-spread": "^7.8.3",
- "@babel/plugin-syntax-optional-catch-binding": "^7.8.3",
- "@babel/plugin-syntax-optional-chaining": "^7.8.3",
- "@babel/plugin-syntax-top-level-await": "^7.8.3"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
- "node_modules/babel-preset-jest": {
- "version": "29.5.0",
- "resolved": "https://registry.npmjs.org/babel-preset-jest/-/babel-preset-jest-29.5.0.tgz",
- "integrity": "sha512-JOMloxOqdiBSxMAzjRaH023/vvcaSaec49zvg+2LmNsktC7ei39LTJGw02J+9uUtTZUq6xbLyJ4dxe9sSmIuAg==",
- "dependencies": {
- "babel-plugin-jest-hoist": "^29.5.0",
- "babel-preset-current-node-syntax": "^1.0.0"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "peerDependencies": {
- "@babel/core": "^7.0.0"
- }
- },
"node_modules/balanced-match": {
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.2.tgz",
- "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw=="
+ "integrity": "sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==",
+ "dev": true
},
"node_modules/binary-extensions": {
"version": "2.2.0",
@@ -6238,6 +5529,7 @@
"version": "1.1.11",
"resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz",
"integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==",
+ "dev": true,
"dependencies": {
"balanced-match": "^1.0.0",
"concat-map": "0.0.1"
@@ -6247,6 +5539,7 @@
"version": "3.0.2",
"resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz",
"integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==",
+ "dev": true,
"dependencies": {
"fill-range": "^7.0.1"
},
@@ -6258,6 +5551,7 @@
"version": "4.22.2",
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.22.2.tgz",
"integrity": "sha512-0UgcrvQmBDvZHFGdYUehrCNIazki7/lUP3kkoi/r3YB2amZbFM9J43ZRkJTXBUZK4gmx56+Sqk9+Vs9mwZx9+A==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -6285,14 +5579,6 @@
"node": "^6 || ^7 || ^8 || ^9 || ^10 || ^11 || ^12 || >=13.7"
}
},
- "node_modules/bser": {
- "version": "2.1.1",
- "resolved": "https://registry.npmjs.org/bser/-/bser-2.1.1.tgz",
- "integrity": "sha512-gQxTNE/GAfIIrmHLUE3oJyp5FO6HRBfhjnw4/wMmA63ZGDJnWBmgY/lyQBpnDUkGmAhbSe39tx2d/iTOAfglwQ==",
- "dependencies": {
- "node-int64": "^0.4.0"
- }
- },
"node_modules/buf-compare": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/buf-compare/-/buf-compare-1.0.1.tgz",
@@ -6336,14 +5622,6 @@
"node": ">=6"
}
},
- "node_modules/camelcase": {
- "version": "5.3.1",
- "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
- "integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg==",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/camelcase-css": {
"version": "2.0.1",
"resolved": "https://registry.npmjs.org/camelcase-css/-/camelcase-css-2.0.1.tgz",
@@ -6366,6 +5644,7 @@
"version": "1.0.30001572",
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001572.tgz",
"integrity": "sha512-1Pbh5FLmn5y4+QhNyJE9j3/7dK44dGB83/ZMjv/qJk86TvDbjk0LosiZo0i0WB0Vx607qMX9jYrn1VLHCkN4rw==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -6390,14 +5669,6 @@
"element-size": "^1.1.1"
}
},
- "node_modules/cartocolor": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/cartocolor/-/cartocolor-4.0.2.tgz",
- "integrity": "sha512-+Gh9mb6lFxsDOLQlBLPxAHCnWXlg2W8q3AcVwqRcy95TdBbcOU89Wrb6h2Hd/6Ww1Kc1pzXmUdpnWD+xeCG0dg==",
- "dependencies": {
- "colorbrewer": "1.0.0"
- }
- },
"node_modules/chai": {
"version": "4.4.0",
"resolved": "https://registry.npmjs.org/chai/-/chai-4.4.0.tgz",
@@ -6488,20 +5759,6 @@
"node": ">= 6"
}
},
- "node_modules/ci-info": {
- "version": "3.8.0",
- "resolved": "https://registry.npmjs.org/ci-info/-/ci-info-3.8.0.tgz",
- "integrity": "sha512-eXTggHWSooYhq49F2opQhuHWgzucfF2YgODK4e1566GQs5BIfP30B0oenwBJHfWxAs2fyPB1s7Mg949zLf61Yw==",
- "funding": [
- {
- "type": "github",
- "url": "https://github.com/sponsors/sibiraj-s"
- }
- ],
- "engines": {
- "node": ">=8"
- }
- },
"node_modules/clamp": {
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/clamp/-/clamp-1.0.1.tgz",
@@ -6595,11 +5852,6 @@
"mumath": "^3.3.4"
}
},
- "node_modules/colorbrewer": {
- "version": "1.0.0",
- "resolved": "https://registry.npmjs.org/colorbrewer/-/colorbrewer-1.0.0.tgz",
- "integrity": "sha512-NZuIOVdErK/C6jDH3jWT/roxWJbJAinMiqEpbuWniKvQAoWdg6lGra3pPrSHvaIf8PlX8wLs/RAC6nULFJbgmg=="
- },
"node_modules/combined-stream": {
"version": "1.0.8",
"resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.8.tgz",
@@ -6612,12 +5864,9 @@
}
},
"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"
- }
+ "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/complex.js": {
"version": "2.1.1",
@@ -6632,14 +5881,15 @@
}
},
"node_modules/compute-scroll-into-view": {
- "version": "2.0.4",
- "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-2.0.4.tgz",
- "integrity": "sha512-y/ZA3BGnxoM/QHHQ2Uy49CLtnWPbt4tTPpEEZiEmmiWBFKjej7nEyH8Ryz54jH0MLXflUYA3Er2zUxPSJu5R+g=="
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/compute-scroll-into-view/-/compute-scroll-into-view-3.1.0.tgz",
+ "integrity": "sha512-rj8l8pD4bJ1nx+dAkMhV1xB5RuZEyVysfxJqB1pRchh1KVvwOv9b7CGB8ZfjTImVv2oF+sYMUkMZq6Na5Ftmbg=="
},
"node_modules/concat-map": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz",
- "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg=="
+ "integrity": "sha512-/Srv4dswyQNBfohGpz9o6Yb3Gz3SrUDqBH5rTuhGR7ahtlbYKnVxw2bCFMRljaA7EXHaXZ8wsHdodFvbkhKmqg==",
+ "dev": true
},
"node_modules/concat-stream": {
"version": "1.6.2",
@@ -6848,9 +6098,9 @@
}
},
"node_modules/d3": {
- "version": "7.8.5",
- "resolved": "https://registry.npmjs.org/d3/-/d3-7.8.5.tgz",
- "integrity": "sha512-JgoahDG51ncUfJu6wX/1vWQEqOflgXyl4MaHqlcSruTez7yhaRKR9i8VjjcQGeS2en/jnFivXuaIMnseMMt0XA==",
+ "version": "7.9.0",
+ "resolved": "https://registry.npmjs.org/d3/-/d3-7.9.0.tgz",
+ "integrity": "sha512-e1U46jVP+w7Iut8Jt8ri1YsPOvFpg46k+K8TpCb0P+zjCkjkPnV7WzfDJzMHy1LnA+wj5pLT1wjO901gLXeEhA==",
"dependencies": {
"d3-array": "3",
"d3-axis": "3",
@@ -6989,27 +6239,24 @@
}
},
"node_modules/d3-dsv": {
- "version": "3.0.1",
- "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
- "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
+ "version": "1.2.0",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-1.2.0.tgz",
+ "integrity": "sha512-9yVlqvZcSOMhCYzniHE7EVUws7Fa1zgw+/EAV2BxJoG3ME19V6BQFBwI855XQDsxyOuG7NibqRMTtiF/Qup46g==",
"dependencies": {
- "commander": "7",
- "iconv-lite": "0.6",
+ "commander": "2",
+ "iconv-lite": "0.4",
"rw": "1"
},
"bin": {
- "csv2json": "bin/dsv2json.js",
- "csv2tsv": "bin/dsv2dsv.js",
- "dsv2dsv": "bin/dsv2dsv.js",
- "dsv2json": "bin/dsv2json.js",
- "json2csv": "bin/json2dsv.js",
- "json2dsv": "bin/json2dsv.js",
- "json2tsv": "bin/json2dsv.js",
- "tsv2csv": "bin/dsv2dsv.js",
- "tsv2json": "bin/dsv2json.js"
- },
- "engines": {
- "node": ">=12"
+ "csv2json": "bin/dsv2json",
+ "csv2tsv": "bin/dsv2dsv",
+ "dsv2dsv": "bin/dsv2dsv",
+ "dsv2json": "bin/dsv2json",
+ "json2csv": "bin/json2dsv",
+ "json2dsv": "bin/json2dsv",
+ "json2tsv": "bin/json2dsv",
+ "tsv2csv": "bin/dsv2dsv",
+ "tsv2json": "bin/dsv2json"
}
},
"node_modules/d3-ease": {
@@ -7076,12 +6323,6 @@
"geostitch": "bin/geostitch"
}
},
- "node_modules/d3-geo-projection/node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "peer": true
- },
"node_modules/d3-geo-projection/node_modules/d3-array": {
"version": "1.2.4",
"resolved": "https://registry.npmjs.org/d3-array/-/d3-array-1.2.4.tgz",
@@ -7174,9 +6415,9 @@
}
},
"node_modules/d3-scale-chromatic": {
- "version": "3.0.0",
- "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.0.0.tgz",
- "integrity": "sha512-Lx9thtxAKrO2Pq6OO2Ua474opeziKr279P/TKZsMAhYyNDD3EnCffdbgeSYN5O7m2ByQsxtuP2CSDczNUIZ22g==",
+ "version": "3.1.0",
+ "resolved": "https://registry.npmjs.org/d3-scale-chromatic/-/d3-scale-chromatic-3.1.0.tgz",
+ "integrity": "sha512-A3s5PWiZ9YCXFye1o246KoscMWqf8BsD9eRiJ3He7C9OBaxKhAd5TFCdEx/7VbKtxxTsu//1mMJFrEt572cEyQ==",
"dependencies": {
"d3-color": "1 - 3",
"d3-interpolate": "1 - 3"
@@ -7267,6 +6508,38 @@
"node": ">=12"
}
},
+ "node_modules/d3/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/d3/node_modules/d3-dsv": {
+ "version": "3.0.1",
+ "resolved": "https://registry.npmjs.org/d3-dsv/-/d3-dsv-3.0.1.tgz",
+ "integrity": "sha512-UG6OvdI5afDIFP9w4G0mNq50dSOsXHJaRE8arAS5o9ApWnIElp8GZw1Dun8vP8OyHOZ/QJUKUJwxiiCCnUwm+Q==",
+ "dependencies": {
+ "commander": "7",
+ "iconv-lite": "0.6",
+ "rw": "1"
+ },
+ "bin": {
+ "csv2json": "bin/dsv2json.js",
+ "csv2tsv": "bin/dsv2dsv.js",
+ "dsv2dsv": "bin/dsv2dsv.js",
+ "dsv2json": "bin/dsv2json.js",
+ "json2csv": "bin/json2dsv.js",
+ "json2dsv": "bin/json2dsv.js",
+ "json2tsv": "bin/json2dsv.js",
+ "tsv2csv": "bin/dsv2dsv.js",
+ "tsv2json": "bin/dsv2json.js"
+ },
+ "engines": {
+ "node": ">=12"
+ }
+ },
"node_modules/d3/node_modules/d3-format": {
"version": "3.1.0",
"resolved": "https://registry.npmjs.org/d3-format/-/d3-format-3.1.0.tgz",
@@ -7276,9 +6549,9 @@
}
},
"node_modules/d3/node_modules/d3-geo": {
- "version": "3.1.0",
- "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.0.tgz",
- "integrity": "sha512-JEo5HxXDdDYXCaWdwLRt79y7giK8SbhZJbFWXqbRTolCHFI5jRqteLzCsq51NKbUoX0PjBVSohxrx+NoOUujYA==",
+ "version": "3.1.1",
+ "resolved": "https://registry.npmjs.org/d3-geo/-/d3-geo-3.1.1.tgz",
+ "integrity": "sha512-637ln3gXKXOwhalDzinUgY83KzNWZRKbYubaG+fGVuc/dxO64RRljtCTnf5ecMyE1RIdtqpkVcq0IbtU2S8j2Q==",
"dependencies": {
"d3-array": "2.5.0 - 3"
},
@@ -7286,10 +6559,22 @@
"node": ">=12"
}
},
+ "node_modules/d3/node_modules/iconv-lite": {
+ "version": "0.6.3",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
+ "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "dependencies": {
+ "safer-buffer": ">= 2.1.2 < 3.0.0"
+ },
+ "engines": {
+ "node": ">=0.10.0"
+ }
+ },
"node_modules/debug": {
"version": "4.3.4",
"resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz",
"integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==",
+ "dev": true,
"dependencies": {
"ms": "2.1.2"
},
@@ -7307,25 +6592,6 @@
"resolved": "https://registry.npmjs.org/decimal.js/-/decimal.js-10.4.3.tgz",
"integrity": "sha512-VBBaLc1MgL5XpzgIP7ny5Z6Nx3UrRkIViUkPUdtl9aya5amy3De1gsUUSB1g3+3sExYNjCAsAznmukyxCb1GRA=="
},
- "node_modules/deck.gl": {
- "version": "8.9.22",
- "resolved": "https://registry.npmjs.org/deck.gl/-/deck.gl-8.9.22.tgz",
- "integrity": "sha512-CkJ/Wtyquh4wpG7Os6n5j4D9fm0NFROa6Go0hEToVU8kbfQoj6drD76ixBnsx47dOtcHNQ11AVaPaaAeHmnTjg==",
- "dependencies": {
- "@babel/runtime": "^7.0.0",
- "@deck.gl/aggregation-layers": "8.9.22",
- "@deck.gl/carto": "8.9.22",
- "@deck.gl/core": "8.9.22",
- "@deck.gl/extensions": "8.9.22",
- "@deck.gl/geo-layers": "8.9.22",
- "@deck.gl/google-maps": "8.9.22",
- "@deck.gl/json": "8.9.22",
- "@deck.gl/layers": "8.9.22",
- "@deck.gl/mapbox": "8.9.22",
- "@deck.gl/mesh-layers": "8.9.22",
- "@deck.gl/react": "8.9.22"
- }
- },
"node_modules/deep-eql": {
"version": "4.1.3",
"resolved": "https://registry.npmjs.org/deep-eql/-/deep-eql-4.1.3.tgz",
@@ -7380,11 +6646,11 @@
}
},
"node_modules/delaunator": {
- "version": "5.0.0",
- "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.0.tgz",
- "integrity": "sha512-AyLvtyJdbv/U1GkiS6gUUzclRoAY4Gs75qkMygJJhU75LW4DNuSF2RMzpxs9jw9Oz1BobHjTdkG3zdP55VxAqw==",
+ "version": "5.0.1",
+ "resolved": "https://registry.npmjs.org/delaunator/-/delaunator-5.0.1.tgz",
+ "integrity": "sha512-8nvh+XBe96aCESrGOqMp/84b13H9cdKbG5P2ejQCh4d4sK9RL4371qou9drQjMhvnPmhWl5hnmqbEE0fXr9Xnw==",
"dependencies": {
- "robust-predicates": "^3.0.0"
+ "robust-predicates": "^3.0.2"
}
},
"node_modules/delayed-stream": {
@@ -7578,25 +6844,20 @@
"integrity": "sha512-6QvTW9mrGeIegrFXdtQi9pk7O/nSK6lSdXW2eqUspN5LWD7UTji2Fqw5V2YLjBpHEoU9Xl/eUWNpDeZvoyOv2w=="
},
"node_modules/downshift": {
- "version": "8.1.0",
- "resolved": "https://registry.npmjs.org/downshift/-/downshift-8.1.0.tgz",
- "integrity": "sha512-e9EBBLZvB2G73qT272x3hExttGCH1q1usbjirm+1aMcFXuzSWhgBdbnAHPlFI2rEq61cU/kDrEIMrY+ozMhvmg==",
+ "version": "8.3.3",
+ "resolved": "https://registry.npmjs.org/downshift/-/downshift-8.3.3.tgz",
+ "integrity": "sha512-f9znQFYF/3AWBkFiEc4H05Vdh41XFgJ80IatLBKIFoA3p86mAXc/iM9/XJ24loF9djtABD5NBEYL7b1b7xh2pw==",
"dependencies": {
- "@babel/runtime": "^7.14.8",
- "compute-scroll-into-view": "^2.0.4",
- "prop-types": "^15.7.2",
- "react-is": "^17.0.2",
- "tslib": "^2.3.0"
+ "@babel/runtime": "^7.22.15",
+ "compute-scroll-into-view": "^3.0.3",
+ "prop-types": "^15.8.1",
+ "react-is": "^18.2.0",
+ "tslib": "^2.6.2"
},
"peerDependencies": {
"react": ">=16.12.0"
}
},
- "node_modules/downshift/node_modules/react-is": {
- "version": "17.0.2",
- "resolved": "https://registry.npmjs.org/react-is/-/react-is-17.0.2.tgz",
- "integrity": "sha512-w2GsyukL62IJnlaff/nRegPQR94C/XXamvMWmSHRJ4y7Ts/4ocGRmTHvOs8PSE6pB3dWOrD/nueuU5sduBsQ4w=="
- },
"node_modules/draco3d": {
"version": "1.5.5",
"resolved": "https://registry.npmjs.org/draco3d/-/draco3d-1.5.5.tgz",
@@ -7653,7 +6914,8 @@
"node_modules/electron-to-chromium": {
"version": "1.4.617",
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.617.tgz",
- "integrity": "sha512-sYNE3QxcDS4ANW1k4S/wWYMXjCVcFSOX3Bg8jpuMFaXt/x8JCmp0R1Xe1ZXDX4WXnSRBf+GJ/3eGWicUuQq5cg=="
+ "integrity": "sha512-sYNE3QxcDS4ANW1k4S/wWYMXjCVcFSOX3Bg8jpuMFaXt/x8JCmp0R1Xe1ZXDX4WXnSRBf+GJ/3eGWicUuQq5cg==",
+ "dev": true
},
"node_modules/element-size": {
"version": "1.1.1",
@@ -7889,6 +7151,7 @@
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
+ "dev": true,
"engines": {
"node": ">=6"
}
@@ -8442,6 +7705,7 @@
"version": "4.0.1",
"resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz",
"integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==",
+ "peer": true,
"bin": {
"esparse": "bin/esparse.js",
"esvalidate": "bin/esvalidate.js"
@@ -8677,7 +7941,8 @@
"node_modules/fast-json-stable-stringify": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.1.0.tgz",
- "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw=="
+ "integrity": "sha512-lhd/wF+Lk98HZoTCtlVraHtfh5XYijIjalXck7saUtuanSDyLMxnHhSXEDJqHxD7msR8D0uCmqlkwjCV8xvwHw==",
+ "dev": true
},
"node_modules/fast-levenshtein": {
"version": "2.0.6",
@@ -8685,17 +7950,17 @@
"integrity": "sha512-DCXu6Ifhqcks7TZKY3Hxp3y6qphY5SJZmrWMDrKcERSOXWQdMhU9Ig/PYrzyw/ul9jOIyh0N4M0tbC5hodg8dw=="
},
"node_modules/fast-xml-parser": {
- "version": "4.2.7",
- "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.2.7.tgz",
- "integrity": "sha512-J8r6BriSLO1uj2miOk1NW0YVm8AGOOu3Si2HQp/cSmo6EA4m3fcwu2WKjJ4RK9wMLBtg69y1kS8baDiQBR41Ig==",
+ "version": "4.3.6",
+ "resolved": "https://registry.npmjs.org/fast-xml-parser/-/fast-xml-parser-4.3.6.tgz",
+ "integrity": "sha512-M2SovcRxD4+vC493Uc2GZVcZaj66CCJhWurC4viynVSTvrpErCShNcDz1lAho6n9REQKvL/ll4A4/fw6Y9z8nw==",
"funding": [
- {
- "type": "paypal",
- "url": "https://paypal.me/naturalintelligence"
- },
{
"type": "github",
"url": "https://github.com/sponsors/NaturalIntelligence"
+ },
+ {
+ "type": "paypal",
+ "url": "https://paypal.me/naturalintelligence"
}
],
"dependencies": {
@@ -8714,14 +7979,6 @@
"reusify": "^1.0.4"
}
},
- "node_modules/fb-watchman": {
- "version": "2.0.2",
- "resolved": "https://registry.npmjs.org/fb-watchman/-/fb-watchman-2.0.2.tgz",
- "integrity": "sha512-p5161BqbuCaSnB8jIbzQHOlpgsPmK5rJVDfDKO91Axs5NC1uu3HRQm6wt9cd9/+GtQQIO53JdGXXoyDpTAsgYA==",
- "dependencies": {
- "bser": "2.1.1"
- }
- },
"node_modules/figures": {
"version": "5.0.0",
"resolved": "https://registry.npmjs.org/figures/-/figures-5.0.0.tgz",
@@ -8766,6 +8023,7 @@
"version": "7.0.1",
"resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz",
"integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==",
+ "dev": true,
"dependencies": {
"to-regex-range": "^5.0.1"
},
@@ -8898,15 +8156,15 @@
}
},
"node_modules/fraction.js": {
- "version": "4.2.0",
- "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.2.0.tgz",
- "integrity": "sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==",
+ "version": "4.3.4",
+ "resolved": "https://registry.npmjs.org/fraction.js/-/fraction.js-4.3.4.tgz",
+ "integrity": "sha512-pwiTgt0Q7t+GHZA4yaLjObx4vXmmdcS0iSJ19o8d/goUGgItX9UZWKWNnLHehxviD8wU2IWRsnR8cD5+yOJP2Q==",
"engines": {
"node": "*"
},
"funding": {
"type": "patreon",
- "url": "https://www.patreon.com/infusion"
+ "url": "https://github.com/sponsors/rawify"
}
},
"node_modules/from2": {
@@ -8935,12 +8193,14 @@
"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=="
+ "integrity": "sha512-OO0pH2lK6a0hZnAdau5ItzHPI6pUlvI7jMVnxUQRtw4owF2wk8lOSabtGDCTP4Ggrg2MbGnWO9X8K1t4+fGMDw==",
+ "dev": true
},
"node_modules/fsevents": {
"version": "2.3.2",
"resolved": "https://registry.npmjs.org/fsevents/-/fsevents-2.3.2.tgz",
"integrity": "sha512-xiqMQR4xAeHTuB9uWm+fFRcIOgKBMiOBP+eXiyT7jsgVCq1bkVygt00oASowB7EdtpOHaaPgKt812P9ab+DDKA==",
+ "dev": true,
"hasInstallScript": true,
"optional": true,
"os": [
@@ -8986,6 +8246,7 @@
"version": "1.0.0-beta.2",
"resolved": "https://registry.npmjs.org/gensync/-/gensync-1.0.0-beta.2.tgz",
"integrity": "sha512-3hN7NaskYvMDLQY55gnW3NQ+mesEAepTqlg+VEbj7zzqEMBVNhzcGYYeqFo/TlYz6eQiFcp1HcsCZO+nGgS8zg==",
+ "dev": true,
"engines": {
"node": ">=6.9.0"
}
@@ -9055,14 +8316,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/get-package-type": {
- "version": "0.1.0",
- "resolved": "https://registry.npmjs.org/get-package-type/-/get-package-type-0.1.0.tgz",
- "integrity": "sha512-pjzuKtY64GYfWizNAJ0fr9VqttZkNiK2iS430LtIHzjBEr6bX8Am2zm4sW4Ro5wjWW5cAlRL1qAMTcXbjNAO2Q==",
- "engines": {
- "node": ">=8.0.0"
- }
- },
"node_modules/get-stream": {
"version": "6.0.1",
"resolved": "https://registry.npmjs.org/get-stream/-/get-stream-6.0.1.tgz",
@@ -9228,6 +8481,7 @@
"version": "11.12.0",
"resolved": "https://registry.npmjs.org/globals/-/globals-11.12.0.tgz",
"integrity": "sha512-WOBp/EEGUiIsJSp7wcv/y6MO+lV9UoncWqxuFfm8eBwzWNgyfBd6Gz+IeKQ9jCmyhoH99g15M3T+QaVHFjizVA==",
+ "dev": true,
"engines": {
"node": ">=4"
}
@@ -9676,11 +8930,11 @@
}
},
"node_modules/iconv-lite": {
- "version": "0.6.3",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.6.3.tgz",
- "integrity": "sha512-4fCk79wshMdzMp2rH06qWrJE4iolqLhCUH+OiuIgU++RB0+94NlDL81atO7GX55uUKueo0txHNtvEyI6D7WdMw==",
+ "version": "0.4.24",
+ "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
+ "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
"dependencies": {
- "safer-buffer": ">= 2.1.2 < 3.0.0"
+ "safer-buffer": ">= 2.1.2 < 3"
},
"engines": {
"node": ">=0.10.0"
@@ -9759,6 +9013,7 @@
"version": "0.1.4",
"resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz",
"integrity": "sha512-JmXMZ6wuvDmLiHEml9ykzqO6lwFbof0GG4IkcGaENdCRDDmMVnny7s5HsIgHCbaq0w2MyPhDqkhTUgS2LU2PHA==",
+ "dev": true,
"engines": {
"node": ">=0.8.19"
}
@@ -9791,6 +9046,7 @@
"version": "1.0.6",
"resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz",
"integrity": "sha512-k92I/b08q4wvFscXCLvqfsHCrjrF7yiXsQuIVvVE7N82W3+aqpzuUdBbfhWcy/FZR3/4IgflMgKLOsvPDrGCJA==",
+ "dev": true,
"dependencies": {
"once": "^1.3.0",
"wrappy": "1"
@@ -10047,6 +9303,7 @@
"version": "7.0.0",
"resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz",
"integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==",
+ "dev": true,
"engines": {
"node": ">=0.12.0"
}
@@ -10235,21 +9492,7 @@
"version": "3.2.2",
"resolved": "https://registry.npmjs.org/istanbul-lib-coverage/-/istanbul-lib-coverage-3.2.2.tgz",
"integrity": "sha512-O8dpsF+r0WV/8MNRKfnmrtCWhuKjxrq2w+jpzBL5UZKTi2LeVWnWOmWRxFlesJONmc+wLAGvKQZEOanko0LFTg==",
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/istanbul-lib-instrument": {
- "version": "5.2.1",
- "resolved": "https://registry.npmjs.org/istanbul-lib-instrument/-/istanbul-lib-instrument-5.2.1.tgz",
- "integrity": "sha512-pzqtp31nLv/XFOzXGuvhCb8qhjmTVo5vjVk19XE4CRlSWz0KoeJ3bw9XsA7nOp9YBf4qHjwBxkDzKcME/J29Yg==",
- "dependencies": {
- "@babel/core": "^7.12.3",
- "@babel/parser": "^7.14.7",
- "@istanbuljs/schema": "^0.1.2",
- "istanbul-lib-coverage": "^3.2.0",
- "semver": "^6.3.0"
- },
+ "dev": true,
"engines": {
"node": ">=8"
}
@@ -10348,161 +9591,52 @@
"resolved": "https://registry.npmjs.org/javascript-natural-sort/-/javascript-natural-sort-0.7.1.tgz",
"integrity": "sha512-nO6jcEfZWQXDhOiBtG2KvKyEptz7RVbpGP4vTD2hLBdmNQSsCiicO2Ioinv6UI4y9ukqnBpy+XZ9H6uLNgJTlw=="
},
- "node_modules/jest-haste-map": {
- "version": "29.6.2",
- "resolved": "https://registry.npmjs.org/jest-haste-map/-/jest-haste-map-29.6.2.tgz",
- "integrity": "sha512-+51XleTDAAysvU8rT6AnS1ZJ+WHVNqhj1k6nTvN2PYP+HjU3kqlaKQ1Lnw3NYW3bm2r8vq82X0Z1nDDHZMzHVA==",
- "dependencies": {
- "@jest/types": "^29.6.1",
- "@types/graceful-fs": "^4.1.3",
- "@types/node": "*",
- "anymatch": "^3.0.3",
- "fb-watchman": "^2.0.0",
- "graceful-fs": "^4.2.9",
- "jest-regex-util": "^29.4.3",
- "jest-util": "^29.6.2",
- "jest-worker": "^29.6.2",
- "micromatch": "^4.0.4",
- "walker": "^1.0.8"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- },
- "optionalDependencies": {
- "fsevents": "^2.3.2"
- }
- },
- "node_modules/jest-regex-util": {
- "version": "29.4.3",
- "resolved": "https://registry.npmjs.org/jest-regex-util/-/jest-regex-util-29.4.3.tgz",
- "integrity": "sha512-O4FglZaMmWXbGHSQInfXewIsd1LMn9p3ZXB/6r4FOkyhX2/iP/soMG98jGvk/A3HAN78+5VWcBGO0BJAPRh4kg==",
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-util": {
- "version": "29.6.2",
- "resolved": "https://registry.npmjs.org/jest-util/-/jest-util-29.6.2.tgz",
- "integrity": "sha512-3eX1qb6L88lJNCFlEADKOkjpXJQyZRiavX1INZ4tRnrBVr2COd3RgcTLyUiEXMNBlDU/cgYq6taUS0fExrWW4w==",
- "dependencies": {
- "@jest/types": "^29.6.1",
- "@types/node": "*",
- "chalk": "^4.0.0",
- "ci-info": "^3.2.0",
- "graceful-fs": "^4.2.9",
- "picomatch": "^2.2.3"
- },
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-util/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/jest-util/node_modules/chalk": {
- "version": "4.1.2",
- "resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.2.tgz",
- "integrity": "sha512-oKnbhFyRIXpUuez8iBMmyEa4nbj4IOQyuhc/wy9kY7/WVPcwIO9VA668Pu8RkO7+0G76SLROeyw9CpQ061i4mA==",
- "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/jest-util/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/jiti": {
+ "version": "1.19.1",
+ "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz",
+ "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==",
+ "dev": true,
+ "bin": {
+ "jiti": "bin/jiti.js"
}
},
- "node_modules/jest-util/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/jest-util/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==",
+ "node_modules/jotai": {
+ "version": "2.6.2",
+ "resolved": "https://registry.npmjs.org/jotai/-/jotai-2.6.2.tgz",
+ "integrity": "sha512-kl4KguU1Fr+tFiLi3A3h9qPEzhvLTTDA10DO3QZAz6k7BEaQJ+qvSBwolzonnfNI4QzEovyQfUqVgnRxfnnQVQ==",
"engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest-util/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"
+ "node": ">=12.20.0"
},
- "engines": {
- "node": ">=8"
- }
- },
- "node_modules/jest-worker": {
- "version": "29.6.2",
- "resolved": "https://registry.npmjs.org/jest-worker/-/jest-worker-29.6.2.tgz",
- "integrity": "sha512-l3ccBOabTdkng8I/ORCkADz4eSMKejTYv1vB/Z83UiubqhC1oQ5Li6dWCyqOIvSifGjUBxuvxvlm6KGK2DtuAQ==",
- "dependencies": {
- "@types/node": "*",
- "jest-util": "^29.6.2",
- "merge-stream": "^2.0.0",
- "supports-color": "^8.0.0"
+ "peerDependencies": {
+ "@types/react": ">=17.0.0",
+ "react": ">=17.0.0"
},
- "engines": {
- "node": "^14.15.0 || ^16.10.0 || >=18.0.0"
- }
- },
- "node_modules/jest-worker/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"
+ "peerDependenciesMeta": {
+ "@types/react": {
+ "optional": true
+ },
+ "react": {
+ "optional": true
+ }
}
},
- "node_modules/jest-worker/node_modules/supports-color": {
- "version": "8.1.1",
- "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-8.1.1.tgz",
- "integrity": "sha512-MpUEN2OodtUzxvKQl72cUF7RQ5EiHsGvSsVG0ia9c5RbWGL2CI4C7EpPS8UTBIplnlzZiNuV56w+FuNxy3ty2Q==",
- "dependencies": {
- "has-flag": "^4.0.0"
- },
- "engines": {
- "node": ">=10"
- },
- "funding": {
- "url": "https://github.com/chalk/supports-color?sponsor=1"
+ "node_modules/jotai-scope": {
+ "version": "0.5.1",
+ "resolved": "https://registry.npmjs.org/jotai-scope/-/jotai-scope-0.5.1.tgz",
+ "integrity": "sha512-GKaqtCj1Hv36nyl63PVm+s5jo+hQqz+wAb81iqA8VuUXp5ot4eXGOZt4Hc66lFZMP0N/yEOISMlazprmDI6kFA==",
+ "peerDependencies": {
+ "jotai": ">=2.5.0",
+ "react": ">=17.0.0"
}
},
- "node_modules/jiti": {
- "version": "1.19.1",
- "resolved": "https://registry.npmjs.org/jiti/-/jiti-1.19.1.tgz",
- "integrity": "sha512-oVhqoRDaBXf7sjkll95LHVS6Myyyb1zaunVwk4Z0+WPSW4gjS0pl01zYKHScTuyEhQsFxV5L4DR5r+YqSyqyyg==",
- "dev": true,
- "bin": {
- "jiti": "bin/jiti.js"
+ "node_modules/jotai-tanstack-query": {
+ "version": "0.8.2",
+ "resolved": "https://registry.npmjs.org/jotai-tanstack-query/-/jotai-tanstack-query-0.8.2.tgz",
+ "integrity": "sha512-NXHbfSTBdH1M+NrnEVG0pUcUcPHzEtqhRJl8JHHoay33whvGkQZW93/ETj4fa1vgA/N7gzScPMRPQFzpp68P+g==",
+ "peerDependencies": {
+ "@tanstack/query-core": "*",
+ "jotai": ">=2.0.0",
+ "wonka": "^6.3.4"
}
},
"node_modules/js-tokens": {
@@ -10534,6 +9668,7 @@
"version": "2.5.2",
"resolved": "https://registry.npmjs.org/jsesc/-/jsesc-2.5.2.tgz",
"integrity": "sha512-OYu7XEzjkCQ3C5Ps3QIZsQfNpqoJyZZA99wd9aWd05NCtC5pWOkShK2mkL6HXQR6/Cy2lbNdPlZBpuQHXE63gA==",
+ "dev": true,
"bin": {
"jsesc": "bin/jsesc"
},
@@ -10561,6 +9696,7 @@
"version": "2.2.3",
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.3.tgz",
"integrity": "sha512-XmOWe7eyHYH14cLdVPoyg+GOH3rYX++KpzrylJwSW98t3Nk+U8XOl8FWKOgwtzdb8lXGf6zYwDUzeHMWfxasyg==",
+ "dev": true,
"bin": {
"json5": "lib/cli.js"
},
@@ -10618,9 +9754,9 @@
"integrity": "sha512-LY3nrmfXl+wZZdPxgJ3ZmLvG+wkOZZP3/dr4RbQj1Pk3Qwz44esOOSFFVQJcNWpXAtiNIC66WgXufX/SYgYz6A=="
},
"node_modules/lerc": {
- "version": "4.0.1",
- "resolved": "https://registry.npmjs.org/lerc/-/lerc-4.0.1.tgz",
- "integrity": "sha512-b351eOjY3DKm1H2hDVhXswsd2RCK6bgREBK6Z639ctClOuYXTi9a44l8yO3zm1pYM2o4WrriloTAKgyrb/0EyA=="
+ "version": "4.0.4",
+ "resolved": "https://registry.npmjs.org/lerc/-/lerc-4.0.4.tgz",
+ "integrity": "sha512-nHZH+ffiGPkgKUQtiZrljGUGV2GddvPcVTV5E345ZFncbKz+/rBIjDPrSxkiqW0EAtg1Jw7qAgRdaCwV+95Fow=="
},
"node_modules/levn": {
"version": "0.4.1",
@@ -10904,6 +10040,7 @@
"version": "5.1.1",
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-5.1.1.tgz",
"integrity": "sha512-KpNARQA3Iwv+jTA0utUVVbrh+Jlrr1Fv0e56GGzAFOXN7dk/FviaDW8LHmK52DlcH4WP2n6gI8vN1aesBFgo9w==",
+ "dev": true,
"dependencies": {
"yallist": "^3.0.2"
}
@@ -10979,14 +10116,6 @@
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
"dev": true
},
- "node_modules/makeerror": {
- "version": "1.0.12",
- "resolved": "https://registry.npmjs.org/makeerror/-/makeerror-1.0.12.tgz",
- "integrity": "sha512-JmqCvUhmt43madlpFzG4BQzG2Z3m6tvQDNKdClZnO3VbIudJYmxsT0FNJMeiB2+JTSlTQTSbU8QdesVmwJcmLg==",
- "dependencies": {
- "tmpl": "1.0.5"
- }
- },
"node_modules/map-limit": {
"version": "0.0.1",
"resolved": "https://registry.npmjs.org/map-limit/-/map-limit-0.0.1.tgz",
@@ -11068,31 +10197,32 @@
}
},
"node_modules/mathjs": {
- "version": "9.5.2",
- "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-9.5.2.tgz",
- "integrity": "sha512-c0erTq0GP503/Ch2OtDOAn50GIOsuxTMjmE00NI/vKJFSWrDaQHRjx6ai+16xYv70yBSnnpUgHZGNf9FR9IwmA==",
+ "version": "12.4.1",
+ "resolved": "https://registry.npmjs.org/mathjs/-/mathjs-12.4.1.tgz",
+ "integrity": "sha512-welnW3khgwYjPYvECFHO+xkCxAx9IKIIPDDWPi8B5rKAvmgoEHnQX9slEmHKZTNaJiE+OS4qrJJcB4sfDn/4sw==",
"dependencies": {
- "@babel/runtime": "^7.15.4",
- "complex.js": "^2.0.15",
- "decimal.js": "^10.3.1",
+ "@babel/runtime": "^7.24.0",
+ "complex.js": "^2.1.1",
+ "decimal.js": "^10.4.3",
"escape-latex": "^1.2.0",
- "fraction.js": "^4.1.1",
+ "fraction.js": "4.3.4",
"javascript-natural-sort": "^0.7.1",
"seedrandom": "^3.0.5",
"tiny-emitter": "^2.1.0",
- "typed-function": "^2.0.0"
+ "typed-function": "^4.1.1"
},
"bin": {
"mathjs": "bin/cli.js"
},
"engines": {
- "node": ">= 12"
+ "node": ">= 18"
}
},
"node_modules/merge-stream": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/merge-stream/-/merge-stream-2.0.0.tgz",
- "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w=="
+ "integrity": "sha512-abv/qOcuPfk3URPfDzmZU1LKmuw8kT+0nIHvKrKgFrwifol/doWcdA4ZqsWQ8ENrFKkd67Mfpo/LovbIUsbt3w==",
+ "dev": true
},
"node_modules/merge2": {
"version": "1.4.1",
@@ -11107,6 +10237,7 @@
"version": "4.0.5",
"resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz",
"integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==",
+ "dev": true,
"dependencies": {
"braces": "^3.0.2",
"picomatch": "^2.3.1"
@@ -11158,6 +10289,7 @@
"version": "3.1.2",
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.1.2.tgz",
"integrity": "sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==",
+ "dev": true,
"dependencies": {
"brace-expansion": "^1.1.7"
},
@@ -11207,25 +10339,6 @@
"ufo": "^1.3.0"
}
},
- "node_modules/moment": {
- "version": "2.29.4",
- "resolved": "https://registry.npmjs.org/moment/-/moment-2.29.4.tgz",
- "integrity": "sha512-5LC9SOxjSc2HF6vO2CyuTDNivEdoz2IvyJJGj6X8DJ0eFyfszE0QiEd+iXmBvUP3WHxSjFH/vIsA0EN00cgr8w==",
- "engines": {
- "node": "*"
- }
- },
- "node_modules/moment-timezone": {
- "version": "0.5.43",
- "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.43.tgz",
- "integrity": "sha512-72j3aNyuIsDxdF1i7CEgV2FfxM1r6aaqJyLB2vwb33mXYyoyLly+F1zbWqhA3/bVIoJ4szlUoMbUnVdid32NUQ==",
- "dependencies": {
- "moment": "^2.29.4"
- },
- "engines": {
- "node": "*"
- }
- },
"node_modules/mouse-change": {
"version": "1.4.0",
"resolved": "https://registry.npmjs.org/mouse-change/-/mouse-change-1.4.0.tgz",
@@ -11294,7 +10407,6 @@
"version": "3.3.7",
"resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz",
"integrity": "sha512-eSRppjcPIatRIMC1U6UngP8XFcz8MQWGQdt1MTBQ7NaAmvXDfvNxbvWV3x2y6CdEUciCSsDHDQZbhYaB8QEo2g==",
- "dev": true,
"funding": [
{
"type": "github",
@@ -11346,18 +10458,6 @@
"ms": "^2.1.1"
}
},
- "node_modules/needle/node_modules/iconv-lite": {
- "version": "0.4.24",
- "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz",
- "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==",
- "peer": true,
- "dependencies": {
- "safer-buffer": ">= 2.1.2 < 3"
- },
- "engines": {
- "node": ">=0.10.0"
- }
- },
"node_modules/neo-async": {
"version": "2.6.2",
"resolved": "https://registry.npmjs.org/neo-async/-/neo-async-2.6.2.tgz",
@@ -11370,20 +10470,17 @@
"integrity": "sha512-CXdUiJembsNjuToQvxayPZF9Vqht7hewsvy2sOWafLvi2awflj9mOC6bHIg50orX8IJvWKY9wYQ/zB2kogPslQ==",
"peer": true
},
- "node_modules/node-int64": {
- "version": "0.4.0",
- "resolved": "https://registry.npmjs.org/node-int64/-/node-int64-0.4.0.tgz",
- "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw=="
- },
"node_modules/node-releases": {
"version": "2.0.14",
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz",
- "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw=="
+ "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==",
+ "dev": true
},
"node_modules/normalize-path": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
"integrity": "sha512-6eZs5Ls3WtCisHWp9S2GUy8dqkpGi4BVSz3GaqiE6ezub0512ESztXUwUB6C6IKbQkY2Pnb/mD4WYojCRwcwLA==",
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -11724,14 +10821,6 @@
"url": "https://github.com/sponsors/sindresorhus"
}
},
- "node_modules/p-try": {
- "version": "2.2.0",
- "resolved": "https://registry.npmjs.org/p-try/-/p-try-2.2.0.tgz",
- "integrity": "sha512-R4nPAVTAU0B9D35/Gk3uJf/7XYbQcyohSKdvAxIRSNghFl4e71hVoGnBNQz9cWaXxO2I10KTC+3jMdvvoKw6dQ==",
- "engines": {
- "node": ">=6"
- }
- },
"node_modules/pako": {
"version": "1.0.11",
"resolved": "https://registry.npmjs.org/pako/-/pako-1.0.11.tgz",
@@ -11796,6 +10885,7 @@
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/path-exists/-/path-exists-4.0.0.tgz",
"integrity": "sha512-ak9Qy5Q7jYb2Wwcey5Fpvg2KoAc/ZIhLSLOSBmRmygPsGwkVVt0fZa0qrtMz+m6tJTAHfZQ8FnmB4MG4LWy7/w==",
+ "dev": true,
"engines": {
"node": ">=8"
}
@@ -11804,6 +10894,7 @@
"version": "1.0.1",
"resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz",
"integrity": "sha512-AVbw3UJ2e9bq64vSaS9Am0fje1Pa8pbGqTTsmXfaIiMpnr5DlDhfJOuLj9Sf95ZPVDAUerDfEk88MPmPe7UCQg==",
+ "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -11903,6 +10994,7 @@
"version": "2.3.1",
"resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz",
"integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==",
+ "dev": true,
"engines": {
"node": ">=8.6"
},
@@ -11923,6 +11015,7 @@
"version": "4.0.6",
"resolved": "https://registry.npmjs.org/pirates/-/pirates-4.0.6.tgz",
"integrity": "sha512-saLsH7WeYYPiD25LDuLRRY/i+6HaPYr6G1OUlN39otzkSTxKnubR9RTxS3/Kk50s1g2JTgFwWQDQyplC5/SHZg==",
+ "dev": true,
"engines": {
"node": ">= 6"
}
@@ -12446,17 +11539,6 @@
"url": "https://github.com/sponsors/ljharb"
}
},
- "node_modules/quadbin": {
- "version": "0.1.9",
- "resolved": "https://registry.npmjs.org/quadbin/-/quadbin-0.1.9.tgz",
- "integrity": "sha512-5V6m6+cL/6+uBl3hYL+CWF06rRvlHkIepYKGQjTLYaHhu9InPppql0+0ROiCaOQdz8gPNlgge3glk5Qg1mWOYw==",
- "dependencies": {
- "@mapbox/tile-cover": "3.0.1"
- },
- "engines": {
- "node": ">=14"
- }
- },
"node_modules/queue-microtask": {
"version": "1.2.3",
"resolved": "https://registry.npmjs.org/queue-microtask/-/queue-microtask-1.2.3.tgz",
@@ -12604,9 +11686,9 @@
}
},
"node_modules/react-resize-detector": {
- "version": "9.1.0",
- "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-9.1.0.tgz",
- "integrity": "sha512-vGFbfkIZp4itJqR4yl+GhjrZHtdlQvou1r10ek0yZUMkizKbPdekKTpPb003IV3b8E5BJFThVG0oocjE3lNsug==",
+ "version": "9.1.1",
+ "resolved": "https://registry.npmjs.org/react-resize-detector/-/react-resize-detector-9.1.1.tgz",
+ "integrity": "sha512-siLzop7i4xIvZIACE/PHTvRegA8QRCEt0TfmvJ/qCIFQJ4U+3NuYcF8tNDmDWxfIn+X1eNCyY2rauH4KRxge8w==",
"dependencies": {
"lodash": "^4.17.21"
},
@@ -13115,6 +12197,7 @@
"version": "6.3.1",
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.1.tgz",
"integrity": "sha512-BR7VvDCVHO+q2xBEWskxS6DJE1qRnb7DxzUrogb71CWoSficBxYsiAGd+Kl0mmq/MprG9yArRkyrQxTO6XjMzA==",
+ "dev": true,
"bin": {
"semver": "bin/semver.js"
}
@@ -13244,6 +12327,7 @@
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/slash/-/slash-3.0.0.tgz",
"integrity": "sha512-g9Q1haeby36OSStwb4ntCGGGaKsaVSjQ68fBxoQcutl5fS1vuY18H3wSt3jFyFtrkx+Kz0V1G85A4MyAdDMi2Q==",
+ "dev": true,
"engines": {
"node": ">=8"
}
@@ -13260,7 +12344,6 @@
"version": "1.0.2",
"resolved": "https://registry.npmjs.org/source-map-js/-/source-map-js-1.0.2.tgz",
"integrity": "sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==",
- "dev": true,
"engines": {
"node": ">=0.10.0"
}
@@ -13561,24 +12644,23 @@
"peer": true
},
"node_modules/styled-components": {
- "version": "5.3.11",
- "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-5.3.11.tgz",
- "integrity": "sha512-uuzIIfnVkagcVHv9nE0VPlHPSCmXIUGKfJ42LNjxCCTDTL5sgnJ8Z7GZBq0EnLYGln77tPpEpExt2+qa+cZqSw==",
+ "version": "6.1.8",
+ "resolved": "https://registry.npmjs.org/styled-components/-/styled-components-6.1.8.tgz",
+ "integrity": "sha512-PQ6Dn+QxlWyEGCKDS71NGsXoVLKfE1c3vApkvDYS5KAK+V8fNWGhbSUEo9Gg2iaID2tjLXegEW3bZDUGpofRWw==",
"peer": true,
"dependencies": {
- "@babel/helper-module-imports": "^7.0.0",
- "@babel/traverse": "^7.4.5",
- "@emotion/is-prop-valid": "^1.1.0",
- "@emotion/stylis": "^0.8.4",
- "@emotion/unitless": "^0.7.4",
- "babel-plugin-styled-components": ">= 1.12.0",
- "css-to-react-native": "^3.0.0",
- "hoist-non-react-statics": "^3.0.0",
- "shallowequal": "^1.1.0",
- "supports-color": "^5.5.0"
+ "@emotion/is-prop-valid": "1.2.1",
+ "@emotion/unitless": "0.8.0",
+ "@types/stylis": "4.2.0",
+ "css-to-react-native": "3.2.0",
+ "csstype": "3.1.2",
+ "postcss": "8.4.31",
+ "shallowequal": "1.1.0",
+ "stylis": "4.3.1",
+ "tslib": "2.5.0"
},
"engines": {
- "node": ">=10"
+ "node": ">= 16"
},
"funding": {
"type": "opencollective",
@@ -13586,14 +12668,53 @@
},
"peerDependencies": {
"react": ">= 16.8.0",
- "react-dom": ">= 16.8.0",
- "react-is": ">= 16.8.0"
+ "react-dom": ">= 16.8.0"
}
},
"node_modules/styled-components/node_modules/@emotion/unitless": {
- "version": "0.7.5",
- "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.7.5.tgz",
- "integrity": "sha512-OWORNpfjMsSSUBVrRBVGECkhWcULOAJz9ZW8uK9qgxD+87M7jHRcvh/A96XXNhXTLmKcoYSQtBEX7lHMO7YRwg==",
+ "version": "0.8.0",
+ "resolved": "https://registry.npmjs.org/@emotion/unitless/-/unitless-0.8.0.tgz",
+ "integrity": "sha512-VINS5vEYAscRl2ZUDiT3uMPlrFQupiKgHz5AA4bCH1miKBg4qtwkim1qPmJj/4WG6TreYMY111rEFsjupcOKHw==",
+ "peer": true
+ },
+ "node_modules/styled-components/node_modules/postcss": {
+ "version": "8.4.31",
+ "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.31.tgz",
+ "integrity": "sha512-PS08Iboia9mts/2ygV3eLpY5ghnUcfLV/EXTOW1E2qYxJKGGBUtNjN76FYHnMs36RmARn41bC0AZmn+rR0OVpQ==",
+ "funding": [
+ {
+ "type": "opencollective",
+ "url": "https://opencollective.com/postcss/"
+ },
+ {
+ "type": "tidelift",
+ "url": "https://tidelift.com/funding/github/npm/postcss"
+ },
+ {
+ "type": "github",
+ "url": "https://github.com/sponsors/ai"
+ }
+ ],
+ "peer": true,
+ "dependencies": {
+ "nanoid": "^3.3.6",
+ "picocolors": "^1.0.0",
+ "source-map-js": "^1.0.2"
+ },
+ "engines": {
+ "node": "^10 || ^12 || >=14"
+ }
+ },
+ "node_modules/styled-components/node_modules/stylis": {
+ "version": "4.3.1",
+ "resolved": "https://registry.npmjs.org/stylis/-/stylis-4.3.1.tgz",
+ "integrity": "sha512-EQepAV+wMsIaGVGX1RECzgrcqRRU/0sYOHkeLsZ3fzHaHXZy4DaOOX0vOlGQdlsjkh3mFHAIlVimpwAs4dslyQ==",
+ "peer": true
+ },
+ "node_modules/styled-components/node_modules/tslib": {
+ "version": "2.5.0",
+ "resolved": "https://registry.npmjs.org/tslib/-/tslib-2.5.0.tgz",
+ "integrity": "sha512-336iVw3rtn2BUK7ORdIAHTyxHGRIHVReokCR3XjbckJMK7ms8FysBfhLR8IXnAgy7T0PTPNBWKiH514FOW/WSg==",
"peer": true
},
"node_modules/stylis": {
@@ -13790,6 +12911,7 @@
"version": "6.0.0",
"resolved": "https://registry.npmjs.org/test-exclude/-/test-exclude-6.0.0.tgz",
"integrity": "sha512-cAGWPIyOHU6zlmg88jwm7VRyXnMN7iV68OGAbYDk/Mh/xC/pzVPlQtY6ngoIH/5/tciuhGfvESU8GrHrcxD56w==",
+ "dev": true,
"dependencies": {
"@istanbuljs/schema": "^0.1.2",
"glob": "^7.1.4",
@@ -13803,6 +12925,7 @@
"version": "7.2.3",
"resolved": "https://registry.npmjs.org/glob/-/glob-7.2.3.tgz",
"integrity": "sha512-nFR0zLpU2YCaRxwoCJvL6UvCH2JFyFVIvwTLsIf21AuHlMskA1hhTdk+LlYJtOlYt9v6dvszD2BGRqBL+iQK9Q==",
+ "dev": true,
"dependencies": {
"fs.realpath": "^1.0.0",
"inflight": "^1.0.4",
@@ -13875,12 +12998,6 @@
"xtend": "~4.0.1"
}
},
- "node_modules/tilebelt": {
- "version": "1.0.1",
- "resolved": "https://registry.npmjs.org/tilebelt/-/tilebelt-1.0.1.tgz",
- "integrity": "sha512-cxHzpa5JgsugY9NUVRH43gPaGJw/29LecAn4X7UGOP64+kB8pU4VQ3bIhSyfb5Mk4jDxwl3yk330L/EIhbJ5aw==",
- "deprecated": "This module is now under the @mapbox namespace: install @mapbox/tilebelt instead"
- },
"node_modules/tiny-emitter": {
"version": "2.1.0",
"resolved": "https://registry.npmjs.org/tiny-emitter/-/tiny-emitter-2.1.0.tgz",
@@ -13927,11 +13044,6 @@
"node": ">=14.0.0"
}
},
- "node_modules/tmpl": {
- "version": "1.0.5",
- "resolved": "https://registry.npmjs.org/tmpl/-/tmpl-1.0.5.tgz",
- "integrity": "sha512-3f0uOEAQwIqGuWW2MVzYg8fV/QNnc/IpuJNG837rLuczAaLVHslWHZQj4IGiEl5Hs3kkbhwL9Ab7Hrsmuj+Smw=="
- },
"node_modules/to-fast-properties": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/to-fast-properties/-/to-fast-properties-2.0.0.tgz",
@@ -13959,6 +13071,7 @@
"version": "5.0.1",
"resolved": "https://registry.npmjs.org/to-regex-range/-/to-regex-range-5.0.1.tgz",
"integrity": "sha512-65P7iz6X5yEr1cwcgvQxbbIw7Uk3gOy5dIdtZ4rDveLqhrdJP+Li/Hx6tyK0NEb+2GCyneCMJiGqrADCSNk8sQ==",
+ "dev": true,
"dependencies": {
"is-number": "^7.0.0"
},
@@ -13980,12 +13093,6 @@
"topoquantize": "bin/topoquantize"
}
},
- "node_modules/topojson-client/node_modules/commander": {
- "version": "2.20.3",
- "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz",
- "integrity": "sha512-GpVkmM8vF2vQUkj2LvZmD35JxeJOLCwJ9cUkugyk2nuhbv3+mJvpLYYt+0+USMxE+oj+ey/lJEnhZw75x/OMcQ==",
- "peer": true
- },
"node_modules/ts-api-utils": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/ts-api-utils/-/ts-api-utils-1.2.0.tgz",
@@ -14259,11 +13366,11 @@
}
},
"node_modules/typed-function": {
- "version": "2.1.0",
- "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-2.1.0.tgz",
- "integrity": "sha512-bctQIOqx2iVbWGDGPWwIm18QScpu2XRmkC19D8rQGFsjKSgteq/o1hTZvIG/wuDq8fanpBDrLkLq+aEN/6y5XQ==",
+ "version": "4.1.1",
+ "resolved": "https://registry.npmjs.org/typed-function/-/typed-function-4.1.1.tgz",
+ "integrity": "sha512-Pq1DVubcvibmm8bYcMowjVnnMwPVMeh0DIdA8ad8NZY2sJgapANJmiigSUwlt+EgXxpfIv8MWrQXTIzkfYZLYQ==",
"engines": {
- "node": ">= 10"
+ "node": ">= 14"
}
},
"node_modules/typedarray": {
@@ -14347,6 +13454,7 @@
"version": "1.0.13",
"resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.0.13.tgz",
"integrity": "sha512-xebP81SNcPuNpPP3uzeW1NYXxI3rxyJzF3pD6sH4jE7o/IX+WtSpwnVU+qIsDPyk0d3hmFQ7mjqc6AtV604hbg==",
+ "dev": true,
"funding": [
{
"type": "opencollective",
@@ -14916,14 +14024,6 @@
"pbf": "^3.2.1"
}
},
- "node_modules/walker": {
- "version": "1.0.8",
- "resolved": "https://registry.npmjs.org/walker/-/walker-1.0.8.tgz",
- "integrity": "sha512-ts/8E8l5b7kY0vlWLewOkDXMmPdLcVV4GmOQLyxuSswIJsweeFZtAsMF7k1Nszz+TYBQrlYRmzOnr398y1JemQ==",
- "dependencies": {
- "makeerror": "1.0.12"
- }
- },
"node_modules/watskeburt": {
"version": "0.11.6",
"resolved": "https://registry.npmjs.org/watskeburt/-/watskeburt-0.11.6.tgz",
@@ -15017,6 +14117,11 @@
"node": ">=8"
}
},
+ "node_modules/wonka": {
+ "version": "6.3.4",
+ "resolved": "https://registry.npmjs.org/wonka/-/wonka-6.3.4.tgz",
+ "integrity": "sha512-CjpbqNtBGNAeyNS/9W6q3kSkKE52+FjIj7AkFlLr11s/VWGUu6a2CdYSdGxocIhIVjaW/zchesBQUKPVU69Cqg=="
+ },
"node_modules/word-wrap": {
"version": "1.2.5",
"resolved": "https://registry.npmjs.org/word-wrap/-/word-wrap-1.2.5.tgz",
@@ -15032,6 +14137,11 @@
"integrity": "sha512-gvVzJFlPycKc5dZN4yPkP8w7Dc37BtP1yczEneOb4uq34pXZcvrtRTmWV8W+Ume+XCxKgbjM+nevkyFPMybd4Q==",
"dev": true
},
+ "node_modules/workerpool": {
+ "version": "9.1.0",
+ "resolved": "https://registry.npmjs.org/workerpool/-/workerpool-9.1.0.tgz",
+ "integrity": "sha512-+wRWfm9yyJghvXLSHMQj3WXDxHbibHAQmRrWbqKBfy0RjftZNeQaW+Std5bSYc83ydkrxoPTPOWVlXUR9RWJdQ=="
+ },
"node_modules/world-calendars": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/world-calendars/-/world-calendars-1.0.3.tgz",
@@ -15173,23 +14283,6 @@
"resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz",
"integrity": "sha512-l4Sp/DRseor9wL6EvV2+TuQn63dMkPjZ/sp9XkghTEbV9KlPS1xUsZ3u7/IQO4wxtcFB4bgpQPRcR3QCvezPcQ=="
},
- "node_modules/write-file-atomic": {
- "version": "4.0.2",
- "resolved": "https://registry.npmjs.org/write-file-atomic/-/write-file-atomic-4.0.2.tgz",
- "integrity": "sha512-7KxauUdBmSdWnmpaGFg+ppNjKF8uNLry8LyzjauQDOVONfFLNKrKvQOxZ/VuTIcS/gge/YNahf5RIIQWTSarlg==",
- "dependencies": {
- "imurmurhash": "^0.1.4",
- "signal-exit": "^3.0.7"
- },
- "engines": {
- "node": "^12.13.0 || ^14.15.0 || >=16.0.0"
- }
- },
- "node_modules/write-file-atomic/node_modules/signal-exit": {
- "version": "3.0.7",
- "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz",
- "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ=="
- },
"node_modules/xtend": {
"version": "4.0.2",
"resolved": "https://registry.npmjs.org/xtend/-/xtend-4.0.2.tgz",
@@ -15202,7 +14295,8 @@
"node_modules/yallist": {
"version": "3.1.1",
"resolved": "https://registry.npmjs.org/yallist/-/yallist-3.1.1.tgz",
- "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g=="
+ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==",
+ "dev": true
},
"node_modules/yaml": {
"version": "1.10.2",
diff --git a/frontend/package.json b/frontend/package.json
index 1be7af583..721bdb17e 100644
--- a/frontend/package.json
+++ b/frontend/package.json
@@ -23,18 +23,23 @@
"@headlessui/react": "^1.7.8",
"@mui/base": "^5.0.0-beta.3",
"@mui/icons-material": "^5.14.9",
+ "@tanstack/query-core": "^5.17.19",
"@tanstack/react-query": "^5.0.5",
"@tanstack/react-query-devtools": "^5.4.2",
- "@webviz/subsurface-viewer": "^0.3.1",
+ "@webviz/subsurface-viewer": "^0.21.0",
"@webviz/well-completions-plot": "^0.0.1-alpha.1",
"animate.css": "^4.1.1",
"axios": "^1.6.5",
"culori": "^3.2.0",
+ "jotai": "^2.6.2",
+ "jotai-scope": "^0.5.1",
+ "jotai-tanstack-query": "^0.8.2",
"lodash": "^4.17.21",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"react-plotly.js": "^2.6.0",
- "uuid": "^9.0.0"
+ "uuid": "^9.0.0",
+ "wonka": "^6.3.4"
},
"devDependencies": {
"@playwright/experimental-ct-react": "^1.39.0",
@@ -70,4 +75,4 @@
"vite-plugin-checker": "^0.6.0",
"vitest": "^1.1.3"
}
-}
\ No newline at end of file
+}
diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx
index 2adc24f3e..74ed0657d 100644
--- a/frontend/src/App.tsx
+++ b/frontend/src/App.tsx
@@ -126,7 +126,7 @@ function App() {
);
}
- const isInitialisingApp = initAppState !== InitAppState.InitCompleted;
+ const isInitializingApp = initAppState !== InitAppState.InitCompleted;
return (
<>
@@ -138,12 +138,12 @@ function App() {