diff --git a/burr/tracking/server/run.py b/burr/tracking/server/run.py index 2e9759659..b6be79923 100644 --- a/burr/tracking/server/run.py +++ b/burr/tracking/server/run.py @@ -26,6 +26,7 @@ # TODO -- remove this, just for testing from burr.log_setup import setup_logging +from burr.tracking.server import workspace from burr.tracking.server.backend import ( AnnotationsBackendMixin, BackendBase, @@ -137,7 +138,10 @@ async def lifespan(app: FastAPI): global initialized initialized = True yield - await backend.lifespan(app).__anext__() + try: + await workspace.cleanup_processes() + finally: + await backend.lifespan(app).__anext__() def _get_app_spec() -> BackendSpec: @@ -151,6 +155,7 @@ def _get_app_spec() -> BackendSpec: snapshotting=is_snapshotting_backend, supports_demos=supports_demos, supports_annotations=is_annotations_backend, + supports_workspace=workspace.is_available(), ) @@ -342,6 +347,7 @@ async def version() -> dict: burr_version = "unknown" return {"version": burr_version} + ui_app.include_router(workspace.router, prefix="/api/v0/workspace") # Examples -- todo -- put them behind `if` statements ui_app.include_router(chatbot.router, prefix="/api/v0/chatbot") ui_app.include_router(email_assistant.router, prefix="/api/v0/email_assistant") diff --git a/burr/tracking/server/schema.py b/burr/tracking/server/schema.py index 749f1e3a2..78b277f8d 100644 --- a/burr/tracking/server/schema.py +++ b/burr/tracking/server/schema.py @@ -200,6 +200,7 @@ class BackendSpec(pydantic.BaseModel): snapshotting: bool supports_demos: bool supports_annotations: bool + supports_workspace: bool class AnnotationDataPointer(pydantic.BaseModel): diff --git a/burr/tracking/server/workspace.py b/burr/tracking/server/workspace.py new file mode 100644 index 000000000..e17564bc7 --- /dev/null +++ b/burr/tracking/server/workspace.py @@ -0,0 +1,700 @@ +# Licensed to the Apache Software Foundation (ASF) under one +# or more contributor license agreements. See the NOTICE file +# distributed with this work for additional information +# regarding copyright ownership. The ASF licenses this file +# to you under the Apache License, Version 2.0 (the +# "License"); you may not use this file except in compliance +# with the License. You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, +# software distributed under the License is distributed on an +# "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +# KIND, either express or implied. See the License for the +# specific language governing permissions and limitations +# under the License. + +"""Workspace API router for the Burr tracking server. + +Provides endpoints for: +- File browsing and content reading within a workspace directory +- Python script execution with SSE output streaming +- Process lifecycle management (start, stop, list) +- Workspace-to-project linking (stored in ~/.burr/workspace_links.json) +- Builder project persistence (stored in ~/.burr/builder_projects/) +- Burr ApplicationBuilder usage scanning across .py files +""" + +import asyncio +import json as json_module +import logging +import os +import re +import signal +import threading +import time +from typing import Dict, List, Optional + +from fastapi import APIRouter, HTTPException, Query +from fastapi.responses import StreamingResponse +from pydantic import BaseModel + +logger = logging.getLogger(__name__) + +router = APIRouter() + +_initialized = True # Module loaded successfully if we reach this point + +MAX_FILE_SIZE = 1_048_576 # 1MB + +LANGUAGE_MAP = { + ".py": "python", + ".js": "javascript", + ".ts": "typescript", + ".tsx": "tsx", + ".jsx": "jsx", + ".json": "json", + ".yaml": "yaml", + ".yml": "yaml", + ".toml": "toml", + ".md": "markdown", + ".html": "html", + ".css": "css", + ".sql": "sql", + ".sh": "bash", + ".txt": "text", +} + +BURR_APP_PATTERN = re.compile(r"ApplicationBuilder") + + +# --- Pydantic Models --- + + +class WorkspaceLinkRequest(BaseModel): + """Request body for linking a workspace directory to a project.""" + + project_id: str + workspace_path: str + + +class WorkspaceLinkInfo(BaseModel): + """Response for workspace link queries. workspace_path is None if not linked.""" + + project_id: str + workspace_path: Optional[str] + + +class BuilderProjectSave(BaseModel): + """Request body for saving a builder project.""" + + name: str + graph_json: str # JSON-serialized tree + + +class BuilderProjectSummary(BaseModel): + """Summary of a saved builder project (used in list responses).""" + + id: str + name: str + updated_at: float + + +class BuilderProjectFull(BaseModel): + """Full builder project including the serialized graph.""" + + id: str + name: str + graph_json: str + updated_at: float + + +class WorkspaceOpenRequest(BaseModel): + """Request body for opening/validating a workspace directory.""" + + path: str + + +class WorkspaceInfo(BaseModel): + """Basic info about an opened workspace.""" + + path: str + name: str + + +class FileEntry(BaseModel): + """A single file or directory entry in a workspace listing.""" + + name: str + path: str # relative to workspace root + is_dir: bool + size: int + modified: float + is_python: bool + has_burr_app: bool + + +class FileContent(BaseModel): + """Contents of a single file with detected language.""" + + path: str + content: str + language: str + size: int + + +class ProcessInfo(BaseModel): + """Status of a running or completed Python process.""" + + pid: int + script_path: str + started_at: float + status: str # "running" | "stopped" | "exited" + exit_code: Optional[int] + + +class RunRequest(BaseModel): + """Request body to start a Python script.""" + + workspace: str + script: str + + +# --- Security --- + + +def _validate_path(workspace: str, relative: str) -> str: + """Resolve and validate a file path within a workspace. + + Prevents path traversal by ensuring the resolved target stays within + the workspace directory. Uses os.sep suffix check to prevent /foo + matching /foobar. + + Args: + workspace: Absolute path to the workspace root. + relative: Relative path within the workspace (may be empty). + + Returns: + The resolved absolute path to the target. + + Raises: + HTTPException: 403 if path traversal is detected. + """ + workspace_real = os.path.realpath(workspace) + if relative: + target = os.path.realpath(os.path.join(workspace_real, relative)) + else: + target = workspace_real + # Use os.sep suffix to prevent /foo matching /foobar + if target != workspace_real and not target.startswith(workspace_real + os.sep): + raise HTTPException(status_code=403, detail="Path traversal detected") + return target + + +def _validate_workspace(workspace: str) -> str: + """Validate that a workspace path is registered via the /link endpoint. + + Checks the workspace against ~/.burr/workspace_links.json to ensure + only explicitly linked directories can be accessed. + + Args: + workspace: Absolute path to validate. + + Returns: + The resolved absolute path. + + Raises: + HTTPException: 400 if directory doesn't exist, 403 if not registered. + """ + workspace_real = os.path.realpath(workspace) + if not os.path.isdir(workspace_real): + raise HTTPException(status_code=400, detail="Workspace directory does not exist") + links = _read_links() + allowed = {os.path.realpath(p) for p in links.values()} + if workspace_real not in allowed: + raise HTTPException(status_code=403, detail="Workspace not registered") + return workspace_real + + +def _is_binary(file_path: str) -> bool: + """Detect if a file is binary by checking for null bytes in the first 8KB.""" + try: + with open(file_path, "rb") as f: + chunk = f.read(8192) + return b"\x00" in chunk + except OSError: + return True + + +# --- Workspace Links --- + +_LINKS_PATH = os.path.join(os.path.expanduser("~/.burr"), "workspace_links.json") + +# In-process cache for workspace links to avoid disk reads on every request. +_links_cache: Optional[dict] = None +_links_cache_lock = threading.Lock() + + +def _read_links() -> dict: + """Read workspace-to-project links from ~/.burr/workspace_links.json. + + Uses an in-process cache that is invalidated on writes via _write_links(). + """ + global _links_cache + with _links_cache_lock: + if _links_cache is not None: + return _links_cache + if os.path.exists(_LINKS_PATH): + with open(_LINKS_PATH, "r") as f: + data = json_module.load(f) + else: + data = {} + with _links_cache_lock: + _links_cache = data + return data + + +def _write_links(data: dict): + """Write workspace-to-project links to ~/.burr/workspace_links.json. + + Invalidates the in-process cache so subsequent reads pick up changes. + """ + global _links_cache + os.makedirs(os.path.dirname(_LINKS_PATH), exist_ok=True) + with open(_LINKS_PATH, "w") as f: + json_module.dump(data, f, indent=2) + with _links_cache_lock: + _links_cache = data + + +def is_available() -> bool: + """Return True if the workspace module initialized successfully. + + Used by run.py to dynamically set supports_workspace in the BackendSpec + instead of hardcoding True. + """ + return _initialized + + +# --- Process Management --- +# Uses asyncio.create_subprocess_exec which takes explicit argv (no shell injection). + +_processes: Dict[int, dict] = {} + + +async def cleanup_processes(): + """Terminate all tracked subprocesses. Called during FastAPI lifespan shutdown.""" + for pid, info in list(_processes.items()): + proc = info.get("process") + if proc and proc.returncode is None: + try: + proc.terminate() + await asyncio.wait_for(proc.wait(), timeout=5) + except (ProcessLookupError, asyncio.TimeoutError): + try: + proc.kill() + except ProcessLookupError: + pass + _processes.clear() + + +# --- Endpoints --- + + +@router.post("/open", response_model=WorkspaceInfo) +async def open_workspace(request: WorkspaceOpenRequest): + """Validate and return info about a workspace directory.""" + path = os.path.realpath(request.path) + if not os.path.isdir(path): + raise HTTPException(status_code=400, detail="Directory does not exist") + return WorkspaceInfo(path=path, name=os.path.basename(path)) + + +@router.get("/link", response_model=WorkspaceLinkInfo) +async def get_workspace_link(project_id: str = Query(...)): + """Get the linked workspace path for a project, or null if not linked.""" + links = _read_links() + return WorkspaceLinkInfo( + project_id=project_id, + workspace_path=links.get(project_id), + ) + + +@router.post("/link", response_model=WorkspaceLinkInfo) +async def set_workspace_link(request: WorkspaceLinkRequest): + """Link a workspace directory to a project.""" + path = os.path.realpath(request.workspace_path) + if not os.path.isdir(path): + raise HTTPException(status_code=400, detail="Directory does not exist") + links = _read_links() + links[request.project_id] = path + _write_links(links) + return WorkspaceLinkInfo(project_id=request.project_id, workspace_path=path) + + +@router.delete("/link") +async def remove_workspace_link(project_id: str = Query(...)): + """Remove the workspace link for a project.""" + links = _read_links() + links.pop(project_id, None) + _write_links(links) + return {"ok": True} + + +@router.get("/tree", response_model=List[FileEntry]) +async def get_tree( + workspace: str = Query(...), + relative_path: str = Query(""), +): + """List one level of a directory within a workspace.""" + _validate_workspace(workspace) + target = _validate_path(workspace, relative_path) + if not os.path.isdir(target): + raise HTTPException(status_code=400, detail="Not a directory") + + entries = [] + try: + for item in sorted(os.listdir(target)): + if item.startswith("."): + continue + full_path = os.path.join(target, item) + rel = os.path.relpath(full_path, os.path.realpath(workspace)) + try: + stat = os.stat(full_path) + except OSError: + continue + is_dir = os.path.isdir(full_path) + is_python = item.endswith(".py") + has_burr = False + if is_python and not is_dir: + try: + with open(full_path, "r", errors="ignore") as f: + content = f.read(65536) + has_burr = bool(BURR_APP_PATTERN.search(content)) + except OSError: + pass + entries.append( + FileEntry( + name=item, + path=rel, + is_dir=is_dir, + size=stat.st_size if not is_dir else 0, + modified=stat.st_mtime, + is_python=is_python, + has_burr_app=has_burr, + ) + ) + except PermissionError: + raise HTTPException(status_code=403, detail="Permission denied") + return entries + + +@router.get("/file", response_model=FileContent) +async def get_file( + workspace: str = Query(...), + relative_path: str = Query(...), +): + """Read the contents of a file within a workspace. Max 1MB, no binaries.""" + _validate_workspace(workspace) + target = _validate_path(workspace, relative_path) + if not os.path.isfile(target): + raise HTTPException(status_code=404, detail="File not found") + size = os.path.getsize(target) + if size > MAX_FILE_SIZE: + raise HTTPException(status_code=413, detail="File too large (max 1MB)") + if _is_binary(target): + raise HTTPException(status_code=415, detail="Binary file not supported") + + ext = os.path.splitext(target)[1].lower() + language = LANGUAGE_MAP.get(ext, "text") + + with open(target, "r", errors="replace") as f: + content = f.read() + + return FileContent( + path=relative_path, + content=content, + language=language, + size=size, + ) + + +@router.post("/run", response_model=ProcessInfo) +async def run_script(request: RunRequest): + """Start a Python script as a subprocess within a workspace.""" + _validate_workspace(request.workspace) + target = _validate_path(request.workspace, request.script) + if not os.path.isfile(target): + raise HTTPException(status_code=404, detail="Script not found") + if not target.endswith(".py"): + raise HTTPException(status_code=400, detail="Only Python scripts supported") + + # asyncio.create_subprocess_exec takes an explicit argv list, + # so there is no shell interpretation and no injection risk. + proc = await asyncio.create_subprocess_exec( + "python", + target, + stdout=asyncio.subprocess.PIPE, + stderr=asyncio.subprocess.PIPE, + cwd=os.path.realpath(request.workspace), + ) + + started_at = time.time() + info = { + "process": proc, + "script_path": request.script, + "started_at": started_at, + "workspace": request.workspace, + } + _processes[proc.pid] = info + + return ProcessInfo( + pid=proc.pid, + script_path=request.script, + started_at=started_at, + status="running", + exit_code=None, + ) + + +@router.get("/run/{pid}/output") +async def stream_output(pid: int): + """Stream stdout/stderr from a running process via Server-Sent Events.""" + if pid not in _processes: + raise HTTPException(status_code=404, detail="Process not found") + + proc = _processes[pid]["process"] + + async def event_generator(): + """Yield SSE-formatted lines by interleaving stdout and stderr.""" + + async def read_stream(stream, stream_type): + """Read lines from an async stream and yield them as SSE data.""" + while True: + line = await stream.readline() + if not line: + break + text = line.decode("utf-8", errors="replace") + yield f'data: {{"type": "{stream_type}", "data": {_json_escape(text)}}}\n\n' + + stdout_gen = read_stream(proc.stdout, "stdout") + stderr_gen = read_stream(proc.stderr, "stderr") + + stdout_done = False + stderr_done = False + + while not stdout_done or not stderr_done: + tasks = [] + if not stdout_done: + tasks.append(("stdout", stdout_gen)) + if not stderr_done: + tasks.append(("stderr", stderr_gen)) + + for name, gen in tasks: + try: + line = await asyncio.wait_for(gen.__anext__(), timeout=0.1) + yield line + except StopAsyncIteration: + if name == "stdout": + stdout_done = True + else: + stderr_done = True + except asyncio.TimeoutError: + continue + + exit_code = await proc.wait() + yield f'data: {{"type": "exit", "data": "{exit_code}"}}\n\n' + + return StreamingResponse( + event_generator(), + media_type="text/event-stream", + headers={ + "Cache-Control": "no-cache", + "Connection": "keep-alive", + "X-Accel-Buffering": "no", + }, + ) + + +@router.post("/run/{pid}/stop", response_model=ProcessInfo) +async def stop_process(pid: int): + """Send SIGTERM to a running process.""" + if pid not in _processes: + raise HTTPException(status_code=404, detail="Process not found") + + info = _processes[pid] + proc = info["process"] + + if proc.returncode is None: + try: + proc.send_signal(signal.SIGTERM) + await asyncio.wait_for(proc.wait(), timeout=5) + except (ProcessLookupError, asyncio.TimeoutError): + try: + proc.kill() + except ProcessLookupError: + pass + + return ProcessInfo( + pid=pid, + script_path=info["script_path"], + started_at=info["started_at"], + status="stopped" if proc.returncode is None else "exited", + exit_code=proc.returncode, + ) + + +@router.get("/processes", response_model=List[ProcessInfo]) +async def list_processes(workspace: str = Query(...)): + """List all tracked processes for a workspace.""" + _validate_workspace(workspace) + result = [] + for pid, info in _processes.items(): + if info["workspace"] != workspace: + continue + proc = info["process"] + if proc.returncode is None: + status = "running" + else: + status = "exited" + result.append( + ProcessInfo( + pid=pid, + script_path=info["script_path"], + started_at=info["started_at"], + status=status, + exit_code=proc.returncode, + ) + ) + return result + + +@router.get("/scan", response_model=List[FileEntry]) +async def scan_burr_apps(workspace: str = Query(...)): + """Scan a workspace for .py files containing ApplicationBuilder usage.""" + _validate_workspace(workspace) + workspace_real = os.path.realpath(workspace) + if not os.path.isdir(workspace_real): + raise HTTPException(status_code=400, detail="Workspace not found") + + results = [] + for root, dirs, filenames in os.walk(workspace_real): + dirs[:] = [ + d for d in dirs if not d.startswith(".") and d != "__pycache__" and d != "node_modules" + ] + for fname in filenames: + if not fname.endswith(".py"): + continue + full_path = os.path.join(root, fname) + rel = os.path.relpath(full_path, workspace_real) + try: + with open(full_path, "r", errors="ignore") as f: + content = f.read(65536) + if BURR_APP_PATTERN.search(content): + stat = os.stat(full_path) + results.append( + FileEntry( + name=fname, + path=rel, + is_dir=False, + size=stat.st_size, + modified=stat.st_mtime, + is_python=True, + has_burr_app=True, + ) + ) + except OSError: + continue + return results + + +def _json_escape(s: str) -> str: + """Escape a string for embedding in SSE JSON data.""" + import json + + return json.dumps(s) + + +# --- Builder Projects --- + +_BUILDER_DIR = os.path.join(os.path.expanduser("~/.burr"), "builder_projects") + + +def _ensure_builder_dir(): + """Create the builder projects directory if it doesn't exist.""" + os.makedirs(_BUILDER_DIR, exist_ok=True) + + +@router.get("/builder/projects", response_model=List[BuilderProjectSummary]) +async def list_builder_projects(): + """List all saved builder projects from ~/.burr/builder_projects/.""" + _ensure_builder_dir() + projects = [] + for fname in sorted(os.listdir(_BUILDER_DIR)): + if not fname.endswith(".json"): + continue + fpath = os.path.join(_BUILDER_DIR, fname) + try: + with open(fpath, "r") as f: + data = json_module.load(f) + projects.append( + BuilderProjectSummary( + id=fname.replace(".json", ""), + name=data.get("name", fname), + updated_at=os.path.getmtime(fpath), + ) + ) + except (OSError, json_module.JSONDecodeError): + continue + return sorted(projects, key=lambda p: p.updated_at, reverse=True) + + +@router.post("/builder/projects", response_model=BuilderProjectFull) +async def save_builder_project(request: BuilderProjectSave): + """Save a builder project graph to ~/.burr/builder_projects/.""" + _ensure_builder_dir() + # Generate ID from name + project_id = re.sub(r"[^a-zA-Z0-9_-]", "_", request.name).lower() + if not project_id: + project_id = "untitled" + fpath = os.path.join(_BUILDER_DIR, f"{project_id}.json") + data = { + "name": request.name, + "graph_json": request.graph_json, + } + with open(fpath, "w") as f: + json_module.dump(data, f, indent=2) + return BuilderProjectFull( + id=project_id, + name=request.name, + graph_json=request.graph_json, + updated_at=time.time(), + ) + + +@router.get("/builder/projects/{project_id}", response_model=BuilderProjectFull) +async def get_builder_project(project_id: str): + """Load a saved builder project by ID.""" + safe_id = re.sub(r"[^a-zA-Z0-9_-]", "", project_id) + fpath = os.path.join(_BUILDER_DIR, f"{safe_id}.json") + if not os.path.isfile(fpath): + raise HTTPException(status_code=404, detail="Project not found") + with open(fpath, "r") as f: + data = json_module.load(f) + return BuilderProjectFull( + id=safe_id, + name=data.get("name", safe_id), + graph_json=data.get("graph_json", "{}"), + updated_at=os.path.getmtime(fpath), + ) + + +@router.delete("/builder/projects/{project_id}") +async def delete_builder_project(project_id: str): + """Delete a saved builder project by ID.""" + safe_id = re.sub(r"[^a-zA-Z0-9_-]", "", project_id) + fpath = os.path.join(_BUILDER_DIR, f"{safe_id}.json") + if os.path.isfile(fpath): + os.remove(fpath) + return {"ok": True} diff --git a/telemetry/ui/package-lock.json b/telemetry/ui/package-lock.json index 737eb8992..1656fa1e5 100644 --- a/telemetry/ui/package-lock.json +++ b/telemetry/ui/package-lock.json @@ -11,10 +11,11 @@ "@headlessui/react": "^2.1.9", "@heroicons/react": "^2.1.1", "@microsoft/fetch-event-source": "^2.0.1", + "@monaco-editor/react": "^4.7.0", + "@tanstack/react-query": "^5.95.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", - "@tisoap/react-flow-smart-edge": "^3.0.0", "@types/fuse": "^2.6.0", "@types/jest": "^27.5.2", "@types/node": "^16.18.82", @@ -23,6 +24,7 @@ "@types/react-select": "^5.0.1", "@types/react-syntax-highlighter": "^15.5.11", "@uiw/react-json-view": "^2.0.0-alpha.12", + "@xyflow/react": "^12.10.1", "clsx": "^2.1.0", "dagre": "^0.8.5", "es-abstract": "^1.22.4", @@ -31,13 +33,12 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^5.0.1", + "react-joyride": "^2.9.3", "react-markdown": "^9.0.1", - "react-query": "^3.39.3", "react-router-dom": "^6.22.1", "react-scripts": "5.0.1", "react-select": "^5.8.1", "react-syntax-highlighter": "^15.5.0", - "reactflow": "^11.10.4", "remark-gfm": "^4.0.0", "string.prototype.matchall": "^4.0.10", "tailwindcss-question-mark": "^0.4.0", @@ -54,7 +55,7 @@ "eslint-plugin-react": "^7.33.2", "eslint-plugin-react-hooks": "^4.6.0", "husky": "^9.0.11", - "lint-staged": "^15.5.2", + "lint-staged": "^15.2.2", "openapi-typescript-codegen": "^0.27.0", "prettier": "^3.2.5", "react-json-tree": "^0.18.0", @@ -3245,20 +3246,22 @@ } }, "node_modules/@floating-ui/core": { - "version": "1.6.0", - "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.6.0.tgz", - "integrity": "sha512-PcF++MykgmTj3CIyOQbKA/hDzOAiqI3mhuoN44WRCopIs1sgoDoU4oty4Jtqaj/y3oDU6fnVSm4QG0a3t5i0+g==", + "version": "1.7.5", + "resolved": "https://registry.npmjs.org/@floating-ui/core/-/core-1.7.5.tgz", + "integrity": "sha512-1Ih4WTWyw0+lKyFMcBHGbb5U5FtuHJuujoyyr5zTaWS5EYMeT6Jb2AuDeftsCsEuchO+mM2ij5+q9crhydzLhQ==", + "license": "MIT", "dependencies": { - "@floating-ui/utils": "^0.2.1" + "@floating-ui/utils": "^0.2.11" } }, "node_modules/@floating-ui/dom": { - "version": "1.6.3", - "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.6.3.tgz", - "integrity": "sha512-RnDthu3mzPlQ31Ss/BTwQ1zjzIhr3lk1gZB1OC56h/1vEtaXkESrOqL5fQVMfXpwGtRwX+YsZBdyHtJMQnkArw==", + "version": "1.7.6", + "resolved": "https://registry.npmjs.org/@floating-ui/dom/-/dom-1.7.6.tgz", + "integrity": "sha512-9gZSAI5XM36880PPMm//9dfiEngYoC6Am2izES1FF406YFsjvyBMmeJ2g4SAju3xWwtuynNRFL2s9hgxpLI5SQ==", + "license": "MIT", "dependencies": { - "@floating-ui/core": "^1.0.0", - "@floating-ui/utils": "^0.2.0" + "@floating-ui/core": "^1.7.5", + "@floating-ui/utils": "^0.2.11" } }, "node_modules/@floating-ui/react": { @@ -3276,11 +3279,12 @@ } }, "node_modules/@floating-ui/react-dom": { - "version": "2.1.2", - "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.2.tgz", - "integrity": "sha512-06okr5cgPzMNBy+Ycse2A6udMi4bqwW/zgBF/rwjcNqWkyr82Mcg8b0vjX8OJpZFy/FKjJmw6wV7t44kK6kW7A==", + "version": "2.1.8", + "resolved": "https://registry.npmjs.org/@floating-ui/react-dom/-/react-dom-2.1.8.tgz", + "integrity": "sha512-cC52bHwM/n/CxS87FH0yWdngEZrjdtLW/qVruo68qg+prK7ZQ4YGdut2GyDVpoGeAYe/h899rVeOVm6Oi40k2A==", + "license": "MIT", "dependencies": { - "@floating-ui/dom": "^1.0.0" + "@floating-ui/dom": "^1.7.6" }, "peerDependencies": { "react": ">=16.8.0", @@ -3288,9 +3292,16 @@ } }, "node_modules/@floating-ui/utils": { - "version": "0.2.8", - "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.8.tgz", - "integrity": "sha512-kym7SodPp8/wloecOpcmSnWJsK7M0E5Wg8UcFA+uO4B9s5d0ywXOEro/8HM9x0rW+TljRzul/14UYz3TleT3ig==" + "version": "0.2.11", + "resolved": "https://registry.npmjs.org/@floating-ui/utils/-/utils-0.2.11.tgz", + "integrity": "sha512-RiB/yIh78pcIxl6lLMG0CgBXAZ2Y0eVHqMPYugu+9U0AeT6YBeiJpf7lbdJNIugFP5SIjwNRgo4DhR1Qxi26Gg==", + "license": "MIT" + }, + "node_modules/@gilbarbara/deep-equal": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.3.1.tgz", + "integrity": "sha512-I7xWjLs2YSVMc5gGx1Z3ZG1lgFpITPndpi8Ku55GeEIKpACCPQNS/OTqQbxgTCfq0Ncvcc+CrFov96itVh6Qvw==", + "license": "MIT" }, "node_modules/@graphql-codegen/add": { "version": "5.0.3", @@ -3603,18 +3614,14 @@ } }, "node_modules/@graphql-codegen/cli/node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", - "license": "ISC", + "version": "2.5.1", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.5.1.tgz", + "integrity": "sha512-bLQOjaX/ADgQ20isPJRvF0iRUHIxVhYvr53Of7wGcWlO2jvtUlH5m87DsmulFVxRpNLOnI4tB6p/oh8D7kpn9Q==", "bin": { "yaml": "bin.mjs" }, "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" + "node": ">= 14" } }, "node_modules/@graphql-codegen/cli/node_modules/yargs": { @@ -5535,10 +5542,9 @@ "integrity": "sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==" }, "node_modules/@jridgewell/trace-mapping": { - "version": "0.3.31", - "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.31.tgz", - "integrity": "sha512-zzNR+SdQSDJzc8joaeP8QQoCQr8NuYx2dIIytl1QeBEZHJ9uW6hebsrYgbz8hJwUQao3TWCMtmfV8Nu1twOLAw==", - "license": "MIT", + "version": "0.3.22", + "resolved": "https://registry.npmjs.org/@jridgewell/trace-mapping/-/trace-mapping-0.3.22.tgz", + "integrity": "sha512-Wf963MzWtA2sjrNt+g18IAln9lKnlRp+K2eH4jjIoF1wYeq3aMREpG09xhlhdzS0EjwU7qmUJYangWa+151vZw==", "dependencies": { "@jridgewell/resolve-uri": "^3.1.0", "@jridgewell/sourcemap-codec": "^1.4.14" @@ -5565,6 +5571,29 @@ "resolved": "https://registry.npmjs.org/@microsoft/fetch-event-source/-/fetch-event-source-2.0.1.tgz", "integrity": "sha512-W6CLUJ2eBMw3Rec70qrsEW0jOm/3twwJv21mrmj2yORiaVmVYGS4sSS5yUwvQc1ZlDLYGPnClVWmUUMagKNsfA==" }, + "node_modules/@monaco-editor/loader": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/loader/-/loader-1.7.0.tgz", + "integrity": "sha512-gIwR1HrJrrx+vfyOhYmCZ0/JcWqG5kbfG7+d3f/C1LXk2EvzAbHSg3MQ5lO2sMlo9izoAZ04shohfKLVT6crVA==", + "license": "MIT", + "dependencies": { + "state-local": "^1.0.6" + } + }, + "node_modules/@monaco-editor/react": { + "version": "4.7.0", + "resolved": "https://registry.npmjs.org/@monaco-editor/react/-/react-4.7.0.tgz", + "integrity": "sha512-cyzXQCtO47ydzxpQtCGSQGOC8Gk3ZUeBXFAxD+CWXYFo5OqZyZUonFl0DwUlTyAfRHntBfw2p3w4s9R6oe1eCA==", + "license": "MIT", + "dependencies": { + "@monaco-editor/loader": "^1.5.0" + }, + "peerDependencies": { + "monaco-editor": ">= 0.25.0 < 1", + "react": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0", + "react-dom": "^16.8.0 || ^17.0.0 || ^18.0.0 || ^19.0.0" + } + }, "node_modules/@next/env": { "version": "14.2.14", "resolved": "https://registry.npmjs.org/@next/env/-/env-14.2.14.tgz", @@ -6263,102 +6292,6 @@ "react": "^16.8.0 || ^17.0.0-rc.1 || ^18.0.0 || ^19.0.0" } }, - "node_modules/@reactflow/background": { - "version": "11.3.9", - "resolved": "https://registry.npmjs.org/@reactflow/background/-/background-11.3.9.tgz", - "integrity": "sha512-byj/G9pEC8tN0wT/ptcl/LkEP/BBfa33/SvBkqE4XwyofckqF87lKp573qGlisfnsijwAbpDlf81PuFL41So4Q==", - "dependencies": { - "@reactflow/core": "11.10.4", - "classcat": "^5.0.3", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/controls": { - "version": "11.2.9", - "resolved": "https://registry.npmjs.org/@reactflow/controls/-/controls-11.2.9.tgz", - "integrity": "sha512-e8nWplbYfOn83KN1BrxTXS17+enLyFnjZPbyDgHSRLtI5ZGPKF/8iRXV+VXb2LFVzlu4Wh3la/pkxtfP/0aguA==", - "dependencies": { - "@reactflow/core": "11.10.4", - "classcat": "^5.0.3", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/core": { - "version": "11.10.4", - "resolved": "https://registry.npmjs.org/@reactflow/core/-/core-11.10.4.tgz", - "integrity": "sha512-j3i9b2fsTX/sBbOm+RmNzYEFWbNx4jGWGuGooh2r1jQaE2eV+TLJgiG/VNOp0q5mBl9f6g1IXs3Gm86S9JfcGw==", - "dependencies": { - "@types/d3": "^7.4.0", - "@types/d3-drag": "^3.0.1", - "@types/d3-selection": "^3.0.3", - "@types/d3-zoom": "^3.0.1", - "classcat": "^5.0.3", - "d3-drag": "^3.0.0", - "d3-selection": "^3.0.0", - "d3-zoom": "^3.0.0", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/minimap": { - "version": "11.7.9", - "resolved": "https://registry.npmjs.org/@reactflow/minimap/-/minimap-11.7.9.tgz", - "integrity": "sha512-le95jyTtt3TEtJ1qa7tZ5hyM4S7gaEQkW43cixcMOZLu33VAdc2aCpJg/fXcRrrf7moN2Mbl9WIMNXUKsp5ILA==", - "dependencies": { - "@reactflow/core": "11.10.4", - "@types/d3-selection": "^3.0.3", - "@types/d3-zoom": "^3.0.1", - "classcat": "^5.0.3", - "d3-selection": "^3.0.0", - "d3-zoom": "^3.0.0", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/node-resizer": { - "version": "2.2.9", - "resolved": "https://registry.npmjs.org/@reactflow/node-resizer/-/node-resizer-2.2.9.tgz", - "integrity": "sha512-HfickMm0hPDIHt9qH997nLdgLt0kayQyslKE0RS/GZvZ4UMQJlx/NRRyj5y47Qyg0NnC66KYOQWDM9LLzRTnUg==", - "dependencies": { - "@reactflow/core": "11.10.4", - "classcat": "^5.0.4", - "d3-drag": "^3.0.0", - "d3-selection": "^3.0.0", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, - "node_modules/@reactflow/node-toolbar": { - "version": "1.3.9", - "resolved": "https://registry.npmjs.org/@reactflow/node-toolbar/-/node-toolbar-1.3.9.tgz", - "integrity": "sha512-VmgxKmToax4sX1biZ9LXA7cj/TBJ+E5cklLGwquCCVVxh+lxpZGTBF3a5FJGVHiUNBBtFsC8ldcSZIK4cAlQww==", - "dependencies": { - "@reactflow/core": "11.10.4", - "classcat": "^5.0.3", - "zustand": "^4.4.1" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, "node_modules/@remix-run/router": { "version": "1.15.1", "resolved": "https://registry.npmjs.org/@remix-run/router/-/router-1.15.1.tgz", @@ -6993,6 +6926,32 @@ "tslib": "^2.4.0" } }, + "node_modules/@tanstack/query-core": { + "version": "5.95.2", + "resolved": "https://registry.npmjs.org/@tanstack/query-core/-/query-core-5.95.2.tgz", + "integrity": "sha512-o4T8vZHZET4Bib3jZ/tCW9/7080urD4c+0/AUaYVpIqOsr7y0reBc1oX3ttNaSW5mYyvZHctiQ/UOP2PfdmFEQ==", + "license": "MIT", + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + } + }, + "node_modules/@tanstack/react-query": { + "version": "5.95.2", + "resolved": "https://registry.npmjs.org/@tanstack/react-query/-/react-query-5.95.2.tgz", + "integrity": "sha512-/wGkvLj/st5Ud1Q76KF1uFxScV7WeqN1slQx5280ycwAyYkIPGaRZAEgHxe3bjirSd5Zpwkj6zNcR4cqYni/ZA==", + "license": "MIT", + "dependencies": { + "@tanstack/query-core": "5.95.2" + }, + "funding": { + "type": "github", + "url": "https://github.com/sponsors/tannerlinsley" + }, + "peerDependencies": { + "react": "^18 || ^19" + } + }, "node_modules/@tanstack/react-virtual": { "version": "3.10.8", "resolved": "https://registry.npmjs.org/@tanstack/react-virtual/-/react-virtual-3.10.8.tgz", @@ -7320,24 +7279,6 @@ "@testing-library/dom": ">=7.21.4" } }, - "node_modules/@tisoap/react-flow-smart-edge": { - "version": "3.0.0", - "resolved": "https://registry.npmjs.org/@tisoap/react-flow-smart-edge/-/react-flow-smart-edge-3.0.0.tgz", - "integrity": "sha512-XtEQT0IrOqPwJvCzgEoj3Y16/EK4SOcjZO7FmOPU+qJWmgYjeTyv7J35CGm6dFeJYdZ2gHDrvQ1zwaXuo23/8g==", - "dependencies": { - "pathfinding": "0.4.18" - }, - "engines": { - "node": ">=16", - "npm": "^8.0.0" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17", - "reactflow": ">=11", - "typescript": ">=4.6" - } - }, "node_modules/@tootallnate/once": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/@tootallnate/once/-/once-1.1.2.tgz", @@ -7436,93 +7377,11 @@ "@types/node": "*" } }, - "node_modules/@types/d3": { - "version": "7.4.3", - "resolved": "https://registry.npmjs.org/@types/d3/-/d3-7.4.3.tgz", - "integrity": "sha512-lZXZ9ckh5R8uiFVt8ogUNf+pIrK4EsWrx2Np75WvF/eTpJ0FMHNhjXk8CKEx/+gpHbNQyJWehbFaTvqmHWB3ww==", - "dependencies": { - "@types/d3-array": "*", - "@types/d3-axis": "*", - "@types/d3-brush": "*", - "@types/d3-chord": "*", - "@types/d3-color": "*", - "@types/d3-contour": "*", - "@types/d3-delaunay": "*", - "@types/d3-dispatch": "*", - "@types/d3-drag": "*", - "@types/d3-dsv": "*", - "@types/d3-ease": "*", - "@types/d3-fetch": "*", - "@types/d3-force": "*", - "@types/d3-format": "*", - "@types/d3-geo": "*", - "@types/d3-hierarchy": "*", - "@types/d3-interpolate": "*", - "@types/d3-path": "*", - "@types/d3-polygon": "*", - "@types/d3-quadtree": "*", - "@types/d3-random": "*", - "@types/d3-scale": "*", - "@types/d3-scale-chromatic": "*", - "@types/d3-selection": "*", - "@types/d3-shape": "*", - "@types/d3-time": "*", - "@types/d3-time-format": "*", - "@types/d3-timer": "*", - "@types/d3-transition": "*", - "@types/d3-zoom": "*" - } - }, - "node_modules/@types/d3-array": { - "version": "3.2.1", - "resolved": "https://registry.npmjs.org/@types/d3-array/-/d3-array-3.2.1.tgz", - "integrity": "sha512-Y2Jn2idRrLzUfAKV2LyRImR+y4oa2AntrgID95SHJxuMUrkNXmanDSed71sRNZysveJVt1hLLemQZIady0FpEg==" - }, - "node_modules/@types/d3-axis": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-axis/-/d3-axis-3.0.6.tgz", - "integrity": "sha512-pYeijfZuBd87T0hGn0FO1vQ/cgLk6E1ALJjfkC0oJ8cbwkZl3TpgS8bVBLZN+2jjGgg38epgxb2zmoGtSfvgMw==", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-brush": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-brush/-/d3-brush-3.0.6.tgz", - "integrity": "sha512-nH60IZNNxEcrh6L1ZSMNA28rj27ut/2ZmI3r96Zd+1jrZD++zD3LsMIjWlvg4AYrHn/Pqz4CF3veCxGjtbqt7A==", - "dependencies": { - "@types/d3-selection": "*" - } - }, - "node_modules/@types/d3-chord": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-chord/-/d3-chord-3.0.6.tgz", - "integrity": "sha512-LFYWWd8nwfwEmTZG9PfQxd17HbNPksHBiJHaKuY1XeqscXacsS2tyoo6OdRsjf+NQYeB6XrNL3a25E3gH69lcg==" - }, "node_modules/@types/d3-color": { "version": "3.1.3", "resolved": "https://registry.npmjs.org/@types/d3-color/-/d3-color-3.1.3.tgz", "integrity": "sha512-iO90scth9WAbmgv7ogoq57O9YpKmFBbmoEoCHDB2xMBY0+/KVrqAaCDyCE16dUspeOvIxFFRI+0sEtqDqy2b4A==" }, - "node_modules/@types/d3-contour": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-contour/-/d3-contour-3.0.6.tgz", - "integrity": "sha512-BjzLgXGnCWjUSYGfH1cpdo41/hgdWETu4YxpezoztawmqsvCeep+8QGfiY6YbDvfgHz/DkjeIkkZVJavB4a3rg==", - "dependencies": { - "@types/d3-array": "*", - "@types/geojson": "*" - } - }, - "node_modules/@types/d3-delaunay": { - "version": "6.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-delaunay/-/d3-delaunay-6.0.4.tgz", - "integrity": "sha512-ZMaSKu4THYCU6sV64Lhg6qjf1orxBthaC161plr5KuPHo3CNm8DTHiLw/5Eq2b6TsNP0W0iJrUOFscY6Q450Hw==" - }, - "node_modules/@types/d3-dispatch": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-dispatch/-/d3-dispatch-3.0.6.tgz", - "integrity": "sha512-4fvZhzMeeuBJYZXRXrRIQnvUYfyXwYmLsdiN7XXmVNQKKw1cM8a5WdID0g1hVFZDqT9ZqZEY5pD44p24VS7iZQ==" - }, "node_modules/@types/d3-drag": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/@types/d3-drag/-/d3-drag-3.0.7.tgz", @@ -7531,47 +7390,6 @@ "@types/d3-selection": "*" } }, - "node_modules/@types/d3-dsv": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-dsv/-/d3-dsv-3.0.7.tgz", - "integrity": "sha512-n6QBF9/+XASqcKK6waudgL0pf/S5XHPPI8APyMLLUHd8NqouBGLsU8MgtO7NINGtPBtk9Kko/W4ea0oAspwh9g==" - }, - "node_modules/@types/d3-ease": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-ease/-/d3-ease-3.0.2.tgz", - "integrity": "sha512-NcV1JjO5oDzoK26oMzbILE6HW7uVXOHLQvHshBUW4UMdZGfiY6v5BeQwh9a9tCzv+CeefZQHJt5SRgK154RtiA==" - }, - "node_modules/@types/d3-fetch": { - "version": "3.0.7", - "resolved": "https://registry.npmjs.org/@types/d3-fetch/-/d3-fetch-3.0.7.tgz", - "integrity": "sha512-fTAfNmxSb9SOWNB9IoG5c8Hg6R+AzUHDRlsXsDZsNp6sxAEOP0tkP3gKkNSO/qmHPoBFTxNrjDprVHDQDvo5aA==", - "dependencies": { - "@types/d3-dsv": "*" - } - }, - "node_modules/@types/d3-force": { - "version": "3.0.9", - "resolved": "https://registry.npmjs.org/@types/d3-force/-/d3-force-3.0.9.tgz", - "integrity": "sha512-IKtvyFdb4Q0LWna6ymywQsEYjK/94SGhPrMfEr1TIc5OBeziTi+1jcCvttts8e0UWZIxpasjnQk9MNk/3iS+kA==" - }, - "node_modules/@types/d3-format": { - "version": "3.0.4", - "resolved": "https://registry.npmjs.org/@types/d3-format/-/d3-format-3.0.4.tgz", - "integrity": "sha512-fALi2aI6shfg7vM5KiR1wNJnZ7r6UuggVqtDA+xiEdPZQwy/trcQaHnwShLuLdta2rTymCNpxYTiMZX/e09F4g==" - }, - "node_modules/@types/d3-geo": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-geo/-/d3-geo-3.1.0.tgz", - "integrity": "sha512-856sckF0oP/diXtS4jNsiQw/UuK5fQG8l/a9VVLeSouf1/PPbBE1i1W852zVwKwYCBkFJJB7nCFTbk6UMEXBOQ==", - "dependencies": { - "@types/geojson": "*" - } - }, - "node_modules/@types/d3-hierarchy": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@types/d3-hierarchy/-/d3-hierarchy-3.1.6.tgz", - "integrity": "sha512-qlmD/8aMk5xGorUvTUWHCiumvgaUXYldYjNVOWtYoTYY/L+WwIEAmJxUmTgr9LoGNG0PPAOmqMDJVDPc7DOpPw==" - }, "node_modules/@types/d3-interpolate": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/@types/d3-interpolate/-/d3-interpolate-3.0.4.tgz", @@ -7580,67 +7398,11 @@ "@types/d3-color": "*" } }, - "node_modules/@types/d3-path": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/@types/d3-path/-/d3-path-3.1.0.tgz", - "integrity": "sha512-P2dlU/q51fkOc/Gfl3Ul9kicV7l+ra934qBFXCFhrZMOL6du1TM0pm1ThYvENukyOn5h9v+yMJ9Fn5JK4QozrQ==" - }, - "node_modules/@types/d3-polygon": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-polygon/-/d3-polygon-3.0.2.tgz", - "integrity": "sha512-ZuWOtMaHCkN9xoeEMr1ubW2nGWsp4nIql+OPQRstu4ypeZ+zk3YKqQT0CXVe/PYqrKpZAi+J9mTs05TKwjXSRA==" - }, - "node_modules/@types/d3-quadtree": { - "version": "3.0.6", - "resolved": "https://registry.npmjs.org/@types/d3-quadtree/-/d3-quadtree-3.0.6.tgz", - "integrity": "sha512-oUzyO1/Zm6rsxKRHA1vH0NEDG58HrT5icx/azi9MF1TWdtttWl0UIUsjEQBBh+SIkrpd21ZjEv7ptxWys1ncsg==" - }, - "node_modules/@types/d3-random": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-random/-/d3-random-3.0.3.tgz", - "integrity": "sha512-Imagg1vJ3y76Y2ea0871wpabqp613+8/r0mCLEBfdtqC7xMSfj9idOnmBYyMoULfHePJyxMAw3nWhJxzc+LFwQ==" - }, - "node_modules/@types/d3-scale": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/@types/d3-scale/-/d3-scale-4.0.8.tgz", - "integrity": "sha512-gkK1VVTr5iNiYJ7vWDI+yUFFlszhNMtVeneJ6lUTKPjprsvLLI9/tgEGiXJOnlINJA8FyA88gfnQsHbybVZrYQ==", - "dependencies": { - "@types/d3-time": "*" - } - }, - "node_modules/@types/d3-scale-chromatic": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-scale-chromatic/-/d3-scale-chromatic-3.0.3.tgz", - "integrity": "sha512-laXM4+1o5ImZv3RpFAsTRn3TEkzqkytiOY0Dz0sq5cnd1dtNlk6sHLon4OvqaiJb28T0S/TdsBI3Sjsy+keJrw==" - }, "node_modules/@types/d3-selection": { "version": "3.0.10", "resolved": "https://registry.npmjs.org/@types/d3-selection/-/d3-selection-3.0.10.tgz", "integrity": "sha512-cuHoUgS/V3hLdjJOLTT691+G2QoqAjCVLmr4kJXR4ha56w1Zdu8UUQ5TxLRqudgNjwXeQxKMq4j+lyf9sWuslg==" }, - "node_modules/@types/d3-shape": { - "version": "3.1.6", - "resolved": "https://registry.npmjs.org/@types/d3-shape/-/d3-shape-3.1.6.tgz", - "integrity": "sha512-5KKk5aKGu2I+O6SONMYSNflgiP0WfZIQvVUMan50wHsLG1G94JlxEVnCpQARfTtzytuY0p/9PXXZb3I7giofIA==", - "dependencies": { - "@types/d3-path": "*" - } - }, - "node_modules/@types/d3-time": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-time/-/d3-time-3.0.3.tgz", - "integrity": "sha512-2p6olUZ4w3s+07q3Tm2dbiMZy5pCDfYwtLXXHUnVzXgQlZ/OyPtUz6OL382BkOuGlLXqfT+wqv8Fw2v8/0geBw==" - }, - "node_modules/@types/d3-time-format": { - "version": "4.0.3", - "resolved": "https://registry.npmjs.org/@types/d3-time-format/-/d3-time-format-4.0.3.tgz", - "integrity": "sha512-5xg9rC+wWL8kdDj153qZcsJ0FWiFt0J5RB6LYUNZjwSnesfblqrI/bJ1wBdJ8OQfncgbJG5+2F+qfqnqyzYxyg==" - }, - "node_modules/@types/d3-timer": { - "version": "3.0.2", - "resolved": "https://registry.npmjs.org/@types/d3-timer/-/d3-timer-3.0.2.tgz", - "integrity": "sha512-Ps3T8E8dZDam6fUyNiMkekK3XUsaUEik+idO9/YjPtfj2qruF8tFBXS7XhtE4iIXBLxhmLjP3SXpLhVf21I9Lw==" - }, "node_modules/@types/d3-transition": { "version": "3.0.8", "resolved": "https://registry.npmjs.org/@types/d3-transition/-/d3-transition-3.0.8.tgz", @@ -7735,11 +7497,6 @@ "fuse": "*" } }, - "node_modules/@types/geojson": { - "version": "7946.0.14", - "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-7946.0.14.tgz", - "integrity": "sha512-WCfD5Ht3ZesJUsONdhvm84dmzWOiOzOAqOncN0++w0lBw1o8OuDNJF2McvvCef/yBqb/HYRahp1BYtODFQ8bRg==" - }, "node_modules/@types/graceful-fs": { "version": "4.1.9", "resolved": "https://registry.npmjs.org/@types/graceful-fs/-/graceful-fs-4.1.9.tgz", @@ -8176,11 +7933,10 @@ } }, "node_modules/@typescript-eslint/eslint-plugin/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -8322,11 +8078,10 @@ } }, "node_modules/@typescript-eslint/parser/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -8490,11 +8245,10 @@ } }, "node_modules/@typescript-eslint/type-utils/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dev": true, - "license": "MIT", "dependencies": { "balanced-match": "^1.0.0" } @@ -8659,148 +8413,133 @@ } }, "node_modules/@webassemblyjs/ast": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz", - "integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==", - "license": "MIT", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.11.6.tgz", + "integrity": "sha512-IN1xI7PwOvLPgjcf180gC1bqn3q/QaOCwYUahIOhbYUu8KA/3tw2RT/T0Gidi1l7Hhj5D/INhJxiICObqpMu4Q==", "dependencies": { - "@webassemblyjs/helper-numbers": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2" + "@webassemblyjs/helper-numbers": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6" } }, "node_modules/@webassemblyjs/floating-point-hex-parser": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz", - "integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA==", - "license": "MIT" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.11.6.tgz", + "integrity": "sha512-ejAj9hfRJ2XMsNHk/v6Fu2dGS+i4UaXBXGemOfQ/JfQ6mdQg/WXtwleQRLLS4OvfDhv8rYnVwH27YJLMyYsxhw==" }, "node_modules/@webassemblyjs/helper-api-error": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz", - "integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ==", - "license": "MIT" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.11.6.tgz", + "integrity": "sha512-o0YkoP4pVu4rN8aTJgAyj9hC2Sv5UlkzCHhxqWj8butaLvnpdc2jOwh4ewE6CX0txSfLn/UYaV/pheS2Txg//Q==" }, "node_modules/@webassemblyjs/helper-buffer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz", - "integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA==", - "license": "MIT" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.11.6.tgz", + "integrity": "sha512-z3nFzdcp1mb8nEOFFk8DrYLpHvhKC3grJD2ardfKOzmbmJvEf/tPIqCY+sNcwZIY8ZD7IkB2l7/pqhUhqm7hLA==" }, "node_modules/@webassemblyjs/helper-numbers": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz", - "integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==", - "license": "MIT", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.11.6.tgz", + "integrity": "sha512-vUIhZ8LZoIWHBohiEObxVm6hwP034jwmc9kuq5GdHZH0wiLVLIPcMCdpJzG4C11cHoQ25TFIQj9kaVADVX7N3g==", "dependencies": { - "@webassemblyjs/floating-point-hex-parser": "1.13.2", - "@webassemblyjs/helper-api-error": "1.13.2", + "@webassemblyjs/floating-point-hex-parser": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/helper-wasm-bytecode": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz", - "integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA==", - "license": "MIT" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.11.6.tgz", + "integrity": "sha512-sFFHKwcmBprO9e7Icf0+gddyWYDViL8bpPjJJl0WHxCdETktXdmtWLGVzoHbqUcY4Be1LkNfwTmXOJUFZYSJdA==" }, "node_modules/@webassemblyjs/helper-wasm-section": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz", - "integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==", - "license": "MIT", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.11.6.tgz", + "integrity": "sha512-LPpZbSOwTpEC2cgn4hTydySy1Ke+XEu+ETXuoyvuyezHO3Kjdu90KK95Sh9xTbmjrCsUwvWwCOQQNta37VrS9g==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/wasm-gen": "1.14.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6" } }, "node_modules/@webassemblyjs/ieee754": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz", - "integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==", - "license": "MIT", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.11.6.tgz", + "integrity": "sha512-LM4p2csPNvbij6U1f19v6WR56QZ8JcHg3QIJTlSwzFcmx6WSORicYj6I63f9yU1kEUtrpG+kjkiIAkevHpDXrg==", "dependencies": { "@xtuc/ieee754": "^1.2.0" } }, "node_modules/@webassemblyjs/leb128": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz", - "integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==", - "license": "Apache-2.0", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.11.6.tgz", + "integrity": "sha512-m7a0FhE67DQXgouf1tbN5XQcdWoNgaAuoULHIfGFIEVKA6tu/edls6XnIlkmS6FrXAquJRPni3ZZKjw6FSPjPQ==", "dependencies": { "@xtuc/long": "4.2.2" } }, "node_modules/@webassemblyjs/utf8": { - "version": "1.13.2", - "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz", - "integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ==", - "license": "MIT" + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.11.6.tgz", + "integrity": "sha512-vtXf2wTQ3+up9Zsg8sa2yWiQpzSsMyXj0qViVP6xKGCUT8p8YJ6HqI7l5eCnWx1T/FYdsv07HQs2wTFbbof/RA==" }, "node_modules/@webassemblyjs/wasm-edit": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz", - "integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==", - "license": "MIT", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.11.6.tgz", + "integrity": "sha512-Ybn2I6fnfIGuCR+Faaz7YcvtBKxvoLV3Lebn1tM4o/IAJzmi9AWYIPWpyBfU8cC+JxAO57bk4+zdsTjJR+VTOw==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/helper-wasm-section": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-opt": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1", - "@webassemblyjs/wast-printer": "1.14.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/helper-wasm-section": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-opt": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6", + "@webassemblyjs/wast-printer": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-gen": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz", - "integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==", - "license": "MIT", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.11.6.tgz", + "integrity": "sha512-3XOqkZP/y6B4F0PBAXvI1/bky7GryoogUtfwExeP/v7Nzwo1QLcq5oQmpKlftZLbT+ERUOAZVQjuNVak6UXjPA==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-opt": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz", - "integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==", - "license": "MIT", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.11.6.tgz", + "integrity": "sha512-cOrKuLRE7PCe6AsOVl7WasYf3wbSo4CeOk6PkrjS7g57MFfVUF9u6ysQBBODX0LdgSvQqRiGz3CXvIDKcPNy4g==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-buffer": "1.14.1", - "@webassemblyjs/wasm-gen": "1.14.1", - "@webassemblyjs/wasm-parser": "1.14.1" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-buffer": "1.11.6", + "@webassemblyjs/wasm-gen": "1.11.6", + "@webassemblyjs/wasm-parser": "1.11.6" } }, "node_modules/@webassemblyjs/wasm-parser": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz", - "integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==", - "license": "MIT", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.11.6.tgz", + "integrity": "sha512-6ZwPeGzMJM3Dqp3hCsLgESxBGtT/OeCvCZ4TA1JUPYgmhAx38tTPR9JaKy0S5H3evQpO/h2uWs2j6Yc/fjkpTQ==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", - "@webassemblyjs/helper-api-error": "1.13.2", - "@webassemblyjs/helper-wasm-bytecode": "1.13.2", - "@webassemblyjs/ieee754": "1.13.2", - "@webassemblyjs/leb128": "1.13.2", - "@webassemblyjs/utf8": "1.13.2" + "@webassemblyjs/ast": "1.11.6", + "@webassemblyjs/helper-api-error": "1.11.6", + "@webassemblyjs/helper-wasm-bytecode": "1.11.6", + "@webassemblyjs/ieee754": "1.11.6", + "@webassemblyjs/leb128": "1.11.6", + "@webassemblyjs/utf8": "1.11.6" } }, "node_modules/@webassemblyjs/wast-printer": { - "version": "1.14.1", - "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz", - "integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==", - "license": "MIT", + "version": "1.11.6", + "resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.11.6.tgz", + "integrity": "sha512-JM7AhRcE+yW2GWYaKeHL5vt4xqee5N2WcezptmgyhNS+ScggqcT1OtXykhAb13Sn5Yas0j2uv9tHgrjwvzAP4A==", "dependencies": { - "@webassemblyjs/ast": "1.14.1", + "@webassemblyjs/ast": "1.11.6", "@xtuc/long": "4.2.2" } }, @@ -8884,14 +8623,44 @@ "node_modules/@xtuc/ieee754": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz", - "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==", - "license": "BSD-3-Clause" + "integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA==" }, "node_modules/@xtuc/long": { "version": "4.2.2", "resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz", - "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==", - "license": "Apache-2.0" + "integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ==" + }, + "node_modules/@xyflow/react": { + "version": "12.10.1", + "resolved": "https://registry.npmjs.org/@xyflow/react/-/react-12.10.1.tgz", + "integrity": "sha512-5eSWtIK/+rkldOuFbOOz44CRgQRjtS9v5nufk77DV+XBnfCGL9HAQ8PG00o2ZYKqkEU/Ak6wrKC95Tu+2zuK3Q==", + "license": "MIT", + "dependencies": { + "@xyflow/system": "0.0.75", + "classcat": "^5.0.3", + "zustand": "^4.4.0" + }, + "peerDependencies": { + "react": ">=17", + "react-dom": ">=17" + } + }, + "node_modules/@xyflow/system": { + "version": "0.0.75", + "resolved": "https://registry.npmjs.org/@xyflow/system/-/system-0.0.75.tgz", + "integrity": "sha512-iXs+AGFLi8w/VlAoc/iSxk+CxfT6o64Uw/k0CKASOPqjqz6E0rb5jFZgJtXGZCpfQI6OQpu5EnumP5fGxQheaQ==", + "license": "MIT", + "dependencies": { + "@types/d3-drag": "^3.0.7", + "@types/d3-interpolate": "^3.0.4", + "@types/d3-selection": "^3.0.10", + "@types/d3-transition": "^3.0.8", + "@types/d3-zoom": "^3.0.8", + "d3-drag": "^3.0.0", + "d3-interpolate": "^3.0.1", + "d3-selection": "^3.0.0", + "d3-zoom": "^3.0.0" + } }, "node_modules/abab": { "version": "2.0.6", @@ -8912,10 +8681,9 @@ } }, "node_modules/acorn": { - "version": "8.15.0", - "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.15.0.tgz", - "integrity": "sha512-NZyJarBfL7nWwIq+FDL6Zp/yHEhePMNnnJ0y3qfieCrmNvYct8uvtiV41UvlSe6apAfk0fY1FbWx+NwfmpvtTg==", - "license": "MIT", + "version": "8.11.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-8.11.3.tgz", + "integrity": "sha512-Y9rRfJG5jcKOE0CLisYbojUjIrIEE7AGMzA/Sm4BslANhbS+cDMpgBdcPT91oJ7OuJ9hYJBx59RjbhxVnrF8Xg==", "bin": { "acorn": "bin/acorn" }, @@ -8943,16 +8711,12 @@ "node": ">=0.4.0" } }, - "node_modules/acorn-import-phases": { - "version": "1.0.4", - "resolved": "https://registry.npmjs.org/acorn-import-phases/-/acorn-import-phases-1.0.4.tgz", - "integrity": "sha512-wKmbr/DDiIXzEOiWrTTUcDm24kQ2vGfZQvM2fwg2vXqR5uW6aapr7ObPtj1th32b9u90/Pf4AItvdTh42fBmVQ==", - "license": "MIT", - "engines": { - "node": ">=10.13.0" - }, + "node_modules/acorn-import-assertions": { + "version": "1.9.0", + "resolved": "https://registry.npmjs.org/acorn-import-assertions/-/acorn-import-assertions-1.9.0.tgz", + "integrity": "sha512-cmMwop9x+8KFhxvKrKfPYmN6/pKTYYHBqLa0DfvVZcKMJWNyWLnaqND7dx/qn66R7ewM1UX5XMaDVP5wlVTaVA==", "peerDependencies": { - "acorn": "^8.14.0" + "acorn": "^8" } }, "node_modules/acorn-jsx": { @@ -9875,15 +9639,6 @@ } ] }, - "node_modules/baseline-browser-mapping": { - "version": "2.9.19", - "resolved": "https://registry.npmjs.org/baseline-browser-mapping/-/baseline-browser-mapping-2.9.19.tgz", - "integrity": "sha512-ipDqC8FrAl/76p2SSWKSI+H9tFwm7vYqXQrItCuiVPt26Km0jS+NzSsBWAaBusvSbQcfJG+JitdMm+wZAgTYqg==", - "license": "Apache-2.0", - "bin": { - "baseline-browser-mapping": "dist/cli.js" - } - }, "node_modules/batch": { "version": "0.6.1", "resolved": "https://registry.npmjs.org/batch/-/batch-0.6.1.tgz", @@ -9904,14 +9659,6 @@ "node": ">= 8.0.0" } }, - "node_modules/big-integer": { - "version": "1.6.52", - "resolved": "https://registry.npmjs.org/big-integer/-/big-integer-1.6.52.tgz", - "integrity": "sha512-QxD8cf2eVqJOOz63z6JIN9BzvVs/dlySa5HGSBH5xtR8dPteIRQnBxxKqkNTiT6jbDTF6jAfrd4oMcND9RGbQg==", - "engines": { - "node": ">=0.6" - } - }, "node_modules/big.js": { "version": "5.2.2", "resolved": "https://registry.npmjs.org/big.js/-/big.js-5.2.2.tgz", @@ -10036,51 +9783,34 @@ "integrity": "sha512-JZOSA7Mo9sNGB8+UjSgzdLtokWAky1zbztM3WRLCbZ70/3cTANmQmOdR7y2g+J0e2WXywy1yS468tY+IruqEww==" }, "node_modules/brace-expansion": { - "version": "1.1.13", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.13.tgz", - "integrity": "sha512-9ZLprWS6EENmhEOpjCYW2c8VkmOvckIJZfkr7rBW6dObmfgJ/L1GpSYW5Hpo9lDz4D1+n0Ckz8rU7FwHDQiG/w==", - "license": "MIT", + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", "dependencies": { "balanced-match": "^1.0.0", "concat-map": "0.0.1" } }, "node_modules/braces": { - "version": "3.0.3", - "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.3.tgz", - "integrity": "sha512-yQbXgO/OSZVD2IsiLlro+7Hf6Q18EJrKSEsdoMzKePKXct3gvD8oLcOQdIzGupr5Fj+EDe8gO/lxc1BzfMpxvA==", - "license": "MIT", + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/braces/-/braces-3.0.2.tgz", + "integrity": "sha512-b8um+L1RzM3WDSzvhm6gIz1yfTbBt6YTlcEKAvsmqCZZFw46z626lVj9j1yEPW33H5H+lBQpZMP1k8l+78Ha0A==", "dependencies": { - "fill-range": "^7.1.1" + "fill-range": "^7.0.1" }, "engines": { "node": ">=8" } }, - "node_modules/broadcast-channel": { - "version": "3.7.0", - "resolved": "https://registry.npmjs.org/broadcast-channel/-/broadcast-channel-3.7.0.tgz", - "integrity": "sha512-cIAKJXAxGJceNZGTZSBzMxzyOn72cVgPnKx4dc6LRjQgbaJUQqhy5rzL3zbMxkMWsGKkv2hSFkPRMEXfoMZ2Mg==", - "dependencies": { - "@babel/runtime": "^7.7.2", - "detect-node": "^2.1.0", - "js-sha3": "0.8.0", - "microseconds": "0.2.0", - "nano-time": "1.0.0", - "oblivious-set": "1.0.0", - "rimraf": "3.0.2", - "unload": "2.2.0" - } - }, "node_modules/browser-process-hrtime": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/browser-process-hrtime/-/browser-process-hrtime-1.0.0.tgz", "integrity": "sha512-9o5UecI3GhkpM6DrXr69PblIuWxPKk9Y0jHBRhdocZ2y7YECBFCsHm79Pr3OyR2AvjhDkabFJaDJMYRazHgsow==" }, "node_modules/browserslist": { - "version": "4.28.1", - "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.28.1.tgz", - "integrity": "sha512-ZC5Bd0LgJXgwGqUknZY/vkUQ04r8NXnJZ3yYi4vDmSiZmC/pdSN0NbNRPxZpbtO4uAfDUAFffO8IZoM3Gj8IkA==", + "version": "4.23.0", + "resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.23.0.tgz", + "integrity": "sha512-QW8HiM1shhT2GuzkvklfjcKDiWFXHOeFCIA/huJPwHsslwcydgk7X+z2zXpEijP98UCY7HbubZt5J2Zgvf0CaQ==", "funding": [ { "type": "opencollective", @@ -10095,13 +9825,11 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { - "baseline-browser-mapping": "^2.9.0", - "caniuse-lite": "^1.0.30001759", - "electron-to-chromium": "^1.5.263", - "node-releases": "^2.0.27", - "update-browserslist-db": "^1.2.0" + "caniuse-lite": "^1.0.30001587", + "electron-to-chromium": "^1.4.668", + "node-releases": "^2.0.14", + "update-browserslist-db": "^1.0.13" }, "bin": { "browserslist": "cli.js" @@ -10261,9 +9989,9 @@ } }, "node_modules/caniuse-lite": { - "version": "1.0.30001770", - "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001770.tgz", - "integrity": "sha512-x/2CLQ1jHENRbHg5PSId2sXq1CIO1CISvwWAj027ltMVG2UNgW+w9oH2+HzgEIRFembL8bUlXtfbBHR1fCg2xw==", + "version": "1.0.30001781", + "resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001781.tgz", + "integrity": "sha512-RdwNCyMsNBftLjW6w01z8bKEvT6e/5tpPVEgtn22TiLGlstHOVecsX2KHFkD5e/vRnIE4EGzpuIODb3mtswtkw==", "funding": [ { "type": "opencollective", @@ -10504,16 +10232,15 @@ } }, "node_modules/cli-cursor": { - "version": "5.0.0", - "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-5.0.0.tgz", - "integrity": "sha512-aCj4O5wKyszjMmDT4tZj93kxyydN/K5zPWSCe6/0AV/AA1pqe5ZBIw0a2ZfPQV7lL5/yb5HsUreJ6UFAF1tEQw==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-4.0.0.tgz", + "integrity": "sha512-VGtlMu3x/4DOtIUwEkRezxUZ2lBacNJCHash0N0WeZDBS+7Ux1dm3XWAgWYxLJFMMdOeXMHXorshEFhbMSGelg==", "dev": true, - "license": "MIT", "dependencies": { - "restore-cursor": "^5.0.0" + "restore-cursor": "^4.0.0" }, "engines": { - "node": ">=18" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" @@ -10535,7 +10262,6 @@ "resolved": "https://registry.npmjs.org/cli-truncate/-/cli-truncate-4.0.0.tgz", "integrity": "sha512-nPdaFdQ0h/GEigbPClz11D0v/ZJEwxmeVZGeMo3Z5StPtUTkA9o1lD6QwoirYiSDzbcwn2XcjwmCp68W1IS4TA==", "dev": true, - "license": "MIT", "dependencies": { "slice-ansi": "^5.0.0", "string-width": "^7.0.0" @@ -10548,11 +10274,10 @@ } }, "node_modules/cli-truncate/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -10561,18 +10286,16 @@ } }, "node_modules/cli-truncate/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true }, "node_modules/cli-truncate/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -10586,13 +10309,12 @@ } }, "node_modules/cli-truncate/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-regex": "^6.2.2" + "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" @@ -11508,12 +11230,11 @@ "integrity": "sha512-XRRe6Glud4rd/ZGQfiV1ruXSfbvfJedlV9Y6zOlP+2K04vBYiJEte6stfFkCP03aMnY5tsipamumUjL14fofug==" }, "node_modules/debug": { - "version": "4.4.3", - "resolved": "https://registry.npmjs.org/debug/-/debug-4.4.3.tgz", - "integrity": "sha512-RGwwWnwQvkVfavKVt22FGLw+xYSdzARwm0ru6DhTVA3umU5hZc28V3kO4stgYryrTlLpuvgI9GiijltAjNbcqA==", - "license": "MIT", + "version": "4.3.4", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.3.4.tgz", + "integrity": "sha512-PRWFHuSU3eDtQJPvnNY7Jcket1j0t5OuOsFzPPzsekD52Zl8qUfFIPEiswXqIvHWGVHOgX+7G/vCNNhehwxfkQ==", "dependencies": { - "ms": "^2.1.3" + "ms": "2.1.2" }, "engines": { "node": ">=6.0" @@ -11563,6 +11284,13 @@ "resolved": "https://registry.npmjs.org/dedent/-/dedent-0.7.0.tgz", "integrity": "sha512-Q6fKUPqnAHAyhiUgFU7BUzLiv0kd8saH9al7tnu5Q/okj6dnupxyTgFIBjVzJATdfIAm9NAsvXNzjaKa+bxVyA==" }, + "node_modules/deep-diff": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/deep-diff/-/deep-diff-1.0.2.tgz", + "integrity": "sha512-aWS3UIVH+NPGCD1kki+DCU9Dua032iSsO43LqQpcs4R3+dVv7tX0qBGjiVHJHjplsoUM2XRO/KB92glqc68awg==", + "deprecated": "Package no longer supported. Contact Support at https://www.npmjs.com/support for more info.", + "license": "MIT" + }, "node_modules/deep-equal": { "version": "2.2.3", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-2.2.3.tgz", @@ -11914,6 +11642,16 @@ "url": "https://github.com/fb55/domhandler?sponsor=1" } }, + "node_modules/dompurify": { + "version": "3.2.7", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.2.7.tgz", + "integrity": "sha512-WhL/YuveyGXJaerVlMYGWhvQswa7myDG17P7Vu65EWC05o8vfeNbvNf4d/BOvH99+ZW+LlQsc1GDKMa1vNK6dw==", + "license": "(MPL-2.0 OR Apache-2.0)", + "peer": true, + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/domutils": { "version": "2.8.0", "resolved": "https://registry.npmjs.org/domutils/-/domutils-2.8.0.tgz", @@ -12000,10 +11738,9 @@ } }, "node_modules/electron-to-chromium": { - "version": "1.5.286", - "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.286.tgz", - "integrity": "sha512-9tfDXhJ4RKFNerfjdCcZfufu49vg620741MNs26a9+bhLThdB+plgMeou98CAaHu/WATj2iHOOHTp1hWtABj2A==", - "license": "ISC" + "version": "1.4.673", + "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.4.673.tgz", + "integrity": "sha512-zjqzx4N7xGdl5468G+vcgzDhaHkaYgVcf9MqgexcTqsl2UHSCmOj/Bi3HAprg4BZCpC7HyD8a6nZl6QAZf72gw==" }, "node_modules/emittery": { "version": "0.8.1", @@ -12038,13 +11775,12 @@ } }, "node_modules/enhanced-resolve": { - "version": "5.19.0", - "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.19.0.tgz", - "integrity": "sha512-phv3E1Xl4tQOShqSte26C7Fl84EwUdZsyOuSSk9qtAGyyQs2s3jJzComh+Abf4g187lUUAvH+H26omrqia2aGg==", - "license": "MIT", + "version": "5.15.0", + "resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.15.0.tgz", + "integrity": "sha512-LXYT42KJ7lpIKECr2mAXIaMldcNCh/7E0KBKOu4KSfkHmP+mZmSs+8V5gBAqisWBy0OO4W5Oyys0GO1Y8KtdKg==", "dependencies": { "graceful-fs": "^4.2.4", - "tapable": "^2.3.0" + "tapable": "^2.2.0" }, "engines": { "node": ">=10.13.0" @@ -12066,19 +11802,6 @@ "node": ">=6" } }, - "node_modules/environment": { - "version": "1.1.0", - "resolved": "https://registry.npmjs.org/environment/-/environment-1.1.0.tgz", - "integrity": "sha512-xUtoPkMggbz0MPyPiIWr1Kp4aeWJjDZ6SMvURhimjdZgsRuDplF5/s9hcgGhyXMhs+6vpnuoiZ2kFiu3FMnS8Q==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/error-ex": { "version": "1.3.2", "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", @@ -12215,10 +11938,9 @@ } }, "node_modules/es-module-lexer": { - "version": "2.0.0", - "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-2.0.0.tgz", - "integrity": "sha512-5POEcUuZybH7IdmGsD8wlf0AI55wMecM9rVBTI/qEAy2c1kTOm3DjFYjrBdI2K3BaJjJYfYFeRtM0t9ssnRuxw==", - "license": "MIT" + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/es-module-lexer/-/es-module-lexer-1.4.1.tgz", + "integrity": "sha512-cXLGjP0c4T3flZJKQSuziYoq7MlT+rnvfZjfp7h+I7K9BNX54kP9nyWvdbwjQ4u1iWbOL4u96fgeZLToQlZC7w==" }, "node_modules/es-object-atoms": { "version": "1.1.1", @@ -12305,10 +12027,9 @@ } }, "node_modules/escalade": { - "version": "3.2.0", - "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.2.0.tgz", - "integrity": "sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==", - "license": "MIT", + "version": "3.1.2", + "resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.2.tgz", + "integrity": "sha512-ErCHMCae19vR8vQGe50xIsVomy19rg6gFu3+r3jkEO46suLMWBksvVyoGgQV+jOfl84ZSOSlmv6Gxa89PmTGmA==", "engines": { "node": ">=6" } @@ -13216,39 +12937,38 @@ } }, "node_modules/express": { - "version": "4.22.1", - "resolved": "https://registry.npmjs.org/express/-/express-4.22.1.tgz", - "integrity": "sha512-F2X8g9P1X7uCPZMA3MVf9wcTqlyNp7IhH5qPCI0izhaOIYXaW9L535tGA3qmjRzpH+bZczqq7hVKxTR4NWnu+g==", - "license": "MIT", + "version": "4.21.2", + "resolved": "https://registry.npmjs.org/express/-/express-4.21.2.tgz", + "integrity": "sha512-28HqgMZAmih1Czt9ny7qr6ek2qddF4FclbMzwhCREB6OFfH+rXAnuNCwo1/wFvrtbgsQDb4kSbX9de9lFbrXnA==", "dependencies": { "accepts": "~1.3.8", "array-flatten": "1.1.1", - "body-parser": "~1.20.3", - "content-disposition": "~0.5.4", + "body-parser": "1.20.3", + "content-disposition": "0.5.4", "content-type": "~1.0.4", - "cookie": "~0.7.1", - "cookie-signature": "~1.0.6", + "cookie": "0.7.1", + "cookie-signature": "1.0.6", "debug": "2.6.9", "depd": "2.0.0", "encodeurl": "~2.0.0", "escape-html": "~1.0.3", "etag": "~1.8.1", - "finalhandler": "~1.3.1", - "fresh": "~0.5.2", - "http-errors": "~2.0.0", + "finalhandler": "1.3.1", + "fresh": "0.5.2", + "http-errors": "2.0.0", "merge-descriptors": "1.0.3", "methods": "~1.1.2", - "on-finished": "~2.4.1", + "on-finished": "2.4.1", "parseurl": "~1.3.3", - "path-to-regexp": "~0.1.12", + "path-to-regexp": "0.1.12", "proxy-addr": "~2.0.7", - "qs": "~6.14.0", + "qs": "6.13.0", "range-parser": "~1.2.1", "safe-buffer": "5.2.1", - "send": "~0.19.0", - "serve-static": "~1.16.2", + "send": "0.19.0", + "serve-static": "1.16.2", "setprototypeof": "1.2.0", - "statuses": "~2.0.1", + "statuses": "2.0.1", "type-is": "~1.6.18", "utils-merge": "1.0.1", "vary": "~1.1.2" @@ -13274,21 +12994,6 @@ "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", "integrity": "sha512-Tpp60P6IUJDTuOq/5Z8cdskzJujfwqfOTkrwIwj7IRISpnkJnT6SyJ4PCPnGMoFjC9ddhal5KVIYtAt97ix05A==" }, - "node_modules/express/node_modules/qs": { - "version": "6.14.2", - "resolved": "https://registry.npmjs.org/qs/-/qs-6.14.2.tgz", - "integrity": "sha512-V/yCWTTF7VJ9hIh18Ugr2zhJMP01MY7c5kh4J870L7imm6/DIzBsNLTXzMwUA3yZ5b/KBqLx8Kp3uRvd7xSe3Q==", - "license": "BSD-3-Clause", - "dependencies": { - "side-channel": "^1.1.0" - }, - "engines": { - "node": ">=0.6" - }, - "funding": { - "url": "https://github.com/sponsors/ljharb" - } - }, "node_modules/extend": { "version": "3.0.2", "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", @@ -13389,22 +13094,6 @@ "fast-decode-uri-component": "^1.0.1" } }, - "node_modules/fast-uri": { - "version": "3.1.0", - "resolved": "https://registry.npmjs.org/fast-uri/-/fast-uri-3.1.0.tgz", - "integrity": "sha512-iPeeDKJSWf4IEOasVVrknXpaBV0IApz/gp7S2bb7Z4Lljbl2MGJRqInZiUrQwV16cpzw/D3S5j5Julj/gT52AA==", - "funding": [ - { - "type": "github", - "url": "https://github.com/sponsors/fastify" - }, - { - "type": "opencollective", - "url": "https://opencollective.com/fastify" - } - ], - "license": "BSD-3-Clause" - }, "node_modules/fast-url-parser": { "version": "1.1.3", "resolved": "https://registry.npmjs.org/fast-url-parser/-/fast-url-parser-1.1.3.tgz", @@ -13537,10 +13226,9 @@ } }, "node_modules/filelist/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", - "license": "MIT", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { "balanced-match": "^1.0.0" } @@ -13565,10 +13253,9 @@ } }, "node_modules/fill-range": { - "version": "7.1.1", - "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.1.1.tgz", - "integrity": "sha512-YsGpe3WHLK8ZYi4tWDg2Jy3ebRz2rXowDxnld4bkQB00cc/1Zw9AWnC0i9ztDJitivtQvaI9KaLyKrc+hBW0yg==", - "license": "MIT", + "version": "7.0.1", + "resolved": "https://registry.npmjs.org/fill-range/-/fill-range-7.0.1.tgz", + "integrity": "sha512-qOo9F+dMUmC2Lcb4BbVvnKJxTPjCm+RRpe4gDuGrzkL7mEVl/djYSu2OdQ2Pa302N4oqkSg9ir6jaLWJ2USVpQ==", "dependencies": { "to-regex-range": "^5.0.1" }, @@ -14610,11 +14297,10 @@ } }, "node_modules/get-east-asian-width": { - "version": "1.5.0", - "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.5.0.tgz", - "integrity": "sha512-CQ+bEO+Tva/qlmw24dCejulK5pMzVnUOFOijVogd3KQs07HnRIgp8TGipvCCRT06xeYEbpbgwaCxglFyiuIcmA==", + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/get-east-asian-width/-/get-east-asian-width-1.2.0.tgz", + "integrity": "sha512-2nk+7SIVb14QrgXFHcm84tD4bKQz0RxPuMT8Ag5KPOq7J5fEmAg0UbXdTOSHqNuHSU28k55qnceesxXRZGzKWA==", "dev": true, - "license": "MIT", "engines": { "node": ">=18" }, @@ -14882,10 +14568,9 @@ "integrity": "sha512-8+9WqebbFzpX9OR+Wa6O29asIogeRMzcGtAINdpMHHyAg10f05aSFVBbcEqGf/PXw1EjAZ+q2/bEBg3DvurK3Q==" }, "node_modules/graphql-config/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", - "license": "MIT", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { "balanced-match": "^1.0.0" } @@ -15079,11 +14764,10 @@ "integrity": "sha512-9Qn4yBxelxoh2Ow62nP+Ka/kMnOXRi8BXnRaUwezLNhqelnN49xKz4F/dPP8OYLxLxq6JDtZb2i9XznUQbNPTg==" }, "node_modules/handlebars": { - "version": "4.7.9", - "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.9.tgz", - "integrity": "sha512-4E71E0rpOaQuJR2A3xDZ+GM1HyWYv1clR58tC8emQNeQe3RH7MAzSbat+V0wG78LQBo6m6bzSG/L4pBuCsgnUQ==", + "version": "4.7.8", + "resolved": "https://registry.npmjs.org/handlebars/-/handlebars-4.7.8.tgz", + "integrity": "sha512-vafaFqs8MZkRrSX7sFVUdo3ap/eNiLnb4IakshzvP56X5Nr1iGKAIqdX6tMlm6HcNRIkr6AxO5jFEoJzzpT8aQ==", "dev": true, - "license": "MIT", "dependencies": { "minimist": "^1.2.5", "neo-async": "^2.6.2", @@ -15316,11 +15000,6 @@ "tslib": "^2.0.3" } }, - "node_modules/heap": { - "version": "0.2.5", - "resolved": "https://registry.npmjs.org/heap/-/heap-0.2.5.tgz", - "integrity": "sha512-G7HLD+WKcrOyJP5VQwYZNC3Z6FcQ7YYjEFiFoIj8PfEr73mu421o8B1N5DKUcc8K37EsJ2XXWA8DtrDz/2dReg==" - }, "node_modules/heroicons": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/heroicons/-/heroicons-2.1.1.tgz", @@ -16197,6 +15876,12 @@ "node": ">=8" } }, + "node_modules/is-lite": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/is-lite/-/is-lite-1.2.1.tgz", + "integrity": "sha512-pgF+L5bxC+10hLBgf6R2P4ZZUBOQIIacbdo8YvuCP8/JvsWxG7aZ9p10DYuLtifFci4l3VITphhMlMV4Y+urPw==", + "license": "MIT" + }, "node_modules/is-lower-case": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-lower-case/-/is-lower-case-2.0.2.tgz", @@ -16233,7 +15918,6 @@ "version": "7.0.0", "resolved": "https://registry.npmjs.org/is-number/-/is-number-7.0.0.tgz", "integrity": "sha512-41Cifkg6e8TylSpdtTpeLVMqvSBEVzTttHvERD741+pnZ8ANv0004MRL43QKPDlK9cGvNp6NZWZUBlbGXYxxng==", - "license": "MIT", "engines": { "node": ">=0.12.0" } @@ -18622,11 +18306,6 @@ "url": "https://github.com/sponsors/panva" } }, - "node_modules/js-sha3": { - "version": "0.8.0", - "resolved": "https://registry.npmjs.org/js-sha3/-/js-sha3-0.8.0.tgz", - "integrity": "sha512-gF1cRrHhIzNfToc802P800N8PpXS+evLLXfsVpowqmAFR9uwbi89WvXg2QspOmXL8QL86J4T1EpFu+yUkwJY3Q==" - }, "node_modules/js-tokens": { "version": "4.0.0", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", @@ -18894,22 +18573,21 @@ "integrity": "sha512-7ylylesZQ/PV29jhEDl3Ufjo6ZX7gCqJr5F7PKrqc93v7fzSymt1BpwEU8nAUXs8qzzvqhbjhK5QZg6Mt/HkBg==" }, "node_modules/lint-staged": { - "version": "15.5.2", - "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.5.2.tgz", - "integrity": "sha512-YUSOLq9VeRNAo/CTaVmhGDKG+LBtA8KF1X4K5+ykMSwWST1vDxJRB2kv2COgLb1fvpCo+A/y9A0G0znNVmdx4w==", + "version": "15.2.2", + "resolved": "https://registry.npmjs.org/lint-staged/-/lint-staged-15.2.2.tgz", + "integrity": "sha512-TiTt93OPh1OZOsb5B7k96A/ATl2AjIZo+vnzFZ6oHK5FuTk63ByDtxGQpHm+kFETjEWqgkF95M8FRXKR/LEBcw==", "dev": true, - "license": "MIT", "dependencies": { - "chalk": "^5.4.1", - "commander": "^13.1.0", - "debug": "^4.4.0", - "execa": "^8.0.1", - "lilconfig": "^3.1.3", - "listr2": "^8.2.5", - "micromatch": "^4.0.8", - "pidtree": "^0.6.0", - "string-argv": "^0.3.2", - "yaml": "^2.7.0" + "chalk": "5.3.0", + "commander": "11.1.0", + "debug": "4.3.4", + "execa": "8.0.1", + "lilconfig": "3.0.0", + "listr2": "8.0.1", + "micromatch": "4.0.5", + "pidtree": "0.6.0", + "string-argv": "0.3.2", + "yaml": "2.3.4" }, "bin": { "lint-staged": "bin/lint-staged.js" @@ -18922,11 +18600,10 @@ } }, "node_modules/lint-staged/node_modules/chalk": { - "version": "5.6.2", - "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.6.2.tgz", - "integrity": "sha512-7NzBL0rN6fMUW+f7A6Io4h40qQlG+xGmtMxfbnH/K7TAtt8JQWVQK+6g0UXKMeVJoyV5EkkNsErQ8pVD3bLHbA==", + "version": "5.3.0", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-5.3.0.tgz", + "integrity": "sha512-dLitG79d+GV1Nb/VYcCDFivJeK1hiukt9QjRNVOsUtTy1rR1YJsmpGGTZ3qJos+uw7WmWF4wUwBd9jxjocFC2w==", "dev": true, - "license": "MIT", "engines": { "node": "^12.17.0 || ^14.13 || >=16.0.0" }, @@ -18935,13 +18612,12 @@ } }, "node_modules/lint-staged/node_modules/commander": { - "version": "13.1.0", - "resolved": "https://registry.npmjs.org/commander/-/commander-13.1.0.tgz", - "integrity": "sha512-/rFeCpNJQbhSZjGVwO9RFV3xPqbnERS8MmIQzCtD/zl6gpJuV/bMLuN92oG3F7d8oDEHHRrujSXNUr8fpjntKw==", + "version": "11.1.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-11.1.0.tgz", + "integrity": "sha512-yPVavfyCcRhmorC7rWlkHn15b4wDVgVmBA7kV4QVBsF7kv/9TKJAbAXVTxvTnwP8HHKjRCJDClKbciiYS7p0DQ==", "dev": true, - "license": "MIT", "engines": { - "node": ">=18" + "node": ">=16" } }, "node_modules/lint-staged/node_modules/execa": { @@ -19001,16 +18677,12 @@ } }, "node_modules/lint-staged/node_modules/lilconfig": { - "version": "3.1.3", - "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.1.3.tgz", - "integrity": "sha512-/vlFKAoH5Cgt3Ie+JLhRbwOsCQePABiU3tJ1egGvyQ+33R/vcwM2Zl2QR/LzjsBeItPt3oSVXapn+m4nQDvpzw==", + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/lilconfig/-/lilconfig-3.0.0.tgz", + "integrity": "sha512-K2U4W2Ff5ibV7j7ydLr+zLAkIg5JJ4lPn1Ltsdt+Tz/IjQ8buJ55pZAxoP34lqIiwtF9iAvtLv3JGv7CAyAg+g==", "dev": true, - "license": "MIT", "engines": { "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/antonk52" } }, "node_modules/lint-staged/node_modules/mimic-fn": { @@ -19092,33 +18764,25 @@ } }, "node_modules/lint-staged/node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "dev": true, - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" + "node": ">= 14" } }, "node_modules/listr2": { - "version": "8.3.3", - "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.3.3.tgz", - "integrity": "sha512-LWzX2KsqcB1wqQ4AHgYb4RsDXauQiqhjLk+6hjbaeHG4zpjjVAB6wC/gz6X0l+Du1cN3pUB5ZlrvTbhGSNnUQQ==", + "version": "8.0.1", + "resolved": "https://registry.npmjs.org/listr2/-/listr2-8.0.1.tgz", + "integrity": "sha512-ovJXBXkKGfq+CwmKTjluEqFi3p4h8xvkxGQQAQan22YCgef4KZ1mKGjzfGh6PL6AW5Csw0QiQPNuQyH+6Xk3hA==", "dev": true, - "license": "MIT", "dependencies": { "cli-truncate": "^4.0.0", "colorette": "^2.0.20", "eventemitter3": "^5.0.1", - "log-update": "^6.1.0", - "rfdc": "^1.4.1", + "log-update": "^6.0.0", + "rfdc": "^1.3.0", "wrap-ansi": "^9.0.0" }, "engines": { @@ -19126,11 +18790,10 @@ } }, "node_modules/listr2/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -19139,11 +18802,10 @@ } }, "node_modules/listr2/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -19152,25 +18814,22 @@ } }, "node_modules/listr2/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true }, "node_modules/listr2/node_modules/eventemitter3": { - "version": "5.0.4", - "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.4.tgz", - "integrity": "sha512-mlsTRyGaPBjPedk6Bvw+aqbsXDtoAyAzm5MO7JgU+yVRyMQ5O8bD4Kcci7BS85f93veegeCPkL8R4GLClnjLFw==", - "dev": true, - "license": "MIT" + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/eventemitter3/-/eventemitter3-5.0.1.tgz", + "integrity": "sha512-GWkBvjiSZK87ELrYOSESUYeVIc9mvLLf/nXalMOS5dYrgZq9o5OVkbZAVM06CVxYsCwH9BDZFPlQTlPA1j4ahA==", + "dev": true }, "node_modules/listr2/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -19184,13 +18843,12 @@ } }, "node_modules/listr2/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-regex": "^6.2.2" + "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" @@ -19200,11 +18858,10 @@ } }, "node_modules/listr2/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -19218,16 +18875,11 @@ } }, "node_modules/loader-runner": { - "version": "4.3.1", - "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.1.tgz", - "integrity": "sha512-IWqP2SCPhyVFTBtRcgMHdzlf9ul25NwaFx4wCEH/KjAXuuHY4yNjvPXsBokp8jCB936PyWRaPKUNh8NvylLp2Q==", - "license": "MIT", + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/loader-runner/-/loader-runner-4.3.0.tgz", + "integrity": "sha512-3R/1M+yS3j5ou80Me59j7F9IMs4PXs3VqRrm0TU3AbKPxlmpoY1TNscJV/oGJXo8qCatFGTfDbY6W6ipGOYXfg==", "engines": { "node": ">=6.11.5" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" } }, "node_modules/loader-utils": { @@ -19384,15 +19036,14 @@ } }, "node_modules/log-update": { - "version": "6.1.0", - "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.1.0.tgz", - "integrity": "sha512-9ie8ItPR6tjY5uYJh8K/Zrv/RMZ5VOlOWvtZdEHYSTFKZfIBPQa9tOAEeAWhd+AnIneLJ22w5fjOYtoutpWq5w==", + "version": "6.0.0", + "resolved": "https://registry.npmjs.org/log-update/-/log-update-6.0.0.tgz", + "integrity": "sha512-niTvB4gqvtof056rRIrTZvjNYE4rCUzO6X/X+kYjd7WFxXeJ0NwEFnRxX6ehkvv3jTwrXnNdtAak5XYZuIyPFw==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-escapes": "^7.0.0", - "cli-cursor": "^5.0.0", - "slice-ansi": "^7.1.0", + "ansi-escapes": "^6.2.0", + "cli-cursor": "^4.0.0", + "slice-ansi": "^7.0.0", "strip-ansi": "^7.1.0", "wrap-ansi": "^9.0.0" }, @@ -19404,27 +19055,25 @@ } }, "node_modules/log-update/node_modules/ansi-escapes": { - "version": "7.3.0", - "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-7.3.0.tgz", - "integrity": "sha512-BvU8nYgGQBxcmMuEeUEmNTvrMVjJNSH7RgW24vXexN4Ven6qCvy4TntnvlnwnMLTVlcRQQdbRY8NKnaIoeWDNg==", + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-6.2.0.tgz", + "integrity": "sha512-kzRaCqXnpzWs+3z5ABPQiVke+iq0KXkHo8xiWV4RPTi5Yli0l97BEQuhXV1s7+aSU/fu1kUuxgS4MsQ0fRuygw==", "dev": true, - "license": "MIT", "dependencies": { - "environment": "^1.0.0" + "type-fest": "^3.0.0" }, "engines": { - "node": ">=18" + "node": ">=14.16" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, "node_modules/log-update/node_modules/ansi-regex": { - "version": "6.2.2", - "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.2.2.tgz", - "integrity": "sha512-Bq3SmSpyFHaWjPk8If9yc6svM8c56dB5BAtW4Qbw5jHTwwXXcTLoRMkpDJp6VL0XzlWaCHTXrkFURMYmD0sLqg==", + "version": "6.0.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-6.0.1.tgz", + "integrity": "sha512-n5M855fKb2SsfMIiFFoVrABHJC8QtHwVx+mHWP3QcEqBHYienj5dHSgjbxtC0WEZXYt4wcD6zrQElDPhFuZgfA==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -19433,11 +19082,10 @@ } }, "node_modules/log-update/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -19446,20 +19094,18 @@ } }, "node_modules/log-update/node_modules/emoji-regex": { - "version": "10.6.0", - "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.6.0.tgz", - "integrity": "sha512-toUI84YS5YmxW219erniWD0CIVOo46xGKColeNQRgOzDorgBi1v4D71/OFzgD9GO2UGKIv1C3Sp8DAn0+j5w7A==", - "dev": true, - "license": "MIT" + "version": "10.3.0", + "resolved": "https://registry.npmjs.org/emoji-regex/-/emoji-regex-10.3.0.tgz", + "integrity": "sha512-QpLs9D9v9kArv4lfDEgg1X/gN5XLnf/A6l9cs8SPZLRZR3ZkY9+kwIQTxm+fsSej5UMYGE8fdoaZVIBlqG0XTw==", + "dev": true }, "node_modules/log-update/node_modules/is-fullwidth-code-point": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.1.0.tgz", - "integrity": "sha512-5XHYaSyiqADb4RnZ1Bdad6cPp8Toise4TzEjcOYDHZkTCbKgiUl7WTUCpNWHuxmDt91wnsZBc9xinNzopv3JMQ==", + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-5.0.0.tgz", + "integrity": "sha512-OVa3u9kkBbw7b8Xw5F9P+D/T9X+Z4+JruYVNapTjPYZYUznQ5YfWeFkOj606XYYW8yugTfC8Pj0hYqvi4ryAhA==", "dev": true, - "license": "MIT", "dependencies": { - "get-east-asian-width": "^1.3.1" + "get-east-asian-width": "^1.0.0" }, "engines": { "node": ">=18" @@ -19469,11 +19115,10 @@ } }, "node_modules/log-update/node_modules/slice-ansi": { - "version": "7.1.2", - "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.2.tgz", - "integrity": "sha512-iOBWFgUX7caIZiuutICxVgX1SdxwAVFFKwt1EvMYYec/NWO5meOJ6K5uQxhrYBdQJne4KxiqZc+KptFOWFSI9w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-7.1.0.tgz", + "integrity": "sha512-bSiSngZ/jWeX93BqeIAbImyTbEihizcwNjFoRUIY/T1wWQsfsm2Vw1agPKylXvQTU7iASGdHhyqRlqQzfz+Htg==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "is-fullwidth-code-point": "^5.0.0" @@ -19486,11 +19131,10 @@ } }, "node_modules/log-update/node_modules/string-width": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.2.0.tgz", - "integrity": "sha512-tsaTIkKW9b4N+AEj+SVA+WhJzV7/zMhcSu78mLKWSk7cXMOSHsBKFWUs0fWwq8QyK3MgJBQRX6Gbi4kYbdvGkQ==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-7.1.0.tgz", + "integrity": "sha512-SEIJCWiX7Kg4c129n48aDRwLbFb2LJmXXFrWBG4NGaRtMQ3myKPKbwrD1BKqQn74oCoNMBVrfDEr5M9YxCsrkw==", "dev": true, - "license": "MIT", "dependencies": { "emoji-regex": "^10.3.0", "get-east-asian-width": "^1.0.0", @@ -19504,13 +19148,12 @@ } }, "node_modules/log-update/node_modules/strip-ansi": { - "version": "7.2.0", - "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.2.0.tgz", - "integrity": "sha512-yDPMNjp4WyfYBkHnjIRLfca1i6KMyGCtsVgoKe/z1+6vukgaENdgGBZt+ZmKPc4gavvEZ5OgHfHdrazhgNyG7w==", + "version": "7.1.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-7.1.0.tgz", + "integrity": "sha512-iq6eVVI64nQQTRYq2KtEg2d2uU7LElhTJwsH4YzIHZshxlgZms/wIc4VoDQTlG/IvVIrBKG06CrZnp0qv7hkcQ==", "dev": true, - "license": "MIT", "dependencies": { - "ansi-regex": "^6.2.2" + "ansi-regex": "^6.0.1" }, "engines": { "node": ">=12" @@ -19519,12 +19162,23 @@ "url": "https://github.com/chalk/strip-ansi?sponsor=1" } }, + "node_modules/log-update/node_modules/type-fest": { + "version": "3.13.1", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-3.13.1.tgz", + "integrity": "sha512-tLq3bSNx+xSpwvAJnzrK0Ep5CLNWjvFTOp71URMaAEWBfRb9nnJiBoUe0tF8bI4ZFO3omgBR6NvnbzVUT3Ly4g==", + "dev": true, + "engines": { + "node": ">=14.16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/log-update/node_modules/wrap-ansi": { - "version": "9.0.2", - "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.2.tgz", - "integrity": "sha512-42AtmgqjV+X1VpdOfyTGOYRi0/zsoLqtXQckTmqTeybT+BDIbM/Guxo7x3pE2vtpr1ok6xRqM9OpBe+Jyoqyww==", + "version": "9.0.0", + "resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-9.0.0.tgz", + "integrity": "sha512-G8ura3S+3Z2G+mkgNRq8dqaFZAuxfsxpBB8OCTGRTCtp+l/v9nbFNmCUP1BZMts3G1142MsZfn6eeUKrr4PD1Q==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.2.1", "string-width": "^7.0.0", @@ -19657,13 +19311,17 @@ "url": "https://github.com/sponsors/wooorm" } }, - "node_modules/match-sorter": { - "version": "6.3.4", - "resolved": "https://registry.npmjs.org/match-sorter/-/match-sorter-6.3.4.tgz", - "integrity": "sha512-jfZW7cWS5y/1xswZo8VBOdudUiSd9nifYRWphc9M5D/ee4w4AoXLgBEdRbgVaxbMuagBPeUC5y2Hi8DO6o9aDg==", - "dependencies": { - "@babel/runtime": "^7.23.8", - "remove-accents": "0.5.0" + "node_modules/marked": { + "version": "14.0.0", + "resolved": "https://registry.npmjs.org/marked/-/marked-14.0.0.tgz", + "integrity": "sha512-uIj4+faQ+MgHgwUW1l2PsPglZLOLOT1uErt06dAPtx2kjteLAkbsd/0FiYg/MGS+i7ZKLb7w2WClxHkzOOuryQ==", + "license": "MIT", + "peer": true, + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 18" } }, "node_modules/math-intrinsics": { @@ -20688,23 +20346,17 @@ ] }, "node_modules/micromatch": { - "version": "4.0.8", - "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.8.tgz", - "integrity": "sha512-PXwfBhYu0hBCPw8Dn0E+WDYb7af3dSLVWKi3HGv84IdF4TyFoC0ysxFd0Goxw7nSv4T/PzEJQxsYsEiFCKo2BA==", - "license": "MIT", + "version": "4.0.5", + "resolved": "https://registry.npmjs.org/micromatch/-/micromatch-4.0.5.tgz", + "integrity": "sha512-DMy+ERcEW2q8Z2Po+WNXuw3c5YaUSFjAO5GsJqfEl7UjvtIuFKO6ZrKvcItdy98dwFI2N1tg3zNIdKaQT+aNdA==", "dependencies": { - "braces": "^3.0.3", + "braces": "^3.0.2", "picomatch": "^2.3.1" }, "engines": { "node": ">=8.6" } }, - "node_modules/microseconds": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/microseconds/-/microseconds-0.2.0.tgz", - "integrity": "sha512-n7DHHMjR1avBbSpsTBj6fmMGh2AGrifVV4e+WYc3Q9lO+xnSZ3NyhcBND3vzzatt05LFhoKFRxrIyklmLlUtyA==" - }, "node_modules/mime": { "version": "1.6.0", "resolved": "https://registry.npmjs.org/mime/-/mime-1.6.0.tgz", @@ -20743,19 +20395,6 @@ "node": ">=6" } }, - "node_modules/mimic-function": { - "version": "5.0.1", - "resolved": "https://registry.npmjs.org/mimic-function/-/mimic-function-5.0.1.tgz", - "integrity": "sha512-VP79XUPxV2CigYP3jWwAUFSku2aKqBH7uTAapFWCBqutsbmDo96KY5o8uh6U+/YSIn5OxJnXp73beVkpqMIGhA==", - "dev": true, - "license": "MIT", - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, "node_modules/min-indent": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/min-indent/-/min-indent-1.0.1.tgz", @@ -20875,6 +20514,17 @@ "mkdirp": "bin/cmd.js" } }, + "node_modules/monaco-editor": { + "version": "0.55.1", + "resolved": "https://registry.npmjs.org/monaco-editor/-/monaco-editor-0.55.1.tgz", + "integrity": "sha512-jz4x+TJNFHwHtwuV9vA9rMujcZRb0CEilTEwG2rRSpe/A7Jdkuj8xPKttCgOh+v/lkHy7HsZ64oj+q3xoAFl9A==", + "license": "MIT", + "peer": true, + "dependencies": { + "dompurify": "3.2.7", + "marked": "14.0.0" + } + }, "node_modules/mri": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/mri/-/mri-1.2.0.tgz", @@ -20884,10 +20534,9 @@ } }, "node_modules/ms": { - "version": "2.1.3", - "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", - "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==", - "license": "MIT" + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.2.tgz", + "integrity": "sha512-sGkPx+VjMtmA6MX27oA4FBFELFCZZ4S4XqeGOXCv68tT+jb3vk/RyaKWP0PTKyWtmLSM0b+adUTEvbs1PEaH2w==" }, "node_modules/multicast-dns": { "version": "7.2.5", @@ -20916,14 +20565,6 @@ "thenify-all": "^1.0.0" } }, - "node_modules/nano-time": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/nano-time/-/nano-time-1.0.0.tgz", - "integrity": "sha512-flnngywOoQ0lLQOTRNexn2gGSNuM9bKj9RZAWSzhQ+UJYaAFG9bac4DW9VHjUAzrOaIcajHybCTHe/bkvozQqA==", - "dependencies": { - "big-integer": "^1.6.16" - } - }, "node_modules/nanoid": { "version": "3.3.7", "resolved": "https://registry.npmjs.org/nanoid/-/nanoid-3.3.7.tgz", @@ -21105,10 +20746,9 @@ } }, "node_modules/node-forge": { - "version": "1.4.0", - "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.4.0.tgz", - "integrity": "sha512-LarFH0+6VfriEhqMMcLX2F7SwSXeWwnEAJEsYm5QKWchiVYVvJyV9v7UDvUv+w5HO23ZpQTXDv/GxdDdMyOuoQ==", - "license": "(BSD-3-Clause OR GPL-2.0)", + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/node-forge/-/node-forge-1.3.1.tgz", + "integrity": "sha512-dPEtOeMvF9VMcYV/1Wb8CPoVAXtp6MKMlcbAt4ddqmGqUJ6fQZFXkNZNkNlfevtNkGtaSoXf/vNNNSvgrdXwtA==", "engines": { "node": ">= 6.13.0" } @@ -21119,10 +20759,9 @@ "integrity": "sha512-O5lz91xSOeoXP6DulyHfllpq+Eg00MWitZIbtPfoSEvqIHdl5gfcY6hYzDWnj0qD5tz52PI08u9qUvSVeUBeHw==" }, "node_modules/node-releases": { - "version": "2.0.27", - "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.27.tgz", - "integrity": "sha512-nmh3lCkYZ3grZvqcCH+fjmQ7X+H0OeZgP40OierEaAptX4XofMh5kwNbWh7lBduUzCcV/8kZ+NDLCwm2iorIlA==", - "license": "MIT" + "version": "2.0.14", + "resolved": "https://registry.npmjs.org/node-releases/-/node-releases-2.0.14.tgz", + "integrity": "sha512-y10wOWt8yZpqXmOgRo77WaHEmhYQYGNA6y421PKsKYWEK8aW+cqAphborZDhqfyKrbZEN92CN1X2KbafY2s7Yw==" }, "node_modules/normalize-path": { "version": "3.0.0", @@ -21337,11 +20976,6 @@ "url": "https://github.com/sponsors/ljharb" } }, - "node_modules/oblivious-set": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/oblivious-set/-/oblivious-set-1.0.0.tgz", - "integrity": "sha512-z+pI07qxo4c2CulUHCDf9lcqDlMSo72N/4rLUpRXf6fu+q8vjt8y0xS+Tlf8NTJDdTXHbdeO1n3MlbctwEoXZw==" - }, "node_modules/obuf": { "version": "1.1.2", "resolved": "https://registry.npmjs.org/obuf/-/obuf-1.1.2.tgz", @@ -21820,30 +21454,20 @@ "node": ">=8" } }, - "node_modules/pathfinding": { - "version": "0.4.18", - "resolved": "https://registry.npmjs.org/pathfinding/-/pathfinding-0.4.18.tgz", - "integrity": "sha512-R0TGEQ9GRcFCDvAWlJAWC+KGJ9SLbW4c0nuZRcioVlXVTlw+F5RvXQ8SQgSqI9KXWC1ew95vgmIiyaWTlCe9Ag==", - "dependencies": { - "heap": "0.2.5" - } - }, "node_modules/performance-now": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", "integrity": "sha512-7EAHlyLHI56VEIdK57uwHdHKIaAGbnXPiw0yWbarQZOKaKpvUIgW0jWRVLiatnM+XXlSwsanIBH/hzGMJulMow==" }, "node_modules/picocolors": { - "version": "1.1.1", - "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.1.tgz", - "integrity": "sha512-xceH2snhtb5M9liqDsmEw56le376mTZkEX/jEb/RxNFyegNul7eNslCXP9FDj/Lcu0X8KEyMceP2ntpaHrDEVA==", - "license": "ISC" + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/picocolors/-/picocolors-1.1.0.tgz", + "integrity": "sha512-TQ92mBOW0l3LeMeyLV6mzy/kWr8lkd/hp3mTg7wYK7zJhuBStmGMBG0BdeDZS/dZx1IukaX6Bk11zcln25o1Aw==" }, "node_modules/picomatch": { - "version": "2.3.2", - "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.2.tgz", - "integrity": "sha512-V7+vQEJ06Z+c5tSye8S+nHUfI51xoXIXjHQ99cQtKUkQqqO1kO/KCJUfZXuB47h/YBlDhah2H3hdUGXn8ie0oA==", - "license": "MIT", + "version": "2.3.1", + "resolved": "https://registry.npmjs.org/picomatch/-/picomatch-2.3.1.tgz", + "integrity": "sha512-JU3teHTNjmE2VCGFzuY8EXzCDVwEqB2a8fsIvwaStHhAWJEeVd1o1QD80CU6+ZdEXXSLbSsuLwJjkCBWqRQUVA==", "engines": { "node": ">=8.6" }, @@ -22005,6 +21629,17 @@ "node": ">=4" } }, + "node_modules/popper.js": { + "version": "1.16.1", + "resolved": "https://registry.npmjs.org/popper.js/-/popper.js-1.16.1.tgz", + "integrity": "sha512-Wb4p1J4zyFTbM+u6WuO4XstYx4Ky9Cewe4DWrel7B0w6VVICvPwdOpotjzcf6eD8TsckVnIMNONQyPIUFOUbCQ==", + "deprecated": "You can find the new Popper v2 at @popperjs/core, this package is dedicated to the legacy v1", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/popperjs" + } + }, "node_modules/postcss": { "version": "8.4.47", "resolved": "https://registry.npmjs.org/postcss/-/postcss-8.4.47.tgz", @@ -22507,18 +22142,11 @@ } }, "node_modules/postcss-load-config/node_modules/yaml": { - "version": "2.8.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.8.3.tgz", - "integrity": "sha512-AvbaCLOO2Otw/lW5bmh9d/WEdcDFdQp2Z2ZUH3pX9U2ihyUY0nvLv7J6TrWowklRGPYbB/IuIMfYgxaCPg5Bpg==", - "license": "ISC", - "bin": { - "yaml": "bin.mjs" - }, + "version": "2.3.4", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-2.3.4.tgz", + "integrity": "sha512-8aAvwVUSHpfEqTQ4w/KMlf3HcRdt50E5ODIQJBw1fQ5RL34xabzxtUlzTXVqc4rkZsPbvrXKWnABCD7kWSmocA==", "engines": { - "node": ">= 14.6" - }, - "funding": { - "url": "https://github.com/sponsors/eemeli" + "node": ">= 14" } }, "node_modules/postcss-loader": { @@ -23698,6 +23326,45 @@ "resolved": "https://registry.npmjs.org/react-error-overlay/-/react-error-overlay-6.0.11.tgz", "integrity": "sha512-/6UZ2qgEyH2aqzYZgQPxEnz33NJ2gNsnHA2o5+o4wW9bLM/JYQitNP9xPhsXwC08hMMovfGe/8retsdDsczPRg==" }, + "node_modules/react-floater": { + "version": "0.7.9", + "resolved": "https://registry.npmjs.org/react-floater/-/react-floater-0.7.9.tgz", + "integrity": "sha512-NXqyp9o8FAXOATOEo0ZpyaQ2KPb4cmPMXGWkx377QtJkIXHlHRAGer7ai0r0C1kG5gf+KJ6Gy+gdNIiosvSicg==", + "license": "MIT", + "dependencies": { + "deepmerge": "^4.3.1", + "is-lite": "^0.8.2", + "popper.js": "^1.16.0", + "prop-types": "^15.8.1", + "tree-changes": "^0.9.1" + }, + "peerDependencies": { + "react": "15 - 18", + "react-dom": "15 - 18" + } + }, + "node_modules/react-floater/node_modules/@gilbarbara/deep-equal": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/@gilbarbara/deep-equal/-/deep-equal-0.1.2.tgz", + "integrity": "sha512-jk+qzItoEb0D0xSSmrKDDzf9sheQj/BAPxlgNxgmOaA3mxpUa6ndJLYGZKsJnIVEQSD8zcTbyILz7I0HcnBCRA==", + "license": "MIT" + }, + "node_modules/react-floater/node_modules/is-lite": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/is-lite/-/is-lite-0.8.2.tgz", + "integrity": "sha512-JZfH47qTsslwaAsqbMI3Q6HNNjUuq6Cmzzww50TdP5Esb6e1y2sK2UAaZZuzfAzpoI2AkxoPQapZdlDuP6Vlsw==", + "license": "MIT" + }, + "node_modules/react-floater/node_modules/tree-changes": { + "version": "0.9.3", + "resolved": "https://registry.npmjs.org/tree-changes/-/tree-changes-0.9.3.tgz", + "integrity": "sha512-vvvS+O6kEeGRzMglTKbc19ltLWNtmNt1cpBoSYLj/iEcPVvpJasemKOlxBrmZaCtDJoF+4bwv3m01UKYi8mukQ==", + "license": "MIT", + "dependencies": { + "@gilbarbara/deep-equal": "^0.1.1", + "is-lite": "^0.8.2" + } + }, "node_modules/react-icons": { "version": "5.0.1", "resolved": "https://registry.npmjs.org/react-icons/-/react-icons-5.0.1.tgz", @@ -23706,11 +23373,62 @@ "react": "*" } }, + "node_modules/react-innertext": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/react-innertext/-/react-innertext-1.1.5.tgz", + "integrity": "sha512-PWAqdqhxhHIv80dT9znP2KvS+hfkbRovFp4zFYHFFlOoQLRiawIic81gKb3U1wEyJZgMwgs3JoLtwryASRWP3Q==", + "license": "MIT", + "peerDependencies": { + "@types/react": ">=0.0.0 <=99", + "react": ">=0.0.0 <=99" + } + }, "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/react-joyride": { + "version": "2.9.3", + "resolved": "https://registry.npmjs.org/react-joyride/-/react-joyride-2.9.3.tgz", + "integrity": "sha512-1+Mg34XK5zaqJ63eeBhqdbk7dlGCFp36FXwsEvgpjqrtyywX2C6h9vr3jgxP0bGHCw8Ilsp/nRDzNVq6HJ3rNw==", + "license": "MIT", + "dependencies": { + "@gilbarbara/deep-equal": "^0.3.1", + "deep-diff": "^1.0.2", + "deepmerge": "^4.3.1", + "is-lite": "^1.2.1", + "react-floater": "^0.7.9", + "react-innertext": "^1.1.5", + "react-is": "^16.13.1", + "scroll": "^3.0.1", + "scrollparent": "^2.1.0", + "tree-changes": "^0.11.2", + "type-fest": "^4.27.0" + }, + "peerDependencies": { + "react": "15 - 18", + "react-dom": "15 - 18" + } + }, + "node_modules/react-joyride/node_modules/react-is": { + "version": "16.13.1", + "resolved": "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz", + "integrity": "sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ==", + "license": "MIT" + }, + "node_modules/react-joyride/node_modules/type-fest": { + "version": "4.41.0", + "resolved": "https://registry.npmjs.org/type-fest/-/type-fest-4.41.0.tgz", + "integrity": "sha512-TeTSQ6H5YHvpqVwBRcnLDCBnDOHWYu7IvGbHT6N8AOymcr9PJGjc1GTtiWZTYg0NCgYwvnYWEkVChQAr9bjfwA==", + "license": "(MIT OR CC0-1.0)", + "engines": { + "node": ">=16" + }, + "funding": { + "url": "https://github.com/sponsors/sindresorhus" + } + }, "node_modules/react-json-tree": { "version": "0.18.0", "resolved": "https://registry.npmjs.org/react-json-tree/-/react-json-tree-0.18.0.tgz", @@ -23759,31 +23477,6 @@ "@types/unist": "*" } }, - "node_modules/react-query": { - "version": "3.39.3", - "resolved": "https://registry.npmjs.org/react-query/-/react-query-3.39.3.tgz", - "integrity": "sha512-nLfLz7GiohKTJDuT4us4X3h/8unOh+00MLb2yJoGTPjxKs2bc1iDhkNx2bd5MKklXnOD3NrVZ+J2UXujA5In4g==", - "dependencies": { - "@babel/runtime": "^7.5.5", - "broadcast-channel": "^3.4.1", - "match-sorter": "^6.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/tannerlinsley" - }, - "peerDependencies": { - "react": "^16.8.0 || ^17.0.0 || ^18.0.0" - }, - "peerDependenciesMeta": { - "react-dom": { - "optional": true - }, - "react-native": { - "optional": true - } - } - }, "node_modules/react-refresh": { "version": "0.11.0", "resolved": "https://registry.npmjs.org/react-refresh/-/react-refresh-0.11.0.tgz", @@ -23944,23 +23637,6 @@ "react-dom": ">=16.6.0" } }, - "node_modules/reactflow": { - "version": "11.10.4", - "resolved": "https://registry.npmjs.org/reactflow/-/reactflow-11.10.4.tgz", - "integrity": "sha512-0CApYhtYicXEDg/x2kvUHiUk26Qur8lAtTtiSlptNKuyEuGti6P1y5cS32YGaUoDMoCqkm/m+jcKkfMOvSCVRA==", - "dependencies": { - "@reactflow/background": "11.3.9", - "@reactflow/controls": "11.2.9", - "@reactflow/core": "11.10.4", - "@reactflow/minimap": "11.7.9", - "@reactflow/node-resizer": "2.2.9", - "@reactflow/node-toolbar": "1.3.9" - }, - "peerDependencies": { - "react": ">=17", - "react-dom": ">=17" - } - }, "node_modules/read-cache": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/read-cache/-/read-cache-1.0.0.tgz", @@ -24240,11 +23916,6 @@ "node": "*" } }, - "node_modules/remove-accents": { - "version": "0.5.0", - "resolved": "https://registry.npmjs.org/remove-accents/-/remove-accents-0.5.0.tgz", - "integrity": "sha512-8g3/Otx1eJaVD12e31UbJj1YzdtVvzH85HV7t+9MJYk/u3XmkOUJ5Ys9wQrf9PCPK8+xn4ymzqYCiZl6QWKn+A==" - }, "node_modules/remove-trailing-separator": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/remove-trailing-separator/-/remove-trailing-separator-1.1.0.tgz", @@ -24398,51 +24069,21 @@ } }, "node_modules/restore-cursor": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-5.1.0.tgz", - "integrity": "sha512-oMA2dcrw6u0YfxJQXm342bFKX/E4sG9rbTzO9ptUcR/e8A33cHuvStiYOwH7fszkZlZ1z/ta9AAoPk2F4qIOHA==", - "dev": true, - "license": "MIT", - "dependencies": { - "onetime": "^7.0.0", - "signal-exit": "^4.1.0" - }, - "engines": { - "node": ">=18" - }, - "funding": { - "url": "https://github.com/sponsors/sindresorhus" - } - }, - "node_modules/restore-cursor/node_modules/onetime": { - "version": "7.0.0", - "resolved": "https://registry.npmjs.org/onetime/-/onetime-7.0.0.tgz", - "integrity": "sha512-VXJjc87FScF88uafS3JllDgvAm+c/Slfz06lorj2uAY34rlUu0Nt+v8wreiImcrgAjjIHp1rXpTDlLOGw29WwQ==", + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-4.0.0.tgz", + "integrity": "sha512-I9fPXU9geO9bHOt9pHHOhOkYerIMsmVaWB0rA2AI9ERh/+x/i7MV5HKBNrg+ljO5eoPVgCcnFuRjJ9uH6I/3eg==", "dev": true, - "license": "MIT", "dependencies": { - "mimic-function": "^5.0.0" + "onetime": "^5.1.0", + "signal-exit": "^3.0.2" }, "engines": { - "node": ">=18" + "node": "^12.20.0 || ^14.13.1 || >=16.0.0" }, "funding": { "url": "https://github.com/sponsors/sindresorhus" } }, - "node_modules/restore-cursor/node_modules/signal-exit": { - "version": "4.1.0", - "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-4.1.0.tgz", - "integrity": "sha512-bzyZ1e88w9O1iNJbKnOlvYTrWPDl46O1bG0D3XInv+9tkPrxrN8jUUTiFlDkkmKWgn1M6CfIA13SuGqOa9Korw==", - "dev": true, - "license": "ISC", - "engines": { - "node": ">=14" - }, - "funding": { - "url": "https://github.com/sponsors/isaacs" - } - }, "node_modules/retry": { "version": "0.13.1", "resolved": "https://registry.npmjs.org/retry/-/retry-0.13.1.tgz", @@ -24461,10 +24102,9 @@ } }, "node_modules/rfdc": { - "version": "1.4.1", - "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.4.1.tgz", - "integrity": "sha512-q1b3N5QkRUWUl7iyylaaj3kOpIT0N2i9MqIEQXP73GVsN9cw3fdx8X63cEmWhJGi2PPCF23Ijp7ktmd39rawIA==", - "license": "MIT" + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/rfdc/-/rfdc-1.3.1.tgz", + "integrity": "sha512-r5a3l5HzYlIC68TpmYKlxWjmOP6wiPJ1vWv2HeLhNsRZMrCkxeqxiHlQ21oXmQ4F3SiryXBHhAD7JZqvOJjFmg==" }, "node_modules/rimraf": { "version": "3.0.2", @@ -24738,6 +24378,18 @@ "url": "https://opencollective.com/webpack" } }, + "node_modules/scroll": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/scroll/-/scroll-3.0.1.tgz", + "integrity": "sha512-pz7y517OVls1maEzlirKO5nPYle9AXsFzTMNJrRGmT951mzpIBy7sNHOg5o/0MQd/NqliCiWnAi0kZneMPFLcg==", + "license": "MIT" + }, + "node_modules/scrollparent": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/scrollparent/-/scrollparent-2.1.0.tgz", + "integrity": "sha512-bnnvJL28/Rtz/kz2+4wpBjHzWoEzXhVg/TE8BeVGJHUqE8THNIRnDxDWMktwM+qahvlRdvlLdsQfYe+cuqfZeA==", + "license": "ISC" + }, "node_modules/scuid": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/scuid/-/scuid-1.1.0.tgz", @@ -24839,6 +24491,11 @@ "node": ">= 0.8" } }, + "node_modules/send/node_modules/ms": { + "version": "2.1.3", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", + "integrity": "sha512-6FlzubTLZG3J2a/NVCAleEhjzq5oxgHyaCU9yYXvcLsvoVaHJq/s5xXI6/XXP6tz7R9xAOtHnSO/tXtF3WRTlA==" + }, "node_modules/sentence-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/sentence-case/-/sentence-case-3.0.4.tgz", @@ -25123,7 +24780,6 @@ "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-5.0.0.tgz", "integrity": "sha512-FC+lgizVPfie0kkhqUScwRu1O/lF6NOgJmlCgK+/LYxDCTk8sGelYaHDhFcDN+Sn3Cv+3VSa4Byeo+IMCzpMgQ==", "dev": true, - "license": "MIT", "dependencies": { "ansi-styles": "^6.0.0", "is-fullwidth-code-point": "^4.0.0" @@ -25136,11 +24792,10 @@ } }, "node_modules/slice-ansi/node_modules/ansi-styles": { - "version": "6.2.3", - "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.3.tgz", - "integrity": "sha512-4Dj6M28JB+oAH8kFkTLUo+a2jwOFkuqb3yucU0CANcRRUbxS0cP0nZYCGjcc3BNXwRIsUVmDGgzawme7zvJHvg==", + "version": "6.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-6.2.1.tgz", + "integrity": "sha512-bN798gFfQX+viw3R7yrGWRqnrN2oRkEkUjjl4JNn4E8GxxbjtG3FbrEIIY3l8/hrwUwIeCZvi4QuOTP4MErVug==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -25153,7 +24808,6 @@ "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-4.0.0.tgz", "integrity": "sha512-O4L094N2/dZ7xqVdrXhh9r1KODPJpFms8B5sGdJLPy664AgvXsreZUyCQQNItZRDlYug4xStLjNp/sz3HvBowQ==", "dev": true, - "license": "MIT", "engines": { "node": ">=12" }, @@ -25324,6 +24978,12 @@ "resolved": "https://registry.npmjs.org/stackframe/-/stackframe-1.3.4.tgz", "integrity": "sha512-oeVtt7eWQS+Na6F//S4kJ2K2VbRlS9D43mAlMyVpVWovy9o+jfgH8O9agzANzaiLjclA0oYzUXEM4PurhSUChw==" }, + "node_modules/state-local": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/state-local/-/state-local-1.0.7.tgz", + "integrity": "sha512-HTEHMNieakEnoe33shBYcZ7NX83ACUjCu8c40iOGEZsngj9zRnkqS9j1pqQPXwobB0ZcVTk27REb7COQ0UR59w==", + "license": "MIT" + }, "node_modules/static-eval": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/static-eval/-/static-eval-2.0.2.tgz", @@ -25797,10 +25457,9 @@ } }, "node_modules/sucrase/node_modules/brace-expansion": { - "version": "2.0.3", - "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.3.tgz", - "integrity": "sha512-MCV/fYJEbqx68aE58kv2cA/kiky1G8vux3OR6/jbS+jIMe/6fJWa0DTzJU7dqijOWYwHi1t29FlfYI9uytqlpA==", - "license": "MIT", + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-2.0.1.tgz", + "integrity": "sha512-XnAIvQ8eM+kC6aULx6wuQiwVsnzsi9d3WxzV3FpWTGA19F621kwdbsAcFKXgKUHZWsy+mY6iL1sHTxWEFCytDA==", "dependencies": { "balanced-match": "^1.0.0" } @@ -26065,16 +25724,11 @@ } }, "node_modules/tapable": { - "version": "2.3.0", - "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.3.0.tgz", - "integrity": "sha512-g9ljZiwki/LfxmQADO3dEY1CbpmXT5Hm2fJ+QaGKwSXUylMybePR7/67YW7jOrrvjEgL1Fmz5kzyAjWVWLlucg==", - "license": "MIT", + "version": "2.2.1", + "resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz", + "integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==", "engines": { "node": ">=6" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" } }, "node_modules/temp-dir": { @@ -26129,13 +25783,12 @@ } }, "node_modules/terser": { - "version": "5.46.0", - "resolved": "https://registry.npmjs.org/terser/-/terser-5.46.0.tgz", - "integrity": "sha512-jTwoImyr/QbOWFFso3YoU3ik0jBBDJ6JTOQiy/J2YxVJdZCc+5u7skhNwiOR3FQIygFqVUPHl7qbbxtjW2K3Qg==", - "license": "BSD-2-Clause", + "version": "5.27.1", + "resolved": "https://registry.npmjs.org/terser/-/terser-5.27.1.tgz", + "integrity": "sha512-29wAr6UU/oQpnTw5HoadwjUZnFQXGdOfj0LjZ4sVxzqwHh/QVkvr7m8y9WoR4iN3FRitVduTc6KdjcW38Npsug==", "dependencies": { "@jridgewell/source-map": "^0.3.3", - "acorn": "^8.15.0", + "acorn": "^8.8.2", "commander": "^2.20.0", "source-map-support": "~0.5.20" }, @@ -26147,16 +25800,15 @@ } }, "node_modules/terser-webpack-plugin": { - "version": "5.3.16", - "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.16.tgz", - "integrity": "sha512-h9oBFCWrq78NyWWVcSwZarJkZ01c2AyGrzs1crmHZO3QUg9D61Wu4NPjBy69n7JqylFF5y+CsUZYmYEIZ3mR+Q==", - "license": "MIT", + "version": "5.3.10", + "resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-5.3.10.tgz", + "integrity": "sha512-BKFPWlPDndPs+NGGCr1U59t0XScL5317Y0UReNrHaw9/FwhPENlq6bfgs+4yPfyP51vqC1bQ4rp1EfXW5ZSH9w==", "dependencies": { - "@jridgewell/trace-mapping": "^0.3.25", + "@jridgewell/trace-mapping": "^0.3.20", "jest-worker": "^27.4.5", - "schema-utils": "^4.3.0", - "serialize-javascript": "^6.0.2", - "terser": "^5.31.1" + "schema-utils": "^3.1.1", + "serialize-javascript": "^6.0.1", + "terser": "^5.26.0" }, "engines": { "node": ">= 10.13.0" @@ -26180,59 +25832,6 @@ } } }, - "node_modules/terser-webpack-plugin/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/terser-webpack-plugin/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, - "node_modules/terser-webpack-plugin/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "node_modules/terser-webpack-plugin/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/terser/node_modules/commander": { "version": "2.20.3", "resolved": "https://registry.npmjs.org/commander/-/commander-2.20.3.tgz", @@ -26326,7 +25925,6 @@ "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==", - "license": "MIT", "dependencies": { "is-number": "^7.0.0" }, @@ -26375,6 +25973,16 @@ "node": ">=8" } }, + "node_modules/tree-changes": { + "version": "0.11.3", + "resolved": "https://registry.npmjs.org/tree-changes/-/tree-changes-0.11.3.tgz", + "integrity": "sha512-r14mvDZ6tqz8PRQmlFKjhUVngu4VZ9d92ON3tp0EGpFBE6PAHOq8Bx8m8ahbNoGE3uI/npjYcJiqVydyOiYXag==", + "license": "MIT", + "dependencies": { + "@gilbarbara/deep-equal": "^0.3.1", + "is-lite": "^1.2.1" + } + }, "node_modules/trim-lines": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/trim-lines/-/trim-lines-3.0.1.tgz", @@ -26879,15 +26487,6 @@ "node": ">=0.10.0" } }, - "node_modules/unload": { - "version": "2.2.0", - "resolved": "https://registry.npmjs.org/unload/-/unload-2.2.0.tgz", - "integrity": "sha512-B60uB5TNBLtN6/LsgAf3udH9saB5p7gqJwcFfbOEZ8BcBHnGwCf6G/TGiEqkRAxX7zAFIUtzdrXQSdL3Q/wqNA==", - "dependencies": { - "@babel/runtime": "^7.6.2", - "detect-node": "^2.0.4" - } - }, "node_modules/unpipe": { "version": "1.0.0", "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", @@ -26911,9 +26510,9 @@ } }, "node_modules/update-browserslist-db": { - "version": "1.2.3", - "resolved": "https://registry.npmjs.org/update-browserslist-db/-/update-browserslist-db-1.2.3.tgz", - "integrity": "sha512-Js0m9cx+qOgDxo0eMiFGEueWztz+d4+M3rGlmKPT+T4IS/jP4ylw3Nwpu6cpTTP8R1MAC1kF4VbdLt3ARf209w==", + "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==", "funding": [ { "type": "opencollective", @@ -26928,10 +26527,9 @@ "url": "https://github.com/sponsors/ai" } ], - "license": "MIT", "dependencies": { - "escalade": "^3.2.0", - "picocolors": "^1.1.1" + "escalade": "^3.1.1", + "picocolors": "^1.0.0" }, "bin": { "update-browserslist-db": "cli.js" @@ -27187,10 +26785,9 @@ } }, "node_modules/watchpack": { - "version": "2.5.1", - "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.5.1.tgz", - "integrity": "sha512-Zn5uXdcFNIA1+1Ei5McRd+iRzfhENPCe7LeABkJtNulSxjma+l7ltNx55BWZkRlwRnpOgHqxnjyaDgJnNXnqzg==", - "license": "MIT", + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/watchpack/-/watchpack-2.4.0.tgz", + "integrity": "sha512-Lcvm7MGST/4fup+ifyKi2hjyIAwcdI4HRgtvTpIUxBRhB+RFtUh8XtDOxUfctVCnhVi+QQj49i91OyvzkJl6cg==", "dependencies": { "glob-to-regexp": "^0.4.1", "graceful-fs": "^4.1.2" @@ -27249,36 +26846,34 @@ } }, "node_modules/webpack": { - "version": "5.105.2", - "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.105.2.tgz", - "integrity": "sha512-dRXm0a2qcHPUBEzVk8uph0xWSjV/xZxenQQbLwnwP7caQCYpqG1qddwlyEkIDkYn0K8tvmcrZ+bOrzoQ3HxCDw==", - "license": "MIT", - "dependencies": { - "@types/eslint-scope": "^3.7.7", - "@types/estree": "^1.0.8", - "@types/json-schema": "^7.0.15", - "@webassemblyjs/ast": "^1.14.1", - "@webassemblyjs/wasm-edit": "^1.14.1", - "@webassemblyjs/wasm-parser": "^1.14.1", - "acorn": "^8.15.0", - "acorn-import-phases": "^1.0.3", - "browserslist": "^4.28.1", + "version": "5.90.2", + "resolved": "https://registry.npmjs.org/webpack/-/webpack-5.90.2.tgz", + "integrity": "sha512-ziXu8ABGr0InCMEYFnHrYweinHK2PWrMqnwdHk2oK3rRhv/1B+2FnfwYv5oD+RrknK/Pp/Hmyvu+eAsaMYhzCw==", + "dependencies": { + "@types/eslint-scope": "^3.7.3", + "@types/estree": "^1.0.5", + "@webassemblyjs/ast": "^1.11.5", + "@webassemblyjs/wasm-edit": "^1.11.5", + "@webassemblyjs/wasm-parser": "^1.11.5", + "acorn": "^8.7.1", + "acorn-import-assertions": "^1.9.0", + "browserslist": "^4.21.10", "chrome-trace-event": "^1.0.2", - "enhanced-resolve": "^5.19.0", - "es-module-lexer": "^2.0.0", + "enhanced-resolve": "^5.15.0", + "es-module-lexer": "^1.2.1", "eslint-scope": "5.1.1", "events": "^3.2.0", "glob-to-regexp": "^0.4.1", - "graceful-fs": "^4.2.11", + "graceful-fs": "^4.2.9", "json-parse-even-better-errors": "^2.3.1", - "loader-runner": "^4.3.1", + "loader-runner": "^4.2.0", "mime-types": "^2.1.27", "neo-async": "^2.6.2", - "schema-utils": "^4.3.3", - "tapable": "^2.3.0", - "terser-webpack-plugin": "^5.3.16", - "watchpack": "^2.5.1", - "webpack-sources": "^3.3.3" + "schema-utils": "^3.2.0", + "tapable": "^2.1.1", + "terser-webpack-plugin": "^5.3.10", + "watchpack": "^2.4.0", + "webpack-sources": "^3.2.3" }, "bin": { "webpack": "bin/webpack.js" @@ -27530,42 +27125,13 @@ } }, "node_modules/webpack-sources": { - "version": "3.3.4", - "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.3.4.tgz", - "integrity": "sha512-7tP1PdV4vF+lYPnkMR0jMY5/la2ub5Fc/8VQrrU+lXkiM6C4TjVfGw7iKfyhnTQOsD+6Q/iKw0eFciziRgD58Q==", - "license": "MIT", + "version": "3.2.3", + "resolved": "https://registry.npmjs.org/webpack-sources/-/webpack-sources-3.2.3.tgz", + "integrity": "sha512-/DyMEOrDgLKKIG0fmvtz+4dUX/3Ghozwgm6iPp8KRhvn+eQf9+Q7GWxVNMk3+uCPWfdXYC4ExGBckIXdFEfH1w==", "engines": { "node": ">=10.13.0" } }, - "node_modules/webpack/node_modules/ajv": { - "version": "8.18.0", - "resolved": "https://registry.npmjs.org/ajv/-/ajv-8.18.0.tgz", - "integrity": "sha512-PlXPeEWMXMZ7sPYOHqmDyCJzcfNrUr3fGNKtezX14ykXOEIvyK81d+qydx89KY5O71FKMPaQ2vBfBFI5NHR63A==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3", - "fast-uri": "^3.0.1", - "json-schema-traverse": "^1.0.0", - "require-from-string": "^2.0.2" - }, - "funding": { - "type": "github", - "url": "https://github.com/sponsors/epoberezkin" - } - }, - "node_modules/webpack/node_modules/ajv-keywords": { - "version": "5.1.0", - "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-5.1.0.tgz", - "integrity": "sha512-YCS/JNFAUyr5vAuhk1DWm1CBxRHW9LbJ2ozWeemrIqpbsqKjHVxYPyi5GC0rjZIT5JxJ3virVTS8wk4i/Z+krw==", - "license": "MIT", - "dependencies": { - "fast-deep-equal": "^3.1.3" - }, - "peerDependencies": { - "ajv": "^8.8.2" - } - }, "node_modules/webpack/node_modules/eslint-scope": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-5.1.1.tgz", @@ -27586,31 +27152,6 @@ "node": ">=4.0" } }, - "node_modules/webpack/node_modules/json-schema-traverse": { - "version": "1.0.0", - "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-1.0.0.tgz", - "integrity": "sha512-NM8/P9n3XjXhIZn1lLhkFaACTOURQXjWhV4BA/RnOv8xvgqtqpAX9IO4mRQxSx1Rlo4tqzeqb0sOlruaOy3dug==", - "license": "MIT" - }, - "node_modules/webpack/node_modules/schema-utils": { - "version": "4.3.3", - "resolved": "https://registry.npmjs.org/schema-utils/-/schema-utils-4.3.3.tgz", - "integrity": "sha512-eflK8wEtyOE6+hsaRVPxvUKYCpRgzLqDTb8krvAsRIwOGlHoSgYLgBXoubGgLd2fT41/OUYdb48v4k4WWHQurA==", - "license": "MIT", - "dependencies": { - "@types/json-schema": "^7.0.9", - "ajv": "^8.9.0", - "ajv-formats": "^2.1.1", - "ajv-keywords": "^5.1.0" - }, - "engines": { - "node": ">= 10.13.0" - }, - "funding": { - "type": "opencollective", - "url": "https://opencollective.com/webpack" - } - }, "node_modules/websocket-driver": { "version": "0.7.4", "resolved": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.7.4.tgz", @@ -28261,10 +27802,9 @@ "integrity": "sha512-a4UGQaWPH59mOXUYnAG2ewncQS4i4F43Tv3JoAM+s2VDAmS9NsK8GpDMLrCHPksFT7h3K6TOoUNn2pb7RoXx4g==" }, "node_modules/yaml": { - "version": "1.10.3", - "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.3.tgz", - "integrity": "sha512-vIYeF1u3CjlhAFekPPAk2h/Kv4T3mAkMox5OymRiJQB0spDP10LHvt+K7G9Ny6NuuMAb25/6n1qyUjAcGNf/AA==", - "license": "ISC", + "version": "1.10.2", + "resolved": "https://registry.npmjs.org/yaml/-/yaml-1.10.2.tgz", + "integrity": "sha512-r3vXyErRCYJ7wg28yvBY5VSoAF8ZvlcW9/BwUzEtUsjvX/DKs24dIkuwjtuprwJJHsbyUbLApepYTR1BN4uHrg==", "engines": { "node": ">= 6" } diff --git a/telemetry/ui/package.json b/telemetry/ui/package.json index ade1a96c0..78d36a17e 100644 --- a/telemetry/ui/package.json +++ b/telemetry/ui/package.json @@ -6,10 +6,12 @@ "@headlessui/react": "^2.1.9", "@heroicons/react": "^2.1.1", "@microsoft/fetch-event-source": "^2.0.1", + "@monaco-editor/react": "^4.7.0", + "@tanstack/react-query": "^5.95.0", "@testing-library/jest-dom": "^5.17.0", "@testing-library/react": "^13.4.0", "@testing-library/user-event": "^13.5.0", - "@tisoap/react-flow-smart-edge": "^3.0.0", + "@xyflow/react": "^12.0.0", "@types/fuse": "^2.6.0", "@types/jest": "^27.5.2", "@types/node": "^16.18.82", @@ -18,6 +20,7 @@ "@types/react-select": "^5.0.1", "@types/react-syntax-highlighter": "^15.5.11", "@uiw/react-json-view": "^2.0.0-alpha.12", + "@xyflow/react": "^12.10.1", "clsx": "^2.1.0", "dagre": "^0.8.5", "es-abstract": "^1.22.4", @@ -26,13 +29,12 @@ "react": "^18.2.0", "react-dom": "^18.2.0", "react-icons": "^5.0.1", + "react-joyride": "^3.0.0", "react-markdown": "^9.0.1", - "react-query": "^3.39.3", "react-router-dom": "^6.22.1", "react-scripts": "5.0.1", "react-select": "^5.8.1", "react-syntax-highlighter": "^15.5.0", - "reactflow": "^11.10.4", "remark-gfm": "^4.0.0", "string.prototype.matchall": "^4.0.10", "tailwindcss-question-mark": "^0.4.0", diff --git a/telemetry/ui/src/App.tsx b/telemetry/ui/src/App.tsx index 121337ae3..c57a584e7 100644 --- a/telemetry/ui/src/App.tsx +++ b/telemetry/ui/src/App.tsx @@ -22,7 +22,7 @@ import './App.css'; import { ProjectList } from './components/routes/ProjectList'; import { AppList } from './components/routes/AppList'; import { AppViewContainer } from './components/routes/app/AppView'; -import { QueryClient, QueryClientProvider } from 'react-query'; +import { QueryClient, QueryClientProvider } from '@tanstack/react-query'; import { AppContainer } from './components/nav/appcontainer'; import { ChatbotWithTelemetry } from './examples/Chatbot'; import { Counter } from './examples/Counter'; @@ -31,6 +31,9 @@ import { StreamingChatbotWithTelemetry } from './examples/StreamingChatbot'; import { AdminView } from './components/routes/AdminView'; import { AnnotationsViewContainer } from './components/routes/app/AnnotationsView'; import { DeepResearcherWithTelemetry } from './examples/DeepResearcher'; +import { BuilderView } from './components/routes/builder/BuilderView'; +import { WorkspaceSelector } from './components/routes/workspace/WorkspaceSelector'; +import GraphBuilder from './components/routes/graph-builder/components/GraphBuilder'; /** * Basic application. We have an AppContainer -- this has a breadcrumb and a sidebar. @@ -65,6 +68,10 @@ const App = () => { } /> } /> } /> + } /> + } /> + } /> + } /> } /> diff --git a/telemetry/ui/src/api/models/BackendSpec.ts b/telemetry/ui/src/api/models/BackendSpec.ts index b9fd7ede6..61a3ce163 100644 --- a/telemetry/ui/src/api/models/BackendSpec.ts +++ b/telemetry/ui/src/api/models/BackendSpec.ts @@ -29,4 +29,5 @@ export type BackendSpec = { snapshotting: boolean; supports_demos: boolean; supports_annotations: boolean; + supports_workspace: boolean; }; diff --git a/telemetry/ui/src/api/workspaceApi.ts b/telemetry/ui/src/api/workspaceApi.ts new file mode 100644 index 000000000..36be4826d --- /dev/null +++ b/telemetry/ui/src/api/workspaceApi.ts @@ -0,0 +1,185 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { fetchEventSource } from '@microsoft/fetch-event-source'; + +const BASE = '/api/v0/workspace'; + +export interface WorkspaceInfo { + path: string; + name: string; +} + +export interface FileEntry { + name: string; + path: string; + is_dir: boolean; + size: number; + modified: number; + is_python: boolean; + has_burr_app: boolean; +} + +export interface FileContent { + path: string; + content: string; + language: string; + size: number; +} + +export interface ProcessInfo { + pid: number; + script_path: string; + started_at: number; + status: string; + exit_code: number | null; +} + +export interface ProcessOutputEvent { + type: 'stdout' | 'stderr' | 'exit'; + data: string; +} + +export interface WorkspaceLinkInfo { + project_id: string; + workspace_path: string | null; +} + +export interface BuilderProjectSummary { + id: string; + name: string; + updated_at: number; +} + +export interface BuilderProjectFull { + id: string; + name: string; + graph_json: string; + updated_at: number; +} + +async function apiPost(path: string, body: unknown): Promise { + const res = await fetch(`${BASE}${path}`, { + method: 'POST', + headers: { 'Content-Type': 'application/json' }, + body: JSON.stringify(body) + }); + if (!res.ok) { + const detail = await res.json().catch(() => ({ detail: res.statusText })); + throw new Error(detail.detail || res.statusText); + } + return res.json(); +} + +async function apiGet(path: string, params?: Record): Promise { + const url = new URL(`${BASE}${path}`, window.location.origin); + if (params) { + Object.entries(params).forEach(([k, v]) => url.searchParams.set(k, v)); + } + const res = await fetch(url.toString()); + if (!res.ok) { + const detail = await res.json().catch(() => ({ detail: res.statusText })); + throw new Error(detail.detail || res.statusText); + } + return res.json(); +} + +export const workspaceApi = { + getWorkspaceLink(projectId: string): Promise { + return apiGet('/link', { project_id: projectId }); + }, + + setWorkspaceLink(projectId: string, workspacePath: string): Promise { + return apiPost('/link', { project_id: projectId, workspace_path: workspacePath }); + }, + + removeWorkspaceLink(projectId: string): Promise { + const url = new URL(`${BASE}/link`, window.location.origin); + url.searchParams.set('project_id', projectId); + return fetch(url.toString(), { method: 'DELETE' }).then(() => undefined); + }, + + openWorkspace(path: string): Promise { + return apiPost('/open', { path }); + }, + + getFileTree(workspace: string, relativePath = ''): Promise { + return apiGet('/tree', { workspace, relative_path: relativePath }); + }, + + getFileContent(workspace: string, relativePath: string): Promise { + return apiGet('/file', { workspace, relative_path: relativePath }); + }, + + runScript(workspace: string, script: string): Promise { + return apiPost('/run', { workspace, script }); + }, + + stopProcess(pid: number): Promise { + return apiPost(`/run/${pid}/stop`, {}); + }, + + getProcesses(workspace: string): Promise { + return apiGet('/processes', { workspace }); + }, + + scanBurrApps(workspace: string): Promise { + return apiGet('/scan', { workspace }); + }, + + listBuilderProjects(): Promise { + return apiGet('/builder/projects'); + }, + + saveBuilderProject(name: string, graphJson: string): Promise { + return apiPost('/builder/projects', { name, graph_json: graphJson }); + }, + + getBuilderProject(id: string): Promise { + return apiGet(`/builder/projects/${id}`); + }, + + deleteBuilderProject(id: string): Promise { + return fetch(`${BASE}/builder/projects/${id}`, { method: 'DELETE' }).then(() => undefined); + }, + + streamProcessOutput( + pid: number, + onEvent: (event: ProcessOutputEvent) => void, + onError: (err: Error) => void + ): AbortController { + const ctrl = new AbortController(); + fetchEventSource(`${BASE}/run/${pid}/output`, { + signal: ctrl.signal, + onmessage(ev) { + try { + const parsed: ProcessOutputEvent = JSON.parse(ev.data); + onEvent(parsed); + } catch { + // ignore parse errors + } + }, + onerror(err) { + onError(err instanceof Error ? err : new Error(String(err))); + }, + openWhenHidden: true + }); + return ctrl; + } +}; diff --git a/telemetry/ui/src/components/nav/appcontainer.tsx b/telemetry/ui/src/components/nav/appcontainer.tsx index 35c217e5f..ed0c86acc 100644 --- a/telemetry/ui/src/components/nav/appcontainer.tsx +++ b/telemetry/ui/src/components/nav/appcontainer.tsx @@ -22,6 +22,7 @@ import { Dialog, Disclosure, Transition } from '@headlessui/react'; import { ComputerDesktopIcon, Square2StackIcon, + SquaresPlusIcon, QuestionMarkCircleIcon, XMarkIcon, ChatBubbleLeftEllipsisIcon, @@ -36,7 +37,7 @@ import { Link } from 'react-router-dom'; import { classNames } from '../../utils/tailwind'; import React from 'react'; import { DefaultService } from '../../api'; -import { useQuery } from 'react-query'; +import { useQuery } from '@tanstack/react-query'; // Define your GitHub logo SVG as a React component const GithubLogo = () => ( @@ -45,7 +46,8 @@ const GithubLogo = () => ( xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 22 22" - stroke="currentColor"> + stroke="currentColor" + > {/* SVG path for GitHub logo */} void }) = export const AppContainer = (props: { children: React.ReactNode }) => { const [sidebarOpen, setSidebarOpen] = useState(true); const [smallSidebarOpen, setSmallSidebarOpen] = useState(false); - const { data: backendSpec } = useQuery(['backendSpec'], () => - DefaultService.getAppSpecApiV0MetadataAppSpecGet().then((response) => { - return response; - }) - ); + const { data: backendSpec } = useQuery({ + queryKey: ['backendSpec'], + queryFn: () => + DefaultService.getAppSpecApiV0MetadataAppSpecGet().then((response) => { + return response; + }) + }); const toggleSidebar = () => { setSidebarOpen(!sidebarOpen); }; @@ -99,6 +103,12 @@ export const AppContainer = (props: { children: React.ReactNode }) => { icon: Square2StackIcon, linkType: 'internal' }, + { + name: 'Graph Builder', + href: '/graph-builder', + icon: SquaresPlusIcon, + linkType: 'internal' + }, { name: 'Examples', href: 'https://github.com/apache/burr/tree/main/examples', @@ -191,7 +201,8 @@ export const AppContainer = (props: { children: React.ReactNode }) => { enterTo="opacity-100" leave="transition-opacity ease-linear duration-300" leaveFrom="opacity-100" - leaveTo="opacity-0"> + leaveTo="opacity-0" + >
@@ -203,7 +214,8 @@ export const AppContainer = (props: { children: React.ReactNode }) => { enterTo="translate-x-0" leave="transition ease-in-out duration-300 transform" leaveFrom="translate-x-0" - leaveTo="-translate-x-full"> + leaveTo="-translate-x-full" + > { enterTo="opacity-100" leave="ease-in-out duration-300" leaveFrom="opacity-100" - leaveTo="opacity-0"> + leaveTo="opacity-0" + >
@@ -249,7 +263,8 @@ export const AppContainer = (props: { children: React.ReactNode }) => { 'group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold' )} target={item.linkType === 'external' ? '_blank' : undefined} - rel={item.linkType === 'external' ? 'noreferrer' : undefined}> + rel={item.linkType === 'external' ? 'noreferrer' : undefined} + > {
+ }`} + > {/* Sidebar component, swap this element with another sidebar if you like */}
@@ -304,7 +320,8 @@ export const AppContainer = (props: { children: React.ReactNode }) => { 'group flex gap-x-3 rounded-md p-2 text-sm leading-6 font-semibold text-gray-700' )} target={item.linkType === 'external' ? '_blank' : undefined} - rel={item.linkType === 'external' ? 'noreferrer' : undefined}> + rel={item.linkType === 'external' ? 'noreferrer' : undefined} + >
- {/* This is a bit hacky -- just quickly prototyping and these margins were the ones that worked! */} -
-
+
+
-
-
{props.children}
+
+
{props.children}
diff --git a/telemetry/ui/src/components/routes/AdminView.tsx b/telemetry/ui/src/components/routes/AdminView.tsx index 287af2123..950f57c65 100644 --- a/telemetry/ui/src/components/routes/AdminView.tsx +++ b/telemetry/ui/src/components/routes/AdminView.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { useQuery } from 'react-query'; +import { useQuery } from '@tanstack/react-query'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../common/table'; import { DefaultService } from '../../api'; import { Loading } from '../common/loading'; @@ -53,13 +53,15 @@ const RecordsHeader = (props: { export const AdminView = () => { const [displayZeroCount, setDisplayZeroCount] = useState(false); - const { data, isLoading } = useQuery(['indexingJobs', displayZeroCount], () => - DefaultService.getIndexingJobsApiV0IndexingJobsGet( - 0, // TODO -- add pagination - 100, - !displayZeroCount - ) - ); + const { data, isLoading } = useQuery({ + queryKey: ['indexingJobs', displayZeroCount], + queryFn: () => + DefaultService.getIndexingJobsApiV0IndexingJobsGet( + 0, // TODO -- add pagination + 100, + !displayZeroCount + ) + }); if (isLoading) { return ; } diff --git a/telemetry/ui/src/components/routes/AppList.tsx b/telemetry/ui/src/components/routes/AppList.tsx index 03d105f95..9023ca064 100644 --- a/telemetry/ui/src/components/routes/AppList.tsx +++ b/telemetry/ui/src/components/routes/AppList.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { useQuery } from 'react-query'; +import { useQuery } from '@tanstack/react-query'; import { Navigate, useParams } from 'react-router'; import { Loading } from '../common/loading'; import { ApplicationSummary, DefaultService } from '../../api'; @@ -309,17 +309,17 @@ export const AppList = () => { const [searchParams] = useSearchParams(); const currentOffset = searchParams.get('offset') ? parseInt(searchParams.get('offset')!) : 0; const pageSize = DEFAULT_LIMIT; - const { data, error } = useQuery( - ['apps', projectId, partitionKey, pageSize, currentOffset], - () => + const { data, error } = useQuery({ + queryKey: ['apps', projectId, partitionKey, pageSize, currentOffset], + queryFn: () => DefaultService.getAppsApiV0ProjectIdPartitionKeyAppsGet( projectId as string, partitionKey ? partitionKey : '__none__', pageSize, currentOffset ), - { enabled: projectId !== undefined } - ); + enabled: projectId !== undefined + }); const [queriedData, setQueriedData] = useState(data); diff --git a/telemetry/ui/src/components/routes/ProjectList.tsx b/telemetry/ui/src/components/routes/ProjectList.tsx index 8ccabc836..cb96f0b3a 100644 --- a/telemetry/ui/src/components/routes/ProjectList.tsx +++ b/telemetry/ui/src/components/routes/ProjectList.tsx @@ -17,7 +17,7 @@ * under the License. */ -import { useQuery } from 'react-query'; +import { useQuery } from '@tanstack/react-query'; import { DefaultService, Project } from '../../api'; import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../common/table'; import { Loading } from '../common/loading'; @@ -114,12 +114,17 @@ export const ProjectListTable = (props: { projects: Project[]; includeAnnotation * Container for the table -- fetches the data and passes it to the table */ export const ProjectList = () => { - const { data, error } = useQuery('projects', DefaultService.getProjectsApiV0ProjectsGet); - const { data: backendSpec } = useQuery(['backendSpec'], () => - DefaultService.getAppSpecApiV0MetadataAppSpecGet().then((response) => { - return response; - }) - ); + const { data, error } = useQuery({ + queryKey: ['projects'], + queryFn: DefaultService.getProjectsApiV0ProjectsGet + }); + const { data: backendSpec } = useQuery({ + queryKey: ['backendSpec'], + queryFn: () => + DefaultService.getAppSpecApiV0MetadataAppSpecGet().then((response) => { + return response; + }) + }); if (error) return
Error loading projects
; if (data === undefined || backendSpec === undefined) return ; return ( diff --git a/telemetry/ui/src/components/routes/app/AnnotationsView.tsx b/telemetry/ui/src/components/routes/app/AnnotationsView.tsx index a8aa6b824..50c65ae9c 100644 --- a/telemetry/ui/src/components/routes/app/AnnotationsView.tsx +++ b/telemetry/ui/src/components/routes/app/AnnotationsView.tsx @@ -35,7 +35,7 @@ import { FaClipboardList, FaExternalLinkAlt, FaThumbsDown, FaThumbsUp } from 're import { Table, TableBody, TableCell, TableHead, TableHeader, TableRow } from '../../common/table'; import { Chip } from '../../common/chip'; import { Link } from 'react-router-dom'; -import { useMutation, useQuery } from 'react-query'; +import { useMutation, useQuery } from '@tanstack/react-query'; import { Loading } from '../../common/loading'; import { ChevronDownIcon, @@ -535,20 +535,18 @@ export const AnnotationsTable = (props: { refetchAnnotations?: () => void; }) => { // Just in case we want to do live-updating, we need to pass it into the form... - const updateAnnotationMutation = useMutation( - (data: { annotationID: number; annotationData: AnnotationUpdate }) => + const updateAnnotationMutation = useMutation({ + mutationFn: (data: { annotationID: number; annotationData: AnnotationUpdate }) => DefaultService.updateAnnotationApiV0ProjectIdAnnotationIdUpdateAnnotationsPut( props.projectId, data.annotationID, data.annotationData ), - { - onSuccess: () => { - props.refetchAnnotations && props.refetchAnnotations(); - setCurrentlyEditingAnnotation(null); // We have to reset it somehow - } + onSuccess: () => { + props.refetchAnnotations && props.refetchAnnotations(); + setCurrentlyEditingAnnotation(null); // We have to reset it somehow } - ); + }); const anyHavePartitionKey = props.annotations.some( (annotation) => annotation.partition_key !== null ); @@ -572,18 +570,16 @@ export const AnnotationsTable = (props: { actionName: currentlyEditingAnnotation?.step_name || '', spanId: currentlyEditingAnnotation?.span_id || null }; - const { data: appData } = useQuery( - ['steps', currentlyEditingAnnotation?.app_id], - () => + const { data: appData } = useQuery({ + queryKey: ['steps', currentlyEditingAnnotation?.app_id], + queryFn: () => DefaultService.getApplicationLogsApiV0ProjectIdAppIdPartitionKeyAppsGet( props.projectId, currentlyEditingAnnotation?.app_id as string, currentlyEditingAnnotation?.partition_key as string ), - { - enabled: currentlyEditingAnnotation !== null - } - ); + enabled: currentlyEditingAnnotation !== null + }); // Either we're editing one that exists, or we're creating a new one... // TODO -- simplify the logic here, we should have one path... const annotationStep = currentlyEditingAnnotation @@ -1229,16 +1225,19 @@ const AnnotationEditCreateForm = (props: { */ export const AnnotationsViewContainer = () => { const { projectId } = useLocationParams(); - const { data: backendSpec } = useQuery(['backendSpec'], () => - DefaultService.getAppSpecApiV0MetadataAppSpecGet().then((response) => { - return response; - }) - ); + const { data: backendSpec } = useQuery({ + queryKey: ['backendSpec'], + queryFn: () => + DefaultService.getAppSpecApiV0MetadataAppSpecGet().then((response) => { + return response; + }) + }); // TODO -- use a skiptoken to bypass annotation loading if we don't need them - const { data, refetch } = useQuery(['annotations', projectId], () => - DefaultService.getAnnotationsApiV0ProjectIdAnnotationsGet(projectId as string) - ); + const { data, refetch } = useQuery({ + queryKey: ['annotations', projectId], + queryFn: () => DefaultService.getAnnotationsApiV0ProjectIdAnnotationsGet(projectId as string) + }); // dummy value as this will not be linked to if annotations are not supported if (data === undefined || backendSpec === undefined) return ; diff --git a/telemetry/ui/src/components/routes/app/AppView.tsx b/telemetry/ui/src/components/routes/app/AppView.tsx index fa33328f3..3608b3e15 100644 --- a/telemetry/ui/src/components/routes/app/AppView.tsx +++ b/telemetry/ui/src/components/routes/app/AppView.tsx @@ -25,7 +25,7 @@ import { AttributeModel, DefaultService } from '../../../api'; -import { useMutation, useQuery } from 'react-query'; +import { useMutation, useQuery } from '@tanstack/react-query'; import { Loading } from '../../common/loading'; import { ApplicationTable } from './StepList'; import { TwoColumnLayout, TwoRowLayout } from '../../common/layout'; @@ -250,73 +250,67 @@ export const AppView = (props: { const [currentEditingAnnotationContext, setCurrentEditingAnnotationContext] = useState< AnnotationEditingContext | undefined >(undefined); - const { data: backendSpec } = useQuery(['backendSpec'], () => - DefaultService.getAppSpecApiV0MetadataAppSpecGet().then((response) => { - return response; - }) - ); - const { data, error } = useQuery( - ['steps', appID, partitionKey], - () => + const { data: backendSpec } = useQuery({ + queryKey: ['backendSpec'], + queryFn: () => + DefaultService.getAppSpecApiV0MetadataAppSpecGet().then((response) => { + return response; + }) + }); + const { data, error } = useQuery({ + queryKey: ['steps', appID, partitionKey], + queryFn: () => DefaultService.getApplicationLogsApiV0ProjectIdAppIdPartitionKeyAppsGet( projectId as string, appID as string, props.partitionKey !== null ? props.partitionKey : '__none__' ), - { - refetchInterval: autoRefresh ? REFRESH_INTERVAL : false, - enabled: shouldQuery - } - ); + refetchInterval: autoRefresh ? REFRESH_INTERVAL : false, + enabled: shouldQuery + }); - const { data: currentFocusStepsData } = useQuery( - ['steps', currentFocusAppID, currentFocusPartitionKey], - () => + const { data: currentFocusStepsData } = useQuery({ + queryKey: ['steps', currentFocusAppID, currentFocusPartitionKey], + queryFn: () => DefaultService.getApplicationLogsApiV0ProjectIdAppIdPartitionKeyAppsGet( projectId as string, currentFocusAppID as string, currentFocusPartitionKey !== null ? currentFocusPartitionKey : '__none__' ), - { - refetchInterval: autoRefresh ? REFRESH_INTERVAL : false, - enabled: currentFocusAppID !== appID && currentFocusAppID !== undefined - } - ); + refetchInterval: autoRefresh ? REFRESH_INTERVAL : false, + enabled: currentFocusAppID !== appID && currentFocusAppID !== undefined + }); // TODO -- use a skiptoken to bypass annotation loading if we don't need them - const { data: annotationsData, refetch: refetchAnnotationsData } = useQuery( - ['annotations', appID, partitionKey], - () => + const { data: annotationsData, refetch: refetchAnnotationsData } = useQuery({ + queryKey: ['annotations', appID, partitionKey], + queryFn: () => DefaultService.getAnnotationsApiV0ProjectIdAnnotationsGet( projectId as string, appID as string, partitionKey !== null ? partitionKey : '__none__' ), - { - refetchInterval: autoRefresh ? REFRESH_INTERVAL : false, - enabled: shouldQuery && props.allowAnnotations && backendSpec?.supports_annotations - } - ); + refetchInterval: autoRefresh ? REFRESH_INTERVAL : false, + enabled: shouldQuery && props.allowAnnotations && backendSpec?.supports_annotations + }); - const { data: currentFocusAnnotationsData } = useQuery( - ['annotations', currentFocusAppID, currentFocusPartitionKey], - () => + const { data: currentFocusAnnotationsData } = useQuery({ + queryKey: ['annotations', currentFocusAppID, currentFocusPartitionKey], + queryFn: () => DefaultService.getAnnotationsApiV0ProjectIdAnnotationsGet( projectId as string, currentFocusAppID as string, currentFocusPartitionKey !== null ? partitionKey : '__none__' ), - { - enabled: - shouldQuery && - props.allowAnnotations && - backendSpec?.supports_annotations && - currentFocusAppID !== appID && - currentFocusAppID !== undefined - } - ); + enabled: + shouldQuery && + props.allowAnnotations && + backendSpec?.supports_annotations && + currentFocusAppID !== appID && + currentFocusAppID !== undefined + }); - const createAnnotationMutation = useMutation( - (data: { + const createAnnotationMutation = useMutation({ + mutationFn: (data: { projectId: string; annotationData: AnnotationCreate; appID: string; @@ -330,16 +324,16 @@ export const AppView = (props: { data.sequenceID, data.annotationData ) - ); + }); - const updateAnnotationMutation = useMutation( - (data: { annotationID: number; annotationData: AnnotationUpdate }) => + const updateAnnotationMutation = useMutation({ + mutationFn: (data: { annotationID: number; annotationData: AnnotationUpdate }) => DefaultService.updateAnnotationApiV0ProjectIdAnnotationIdUpdateAnnotationsPut( projectId, data.annotationID, data.annotationData ) - ); + }); useEffect(() => { const steps = data?.steps || []; diff --git a/telemetry/ui/src/components/routes/app/GraphView.tsx b/telemetry/ui/src/components/routes/app/GraphView.tsx index 31a5f37e3..e2ecf5ab1 100644 --- a/telemetry/ui/src/components/routes/app/GraphView.tsx +++ b/telemetry/ui/src/components/routes/app/GraphView.tsx @@ -21,7 +21,8 @@ import { ActionModel, ApplicationModel, Step } from '../../../api'; import dagre from 'dagre'; import React, { createContext, useLayoutEffect, useRef, useState } from 'react'; -import ReactFlow, { +import { + ReactFlow, BaseEdge, Controls, EdgeProps, @@ -30,14 +31,12 @@ import ReactFlow, { Position, ReactFlowProvider, getBezierPath, - useNodes, useReactFlow -} from 'reactflow'; +} from '@xyflow/react'; -import 'reactflow/dist/style.css'; +import '@xyflow/react/dist/style.css'; import { backgroundColorsForIndex } from './AppView'; import { getActionStatus } from '../../../utils'; -import { getSmartEdge } from '@tisoap/react-flow-smart-edge'; const dagreGraph = new dagre.graphlib.Graph(); @@ -149,38 +148,26 @@ export const ActionActionEdge = ({ markerEnd, data }: EdgeProps) => { - const nodes = useNodes(); - data = data as EdgeData; + const edgeData = data as EdgeData | undefined; const { highlightedActions: previousActions, currentAction } = React.useContext(NodeStateProvider); const allActionsInPath = [...(previousActions || []), ...(currentAction ? [currentAction] : [])]; const containsFrom = allActionsInPath.some( - (action) => action.step_start_log.action === data.from + (action) => action.step_start_log.action === edgeData?.from + ); + const containsTo = allActionsInPath.some( + (action) => action.step_start_log.action === edgeData?.to ); - const containsTo = allActionsInPath.some((action) => action.step_start_log.action === data.to); const shouldHighlight = containsFrom && containsTo; - const getSmartEdgeResponse = getSmartEdge({ - sourcePosition, - targetPosition, + + const [edgePath] = getBezierPath({ sourceX, sourceY, + sourcePosition, targetX, targetY, - nodes + targetPosition }); - let edgePath = null; - if (getSmartEdgeResponse !== null) { - edgePath = getSmartEdgeResponse.svgPathString; - } else { - edgePath = getBezierPath({ - sourceX, - sourceY, - sourcePosition, - targetX, - targetY, - targetPosition - })[0]; - } const style = { markerColor: shouldHighlight ? 'black' : 'gray', @@ -188,7 +175,7 @@ export const ActionActionEdge = ({ }; return ( <> - + ); }; @@ -359,7 +346,7 @@ export const _Graph = (props: { { return ( @@ -382,31 +382,29 @@ const SelfLoadingSubApplicationContainer = (props: { autoRefresh: boolean; depth: number; }) => { - const { data } = useQuery( - ['steps', props.projectID, props.appID, props.partitionKey], - () => + const { data } = useQuery({ + queryKey: ['steps', props.projectID, props.appID, props.partitionKey], + queryFn: () => DefaultService.getApplicationLogsApiV0ProjectIdAppIdPartitionKeyAppsGet( props.projectId as string, props.appID as string, props.partitionKey !== null ? props.partitionKey : '__none__' ), - { - // TODO -- decide how we want to auto-refresh with lots of nested stuff? - // Really, we'll want a bulk API but this is OK for now... - refetchInterval: props.autoRefresh ? REFRESH_INTERVAL : false, - enabled: true - } - ); + // TODO -- decide how we want to auto-refresh with lots of nested stuff? + // Really, we'll want a bulk API but this is OK for now... + refetchInterval: props.autoRefresh ? REFRESH_INTERVAL : false, + enabled: true + }); // TODO -- use a skiptoken to bypass annotation loading if we don't need them - const { data: annotationsData } = useQuery( - ['annotations', props.projectID, props.appID, props.partitionKey], - () => + const { data: annotationsData } = useQuery({ + queryKey: ['annotations', props.projectID, props.appID, props.partitionKey], + queryFn: () => DefaultService.getAnnotationsApiV0ProjectIdAnnotationsGet( props.projectId as string, props.appID as string, props.partitionKey !== null ? props.partitionKey : '__none__' ) - ); + }); const [traceExpandedActions, setTraceExpandedActions] = useState([]); const [linksExpandedActions, setLinksExpandedActions] = useState([]); diff --git a/telemetry/ui/src/components/routes/builder/BuilderEdge.tsx b/telemetry/ui/src/components/routes/builder/BuilderEdge.tsx new file mode 100644 index 000000000..6637a1022 --- /dev/null +++ b/telemetry/ui/src/components/routes/builder/BuilderEdge.tsx @@ -0,0 +1,57 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { BaseEdge, EdgeProps, getBezierPath } from '@xyflow/react'; + +type BuilderEdgeData = { + condition: string; + onConditionChange: (condition: string) => void; +}; + +export const BuilderEdgeComponent = ({ + sourceX, + sourceY, + targetX, + targetY, + sourcePosition, + targetPosition, + markerEnd, + data +}: EdgeProps) => { + const edgeData = data as BuilderEdgeData; + const [edgePath] = getBezierPath({ + sourceX, + sourceY, + sourcePosition, + targetX, + targetY, + targetPosition + }); + + const label = edgeData?.condition === 'default' ? '' : edgeData?.condition || ''; + + return ( + + ); +}; diff --git a/telemetry/ui/src/components/routes/builder/BuilderGraph.tsx b/telemetry/ui/src/components/routes/builder/BuilderGraph.tsx new file mode 100644 index 000000000..ed4e36246 --- /dev/null +++ b/telemetry/ui/src/components/routes/builder/BuilderGraph.tsx @@ -0,0 +1,132 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useEffect, useMemo } from 'react'; +import { + ReactFlow, + Controls, + Background, + ReactFlowProvider, + useReactFlow +} from '@xyflow/react'; +import '@xyflow/react/dist/style.css'; + +import { BurrNodeType, BurrEdgeType, BurrGraph, BurrStepNode, InsertContext } from '../../../utils/builderTypes'; +import { NodeType } from '../../../utils/codeGenerator'; + +import { StepNodeComponent } from './nodes/StepNode'; +import { BigAddButtonComponent } from './nodes/BigAddButton'; +import { GraphEndWidgetComponent } from './nodes/GraphEndWidget'; +import { LoopReturnNodeComponent } from './nodes/LoopReturnNode'; + +import { StraightLineEdgeComponent } from './edges/StraightLineEdge'; +import { LoopStartEdgeComponent } from './edges/LoopStartEdge'; +import { LoopReturnEdgeComponent } from './edges/LoopReturnEdge'; +import { RouterStartEdgeComponent } from './edges/RouterStartEdge'; +import { RouterEndEdgeComponent } from './edges/RouterEndEdge'; + +const nodeTypes = { + [BurrNodeType.STEP]: StepNodeComponent, + [BurrNodeType.BIG_ADD_BUTTON]: BigAddButtonComponent, + [BurrNodeType.GRAPH_END]: GraphEndWidgetComponent, + [BurrNodeType.LOOP_RETURN]: LoopReturnNodeComponent +}; + +const edgeTypes = { + [BurrEdgeType.STRAIGHT_LINE]: StraightLineEdgeComponent, + [BurrEdgeType.LOOP_START]: LoopStartEdgeComponent, + [BurrEdgeType.LOOP_RETURN]: LoopReturnEdgeComponent, + [BurrEdgeType.ROUTER_START]: RouterStartEdgeComponent, + [BurrEdgeType.ROUTER_END]: RouterEndEdgeComponent +}; + +type BuilderGraphProps = { + layoutGraph: BurrGraph; + selectedNodeId: string | null; + onSelectNode: (id: string | null) => void; + onInsert: (nodeType: NodeType, ctx: InsertContext) => void; + unresolvedReads: Map; +}; + +const BuilderGraphInner = (props: BuilderGraphProps) => { + const { fitView } = useReactFlow(); + + useEffect(() => { + const timer = setTimeout(() => fitView({ padding: 0.3 }), 50); + return () => clearTimeout(timer); + }, [props.layoutGraph, fitView]); + + const flowNodes = useMemo(() => { + return props.layoutGraph.nodes.map((node) => { + if (node.type === BurrNodeType.STEP) { + const stepData = node.data as BurrStepNode['data']; + return { + ...node, + data: { + ...stepData, + isSelected: stepData.stepId === props.selectedNodeId, + unresolvedReads: props.unresolvedReads.get(stepData.name) || [], + onSelect: () => props.onSelectNode(stepData.stepId) + } + }; + } + if (node.type === BurrNodeType.BIG_ADD_BUTTON) { + return { + ...node, + data: { ...node.data, onInsert: props.onInsert } + }; + } + return node; + }); + }, [props.layoutGraph.nodes, props.selectedNodeId, props.unresolvedReads, props.onSelectNode]); + + const flowEdges = useMemo(() => { + return props.layoutGraph.edges.map((edge) => ({ + ...edge, + data: { ...edge.data, onInsert: props.onInsert } + })); + }, [props.layoutGraph.edges, props.onInsert]); + + return ( + props.onSelectNode(null)} + fitView + maxZoom={2} + minZoom={0.1} + > + + + + ); +}; + +export const BuilderGraph = (props: BuilderGraphProps) => { + return ( + + + + ); +}; diff --git a/telemetry/ui/src/components/routes/builder/BuilderNode.tsx b/telemetry/ui/src/components/routes/builder/BuilderNode.tsx new file mode 100644 index 000000000..1ab7d568d --- /dev/null +++ b/telemetry/ui/src/components/routes/builder/BuilderNode.tsx @@ -0,0 +1,112 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Handle, Position } from '@xyflow/react'; +import { Chip } from '../../common/chip'; +import { + ExclamationTriangleIcon, + BoltIcon, + ArrowDownTrayIcon, + FlagIcon, + SparklesIcon, + GlobeAltIcon, + CodeBracketIcon, + SignalIcon, + ArrowPathIcon, + ArrowsRightLeftIcon +} from '@heroicons/react/24/outline'; +import { NodeType, NODE_TYPE_META } from '../../../utils/codeGenerator'; + +// eslint-disable-next-line @typescript-eslint/no-explicit-any +const NODE_ICONS: Record> = { + action: BoltIcon, + input: ArrowDownTrayIcon, + result: FlagIcon, + llm_call: SparklesIcon, + api_call: GlobeAltIcon, + code: CodeBracketIcon, + streaming: SignalIcon, + loop: ArrowPathIcon, + router: ArrowsRightLeftIcon +}; + +type BuilderNodeData = { + label: string; + nodeType: NodeType; + reads: string[]; + writes: string[]; + inputs: string[]; + isSelected: boolean; + unresolvedReads: string[]; + onSelect: () => void; +}; + +export const BuilderNodeComponent = (props: { data: BuilderNodeData }) => { + const { label, nodeType, reads, writes, inputs, isSelected, unresolvedReads, onSelect } = + props.data; + const meta = NODE_TYPE_META[nodeType]; + const Icon = NODE_ICONS[nodeType]; + + return ( + <> + +
+
+ + {label} + {meta.label} + {unresolvedReads.length > 0 && ( + + )} +
+ + {reads.length > 0 && ( +
+ {reads.map((r) => ( + + ))} +
+ )} + {writes.length > 0 && ( +
+ {writes.map((w) => ( + + ))} +
+ )} + {inputs.length > 0 && ( +
+ {inputs.map((i) => ( + + ))} +
+ )} +
+ + + ); +}; diff --git a/telemetry/ui/src/components/routes/builder/BuilderToolbar.tsx b/telemetry/ui/src/components/routes/builder/BuilderToolbar.tsx new file mode 100644 index 000000000..896abb3b9 --- /dev/null +++ b/telemetry/ui/src/components/routes/builder/BuilderToolbar.tsx @@ -0,0 +1,222 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useEffect, useRef, useState } from 'react'; +import { + PlusIcon, + ShieldCheckIcon, + ArrowDownTrayIcon, + FolderOpenIcon, + DocumentArrowDownIcon, + TrashIcon +} from '@heroicons/react/24/outline'; +import { NodeType } from '../../../utils/codeGenerator'; +import { NodeTypePicker } from './NodeTypePicker'; +import { + workspaceApi, + BuilderProjectSummary +} from '../../../api/workspaceApi'; + +export const BuilderToolbar = (props: { + onAddNode: (nodeType: NodeType) => void; + onValidate: () => void; + validationCount: number; + projectName: string; + onProjectNameChange: (name: string) => void; + onSave: () => void; + onLoad: (graphJson: string) => void; + onNew: () => void; +}) => { + const [pickerOpen, setPickerOpen] = useState(false); + const [fileMenuOpen, setFileMenuOpen] = useState(false); + const [savedProjects, setSavedProjects] = useState([]); + const [showOpenDialog, setShowOpenDialog] = useState(false); + const addBtnRef = useRef(null); + const fileMenuRef = useRef(null); + + useEffect(() => { + const handler = (e: MouseEvent) => { + if (fileMenuRef.current && !fileMenuRef.current.contains(e.target as Node)) { + setFileMenuOpen(false); + } + }; + document.addEventListener('mousedown', handler); + return () => document.removeEventListener('mousedown', handler); + }, []); + + const loadProjects = async () => { + const projects = await workspaceApi.listBuilderProjects(); + setSavedProjects(projects); + setShowOpenDialog(true); + setFileMenuOpen(false); + }; + + const handleOpen = async (id: string) => { + const project = await workspaceApi.getBuilderProject(id); + props.onProjectNameChange(project.name); + props.onLoad(project.graph_json); + setShowOpenDialog(false); + }; + + const handleDelete = async (id: string) => { + await workspaceApi.deleteBuilderProject(id); + setSavedProjects((prev) => prev.filter((p) => p.id !== id)); + }; + + return ( + <> +
+ {/* File menu */} +
+ + {fileMenuOpen && ( +
+ + + +
+ +
+ )} +
+ +
+ + {/* Project name */} + props.onProjectNameChange(e.target.value)} + className="px-2 py-1 text-sm font-medium text-gray-700 bg-transparent border-b border-transparent hover:border-gray-300 focus:border-blue-500 outline-none w-40" + placeholder="Untitled Project" + /> + +
+ + {/* Add Node */} +
+ + {pickerOpen && ( + } + onSelect={(type) => props.onAddNode(type)} + onClose={() => setPickerOpen(false)} + /> + )} +
+ + {/* Validation */} + +
+ + {/* Open Project Dialog */} + {showOpenDialog && ( +
+
+
+

Open Project

+ +
+
+ {savedProjects.length === 0 && ( +
No saved projects
+ )} + {savedProjects.map((p) => ( +
+ + +
+ ))} +
+
+
+ )} + + ); +}; diff --git a/telemetry/ui/src/components/routes/builder/BuilderView.tsx b/telemetry/ui/src/components/routes/builder/BuilderView.tsx new file mode 100644 index 000000000..d6bd98161 --- /dev/null +++ b/telemetry/ui/src/components/routes/builder/BuilderView.tsx @@ -0,0 +1,507 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useCallback, useEffect, useRef, useState } from 'react'; +import { useParams } from 'react-router-dom'; +import { useQuery } from '@tanstack/react-query'; +import Editor, { OnMount } from '@monaco-editor/react'; +import { + DocumentTextIcon, + XMarkIcon, + ChevronRightIcon, + FolderIcon, + FolderOpenIcon +} from '@heroicons/react/24/outline'; +import { DefaultService } from '../../../api'; +import { useBuilderState } from '../../../hooks/useBuilderState'; +import { BuilderGraph } from './BuilderGraph'; +import { BuilderToolbar } from './BuilderToolbar'; +import { NodeEditor } from './NodeEditor'; +import { NodeType, ProjectFile } from '../../../utils/codeGenerator'; +import { parsePythonCode, buildTreeFromParsed } from '../../../utils/codeParser'; +import { FileEntry, workspaceApi } from '../../../api/workspaceApi'; + +type OpenTab = { + name: string; + language: string; + content: string; + source: 'generated' | 'workspace'; + path?: string; // workspace relative path + modified?: boolean; +}; + +// Mini file explorer for the editor sidebar +const EditorFileExplorer = (props: { + generatedFiles: ProjectFile[]; + workspacePath: string | null; + onOpenFile: (tab: OpenTab) => void; +}) => { + const [expanded, setExpanded] = useState(true); + const [wsExpanded, setWsExpanded] = useState(false); + const [wsFiles, setWsFiles] = useState([]); + const [wsSubFiles, setWsSubFiles] = useState>({}); + + useEffect(() => { + if (props.workspacePath && wsExpanded) { + workspaceApi.getFileTree(props.workspacePath).then(setWsFiles); + } + }, [props.workspacePath, wsExpanded]); + + const loadSubDir = async (path: string) => { + if (!props.workspacePath || wsSubFiles[path]) return; + const entries = await workspaceApi.getFileTree(props.workspacePath, path); + setWsSubFiles((prev) => ({ ...prev, [path]: entries })); + }; + + const openWsFile = async (entry: FileEntry) => { + if (!props.workspacePath || entry.is_dir) return; + const data = await workspaceApi.getFileContent(props.workspacePath, entry.path); + props.onOpenFile({ + name: entry.name, + language: data.language, + content: data.content, + source: 'workspace', + path: entry.path + }); + }; + + return ( +
+ {/* Generated files */} + + {expanded && + props.generatedFiles.map((f) => ( + + ))} + + {/* Workspace files */} + {props.workspacePath && ( + <> + + {wsExpanded && + wsFiles.map((entry) => + entry.is_dir ? ( +
+ + {wsSubFiles[entry.path]?.map((sub) => + !sub.is_dir ? ( + + ) : null + )} +
+ ) : ( + + ) + )} + + )} +
+ ); +}; + +export const BuilderView = () => { + const { projectId, appId } = useParams<{ projectId?: string; appId?: string }>(); + const [projectName, setProjectName] = useState('Untitled Project'); + + const builder = useBuilderState(); + + const editSourceRef = useRef<'graph' | 'editor'>('graph'); + const [editorOverrides, setEditorOverrides] = useState>({}); + const debounceRef = useRef | null>(null); + const [parseError, setParseError] = useState(null); + + // Cleanup debounce on unmount + useEffect(() => { + return () => { + if (debounceRef.current) clearTimeout(debounceRef.current); + }; + }, []); + + // Open tabs + const [openTabs, setOpenTabs] = useState([]); + const [activeTabName, setActiveTabName] = useState(null); + + // Workspace link + const { data: linkInfo } = useQuery({ + queryKey: ['workspace-link', projectId], + queryFn: () => workspaceApi.getWorkspaceLink(projectId!), + enabled: !!projectId + }); + const workspacePath = linkInfo?.workspace_path || null; + + const { data: appData } = useQuery({ + queryKey: ['steps', appId], + queryFn: () => + DefaultService.getApplicationLogsApiV0ProjectIdAppIdPartitionKeyAppsGet(projectId!, appId!, '__none__'), + enabled: !!projectId && !!appId + }); + + const [imported, setImported] = useState(false); + useEffect(() => { + if (appData && !imported) { + builder.importFromApplication(appData.application); + setImported(true); + } + }, [appData, imported, builder]); + + // Auto-open actions.py on first load + useEffect(() => { + if (builder.projectFiles.length > 0 && openTabs.length === 0) { + const actionsFile = builder.projectFiles[0]; + const tab: OpenTab = { + name: actionsFile.name, + language: actionsFile.language, + content: actionsFile.content, + source: 'generated' + }; + setOpenTabs([tab]); + setActiveTabName(tab.name); + } + }, [builder.projectFiles]); + + const handleAddNode = useCallback( + (nodeType: NodeType) => { + editSourceRef.current = 'graph'; + setEditorOverrides({}); + builder.addNode({ x: 0, y: 0 }, nodeType); + }, + [builder] + ); + + const handleSave = useCallback(async () => { + const graphJson = JSON.stringify(builder.rootNode); + await workspaceApi.saveBuilderProject(projectName, graphJson); + }, [builder.rootNode, projectName]); + + const handleLoad = useCallback( + (graphJson: string) => { + try { + const parsed = JSON.parse(graphJson); + builder.setRootNode(parsed); + editSourceRef.current = 'graph'; + setEditorOverrides({}); + setOpenTabs([]); + setActiveTabName(null); + } catch { + // invalid JSON + } + }, + [builder] + ); + + const handleNew = useCallback(() => { + builder.setRootNode(null); + setProjectName('Untitled Project'); + editSourceRef.current = 'graph'; + setEditorOverrides({}); + setOpenTabs([]); + setActiveTabName(null); + }, [builder]); + + // Ctrl+S to save + useEffect(() => { + const handler = (e: KeyboardEvent) => { + if ((e.ctrlKey || e.metaKey) && e.key === 's') { + e.preventDefault(); + handleSave(); + } + }; + document.addEventListener('keydown', handler); + return () => document.removeEventListener('keydown', handler); + }, [handleSave]); + + const getTabKey = (t: OpenTab) => t.path || t.name; + + const openFile = useCallback((tab: OpenTab) => { + const key = getTabKey(tab); + setOpenTabs((prev) => { + const exists = prev.find((t) => getTabKey(t) === key); + if (exists) return prev; + return [...prev, tab]; + }); + setActiveTabName(key); + }, []); + + const closeTab = useCallback( + (key: string) => { + setOpenTabs((prev) => { + const filtered = prev.filter((t) => getTabKey(t) !== key); + if (activeTabName === key) { + setActiveTabName(filtered.length > 0 ? getTabKey(filtered[filtered.length - 1]) : null); + } + return filtered; + }); + }, + [activeTabName] + ); + + const activeTab = openTabs.find((t) => getTabKey(t) === activeTabName); + + // Get content for active tab (generated files update from graph) + const getTabContent = (tab: OpenTab): string => { + if (tab.source === 'generated') { + if (editSourceRef.current === 'editor' && editorOverrides[tab.name] !== undefined) { + return editorOverrides[tab.name]; + } + const gen = builder.projectFiles.find((f) => f.name === tab.name); + return gen?.content || tab.content; + } + return editorOverrides[getTabKey(tab)] ?? tab.content; + }; + + const getTabLanguage = (tab: OpenTab): string => { + if (tab.source === 'generated') { + return builder.projectFiles.find((f) => f.name === tab.name)?.language || tab.language; + } + return tab.language; + }; + + const handleEditorChange = useCallback( + (value: string | undefined) => { + if (!value || !activeTabName) return; + editSourceRef.current = 'editor'; + setEditorOverrides((prev) => ({ ...prev, [activeTabName]: value })); + + // Parse for graph sync only on generated Python files + const tab = openTabs.find((t) => t.name === activeTabName); + if (!tab || tab.source !== 'generated') return; + if (activeTabName !== 'actions.py' && activeTabName !== 'app.py') return; + + if (debounceRef.current) clearTimeout(debounceRef.current); + debounceRef.current = setTimeout(() => { + const actionsCode = + activeTabName === 'actions.py' + ? value + : editorOverrides['actions.py'] || + builder.projectFiles.find((f) => f.name === 'actions.py')?.content || + ''; + const appCode = + activeTabName === 'app.py' + ? value + : editorOverrides['app.py'] || + builder.projectFiles.find((f) => f.name === 'app.py')?.content || + ''; + + const parsed = parsePythonCode(actionsCode + '\n\n' + appCode); + if (parsed.error || parsed.actions.length === 0) { + setParseError(parsed.error || null); + return; + } + setParseError(null); + const tree = buildTreeFromParsed(parsed); + if (tree) builder.setRootFromCode(tree); + }, 1000); + }, + [activeTabName, builder, editorOverrides, openTabs] + ); + + const handleEditorMount: OnMount = (editor) => { + editor.onDidFocusEditorText(() => { + editSourceRef.current = 'editor'; + }); + editor.onDidBlurEditorText(() => { + editSourceRef.current = 'graph'; + setEditorOverrides({}); + }); + }; + + return ( +
+ {}} + validationCount={builder.validationErrors.size} + projectName={projectName} + onProjectNameChange={setProjectName} + onSave={handleSave} + onLoad={handleLoad} + onNew={handleNew} + /> + +
+ {/* Left: Visual Builder */} +
+
+ { + editSourceRef.current = 'graph'; + setEditorOverrides({}); + builder.setSelectedNodeId(id); + }} + onInsert={(nodeType, ctx) => { + editSourceRef.current = 'graph'; + setEditorOverrides({}); + builder.handleInsert(nodeType, ctx); + }} + unresolvedReads={builder.validationErrors} + /> +
+ + {builder.selectedNode && ( + { + editSourceRef.current = 'graph'; + setEditorOverrides({}); + builder.updateNode(builder.selectedNode!.id, updates); + }} + onDelete={() => { + editSourceRef.current = 'graph'; + setEditorOverrides({}); + builder.removeNode(builder.selectedNode!.id); + }} + unresolvedReads={builder.validationErrors.get(builder.selectedNode.name) || []} + /> + )} +
+ + {/* Right: VS Code-style editor */} +
+ {/* Mini file explorer */} + + + {/* Editor area */} +
+ {/* Tabs */} +
+ {openTabs.map((tab) => { + const key = getTabKey(tab); + return ( +
setActiveTabName(key)} + className={`flex items-center gap-1 px-3 py-1.5 text-xs cursor-pointer border-r border-gray-200 shrink-0 select-none ${ + key === activeTabName + ? 'bg-white text-gray-900 font-medium border-b-2 border-b-blue-500' + : 'bg-gray-50 text-gray-500 hover:bg-gray-100' + }`} + > + + {tab.name} + +
+ ); + })} +
+ {parseError && Parse error} +
+ + {/* Monaco Editor */} +
+ {activeTab ? ( + + ) : ( +
+ Open a file from the explorer +
+ )} +
+
+
+
+
+ ); +}; diff --git a/telemetry/ui/src/components/routes/builder/CodePreview.tsx b/telemetry/ui/src/components/routes/builder/CodePreview.tsx new file mode 100644 index 000000000..ae759b418 --- /dev/null +++ b/telemetry/ui/src/components/routes/builder/CodePreview.tsx @@ -0,0 +1,52 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { Prism as SyntaxHighlighter } from 'react-syntax-highlighter'; +import { base16AteliersulphurpoolLight } from 'react-syntax-highlighter/dist/esm/styles/prism'; + +export const CodePreview = (props: { code: string }) => { + const copyToClipboard = () => { + navigator.clipboard.writeText(props.code); + }; + + return ( +
+
+ Generated Python + +
+
+ + {props.code} + +
+
+ ); +}; diff --git a/telemetry/ui/src/components/routes/builder/NodeEditor.tsx b/telemetry/ui/src/components/routes/builder/NodeEditor.tsx new file mode 100644 index 000000000..c572f2761 --- /dev/null +++ b/telemetry/ui/src/components/routes/builder/NodeEditor.tsx @@ -0,0 +1,359 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +import { useState } from 'react'; +import { BuilderNode, NodeType, NODE_TYPE_META } from '../../../utils/codeGenerator'; +import { TrashIcon } from '@heroicons/react/24/outline'; + +const TagInput = (props: { + label: string; + values: string[]; + onChange: (values: string[]) => void; + colorClass: string; +}) => { + const [input, setInput] = useState(''); + + const addTag = () => { + const trimmed = input.trim(); + if (trimmed && !props.values.includes(trimmed)) { + props.onChange([...props.values, trimmed]); + setInput(''); + } + }; + + return ( +
+ +
+ {props.values.map((v) => ( + + {v} + + + ))} +
+ setInput(e.target.value)} + onKeyDown={(e) => { + if (e.key === 'Enter') { + e.preventDefault(); + addTag(); + } + }} + placeholder={`Add ${props.label.toLowerCase()}...`} + className="border border-gray-200 rounded px-2 py-1 text-sm" + /> +
+ ); +}; + +const TextInput = (props: { + label: string; + value: string; + onChange: (v: string) => void; + placeholder?: string; + mono?: boolean; +}) => ( +
+ + props.onChange(e.target.value)} + placeholder={props.placeholder} + className={`border border-gray-200 rounded px-2 py-1 text-sm ${props.mono ? 'font-mono' : ''}`} + /> +
+); + +const SelectInput = (props: { + label: string; + value: string; + onChange: (v: string) => void; + options: { value: string; label: string }[]; +}) => ( +
+ + +
+); + +const CodeInput = (props: { label: string; value: string; onChange: (v: string) => void }) => ( +
+ +